title: 动手撸一个 mvc 框架5
date: 2020/04/27 10:21
本节内容
- Init#afterPropertiesSet 初始化参数解析器、Binder的参数解析器、返回值解析器、@MA的缓存、@IB的缓存、ResponseBodyAdvice
ha.handlerInternal()
- checkAndPrepare(现在已废弃,不管)
- 检查请求的类型是否支持(默认不管)
- 判断session是否必须存在(默认不管)
- 给响应设置缓存过期时间
- invokeHandlerMethod
- 初始化当前请求的 DataBinderFactory ,用于参数绑定
- 初始化 ModelFactory (作用:请求处理前对Model初始化,请求处理后更新Model)
- 将 Session 域下的参数 copy 到 Model 对象中
- 执行 @ModelAttribute 标注的方法
- 创建 ServletInvHandlerMethod 并设置参数解析器、返回值解析器、Binder工厂
- 新建 mavContainer (将 FlashMap 中参数放进Model、看不懂)
- 执行请求
- 后置处理
- 调用 MF 的更新方法,更新Model
- 根据 mavContainer创建MAV
- 如果 model是 重定向Attr类型,则设置到 FlashMap中
前言
本节内容涉及到 @InitBinder、@ModelAttribute 和 @ControllerAdvice 注解,所以我们先介绍一下
@InitBinder 是参数绑定器,例如:
@InitBinder
protected void initBinder(WebDataBinder binder) {
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
simpleDateFormat.setLenient(false);
binder.registerCustomEditor(Date.class, new CustomDateEditor(simpleDateFormat, false));
}
如果用户请求时输入的是 String 类型的时间,而我们接收的是 Date 类型的,那么通过这个参数绑定器,Spring 就会自动帮我们把 String 类型的转换成 Date 类型的参数。
@ModelAttribute 比较复杂,我们举个例子来说明:
// 向 Model 中设置 {"className": cn.x5456.XXX}
@ModelAttribute("className")
public String setModel() {
return this.getClass().getName();
}
// 向 Model 中设置 {"string": cn.x5456.XXX}
@ModelAttribute
public String setModel2() {
return this.getClass().getName();
}
// 向 Model 中设置 {"className2": cn.x5456.XXX}
@ModelAttribute
public void setModel3(Model model) {
model.addAttribute("className2", this.getClass().getName());
}
@ModelAttribute 就是为了在请求调用之前,让我们将一些参数放进 Model 中,例如:cookie 中用户登录的信息,我们只需要里面的角色,那么就不用每次 @CookieValue 获取 User 对象,然后再获取它的角色了。
@ControllerAdvice Advice 是“通知”的意思,顾名思义他和 AOP 有关,解释一下就是针对标注了 @Controller 注解的类的通知
它可以结合 @InitBinder 和 @ModelAttribute 注解一起使用,这样 @InitBinder 和 @ModelAttribute 注解的方法则针对所有的 Controller 都生效。
ResponseBodyAdvice 接口的实现类将在标注了 @ResponseBody 注解的方法返回之后进行调用,这样我们就可以对响应进行处理,它有 2 种注册方式 1. 直接注册到 RequestMappingHandlerAdapter 中,2. 直接给实现类添加 @ControllerAdvice 注解
Spring 4.0
我们先来看一个重点的 HandlerAdapter ,也就是 RequestMappingHandlerAdapter
它实现了 InitializingBean ,我们先来看看

请求来了



getDataBinderFactory() & getModelFactory()


tag1
注:ModelFactory 的作用是在调用方法前对 Model 初始化,调用方法后更新 Model


tag2

tag4
在处理 @ModelAttribute 时也调用的这个方法(invokeModelAttributeMethods(request, mavContainer);)




我们先看第 3 行

再看第 4 行

这个方法中从“类型注册中心”中找到合适的转换器,然后对其进行转换。
tag5




tag3

自己实现
本部分设计到的组件太多,还是去 git 上下代码吧
网友评论