SPRING MVC工作原理

Spring MVC简介

Spring MVC是一个开源的web开发框架, Spring MVC 分离了控制器、模型对象、分派器以及处理程序对象的角色,这种分离让它们更容易进行定制。它以零配置,性能优,开发效率高和与spring无逢集成等优点被广大java开发者所喜爱。Spring MVCstruts2是目前最流行的MVC开发框架。

 

Spring MVC工作原理

Spring mvc启动

web.xml中配置一个DispatcherServlet来启动spring mvcSpring MVC启动的同时也启动了spring。通过init-param参数来指定spring的上下文。配置如下:

<servlet>

        <servlet-name>dispatch</servlet-name>

        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>

        <init-param>

            <param-name>contextConfigLocation</param-name>

            <param-value>/WEB-INF/applicationContext.xml</param-value>

        </init-param>

        <load-on-startup>1</load-on-startup>

</servlet>

 

<servlet-mapping>

<servlet-name>dispatch</servlet-name>

<url-pattern>/*</url-pattern>

</servlet-mapping>

 

init-param参数指定了spring的上下文位置,url-pattern参数指定了spring mvc将拦截哪些请求(/*表示拦截所有请求,/*.do表示拦截以.do结尾的所有请求)。

 

DispatcherServlet类的继承关系如图1所示:

 

 

可见spring mvcHttpServletBeanFramworkServletDispathcerServlet三个Servelt来实现,它们分别做不同的初始化工作,具体的初始化过程如图2

 

Spring mvc 一些默认的策略接口:

# Default implementation classes for DispatcherServlet's strategy interfaces.

# Used as fallback when no matching beans are found in the DispatcherServlet context.

# Not meant to be customized by application developers.

 

org.springframework.web.servlet.LocaleResolver=org.springframework.web.servlet.i18n.AcceptHeaderLocaleResolver

 

org.springframework.web.servlet.ThemeResolver=org.springframework.web.servlet.theme.FixedThemeResolver

 

org.springframework.web.servlet.HandlerMapping=org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping,\

org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping

 

org.springframework.web.servlet.HandlerAdapter=org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter,\

org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter,\

org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter

 

org.springframework.web.servlet.HandlerExceptionResolver=org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerExceptionResolver,\

org.springframework.web.servlet.mvc.annotation.ResponseStatusExceptionResolver,\

org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver

 

org.springframework.web.servlet.RequestToViewNameTranslator=org.springframework.web.servlet.view.DefaultRequestToViewNameTranslator

 

org.springframework.web.servlet.ViewResolver=org.springframework.web.servlet.view.InternalResourceViewResolver

 

org.springframework.web.servlet.FlashMapManager=org.springframework.web.servlet.support.SessionFlashMapManager

Spring MVC请求处理过程

Spring mvc请求处理主要包括以下几个组件:

 

DispatcherServlet: 请求的入口,以及控制请求的处理流程。

Controller: 请求的实际处理类。

HandlerMapping: 来找到并保存url请求和处理函数间的mapping关系。

Handleradapter: 实际调用处理函数。

ViewResolver: 视图解析器。

 

所有被拦截的请求进入DispatcherServletdoService方法,这是所有请求的入口,doService方法代码如下:

@Override

protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception {

if (logger.isDebugEnabled()) {

String requestUri = urlPathHelper.getRequestUri(request);

logger.debug("DispatcherServlet with name '" + getServletName() + "' processing " + request.getMethod() +

" request for [" + requestUri + "]");

}

 

// 如果请求包含javax.servlet.include.request_uri参数,则保存原始的请

//求所包含的参数。

//这个地方具体有什么用还不太明白

Map<String, Object> attributesSnapshot = null;

if (WebUtils.isIncludeRequest(request)) {

logger.debug("Taking snapshot of request attributes before include");

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

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 {

// 将真正的处理逻辑交给doDispatch方法

doDispatch(request, response);

}

finally {

// Restore the original attribute snapshot, in case of an include.

if (attributesSnapshot != null) {

restoreAttributesAfterInclude(request, attributesSnapshot);

}

}

}

 

可见doService方法只是做了简单的处理,真正的逻辑处理在doDispatch方法中

protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {

HttpServletRequest processedRequest = request;

HandlerExecutionChain mappedHandler = null;

int interceptorIndex = -1;

 

try {

ModelAndView mv;

boolean errorView = false;

 

try {

// 如果请求中包含文件,且springmvc框架配置了文件解析器,刚将普通// request转换成包含文件的request

processedRequest = checkMultipart(request);

 

// 获取当前请求的HandlerExecutionChain,如果没有找到则直接返回404错误

mappedHandler = getHandler(processedRequest, false);

if (mappedHandler == null || mappedHandler.getHandler() == null) {

noHandlerFound(processedRequest, response);

return;

}

 

// 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()) {

String requestUri = urlPathHelper.getRequestUri(request);

logger.debug("Last-Modified value for [" + requestUri + "] is: " + lastModified);

}

if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) {

return;

}

}

 

// Apply preHandle methods of registered interceptors.

HandlerInterceptor[] interceptors = mappedHandler.getInterceptors();

if (interceptors != null) {

for (int i = 0; i < interceptors.length; i++) {

HandlerInterceptor interceptor = interceptors[i];

if (!interceptor.preHandle(processedRequest, response, mappedHandler.getHandler())) {

triggerAfterCompletion(mappedHandler, interceptorIndex, processedRequest, response, null);

return;

}

interceptorIndex = i;

}

}

 

// Actually invoke the handler.

mv = ha.handle(processedRequest, response, mappedHandler.getHandler());

 

// Do we need view name translation?

if (mv != null && !mv.hasView()) {

mv.setViewName(getDefaultViewName(request));

}

 

// Apply postHandle methods of registered interceptors.

if (interceptors != null) {

for (int i = interceptors.length - 1; i >= 0; i--) {

HandlerInterceptor interceptor = interceptors[i];

interceptor.postHandle(processedRequest, response, mappedHandler.getHandler(), mv);

}

}

}

catch (ModelAndViewDefiningException ex) {

logger.debug("ModelAndViewDefiningException encountered", ex);

mv = ex.getModelAndView();

}

catch (Exception ex) {

Object handler = (mappedHandler != null ? mappedHandler.getHandler() : null);

mv = processHandlerException(processedRequest, response, handler, ex);

errorView = (mv != null);

}

 

// Did the handler return a view to render?

if (mv != null && !mv.wasCleared()) {

render(mv, processedRequest, 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");

}

}

 

// Trigger after-completion for successful outcome.

triggerAfterCompletion(mappedHandler, interceptorIndex, processedRequest, response, null);

}

 

catch (Exception ex) {

// Trigger after-completion for thrown exception.

triggerAfterCompletion(mappedHandler, interceptorIndex, processedRequest, response, ex);

throw ex;

}

catch (Error err) {

ServletException ex = new NestedServletException("Handler processing failed", err);

// Trigger after-completion for thrown exception.

triggerAfterCompletion(mappedHandler, interceptorIndex, processedRequest, response, ex);

throw ex;

}

 

finally {

// Clean up any resources used by a multipart request.

if (processedRequest != request) {

cleanupMultipart(processedRequest);

}

}

}

 

 

 

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值