Spring Boot 2.0深度实践之核心技术篇【第四章 Web MVC 核心 】
4-1 Welcome理解 Spring Web MVC架构认识 Spring Web MVC简化 Spring Web MVC4-2 理解 Spring Web MVC架构基础架构:ServletServlet特点请求/响应式(Request/Response)屏蔽网络通讯的细节API 特性面向 HTTP 协议完整生命周期Servlet职责处理请求资源管理视图渲染(客户端浏览器)核心架构:前端控
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 注解驱动
-
版本依赖
-
Spring Framework 3.1 +
-
-
注解配置:
@Configuration
(Spring
范式注解) -
组件激活:
@EnableWebMvc
(Spring
模块装配) -
自定义组件 :
WebMvcConfigurer
(Spring 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)自定义组件 :
WebMvcConfigurer
(Spring Bean
)
4-9 Web MVC 常用注解
Spring Framework时代的重新认识-Web MVC注解驱动
@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 完全自动装配)
-
完全自动装配
-
理解自动配置顺序性
- 绝对性:
@AutoConfigureOrder
- 相对顺序:
@AutoConfigureAfter
- 绝对性:
-
装配条件
-
Web
类型判断(ConditionalOnWebApplication
):Servlet
WebApplicationType
Servlet
类型:WebApplicationType.SERVLET
-
API
依赖:Servlet、Spring Web Mvc
- API 判断
@ConditionalOnClass
Servlet
Servlet
Spring Web MVC
DispatcherServlet
WebMvcConfigurer
- API 判断
-
Bean
依赖:WebMvcConfigurationSupport
Bean
判断(@ConditionalOnMissingBean 、 @ConditionalOnBean
)WebMvcConfigurationSupport
-
-
外部化配置
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.java
和WebMvcAutoConfiguration.java
。WebMvcProperties.java
的作用是读取外部化配置,比如application.properties
。
WebMvcAutoConfiguration.java
文件是自动配置Spring WebMvc
,这个文件生效的前提是该项目中没有配置相关WebMvcConfigurationSupport.java
的类,比如@EnableWebMvc
注解就间接使用了WebMvcConfigurationSupport.java
。
更多推荐
所有评论(0)