springMVC分析-1

MVC

作为一个MVC框架,必须回答一下几个问题

  • 请求映射到控制器
  • 请求数据进行绑定
  • 视图渲染

而spring mvc是如何解决这几个问题的呢?

首先,从DispatcherServlet这个入口开始分析,DispatcherServlet继承于FrameworkServlet,而FrameworkServlet继承HttpServletBean,HttpServletBean又继承与HttpServlet,先从
HttpServletBean的init方法开始分析

@Override
public final void init() throws ServletException {
	//省略
	// Let subclasses do whatever initialization they like. 
	initServletBean();//这是个空方法,可以给其子类进行重写

}

再从其子类FrameworkServlet重写的initServletBean()方法

@Override
protected final void initServletBean() throws ServletException {
	//日志块省略

	try {
		//初始化springMvc的ApplicationContext、并查找是否有spring的ApplicationContext 并将其设置为root applicationContext ,初始化spring mvc的bean
		this.webApplicationContext = initWebApplicationContext();

		//空方法,可扩展
		initFrameworkServlet();
	}
	//catch块,日志省略
}

继续分析DispatcherServlet init()方法

protected void initStrategies(ApplicationContext context) {
	//初始化处理mine为multipart/form-data的处理器
	initMultipartResolver(context);
	//初始化本地化处理器,默认是以用户的http请求的AcceptHeaderLocaleResolver
	initLocaleResolver(context);
	//初始化主题处理器
	initThemeResolver(context);
	//初始化HandlerMappings
	initHandlerMappings(context);
	//初始化处理器适配器
	initHandlerAdapters(context);
	//处理异常处理器
	initHandlerExceptionResolvers(context);
	initRequestToViewNameTranslator(context);
	//处理视图转换
	initViewResolvers(context);
	initFlashMapManager(context);
}

从上面代码可以看出来,DispatcherServlet会初始化一些处理器,再分析其处理请求的方法

protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
	HttpServletRequest processedRequest = request;
	HandlerExecutionChain mappedHandler = null;
	boolean multipartRequestParsed = false;
	WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
	try {
		ModelAndView mv = null;
		Exception dispatchException = null;
		try {
			//判断是否是multipart/form-data
			processedRequest = checkMultipart(request);
			multipartRequestParsed = (processedRequest != request);

			// 将请求映射到具体的处理器
			mappedHandler = getHandler(processedRequest);
			if (mappedHandler == null || mappedHandler.getHandler() == null) {
				noHandlerFound(processedRequest, response);
				return;
			}

			对处理器进行适配
			HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());

			// Process last-modified header, if supported by the handler.
			String method = request.getMethod();
			boolean isGet = "GET".equals(method);
			if (isGet || "HEAD".equals(method)) {
				long lastModified = ha.getLastModified(request, mappedHandler.getHandler());
				if (logger.isDebugEnabled()) {
					logger.debug("Last-Modified value for [" + getRequestUri(request) + "] is: " + lastModified);
				}
				if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) {
					return;
				}
			}
			拦截器处理
			if (!mappedHandler.applyPreHandle(processedRequest, response)) {
				return;
			}

			// 调用具体的控制器进行处理
			mv = ha.handle(processedRequest, response, mappedHandler.getHandler());

			if (asyncManager.isConcurrentHandlingStarted()) {
				return;
			}

			applyDefaultViewName(processedRequest, mv);
			拦截器处理
			mappedHandler.applyPostHandle(processedRequest, response, mv);
		}
		catch (Exception ex) {
			dispatchException = ex;
		}
		//处理异常、渲染视图
		processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
	}
	//省略
}

上述代码包括了请求到响应 spring做的过程。我们来细化分析一下。

首先我们来分析请求映射到逻辑处理器的过程

protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
	for (HandlerMapping hm : this.handlerMappings) {
		if (logger.isTraceEnabled()) {
			logger.trace(
					"Testing handler map [" + hm + "] in DispatcherServlet with name '" + getServletName() + "'");
		}
		HandlerExecutionChain handler = hm.getHandler(request);
		if (handler != null) {
			return handler;
		}
	}
	return null;
}

从这段代码看,其会遍历所有的HandlerMapping,然后获取一个HandlerExecutionChain执行对象,而入参是HttpServletRequest,意味着这个HandlerMapping可以根据http请求的所有信息获取到一个控制器。这是第一个扩展点,我们可以实现一个HandlerMapping来处理请求映射。再看HandlerExecutionChain这个类

public class HandlerExecutionChain {

	private final Object handler;

	private HandlerInterceptor[] interceptors;

}

这个类最重要的两个属性,可以看出其对执行对象里面包含了两个部分,一个是控制器,另一个则是拦截器数组,这是第二个扩展点,我们可以实现HandlerInterceptor,在控制器处理前后进行一些操作。

我们来这个操作,其会获取一个控制器的适配器
HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());

protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException {
	for (HandlerAdapter ha : this.handlerAdapters) {
		if (logger.isTraceEnabled()) {
			logger.trace("Testing handler adapter [" + ha + "]");
		}
		if (ha.supports(handler)) {
			return ha;
		}
	}
}

从这个方法的执行,我们可以看出来其依旧是遍历handlerAdapters后返回第一个HandlerAdapter进行处理Handler,所以我们可以实现HandlerAdapter这个接口,自定义对Handler进行处理,这是第三个扩展点

继续玩下走,在processDispatchResult()方法中,先判断是否有exception,若有且不是ModelAndViewDefiningException,则交给HandlerExceptionResolver处理,HandlerExceptionResolver是个接口,可以看出这是第四个扩展点。继续往下走,到render()方法,

protected void render(ModelAndView mv, HttpServletRequest request, HttpServletResponse response) throws Exception {
	// Determine locale for request and apply it to the response.
	Locale locale = this.localeResolver.resolveLocale(request);
	response.setLocale(locale);

	View view;
	// 判断View是不是字符串
	if (mv.isReference()) {
		//交给ViewResolvers处理,将其转换成View对象
		view = resolveViewName(mv.getViewName(), mv.getModelInternal(), locale, request);
		if (view == null) {
			throw new ServletException("Could not resolve view with name '" + mv.getViewName() +
					"' in servlet with name '" + getServletName() + "'");
		}
	}
	else {
		// No need to lookup: the ModelAndView object contains the actual View object.
		view = mv.getView();
		if (view == null) {
			throw new ServletException("ModelAndView [" + mv + "] neither contains a view name nor a " +
					"View object in servlet with name '" + getServletName() + "'");
		}
	}

	// Delegate to the View object for rendering.
	if (logger.isDebugEnabled()) {
		logger.debug("Rendering view [" + view + "] in DispatcherServlet with name '" + getServletName() + "'");
	}
	//将数据渲染到视图中
	try {
		view.render(mv.getModelInternal(), request, response);
	}
}

至此springMVC从请求到响应的流程结束,可以看出springMVC玩的是开闭原则,对修改关闭,可扩展。这是个大体流程,下一篇文章将分析其细节化

posted on 2016-03-21 14:32  liaozq  阅读(139)  评论(0编辑  收藏  举报