最近在看Spring MVC的源码,分享一下我的体验。
先让我们看看一般web框架所做的事情:
1)浏览器发来请求,GET或者POST。
2)web框架通过某种方式包装这些数据。
3)后台业务逻辑代码接受传递的请求数据,进行正常的业务操作(查询,增加,修改,删除等)。
4)web服务器发出响应,渲染页面到浏览器,或者重定向。
所有Web框架都离不开Servlet,因为这是Java web框架的运行时容器。根据MVC模式,Web框架的所有职责被分为三部分即(Model(拥有数据),View(展现数据)和Controoler(控制请求的流向))
为了控制整个请求过程的复杂性,所以把所有请求控制逻辑集中于一处。这就是Front Controller模式。在SpringMVC中,所有的控制逻辑都会由一个类来控制,就是DispatcherServlet.下面对主要类的职责进行一下说明:
1)View接口,根据Model中的数据渲染页面。
public interface View {
String getContentType();
void render(Map model, HttpServletRequest request, HttpServletResponse response)
}
2)Controller接口,处理请求,并返回ModelAndView对象(这是一个包含Model和View的类,作用就是hold数据)
public interface Controller {
ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response)
}
3)ModelMap(代表MVC里的M)。 所有的请求数据都是被封装到这个类里。其实就是一个加强型的Map。和Struts不同的是,Struts是用Form来进行数据传递的,所以会有很多Form。Spring把Model抽象为Map,损失了类型信息。带来了灵活性。
4)ViewResolver。 因为控制类可能直接返回一个视图,也可能仅仅返回一个视图的名字,这样就是这里类根据一些规则来找到一个合适的视图并返回。它承担了C->V的部分职责。
5)DispatcherServlet类。 它就是一个路由器,告诉请求该往哪里去。有点向大堂的前台,来一个客人(请求),她会引领你到正确的地方。doDispatch方法负责执行所有Intercepter和handler的执行过程。
6)HandlerMapping接口。 这个类承担什么职责呢?上面我说道了DispatcherServlet,她是路由器,但是她不是随便转发的,她的转发是有根据的。什么是根据呢,这个接口的职责就是干这个的,相当于一个注册表,DispatcherServlet会根据请求信息在这些注册表(HandlerMapping)里找到正确的Handler,然后由Handler来处理这个请求。大家也许有这样的疑问,为什么不直接转到某一个Controller就完了?答案就是,Spring就是这样一个粘合框架,体现在这里,就是他可以兼容很多Web框架,这里又加了一层间接 。Spring认为,所有的请求都是应该Handler来进行处理,而Controller只是其中一种Handler而已。看看代码:
public interface HandlerMapping {
String PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE = HandlerMapping.class.getName() + ".pathWithinHandlerMapping";
HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception;
}
HanderExecutionChain主要是hold了一个HandlerIntercepter的列表,它用了Decorator模式. 所有HandlerExecutionChain中的intercepter会被合并。最终也是在DispatcherServlet的doDispatch得到调用。
7)说到这里,我们该引出HandlerAdapter接口。 上面我说了,什么都有可能是Handler,这个接口就是整整处理请求的地方。看来两个例子:
第一个例子是把请求适配到Controller。
public class SimpleControllerHandlerAdapter implements HandlerAdapter {
public boolean supports(Object handler) {
return (handler instanceof Controller);
}
public ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
return ((Controller) handler).handleRequest(request, response);
}
public long getLastModified(HttpServletRequest request, Object handler) {
if (handler instanceof LastModified) {
return ((LastModified) handler).getLastModified(request);
}
return -1L;
}
}
接下来的例子是将请求适配到某一个Servlet:
public class SimpleServletHandlerAdapter implements HandlerAdapter {
public boolean supports(Object handler) {
return (handler instanceof Servlet);
}
public ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
((Servlet) handler).service(request, response);
return null;
}
public long getLastModified(HttpServletRequest request, Object handler) {
return -1;
}
}
真正的请求是在DispatcherServlet里调用的,请看doDispatch方法片段,就是这里。
// Actually invoke the handler.
HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
还有很多类没说,不过骨架都在这里了,希望我说的明白。