二、注解驅(qū)動控制器

一、注解驅(qū)動控制器

在上面的示例中,是通過BeanNameUrlHandlerMapping的方式完成請求與controller之間的映射關(guān)系。
如果有多個請求時,需要配置多個映射關(guān)系,并建立多個Controller來進(jìn)行請求處理,實現(xiàn)繁瑣,如何解決?


image.png

解決方式是使用SpringMVC提供的基于注解的處理器:


image.png

也就是上面的
<mvc:annotation-driven/>

標(biāo)簽,這個標(biāo)簽也就是一個基于注解的一個處理器,使用注解的方式來進(jìn)行springmvc的開發(fā)。
使用方式:
首先我們需要去更改springmvc的處理器映射,配置從原來的beannameurlmapping更改為現(xiàn)在的支持注解的這個標(biāo)簽。配置這個標(biāo)簽之后,springmvc會幫助我們自動做一些組件注冊之類的事情,比如上圖中該標(biāo)簽下面的兩個組件。注冊之后,springmvc會通過這兩個bean的實例來完成對注解的支持,比如下面的@Controller和@RequestMapping。從而可以找出請求的url和handller也就是處理器的響應(yīng)的方法之間的關(guān)系,進(jìn)行一些相應(yīng)的關(guān)聯(lián)。
對于Controller注解,如果一個javaBean沒有標(biāo)注這個注解,呢他僅僅是一個普通的javabean,如果標(biāo)注了,則它就可以作為一個處理請求的Controller控制器。
對于requestMapping注解,他是對一個請求的一個映射,可以加在類名的上面,也可以加在控制器的處理方法的上面,從而建立與url的請求的映射關(guān)系。
這些注解想要進(jìn)行生效,則必須加入這兩個注解上面的那個標(biāo)簽。

二、示例代碼

配置文件:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:p="http://www.springframework.org/schema/p"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:mvc="http://www.springframework.org/schema/mvc"
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/mvc
        http://www.springframework.org/schema/mvc/spring-mvc.xsd">
        <!-- 配置處理器映射 HandlerMapping:將一個url請求指定給相應(yīng)的controller去處理 -->
       <!--  <bean name="/index.html" class="cn.smbms.controller.IndexController"></bean> -->
        <mvc:annotation-driven></mvc:annotation-driven>
         <context:component-scan base-package="cn.smbms.controller"></context:component-scan>
        <!-- 配置視圖解析器     /WEB-INF/jsp/index.jsp-->
         <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
            <property name="prefix" value="/WEB-INF/jsp/"></property>
            <property name="suffix" value=".jsp"></property>
         </bean>
        
</beans>

控制器:

package cn.smbms.controller;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.AbstractController;

@Controller
public class IndexController {

    @RequestMapping("/index")
    public ModelAndView index() {
        System.out.println("hello, springmvc");
        return new ModelAndView("index");
    }
}

運行結(jié)果正常。
同時因為此時返回的是邏輯視圖名,所以控制器也可以寫成下面這樣:

package cn.smbms.controller;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.AbstractController;

@Controller
public class IndexController {

    @RequestMapping("/index")
    public String index() {
        System.out.println("hello, springmvc");
        return "index";
    }
}

運行結(jié)果正常。

三、springmvc框架的請求處理流程

image.png

springmvc是一個基于請求驅(qū)動的web框架,他也使用了一些前端控制器的模式來進(jìn)行設(shè)計,然后根據(jù)請求映射的規(guī)則來分發(fā)給相應(yīng)的處理器來進(jìn)行業(yè)務(wù)功能的處理。
其具體處理流程如下:
首先,用戶發(fā)送請求給前端控制器,前端控制器根據(jù)這個請求比如說url來決定要選擇哪個處理器來進(jìn)行相應(yīng)的處理,這個處理器接受到請求之后則會進(jìn)行業(yè)務(wù)的處理,這個時候則會調(diào)用相應(yīng)的業(yè)務(wù)對象來進(jìn)行業(yè)務(wù)處理。業(yè)務(wù)對象處理完了之后會返回一個處理結(jié)果,也就是模型數(shù)據(jù)。處理器拿到這個數(shù)據(jù)模型之后,再把他返回給前端控制器,這時候是一個ModelAndView對象。前端控制器得到這個結(jié)果之后,則會把控制權(quán)收回,然后根據(jù)返回的這個邏輯視圖名選擇相應(yīng)的真正的視圖,然后把模型數(shù)據(jù)傳入到視圖里面,進(jìn)行視圖渲染的展示。最后這個前端控制器再次收回控制權(quán),將響應(yīng)的結(jié)果返回給客戶端。這就是整個流程。在這個流程中,處于核心的是前端控制器,它不斷地組織和協(xié)調(diào)各部門的工作,最終再把結(jié)果返回給結(jié)果。這個前端控制器其實就是我們最開始配置的dispatcherServlet。

四、SpringMVC體系結(jié)構(gòu)

image.png

