本节聊一下DispatcherServlet工作流程中的细节问题

1.attributesSnapshot参数快照

在doService()方法开始,取出request请求中的参数,最后finally中恢复request参数;理论上最后关心response就可以了,为什么还要操作request?其实request对象是web服务器生成传递过来执行servlet##service()方法的,service方法对request进行了各种操作后,再回到web服务器的时候 ,request里面的值已经不再是之前传递过来的样子,为了不影响web服务器,必须回复原来的请求

2.last-modified

LastModified或者说“时间戳”,HTTP协议缓存机制,大概的原理就是:浏览器第一次发出请求,HTTP返回状态码200,正常返回view。而同时,在HTTP的响应头上增加一个“Last-Modified”属性,这标志了此次响应的系统时间。获取响应头的数据以后,再次发送同样的请求的时候,会在HTTP请求头上多增加一个属性“IF-Modified-Since”。而这个属性会引发服务器中的一次匹配:查看两次响应的时间戳。如果时间戳一致,服务器就认为这次请求与上次请求是一样的,HTTP返回状态码304,而此次返回的只有HTTP响应头,静态资源就使用到了浏览器的缓存;时间戳不一致,处理返回静态资源,更新时间戳(留着下一次再比较用,简单内存缓存)。如果要使用LastModified,controller类就要先实现LastModified接口,并且重写getLastModified()方法;针对每次和浏览器交互情况保存修改lastModified值。所以我们经常看到get请求在后面拼接随机数的情况,就是禁止浏览器缓存

3.单一职责

多种类型的HandlerMapping、HandlerAdapter、HandlerExceptionResolver等等,实现各自单独的功能,按照优先级组合在一起,循环,各自处理属于自己的职责任务;统一面向接口,代码干净易扩展,如增加一个HandlerExceptionResolver实例,对DispatcherServlet无感知

4.DispatcherServlet是单例对象,spring ioc容器中只会存在一个对象

5.在配置类DispatcherServletAutoConfiguration通过@Bean(name = DEFAULT_DISPATCHER_SERVLET_REGISTRATION_BEAN_NAME) + new DispatcherServlet();的方式,将dispatcherServlet对象注册进spring ioc容器;通过@Bean + new DispatcherServletRegistrationBean(dispatcherServlet,webMvcProperties.getServlet().getPath());将dispatcherServlet对象注册进servlet容器,ServletContextInitializer##onStartup(ServletContext servletContext)之前文章介绍过