Spring MVC
Spring 的应⽤程序上下文
应⽤程序上下文间的关系
SpringContainer即应用程序的上下文,上下文中包含业务的pojo对象和还其他配置信息。
ApplicationContext继承了BeanFactory,管理着所有业务对象的生命周期,如托管inventory service和product service。
如依赖注入,ApplicationContext扩展了BeanFactory,可通过xml文件、file、注解等实现类来注入。一般不会直接使用BeanFactory。
其中BeanFactory 不建议直接使用,
关于上下文常⽤的接⼝
BeanFactory
- DefaultListableBeanFactory
ApplicationContext
- ClassPathXmlApplicationContext
- FileSystemXmlApplicationContext
- AnnotationConfigApplicationContext
WebApplicationContext
Web 上下文层次 (划重点)
DispatherServlet一般分为两大块:Servlet WebApplicationContext和Root WebApplicationContext
各个 context 相互独立!!!
当做AOP增强时(如XSS、MQ日志等),每个 context 的 aop 增强只对本 context 的 bean 生效。切记将增强放入需要的ApplicationContext,否则增强无效。
如果想将切面配置成通用的,对父和子上下文的 bean 均支持增强,则:
1. 切面 fooAspect 定义在父上下文。
2. 父上下文和子上下文,均要开启 aop 的增加,即 @EnableAspectJAutoProxy 或<aop: aspectj-autoproxy /> 的支持。
Spring MVC 的请求处理流程
DispatherServlet中doService大致处理流程
1. 绑定Attribute (request.setAttribute): WebApplicationContext / LocaleResolver / ThemeResolver
2. doDispatch(request,response):
处理 Multipart,如果是,则解析将请求转为 MultipartHttpServletRequest
Handler 预处理、处理 :使用getHandler(processedRequest)方法遍历查找handlerMappings,如果找到对应 Handler,执⾏ Controller 及前后置处理器逻辑
处理返回的 Model :呈现视图
Spring MVC 如何定义映射关系
@Controller 控制器
@RequestMapping
- path / method 指定映射路径与⽅法
- params / headers 限定映射范围
- consumes / produces 限定请求与响应格式
一些快捷⽅式
- @RestController
- @GetMapping / @PostMapping / @PutMapping / @DeleteMapping / @PatchMapping
定义处理⽅法
- @RequestBody 请求正文/ @ResponseBody 响应正文/ @ResponseStatus
- @PathVariable 请求参数/ @RequestParam 请求参数/ @RequestHeader请求头
- HttpEntity / ResponseEntity
自定义WebMvcConfigurer使用addFormatters进行类型转换
Spring Boot 在 WebMvcAutoConfiguration 中实现了一个自动配置类 ,添加自定义的 Converter和自定义的 Formatter
Validator
通过 Validator 对绑定结果进⾏校验 (如Hibernate Validator )。只需要在绑定对象上添加@Valid 注解 即可进行校验, 绑定结果会通过BindingResult 传递。
MultipartResolver上传
Spring Boot ⾃动配置 MultipartAutoConfiguration ,支持类型 multipart/form-data,⽀ MultipartFile 类型
Spring MVC 中的各种机制视图处理
视图解析的实现基础ViewResolver 与 View 接口
- AbstractCachingViewResolver
- UrlBasedViewResolver
- FreeMarkerViewResolver
- ContentNegotiatingViewResolver
- InternalResourceViewResolver
DispatcherServlet 中的视图解析逻辑
initStrategies() initViewResolvers() 初始化了了对应 ViewResolver
doDispatch()
- processDispatchResult()
- 没有返回视图的话,尝试 RequestToViewNameTranslator
- resolveViewName() 解析 View 对象
使用 @ResponseBody 的情况
- 在 HandlerAdapter.handle() 的中完成了了 Response 输出
- RequestMappingHandlerAdapter.invokeHandlerMethod()
- HandlerMethodReturnValueHandlerComposite.handleReturnValue()
- RequestResponseBodyMethodProcessor.handleReturnValue()
- HandlerMethodReturnValueHandlerComposite.handleReturnValue()
- RequestMappingHandlerAdapter.invokeHandlerMethod()
ReturnValueHandler用messageConverters,遍历处理
重定向
两种不同的重定向前缀:redirect:改变url 302 会丢失信息么也不适用于分布式部署的情况 / forward:建议使用不改变url
Spring MVC 中的常用视图解析器
Spring MVC ⽀持的视图列表
- https://docs.spring.io/spring/docs/5.1.5.RELEASE/spring-framework-reference/web.html#mvc-view
- Jackson-based JSON / XML
- Thymeleaf & FreeMarker
配置 MessageConverter
通过 WebMvcConfigurer 的 configureMessageConverters()
- Spring Boot 自动查找 HttpMessageConverters 进行注册
Spring Boot 对 Jackson 的⽀持
JacksonAutoConfiguration
- Spring Boot 通过 @JsonComponent 注册 JSON 序列列化组件
- Jackson2ObjectMapperBuilderCustomizer
JacksonHttpMessageConvertersConfiguration
- 增加 jackson-dataformat-xml 以⽀支持 XML 序列列化
Thymeleaf
添加 Thymeleaf 依赖 org.springframework.boot:spring-boot-starter-thymeleaf
Spring Boot 的自动配置
• ThymeleafAutoConfiguration
- ThymeleafViewResolver
Thymeleaf 的⼀些默认配置
- spring.thymeleaf.cache=true
- spring.thymeleaf.check-template=true
- spring.thymeleaf.check-template-location=true
- spring.thymeleaf.enabled=true
- spring.thymeleaf.encoding=UTF-8
- spring.thymeleaf.mode=HTML
- spring.thymeleaf.servlet.content-type=text/html
- spring.thymeleaf.prefix=classpath:/templates/
- spring.thymeleaf.suffix=.html
Spring Boot 中的静态资源配置
核⼼逻辑
• WebMvcConfigurer.addResourceHandlers()
常⽤配置
• spring.mvc.static-path-pattern=/**
• spring.resources.static-locations=classpath:/META-INF/ resources/,classpath:/resources/,classpath:/static/,classpath:/public/
Spring Boot 中的缓存配置
常⽤配置(默认时间单位都是秒)
- ResourceProperties.Cache
- spring.resources.cache.cachecontrol.max-age=时间
- spring.resources.cache.cachecontrol.no-cache=true/false
- spring.resources.cache.cachecontrol.s-max-age=时间
Controller 中⼿工设置缓存
建议的资源访问方式
Spring MVC 的异常解析
核心接口
- HandlerExceptionResolver
实现类
- SimpleMappingExceptionResolver
- DefaultHandlerExceptionResolver
- ResponseStatusExceptionResolver
- ExceptionHandlerExceptionResolver
异常处理方法
处理方法
- @ExceptionHandler
添加位置
- @Controller / @RestController
- @ControllerAdvice / @RestControllerAdvice
Spring MVC 的拦截器
核心接口
• HandlerInteceptor
- boolean preHandle()
- void postHandle()
- void afterCompletion()
针对 @ResponseBody 和 ResponseEntity 的情况
• ResponseBodyAdvice
针对异步请求的接⼝口
• AsyncHandlerInterceptor
- void afterConcurrentHandlingStarted()
拦截器的配置⽅式
常规⽅法
• WebMvcConfigurer.addInterceptors()
Spring Boot 中的配置
- 创建⼀个带 @Configuration 的 WebMvcConfigurer 配置类
- 不能带 @EnableWebMvc(想彻底⾃己控制 MVC 配置除外)