在上圖中,用戶發(fā)送請求到DispatcherServlet(也不是所有的請求,到底有哪些請求可以在web.xml里面配置),接收到這些請求之后,他會把這些工作委派給其他的組件來進(jìn)行處理,其他組件完成之后再把結(jié)果返回給他,他最后再把結(jié)果進(jìn)行渲染,再輸出返回給用戶。

更細(xì)致的流程如下:
首先,客戶端發(fā)出http請求,web服務(wù)器接受請求,如果匹配dispatcherServlet的話,web服務(wù)器會把這個請求交給dispatcherServlet去處理。dispatcherServlet接受到請求之后,會根據(jù)請求的信息(不僅僅是url)通過HandlerMapping的配置去找到處理請求的handler,這個處理器映射的配置是在servletName-servlet.xml中完成的。通過HandlerMapping,dispatcherServlet找到相應(yīng)的處理器Handler,然后再通過HandlerAdapter對這個Handler進(jìn)行封裝,然后再通過統(tǒng)一的適配器接口調(diào)用相應(yīng)的Handler(這個HandlerAdapter可以理解為具體使用Handler干活的人)。在請求信息到達(dá)處理的Handler之前,在這段時間里,springmvc框架還完成了很多工作,他會將請求信息以一定的方式進(jìn)行轉(zhuǎn)換(就是上圖中右下角紅框框著的那部分),并綁定到這種請求的入?yún)⒅?,入?yún)⒌膶ο髸M(jìn)行數(shù)據(jù)轉(zhuǎn)換,數(shù)據(jù)的格式化以及數(shù)據(jù)驗證等等。等到框架做完這些之后,請求才會到達(dá)最終的Handler里面,進(jìn)行相應(yīng)的業(yè)務(wù)邏輯的處理。在這個地方一直提到的handler和處理器、控制器等等這些可以理解為你項目中所寫的這個controller。這些處理完成之后返回一個ModelAndView對象,這個對象包含邏輯視圖名和數(shù)據(jù)模型給DispatcherServlet。DispatcherServlet此時會把控制權(quán)收回,此時ModelAndView里面包含的邏輯視圖名并非真正的視圖對象,這個時候DispatcherServlet會通過ViewResolver這個組件將邏輯視圖名解析為一個真正的視圖對象。當(dāng)然負(fù)責(zé)進(jìn)行視圖展示的格式有多種多樣,包括jsp、xml、pdf等等。得到真正的視圖對象之后,ModelAndView里面還有一個Model,還可以使用ModelAndView里面的模型數(shù)據(jù)對View再次進(jìn)行視圖渲染,最終把結(jié)果返回給客戶端,最終顯示出來的可能是一個html頁面,也可能是xml,json等等。

4.1DispatcherServlet(前端控制器)

是SpringMVC中最核心的一個類,主要負(fù)責(zé)協(xié)調(diào)組織不同的組件來完成請求處理并且返回響應(yīng)。在配置的時候最早配置的就是這個,在web.xml中進(jìn)行配置。

4.2Handler(處理器)

對應(yīng)MVC中的Controller層。


image.png

ModelAndView對象包含了兩部分內(nèi)容,一部分是視圖界面呈現(xiàn)時所需要使用的模型對象,另一部分是邏輯視圖名。由于java一次只能返回一個對象,所以ModelAndView的作用就是把這兩個對象進(jìn)行了封裝,以方便一次性返回我們所需要的Model和View,當(dāng)然返回的是模型還是視圖也是可以選的,在一些情況下,模型里面沒有任何數(shù)據(jù),此時就返回視圖就可以了,比如說之前的hellospring示例。


image.png

處理器映射

簡單的理解就是根據(jù)請求的url來進(jìn)行相應(yīng)的映射,其接口的實現(xiàn)有很多,默認(rèn)的是BeanNameUrlHandlerMapping,我們在第一個示例中就是使用的這個,當(dāng)你什么都不配置的時候,SpringMVC就會默認(rèn)使用這個,將請求的URl映射到同名的控制器Bean上。但是這種做法存在弊端,就是我需要進(jìn)行多個處理器映射的配置。
應(yīng)用最廣泛的就是DefaultAnnotationHandlerMapping,這種只需要將請求映射到標(biāo)注@Requestmapping注解的控制器和處理方法上。之前示例在使用的時候,配置文件中增加了一鍵式配置,他會自動的幫我們注冊DefaultAnnotationHandlerMapping。

還有一個是RequestMappingHandlerMapping,這個跟DefaultAnnotationHandlerMapping一樣,在3.2版本之后,也可以使用這個,這個知道就可以了。

適配器

HandlerAdapter,這個主要是對Handler進(jìn)行一個封裝,可以把他簡單地理解為他就是使用Handler干活的人。里面有兩個實現(xiàn):AnnotationMethodHandlerAdapter和RequestMappingHandlerAdapter。AnnotationMethodHandlerAdapter和上面的DefaultAnnotationHandlerMapping這兩個是一起的;RequestMappingHandlerAdapter是和RequestMappingHandlerMapping一起的。

視圖解析器

ViewResolver,主要使用InternalResourceView,作為jsp視圖的一個解析。使用這個將一個邏輯視圖名解析為一個真正的視圖對象。

五、SpringMVC框架特點

image.png
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容