Spring Boot Web MVC 核心

理解Spring Web MVC架構(gòu)

基礎(chǔ)架構(gòu):Servlet


  • 特點(diǎn)
    • 請(qǐng)求/響應(yīng)式(Request/Response)
    • 屏蔽網(wǎng)絡(luò)通訊細(xì)節(jié)
  • API特性
    • 面向HTTP協(xié)議
    • 完整生命周期
  • 職責(zé)
  • 處理請(qǐng)求
  • 資源管理(數(shù)據(jù)庫(kù)連接况毅、消息連接、其他)
  • 視圖渲染

核心架構(gòu):前端控制器(Front Controller)

Spring Web MVC 架構(gòu)

認(rèn)識(shí)Spring Web MVC

Spring Framework時(shí)代的一般認(rèn)識(shí)

實(shí)現(xiàn)Controller

@Controller
public class HelloWorldController {
    @RequestMapping("")
    public String index() {
        return "index";
    }
}

配置 Web MVC 組件

 
<?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:context="http://www.springframework.org/schema/context"
       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">
    <context:component-scan base-package="com.imooc.web"/>
    <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"/>
    <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"/>
    <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>
        <property name="prefix" value="/WEB-INF/jsp/"/>
        <property name="suffix" value=".jsp"/>
    </bean>
</beans>

部署DispatchServlet

<web-app>
    <servlet>
    <servlet-name>app</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>/WEB-INF/app-context.xml</param-value>
        </init-param>
    </servlet>
    <servlet-mapping>
        <servlet-name>app</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>
</web-app>

使用可執(zhí)行 Tomcat Maven 插件

 
<plugin>
    <groupId>org.apache.tomcat.maven</groupId>
    <artifactId>tomcat7-maven-plugin</artifactId>
    <version>2.1</version>
    <executions>
        <execution>
            <id>tomcat-run</id>
            <goals>
                <goal>exec-war-only</goal>
            </goals>
            <phase>package</phase>
            <configuration>
                <!-- ServletContext path -->
                <path>/</path>
            </configuration>
        </execution>
    </executions>
</plugin>

Spring Framework時(shí)代的重新認(rèn)識(shí)

Web MVC 核心組件

組件 Bean 類型 說(shuō)明
HandlerMapping 映射請(qǐng)求(Request)到處理器(Handler)加上其關(guān)聯(lián)的攔截器 (HandlerInterceptor)列表尔艇,其映射關(guān)系基于不同的 HandlerMapping 實(shí)現(xiàn)的一些 標(biāo)準(zhǔn)細(xì)節(jié)尔许。其中兩種主要 HandlerMapping 實(shí)現(xiàn), RequestMappingHandlerMapping 支持標(biāo)注 @RequestMapping 的方法终娃, SimpleUrlHandlerMapping 維護(hù)精確的URI 路徑與處理器的映射母债。
HandlerAdapter 幫助 DispatcherServlet 調(diào)用請(qǐng)求處理器(Handler),無(wú)需關(guān)注其中實(shí)際的調(diào)用 細(xì)節(jié)尝抖。比如,調(diào)用注解實(shí)現(xiàn)的 Controller 需要解析其關(guān)聯(lián)的注解. HandlerAdapter 的主要目的是為了屏蔽與 DispatcherServlet 之間的諸多細(xì)節(jié)迅皇。
HandlerExceptionResolver 解析異常昧辽,可能策略是將異常處理映射到其他處理器(Handlers) 、或到某個(gè) HTML 錯(cuò)誤頁(yè)面登颓,或者其他搅荞。
ViewResolver 從處理器(Handler)返回字符類型的邏輯視圖名稱解析出實(shí)際的 View 對(duì)象,該對(duì) 象將渲染后的內(nèi)容輸出到HTTP 響應(yīng)中框咙。
LocaleResolver咕痛, LocaleContextResolver 從客戶端解析出 Locale ,為其實(shí)現(xiàn)國(guó)際化視圖喇嘱。
MultipartResolver 解析多部分請(qǐng)求(如 Web 瀏覽器文件上傳)的抽象實(shí)現(xiàn)

交互流程

MVC 注解驅(qū)動(dòng)

  • 版本依賴

    • Spring Framework3.1+
  • 基本配置步驟

    • 注解配置:@Configuration(Spring 范氏注解)
    • 組件激活:@EnableWebMvc (Spring模塊裝配)
    • 自定義組件:WebMvcConfigurer(Spring Bean)
  • 重構(gòu)代碼:

