4-1 Welcome

4-2 理解 Spring Web MVC架构

基础架构:Servlet

在这里插入图片描述

Servlet特点
  • 请求/响应式(Request/Response)
  • 屏蔽网络通讯的细节
API 特性
  • 面向 HTTP 协议
  • 完整生命周期
Servlet职责
  • 处理请求
  • 资源管理
  • 视图渲染(客户端浏览器)
核心架构:前端控制器(Front Controller)

在这里插入图片描述

Spring Web MVC 架构

在这里插入图片描述

4-3 Spring Framework 时代的一般认识

实现 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"/>
     <!--处理 @RequestMapping-->
    <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>
        <!--并不会在Servlet容器启动的时候执行,而是第一次访问的时候才会执行-->
        <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>
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>demo</artifactId>
        <groupId>com.example</groupId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>
    <!--把普通Java工程转换为Web工程-->
    <packaging>war</packaging>

    <artifactId>spring-webmvc</artifactId>
    <dependencies>

        <!--Spring容器不会提供该API,需要强制依赖进来,
        Servlet容器会提供该api,所以scope为provided-->
        <dependency>
            <groupId>jakarta.servlet</groupId>
            <artifactId>jakarta.servlet-api</artifactId>
            <scope>provided</scope>
        </dependency>

        <!--spring web MVC依赖-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
        </dependency>

        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>jstl</artifactId>
        </dependency>

    </dependencies>
     <!--嵌入式tomcat-->
    <build>
        <plugins>
            <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>
        </plugins>
    </build>


</project>
运行项目

pom.xml文件的同级目录下运行
mvn -Dmaven.skip.test -U clean package

target文件夹下生成以下文件

在这里插入图片描述

spring-webmvc-0.0.1-SNAPSHOT-war-exec.jar是指可执行的jar文件
target问件夹下执行以下命令运行项目:

java -jar spring-webmvc-0.0.1-SNAPSHOT-war-exec.jar

4-4 Spring Framework 时代的重新认识

Web MVC核心组件
组件 Bean 类型说明
HandlerMapping 映射请求(Request)到处理器(Handler)加上其关联的拦截器(HandlerInterceptor)列表,其映射关系基于不同的 HandlerMapping实现的一些标准细节。其中两种主要 HandlerMapping实现, RequestMappingHandlerMapping支持标注 @RequestMapping的方法, SimpleUrlHandlerMapping维护精确的URI路径与处理器的映射
HandlerAdapter帮助 DispatcherServlet调用请求处理器(Handler),无需关注其中实际的调用 细节。比如,调用注解实现的 Controller需要解析其关联的注解. HandlerAdapter 的主要目的是为了屏蔽与 DispatcherServlet之间的诸多细节。
HandlerExceptionResolver解析异常,可能策略是将异常处理映射到其他处理器(Handlers) 、或到某个 HTML错误页面,或者其他
ViewResolver从处理器(Handler)返回字符类型的逻辑视图名称解析出实际的 View对象,该对 象将渲染后的内容输出到HTTP响应中。
LocaleResolver,LocaleContextResolver从客户端解析出 Locale,为其实现国际化视图。
MultipartResolver解析多部分请求(如 Web 浏览器文件上传)的抽象实现
交互流程

在这里插入图片描述

  • 处理器管理(Handler)
    • 映射HandlerMapping(Handler映射)
      org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping

    • 适配 HandlerAdapter
      org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter

    • 执行HandlerExecutionChain(处理器的执行链)

  • 页面渲染
    • 视图解析ViewResolver
      org.springframework.web.servlet.view.InternalResourceViewResolver
    • 国际化ViewResolver、LocaleContextResolver
    • 个性化ThemeResolver
  • 异常处理
    • 异常解析:HandlerExceptionResolver
Web MVC注解驱动
自动装配

4-5 核心组件流程说明

