前面分析了服务端在有SpringMVC框架的加持下,客户端请求到服务端的整个流程,本篇文章就对SpringMVC中用到的亮点做一个总结。
一、优秀的编码习惯
适当封装方法
比如DispatcherServlet初始化功能模块,在主流程中不是写一个大而复杂的代码,而是将每一个独立的功能逻辑都封装到单独的方法中,使主题流程更加简洁明了,提高了易读性。
protected void initStrategies(ApplicationContext context) {
initMultipartResolver(context);
initLocaleResolver(context);
initThemeResolver(context);
initHandlerMappings(context);
initHandlerAdapters(context);
initHandlerExceptionResolvers(context);
initRequestToViewNameTranslator(context);
initViewResolvers(context);
initFlashMapManager(context);
}
代码可拓展
比如HandlerInterceptor接口定义了三个方法preHandle、postHandle、afterCompletion,表示在Controller方法执行前和执行后以及请求处理完成时调用该方法,用户可以实现该接口完成自己项目中特有的处理逻辑,SpringMVC会在调用Controller时的不同节点调用这三个方法,体现了框架良好的可拓展性。
![](https://i-blog.csdnimg.cn/blog_migrate/27ec38a2abbf650e66487e3c71a1352a.png)
面向接口编程,提高代码通用性
比如org.springframework.core.MethodIntrospector#selectMethods(java.lang.Class<?>, org.springframework.core.MethodIntrospector.MetadataLookup<T>)方法,该方法是用来寻找Controller中需要注册到map映射的@RequestMapping注解标注的方法。该方法参数为MetadataLookup接口,用户可以在自己的业务模块中自定义实现该接口,在特定的时机点selectMethods会回调用户自定义的代码逻辑,从而提高了代码的通用性。
![](https://i-blog.csdnimg.cn/blog_migrate/5607e37645431a48f24d9fbb16451441.png)
二、设计模式
模版方法模式
HttpServlet、HttpServletBean、FrameworkServlet、DispatcherServlet中的service方法、init方法都是用的模版方法模式,即父类完成公共的逻辑,创建抽象方法留给子类去实现特有的功能,并在特定的节点进行调用。
![](https://i-blog.csdnimg.cn/blog_migrate/a690f7e15429148aa586846d6bb7bd8c.png)
适配器模式
在SpringMVC中处理请求的Handler有很多种,但是web容器接受到请求后只有固定的request和response两个参数,没法直接由Handler来处理,这个时候就需要适配器HandlerAdapter对Handler进行适配,提供统一的处理入口org.springframework.web.servlet.HandlerAdapter#handle,并传入request、response、handler参数来处理请求。
策略模式
策略模式是应对如果一个业务有多种处理方式时,那么就将该处理方式抽象出一个接口,由子类去实现该接口,以此来写自己独特的处理逻辑,并根据客户端的参数类型来去匹配出最佳适合的处理方式来处理,体现了java多态的特性,后面如果需要新增处理方式时,不用改原有的主逻辑代码,只需再新增一个类来实现该接口就行,从而更加安全。
SpringMVC中的请求参数解析方法:org.springframework.web.method.support.HandlerMethodArgumentResolverComposite#resolveArgument
和返回值解析方法:
org.springframework.web.method.support.HandlerMethodReturnValueHandlerComposite#handleReturnValue
这两个方法里面都使用了策略模式。
三、处理流程
SpringMVC整个处理流程图为:
![](https://i-blog.csdnimg.cn/blog_migrate/5ce074e3b6dc0f5f30fcb53e477a5387.jpeg)