您的位置:首页 > 编程语言 > Java开发

Spring MVC请求处理流程及架构

2016-07-02 17:53 567 查看
     在之前
Spring MVC DispatcherServlet的启动以及初始化  中介绍了DispatcherServlet的启动过程,通过这个过程中建立琪了与DispatcherServlet相关的ioc容器环境,并进行了必要的MVC模块初始化工作,为处理请求做好了准备。下面说明DispatcherServlet另一个重要的功能,就是处理web请求。

1、DispatcherServlet类继承体系



以上类图主要反映DispatcherServlet为处理web请求设计的相关类的继承体系,,可以看到,FrameworkServlet通过继承HttpServletBean而继承了HttpSerbvlet,在HttpSerbvlet实现了void service(HttpServletRequest
request, HttpServletResponse response)方法处理web请求,而FrameworkServlet重写了这个方法,除此之外还重写了doGet()和doPost()等方法。最终都将请求调用DispatcherServlet的doDispatcher()方法,doDispatche()是SpringMVC处理web请求的核心方法,在该方法中充分体现DispatcherServlet前置处理器的功能,将主要说明。

2、SpringMVC模式架构



                                                                                                                                                                       
                                                                                                                                                                                               
                                 

以上架构实现主要在doDispatcher()方法中体现,核心架构的具体流程步骤如下:

1、  首先用户发送请求——>DispatcherServlet,前端控制器收到请求后自己不进行处理,而是委托给其他的解析器进行处理,作为统一访问点,进行全局的流程控制;
2、  DispatcherServlet——>HandlerMapping, HandlerMapping将会把请求映射为HandlerExecutionChain对象(包含一个Handler处理器(页面控制器)对象、多个HandlerInterceptor拦截器)对象,通过这种策略模式,很容易添加新的映射策略;
3、  DispatcherServlet——>HandlerAdapter,HandlerAdapter将会把处理器包装为适配器,从而支持多种类型的处理器,即适配器设计模式的应用,从而很容易支持很多类型的处理器;
4、  HandlerAdapter——>处理器功能处理方法的调用,HandlerAdapter将会根据适配的结果调用真正的处理器的功能处理方法,完成功能处理;并返回一个ModelAndView对象(包含模型数据、逻辑视图名);
5、  ModelAndView的逻辑视图名——> ViewResolver, ViewResolver将把逻辑视图名解析为具体的View,通过这种策略模式,很容易更换其他视图技术;
6、  View——>渲染,View会根据传进来的Model模型数据进行渲染,此处的Model实际是一个Map数据结构,因此很容易支持其他视图技术;
7、返回控制权给DispatcherServlet,由DispatcherServlet返回响应给用户,到此一个流程结束。

                                                                                                                                                                                             
                              

                                                                                                                                                                                             
                       注:  此部分内容参考自互联网

3、SpringMVC请求处理具体流程



    在MVC框架初始化完成后,对Http的请求处理是在doService()方法中完成,doService()方法在DispatcherServlet类中:

@Override
protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception {
if (logger.isDebugEnabled()) {
String resumed = WebAsyncUtils.getAsyncManager(request).hasConcurrentResult() ? " resumed" : "";
logger.debug("DispatcherServlet with name '" + getServletName() + "'" + resumed +
" processing " + request.getMethod() + " request for [" + getRequestUri(request) + "]");
}
//这里对request请求参数进行快照保存
// Keep a snapshot of the request attributes in case of an include,
// to be able to restore the original attributes after the include.
Map<String, Object> attributesSnapshot = null;
if (WebUtils.isIncludeRequest(request)) {
attributesSnapshot = new HashMap<String, Object>();
Enumeration<?> attrNames = request.getAttributeNames();
while (attrNames.hasMoreElements()) {
String attrName = (String) attrNames.nextElement();
if (this.cleanupAfterInclude || attrName.startsWith("org.springframework.web.servlet")) {
attributesSnapshot.put(attrName, request.getAttribute(attrName));
}
}
}
//这里将一些框架全局对象设置到request中,以便于handler和view中使用
// Make framework objects available to handlers and view objects.
request.setAttribute(WEB_APPLICATION_CONTEXT_ATTRIBUTE, getWebApplicationContext());
request.setAttribute(LOCALE_RESOLVER_ATTRIBUTE, this.localeResolver);
request.setAttribute(THEME_RESOLVER_ATTRIBUTE, this.themeResolver);
request.setAttribute(THEME_SOURCE_ATTRIBUTE, getThemeSource());

FlashMap inputFlashMap = this.flashMapManager.retrieveAndUpdate(request, response);
if (inputFlashMap != null) {
request.setAttribute(INPUT_FLASH_MAP_ATTRIBUTE, Collections.unmodifiableMap(inputFlashMap));
}
request.setAttribute(OUTPUT_FLASH_MAP_ATTRIBUTE, new FlashMap());
request.setAttribute(FLASH_MAP_MANAGER_ATTRIBUTE, this.flashMapManager);

try {//这里是doDispatcher()函数分发请求的入口
doDispatch(request, response);
}
finally {
if (!WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted()) {
// Restore the original attribute snapshot, in case of an include.
if (attributesSnapshot != null) {
restoreAttributesAfterInclude(request, attributesSnapshot);
}
}
}
}