4-6 Web MVC 注解驱动

  • 版本依赖
  • 注解配置: @Configuration(Spring范式注解)
  • 组件激活: @EnableWebMvcSpring模块装配)
  • 自定义组件 : WebMvcConfigurerSpring Bean
@Configuration
@EnableWebMvc
public class WebMvcConfig implements WebMvcConfigurer {

    @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(request.getMethod());
                return false;
            }
        });
    }

    @Bean
    public ViewResolver viewResolver(){
        InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
        viewResolver.setViewClass(JstlView.class);
        viewResolver.setPrefix("/WEB-INF/jsp/");
        viewResolver.setSuffix(".jsp");

        return viewResolver;
    }
}
实践
WebMvcConfig.java
@Configuration
@EnableWebMvc
public class WebMvcConfig {

    @Bean
    public ViewResolver viewResolver(){
        InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
        viewResolver.setViewClass(JstlView.class);
        viewResolver.setPrefix("/WEB-INF/jsp/");
        viewResolver.setSuffix(".jsp");

        return viewResolver;
    }
}

4-7 Web MVC 模块组件说明

  • (4.6)自定义组件 : WebMvcConfigurerSpring Bean

4-9 Web MVC 常用注解

Spring Framework时代的重新认识-Web MVC注解驱动
  • 模型属性:@ModelAttribute
@Controller
public class HelloWorldController {

    @RequestMapping("/home")
    public String home(Model model,
    	@RequestHeader(name = "Accept") String accept,
    	@RequestHeader(name = "cookie") String cookieValue){
        model.addAttribute("message","My World!");
        model.addAttribute("accept",accept);
        model.addAttribute("cookieValue",cookieValue);
        return "index";
    }
    
    @RequestMapping("")
    public String index() {
        return "index";
    }

    @ModelAttribute("message")
    public String message(){
        return "Hello Man!";
    }
    
    @ModelAttribute("accept")
    public String requestHeader(@RequestHeader(name = "Accept") String accept){
        return accept;
    }

    @ModelAttribute("cookieValue")
    public String cookie(@RequestHeader(name = "cookie") String cookieValue){
        return cookieValue;
    }
}
index.jsp
<jsp:root xmlns:jsp="http://java.sun.com/JSP/Page" version="2.0">
    <body>
        <message>${message}</message>
        <header>${accept}</header>
        <whaleson>${cookieValue}</whaleson>
    </body>
</jsp:root>
  • 请求头:@RequestHeader
  • Cookie: @CookieValue
  • 参数校验 @Valid @Validated
  • 注解处理:@ExceptionHanlder
    SpringMVC 中 @ControllerAdvice 注解的三种使用场景!
  • 切面通知: @ControllerAdvice
HelloWorldControllerAdvice.java
@ControllerAdvice
public class HelloWorldControllerAdvice {

    @ModelAttribute("message")
    public String message(){
        return "Hello Man!";
    }

    @ModelAttribute("accept")
    public String requestHeader(@RequestHeader(name = "Accept") String accept){
        return accept;
    }

    @ModelAttribute("cookieValue")
    public String cookie(@RequestHeader(name = "cookie") String cookieValue){
        return cookieValue;
    }

    @ExceptionHandler(Throwable.class)
    public ResponseEntity<String> exceptionHandler(Throwable throwable){
        return  ResponseEntity.ok(throwable.getMessage());
    }
}
HelloWorldController.java
@Controller
public class HelloWorldController {

    @RequestMapping("")
    public String index(Model model,
                        @RequestParam("age") int age) {
        model.addAttribute("age",age);
        return "index";
    }
}

index.jsp
<jsp:root xmlns:jsp="http://java.sun.com/JSP/Page" version="2.0">
    <body>
        <message>${message}</message>
        <header>${accept}</header>
        <whaleson>${cookieValue}</whaleson>
        <ages>${age}</ages>
    </body>
</jsp:root>
输出结果
<body>
	<message>Hello Man!</message>
	<header>text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9</header>
	<whaleson>JSESSIONID=8B8A94751F3F72F450B3E6C3353BA242</whaleson>
	<ages>19</ages>