@ComponentScan(basePackages = "com.imooc.web")
public class DispatchServletConfig {

}
@Configuration
@EnableWebMvc
public class WebMvcConfig implements WebMvcConfigurer {
    @Bean
    public ViewResolver viewResolver(){
        InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
        viewResolver.setViewClass(JstlView.class);
        viewResolver.setPrefix("/WEB-INF/jsp/");
        viewResolver.setSuffix(".jsp");
        return viewResolver;
    }
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new HandlerInterceptor() {
            @Override
            public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
                System.out.println("攔截中....");
                return true;
            }
        });
    }

}
  • 常用注解
    • 注冊(cè)模型屬性:@ModelAttribute
    • 讀取請(qǐng)求頭:@RequestHeader
    • 讀取Cookie:@CookieValue
    • 校驗(yàn)參數(shù):@Valid茉贡、@Validated
@Controller
public class HelloWorldController {
    @RequestMapping
    public String index(@RequestHeader("Accept-Language")String acceptLanguage,@CookieValue("JSESSIONID")String jsessionId, Model model){
//        model.addAttribute("acceptLanguage",acceptLanguage);
//        model.addAttribute("jsessionId",jsessionId);
//        model.addAttribute("message","hello,world");
        return "index";
    }
}
@ControllerAdvice(assignableTypes = HelloWorldController.class)
public class HelloWorldControllerAdvice {
    @ModelAttribute("acceptLanguage")
    public String acceptLanguage(@RequestHeader("Accept-Language")String acceptLanguage){
        return acceptLanguage;
    }

    @ModelAttribute("jsessionId")
    public String jsessionId(@CookieValue("JSESSIONID")String jsessionId){
        return jsessionId;
    }

    @ModelAttribute("message")
    public String message(){
        return "hello,world";
    }
    @ExceptionHandler(Throwable.class)
    public ResponseEntity<String> onException(Throwable throwable){
        return ResponseEntity.ok(throwable.getMessage());
    }
}

自動(dòng)裝配

  • 版本依賴
    • Spring Framework3.1+
    • Servlet 3.0+

Servlet SPI

  • ServletContainerInitializer,參考Servlet3.0 規(guī)范
  • 配合 @HandlesTypes

Spring 適配

org.springframework.web.SpringServletContainerInitializer

Spring SPI

  • 基礎(chǔ)接口:org.springframework.web.WebApplicationInitializer
  • 編程驅(qū)動(dòng):org.springframework.web.servlet.support.AbstractDispatcherServletInitializer
  • 注解驅(qū)動(dòng):org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer
public class DefaultAnnotationConfigDispatcherServletInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
    //web.xml
    @Override
    protected Class<?>[] getRootConfigClasses() {
        return new Class[0];
    }
    //dispatchServlet
    @Override
    protected Class<?>[] getServletConfigClasses() {
        return new Class[]{DispatchServletConfig.class};
    }

    @Override
    protected String[] getServletMappings() {
        return new String[]{"/"};
    }
}

Spring Boot 時(shí)代簡(jiǎn)化Spring Web MVC

完全自動(dòng)裝配

  • 自動(dòng)裝配DispatcherServletorg.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration
    • 裝配條件:
@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE)
@Configuration
@ConditionalOnWebApplication(type = Type.SERVLET)
@ConditionalOnClass(DispatcherServlet.class)
@AutoConfigureAfter(ServletWebServerFactoryAutoConfiguration.class)
@EnableConfigurationProperties(ServerProperties.class)
  • 替換@EnableWebMvcorg.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration
    • 裝配條件:
@Configuration
@ConditionalOnWebApplication(type = Type.SERVLET)
@ConditionalOnClass({ Servlet.class, DispatcherServlet.class, WebMvcConfigurer.class })
@ConditionalOnMissingBean(WebMvcConfigurationSupport.class)
@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE + 10)
@AutoConfigureAfter({ DispatcherServletAutoConfiguration.class,
        ValidationAutoConfiguration.class })
  • Servlet 容器:org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryAutoConfiguration

理解自動(dòng)裝配順序性

  • 絕對(duì)順序:@AutoConfigureOrder
  • 相對(duì)順序:@AutoConfigureAfter

裝配條件