doDispatch()函数是DispatcherServlet完成dispatcher的核心方法,在该方法中通过HandlerMapping获取请求所对应的handler,之后选择合适的HandlerAdapter对handler进行适配,通过适配器调用handler相应的请求处理方法,并返回ModelAndView对象,通过ViewResolver对视图进行解析,得到View,最后通过View类渲染视图进行呈现。可以看到这里是SpringMVC模式的核心体现。

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,像文件上传这些,如果是通过MultipartResolver进行解析
processedRequest = checkMultipart(request);
multipartRequestParsed = (processedRequest != request);
//通过getHandler()方法,使用HandlerMapping完成请求到处理器的映射,获取到HandlerExecutionChain
// Determine handler for the current request.
mappedHandler = getHandler(processedRequest);
if (mappedHandler == null || mappedHandler.getHandler() == null) {
noHandlerFound(processedRequest, response);
return;
}
//将获取到的Handler处理器进行适配,用响应的HandlerAdapter进行包装
// Determine handler adapter for the current request.
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;
}
}
//如果设置了拦截器,那么在执行handler处理器方法处理之前,进行拦截器预处理
if (!mappedHandler.applyPreHandle(processedRequest, response)) {
return;
}
//通过适配器调用执行处理器的相关功能处理方法,返回ModelAndView对象,包含视图和Model数据
// Actually invoke the handler.
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());

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

applyDefaultViewName(request, mv);
//如果设置了拦截器,那么在执行handler处理器方法处理之后,进行拦截器后处理
mappedHandler.applyPostHandle(processedRequest, response, mv);
}
catch (Exception ex) {
dispatchException = ex;
}
//这里处理请求结果,在个函数中,将判断是否有dispatchException,如果有,将通过ExceptionResolver进行解析处理。然后由ViewResolver解析View ,最后对View进行渲染呈现视图
processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
}
catch (Exception ex) {
triggerAfterCompletion(processedRequest, response, mappedHandler, ex);
}
catch (Error err) {
triggerAfterCompletionWithError(processedRequest, response, mappedHandler, err);
}
finally {
if (asyncManager.isConcurrentHandlingStarted()) {
// Instead of postHandle and afterCompletion
if (mappedHandler != null) {
mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response);
}
}
else {
//如果请求是multipart,那么这里进行资源清理操作

// Clean up any resources used by a multipart request.
if (multipartRequestParsed) {
cleanupMultipart(processedRequest);
}
}
}
}


继续来看processDispatchResult()函数:

private void processDispatchResult(HttpServletRequest request, HttpServletResponse response,
HandlerExecutionChain mappedHandler, ModelAndView mv, Exception exception) throws Exception {

boolean errorView = false;
//如果有异常发出,那么这里将通过processHandlerException()方法处理异常情况,注意返回值仍然是ModelAndView对象

if (exception != null) {
if (exception instanceof ModelAndViewDefiningException) {
logger.debug("ModelAndViewDefiningException encountered", exception);
mv = ((ModelAndViewDefiningException) exception).getModelAndView();
}
else {
Object handler = (mappedHandler != null ? mappedHandler.getHandler() : null);
mv = processHandlerException(request, response, handler, exception);
errorView = (mv != null);
}
}
//这里得到最终的ModelAndView,然后进行渲染,渲染函数见下面
// Did the handler return a view to render?
if (mv != null && !mv.wasCleared()) {
render(mv, request, response);
if (errorView) {
WebUtils.clearErrorRequestAttributes(request);
}
}
else {
if (logger.isDebugEnabled()) {
logger.debug("Null ModelAndView returned to DispatcherServlet with name '" + getServletName() +
"': assuming HandlerAdapter completed request handling");
}
}
if (WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted()) {
// Concurrent handling started during a forward
return;
}
//这里如果设置有拦截器,那么在完成渲染、视图呈现后,进行拦截器AfterCompletion调用
if (mappedHandler != null) {
mappedHandler.triggerAfterCompletion(request, response, null);
}
}


在渲染函数render中,主要通过ViewResolver完成视图解析获取对应的视图,然后通过View对象渲染呈现视图

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;
if (mv.isReference()) {
//由ViewResolver解析View
// We need to resolve the view name.
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完成视图在渲染,渲染时会把Model传入
view.render(mv.getModelInternal(), request, response);
}
catch (Exception ex) {
if (logger.isDebugEnabled()) {
logger.debug("Error rendering view [" + view + "] in DispatcherServlet with name '" +
getServletName() + "'", ex);
}
throw ex;
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息