Spring MVC源码浅析

  最近在看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());

 

   还有很多类没说,不过骨架都在这里了,希望我说的明白。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值