一、Spring mvc
Spring mvc 作为一个表现框架,必须直面Web领域中表现层中的几大课题:
URL到框架的映射;
http请求参数的绑定;
http响应的生成与输出;
学习一个框架,首要的是西安领会他的设计思想,从抽象。从全局上来审视这个框架,其中最有参考价值的是框架
所定义的核心接口,因为他定义了框架的骨架。
下面将以一个web请求流程为载体,依次介绍Spring mvc的核心接口与类。
浏览器发出一个http请求,请求到达服务器后,首先会被Spring MVC注册在web.xml中的前端转发器DispatcherServlet接收,
DispatcherServlet是一个标准的Servlet,他的作用是接受和转发web请求到内部框架处理单元。
第一个出现的核心接口是:org.springframework.web.servlet中的HanderMapping接口
public interface HandlerMapping{
String PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE = HandlerMapping.class.getName() + ".pathWithinHandlerMapping";
String BEST_MATCHING_PATTERN_ATTRIBUTE = HandlerMapping.class.getName() + ".bestMatchingPattern";
String INTROSPECT_TYPE_LEVEL_MAPPING = HandlerMapping.class.getName() + ".introspectTypeLevelMapping";
String URI_TEMPLATE_VARIABLES_ATTRIBUTE = HandlerMapping.class.getName() + ".uriTemplateVariables";
String PRODUCIBLE_MEDIA_TYPES_ATTRIBUTE = HandlerMapping.class.getName() + ".producibleMediaTypes";
HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception;
}
其中只有一个方法,当DispatcherServlet接收到web请求后,由标准的doGet或doPost,经过几次转发后,最终注册到DispatcherServlet类中的HandlerMapping实现类组成的一个List,然后遍历执行这个List中的HandlerMapping实现类,以该WEB请求的request为参数,依次调用getHandler();第一个不为null的调用结果将会被返回。
protected HandlerExecutionChain getHander(HttpServletRequest request)throws Exception{
for(HandlerMapping hm:this.handlerMappings){
HandlerExecutionChain handler = hm.getHandler(request);
if(handler != null){
return handler;
}
return null;
}
}
第一步处理完成后,会得到一个HandlerExecutionChain对象,这是Spring mvc对URL映射给定的回答。由于参数是HttpServletRequest 因此HandlerMapping的实现类可以利用其中的所有信息来做出HanlderExecutionChain对象的生成决策。
Spring mvc的第一个扩展点就在这里:我们可以编写任意的HandlerMapping实现类,依据任何策略来决定一个web请求到HandlerExecutionCHain对象的生成。
HandlerExecutionChain类,这个对象是一个执行链的封装。HandlerExecutionChain类的代码不长,它定义在org.springframework.web.servlet包中
public class HandlerExecutionChain {
private final Object handler;
private HandlerInterceptor[] interceptors;
private List<HandlerInterceptor> interceptorList;
public HandlerExecutionChain(Object handler) {
this(handler,null);
}
public HandlerExecutionChain(Object handler) {
if (handler instanceof HandlerExecutionChain) {
HandlerExecutionChain originalChain = (HandlerExecutionChain) handler;
this.handler = originalChain.getHandler();
this.interceptorList = new ArrayList<HandlerInterceptor>(); CollectionUtils.mergeArrayIntoCollection(orginalChain.getInterceptors(),this.interceptorList); CollectionUtils.mergeArrayIntoCollection(interceptors,this.interceptorList);
}else{
this.handler = handler;this.interceptors = interceptors;
} ................
}
}
在这里面存在一个实际存在对象,还有一堆拦截器,下面就是HandlerInterceptor这个核心的Spring Mvc接口了
public interface HandlerInterceptor{
boolean preHandler(HttpServletRequest request,HttpServletResponse response,Object handler)throws Exception;
void postHandler(HttpServletRequest request,HttpServletResponse response,Object handler,ModelAndView modelAndView) throws Exception;
void afterCompletion(HttpServletRequest request,HttpServletResponse response,Object handler,Exception ex)throws Exception;
}
到此,HandlerExecutionChain整个执行脉诺也就清楚了,在真正调用其handler对象前,HandlerInterceptor接口实现类组成的数组将会被遍历,其preHandler方法会被一次调用,然后真正的handler对象将会被调用。
handler对象被调用后,就生成了需要的响应数据,在将处理结果写到HttpServletResponse对象之前(Spring mvc 渲染视图),其postHandler方法会被一次调用,视图渲染完成后,最后afterCompletion方法会被依次调用,整个web请求的处理过程就结束了。
在一个处理对象执行之前,之后利用拦截器进行处理,已经成为一种经典的框架设计套路。
HandlerInterceptor,是SpringMvc的第二个扩展点。可以通过自定义拦截器,我们可以在请求被真正处理之前,处理但是没有输出到响应中,已经被输出到响应中之后,三个时间点去做我们自定义的事情。
那么HandlerExecutionChain类中的Object hanler指的是HandlerAdapter: 这又一个核心接口:
public interface HanderAdapter{
boolean supports(Object handler);
ModelAndView handler(HttpServletRequest request,HttpServletResponse response Object handler)throws Exception
long getLastModified(HttpServletRequest request,Object handler);
}
在DispatcherServlet中,除了HandlerMapping实现类的列表,同样也注册了一个HandlerAdapter实现类组成的列表
private List<HandlerMapping>handlerMappings;
private List<HandlerAdapter>handlerAdapters;