Web類型判斷(@ConditionalOnWebApplication
  • WebApplicationType
    • Servlet類型:WebApplicationType.SERVLET
API判斷(@ConditionalOnClass
  • Servlet
    • Servlet
  • Spring Web MVC
    • org.springframework.web.servlet.DispatcherServlet
    • org.springframework.web.servlet.config.annotation.WebMvcConfigurer
Bean判斷(@ConditionalOnMissingBean@ConditionalOnBean

org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport

外部化配置

Web MVC配置

org.springframework.boot.autoconfigure.web.servlet.WebMvcProperties

spring.mvc.view.prefix = /WEB-INF/jsp/
spring.mvc.view.suffix = .jsp

Spring Boot JSP依賴

 <!-- Provided -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-tomcat</artifactId>
    <scope>provided</scope>
</dependency>
<dependency>
    <groupId>org.apache.tomcat.embed</groupId>
    <artifactId>tomcat-embed-jasper</artifactId>
    <scope>provided</scope>
</dependency>
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末者铜,一起剝皮案震驚了整個(gè)濱河市腔丧,隨后出現(xiàn)的幾起案子放椰,更是在濱河造成了極大的恐慌,老刑警劉巖愉粤,帶你破解...
    沈念sama閱讀 216,843評(píng)論 6 502
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件砾医,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡衣厘,警方通過(guò)查閱死者的電腦和手機(jī)如蚜,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,538評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)影暴,“玉大人错邦,你說(shuō)我怎么就攤上這事±ぜ欤” “怎么了兴猩?”我有些...
    開(kāi)封第一講書(shū)人閱讀 163,187評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)早歇。 經(jīng)常有香客問(wèn)我倾芝,道長(zhǎng),這世上最難降的妖魔是什么箭跳? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,264評(píng)論 1 292
  • 正文 為了忘掉前任晨另,我火速辦了婚禮,結(jié)果婚禮上谱姓,老公的妹妹穿的比我還像新娘借尿。我一直安慰自己,他們只是感情好屉来,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,289評(píng)論 6 390
  • 文/花漫 我一把揭開(kāi)白布路翻。 她就那樣靜靜地躺著,像睡著了一般茄靠。 火紅的嫁衣襯著肌膚如雪茂契。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 51,231評(píng)論 1 299
  • 那天慨绳,我揣著相機(jī)與錄音掉冶,去河邊找鬼。 笑死脐雪,一個(gè)胖子當(dāng)著我的面吹牛厌小,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播战秋,決...
    沈念sama閱讀 40,116評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼璧亚,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了脂信?” 一聲冷哼從身側(cè)響起涨岁,我...
    開(kāi)封第一講書(shū)人閱讀 38,945評(píng)論 0 275
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤拐袜,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后梢薪,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體蹬铺,經(jīng)...
    沈念sama閱讀 45,367評(píng)論 1 313
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,581評(píng)論 2 333
  • 正文 我和宋清朗相戀三年秉撇,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了甜攀。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,754評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡琐馆,死狀恐怖规阀,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情瘦麸,我是刑警寧澤谁撼,帶...
    沈念sama閱讀 35,458評(píng)論 5 344
  • 正文 年R本政府宣布,位于F島的核電站滋饲,受9級(jí)特大地震影響厉碟,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜屠缭,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,068評(píng)論 3 327
  • 文/蒙蒙 一箍鼓、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧呵曹,春花似錦款咖、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,692評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至跨新,卻和暖如春富腊,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背玻蝌。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,842評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留词疼,地道東北人俯树。 一個(gè)月前我還...
    沈念sama閱讀 47,797評(píng)論 2 369
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像贰盗,于是被迫代替她去往敵國(guó)和親许饿。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,654評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容

  • Spring Cloud為開(kāi)發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見(jiàn)模式的工具(例如配置管理舵盈,服務(wù)發(fā)現(xiàn)陋率,斷路器球化,智...
    卡卡羅2017閱讀 134,652評(píng)論 18 139
  • Spring Boot 參考指南 介紹 轉(zhuǎn)載自:https://www.gitbook.com/book/qbgb...
    毛宇鵬閱讀 46,806評(píng)論 6 342
  • Spring Web MVC Spring Web MVC 是包含在 Spring 框架中的 Web 框架,建立于...
    Hsinwong閱讀 22,394評(píng)論 1 92
  • SpringMVC原理分析 Spring Boot學(xué)習(xí) 5瓦糟、Hello World探究 1筒愚、POM文件 1、父項(xiàng)目...
    jack_jerry閱讀 1,287評(píng)論 0 1
  • 早上6:30起的結(jié)果是困了一早上 看來(lái)周末的休息模式還是不對(duì) 補(bǔ)了個(gè)覺(jué) 實(shí)際九點(diǎn)開(kāi)始學(xué)習(xí) 進(jìn)入學(xué)習(xí)狀態(tài)以后整天效率...
    28歲的櫻桃丸子想要變身閱讀 255評(píng)論 0 1