</body>

4-11 Web MVC 自动装配

版本依赖
  • Spring Framework 3.1 +
  • Servlet依赖 Servlet3.0 +
  • Servlet SPI: ServletContainerInitializer
  • Spring适配 : SpringServletContainerInitializer
  • Spring SPI: WebApplicationInitializer
  • 编程驱动: AbstractDispatcherServletInitializer
    • 通过编程的方式驱动Bean的组装;
  • 注解驱动: AbstractAnnotationConfigDispatcherServletInitializer
    • 通过XML配置的方式驱动Bean的组装;

4-12 Web MVC 自动装配实现

DispatcherServletConfig.java
@ComponentScan(basePackages = "com.whaleson.web")
public class DispatcherServletConfig {
}
DefaultAnnotationConfigDispatcherServletInitializer.java
public class DefaultAnnotationConfigDispatcherServletInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
    @Override
    protected Class<?>[] getRootConfigClasses() {
        //对应<init-param>元素;相当于web.xml
        return new Class[0];
    }

    @Override
    protected Class<?>[] getServletConfigClasses() {
        //DispatherServlet
        //相当于<context:component-scan base-ackage="com.whaleson.web"/>
        return new Class[]{DispatcherServletConfig.class};
    }

    @Override
    protected String[] getServletMappings() {
        //DispatherServlet的映射
        //相当于url-pattern
        return new String[]{"/"};
    }
}

4-13 Spring Boot 时代的简化(4-14 完全自动装配)

  • 完全自动装配
    • DispatcherServlet:DispatcherServletAutoConfiguration
    • 替换@EnableWebMvc:WebMvcConfiguration
    • Servlet容器:ServletWebServerFactoryAutoConfiguration
  • 理解自动配置顺序性

    • 绝对性: @AutoConfigureOrder
    • 相对顺序: @AutoConfigureAfter
  • 装配条件
    • Web类型判断( ConditionalOnWebApplication):Servlet
      • WebApplicationType
        • Servlet类型: WebApplicationType.SERVLET
    • API依赖:Servlet、Spring Web Mvc
      • API 判断 @ConditionalOnClass
        • Servlet
          • Servlet
        • Spring Web MVC
          • DispatcherServlet
          • WebMvcConfigurer
    • Bean依赖:WebMvcConfigurationSupport
      • Bean判断( @ConditionalOnMissingBean 、 @ConditionalOnBean)
      • WebMvcConfigurationSupport
  • 外部化配置
    • Web MVC配置: WebMvcProperties
    • 资源配置: ResourceProperties

4-18 重构 Spring Web MVC 项目

目录结构

在这里插入图片描述

pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>demo</artifactId>
        <groupId>com.example</groupId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>
    <packaging>war</packaging>
    <groupId>com.whaleson.web</groupId>
    <artifactId>Springboot-webmvc</artifactId>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>jstl</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-tomcat</artifactId>
        </dependency>
        <dependency>
            <groupId>org.apache.tomcat.embed</groupId>
            <artifactId>tomcat-embed-jasper</artifactId>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>
WebMvcConfig.java
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {

    @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(request.getMethod());
                return true;
            }
        });
    }
}
application.properties
spring.mvc.view.prefix=/WEB-INF/jsp/
spring.mvc.view.suffix=.jsp
总结

重点在WebMvcProperties.javaWebMvcAutoConfiguration.javaWebMvcProperties.java的作用是读取外部化配置,比如application.properties
WebMvcAutoConfiguration.java文件是自动配置Spring WebMvc,这个文件生效的前提是该项目中没有配置相关WebMvcConfigurationSupport.java的类,比如@EnableWebMvc注解就间接使用了WebMvcConfigurationSupport.java

Logo

CSDN联合极客时间,共同打造面向开发者的精品内容学习社区,助力成长!

更多推荐