DispatcherServlet 简介

DispatcherServlet 是什么

DispatcherServlet本质上就如其名字所展示的那样是一个Java Servlet。同时它是Spring MVC中最为核心的一块——前端控制器。它主要用来拦截符合要求的外部请求,并把请求分发到不同的控制器去处理,根据控制器处理后的结果,生成相应的响应发送到客户端。

DispatcherServlet作为统一访问点,主要进行全局的流程控制。


DispatcherServlet 在web.xml中的配置

	<servlet>
		<servlet-name>springMVC</servlet-name>
		<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
		<init-param>
			<param-name>contextConfigLocation</param-name>
			<param-value>classpath:spring-mvc.xml</param-value>
		</init-param>
		<load-on-startup>1</load-on-startup>
	</servlet>
	<servlet-mapping>
		<servlet-name>springMVC</servlet-name>
		<url-pattern>/</url-pattern>
	</servlet-mapping>

init-param:初始化参数;
load-on-startup:表示启动容器时初始化该Servlet;

url-pattern:表示哪些请求交给DispatcherServlet(Spring MVC)处理, “/” 是用来定义默认servlet映射的。


DispatcherServlet生命周期

Servlet的生命周期分为三个阶段:

1,初始化阶段,调用init()方法;

2,响应客户请求阶段,调用service()方法;

3,终止阶段,调用destroy()方法;

下面来看看DispatcherServlet的具体生命周期


DispatcherServlet 初始化

从web.xml中的配置可以知道DispatcherServlet在web容器启动时就进入初始化阶段,调用init()方法。

DispatcherServlet的继承结构:

DispatcherServlet继承自抽象类FrameworkServlet,间接继承了HttpServlet(FrameworkServlet继承自HttpServletBean,HttpServletBean继承自HttpServlet)


DispatcherServlet初始化的方法调用关系

从上图可以清晰的看到DispatcherServlet初始化时方法的调用情况

1).调用HttpServlet的init()方法

主要作用:将Servlet初始化参数(init-param)设置到该组件上(如contextAttribute、contextClass、namespace、contextConfigLocation)

	public final void init() throws ServletException {
		// 日志处理代码
		try {
			//将Servlet初始化参数设置到该组件上
			PropertyValues pvs = new ServletConfigPropertyValues(getServletConfig(), this.requiredProperties);
			BeanWrapper bw = PropertyAccessorFactory.forBeanPropertyAccess(this);
			ResourceLoader resourceLoader = new ServletContextResourceLoader(getServletContext());
			bw.registerCustomEditor(Resource.class, new ResourceEditor(resourceLoader, getEnvironment()));
			initBeanWrapper(bw);
			bw.setPropertyValues(pvs, true);
		} catch (BeansException ex) {
			logger.error("Failed to set bean properties on servlet '" + getServletName() + "'", ex);
			throw ex;
		}
		// 调用FrameworkServlet的initServletBean()方法(该方法由FrameworkServlet重写)
		initServletBean();
		// 日志处理代码
	}

2).调用FrameworkServlet的initServletBean()和initWebApplicationContext()方法

主要作用:初始化web上下文

	protected final void initServletBean() throws ServletException {
		// 日志处理代码
		try {
			//调用initWebApplicationContext()方法
			this.webApplicationContext = initWebApplicationContext();
			initFrameworkServlet();
		}
		//异常处理
		// 日志处理代码
	}
    protected WebApplicationContext initWebApplicationContext() {
        // 初始化上下文
        if (!this.refreshEventReceived) {// if条件确保onRefresh只执行一次
            // 调用DispatcherServlet的onRefresh()方法(该方法由DispatcherServlet重写)
            onRefresh(wac);
        }
        //省略部分代码
    }
3).调用DispatcherServlet的onRefresh()和initStrategies()方法

	protected void onRefresh(ApplicationContext context) {
		initStrategies(context);
	}
	protected void initStrategies(ApplicationContext context) {
		initMultipartResolver(context);// 文件上传解析,用于支持文件上传,默认为null
		initLocaleResolver(context);// 本地化解析,默认为AcceptHeaderLocaleResolver
		initThemeResolver(context);// 主题解析,通过它来实现一个页面多套风格,默认为FixedThemeResolver
		initHandlerMappings(context);// 通过HandlerMapping,将请求映射到处理器,详见下文默认值配置
		initHandlerAdapters(context); // 通过HandlerAdapter支持多种类型的处理器,详见下文默认值配置
		initHandlerExceptionResolvers(context);// 如果执行过程中遇到异常将交给HandlerExceptionResolver来解析
		initRequestToViewNameTranslator(context);// 当处理器没有返回视图名时,直接解析请求URL作为视图名,默认为DefaultRequestToViewNameTranslator
		initViewResolvers(context);// 解析逻辑视图名到具体视图实现,默认为InternalResourceViewResolver
		initFlashMapManager(context);// flash映射管理器,默认为SessionFlashMapManager
	}
至此DispatcherServlet的初始化完成。

从上面的过程可以看出DispatcherServlet的初始化主要做了两件事:

    1.初始化Spring Web MVC使用的Web上下文;

    2.初始化DispatcherServlet使用的策略。

DispatcherServlet使用策略默认值

在DispatcherServlet同一个包下有一个DispatcherServlet.properties配置文件,里面配置了DispatcherServlet一些组件的默认值

spring-webmvc-4.1.4.RELEASE的默认配置如下:

# 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
注:HandlerMapping和HandlerAdapter的默认值DefaultAnnotationHandlerMapping和AnnotationMethodHandlerAdapter从3.2版本开始已弃用


DispatcherServlet 响应请求


FrameworkServlet定义了Servlet的service()方法

	@Override
	protected void service(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {

		String method = request.getMethod();
		if (method.equalsIgnoreCase(RequestMethod.PATCH.name())) {
			processRequest(request, response);
		} else {
			super.service(request, response);
		}
	}
无论请求方式是GET、POST、PUT……下一步都会调用FrameworkServlet的processRequest()方法。

以GET为例

	@Override
	protected final void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		processRequest(request, response);
	}

protected final void processRequest(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {

		long startTime = System.currentTimeMillis();
		Throwable failureCause = null;

		LocaleContext previousLocaleContext = LocaleContextHolder.getLocaleContext();
		LocaleContext localeContext = buildLocaleContext(request);

		RequestAttributes previousAttributes = RequestContextHolder.getRequestAttributes();
		ServletRequestAttributes requestAttributes = buildRequestAttributes(request, response, previousAttributes);

		WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
		asyncManager.registerCallableInterceptor(FrameworkServlet.class.getName(), new RequestBindingInterceptor());

		initContextHolders(request, localeContext, requestAttributes);

		try {
            // 调用DispatcherServlet的doService()方法
            doService(request, response);
		} catch (ServletException ex) {
			failureCause = ex;
			throw ex;
		} catch (IOException ex) {
			failureCause = ex;
			throw ex;
		} catch (Throwable ex) {
			failureCause = ex;
			throw new NestedServletException("Request processing failed", ex);
		}
		finally {
			resetContextHolders(request, previousLocaleContext, previousAttributes);
			if (requestAttributes != null) {
				requestAttributes.requestCompleted();
			}
			//日志处理代码
			publishRequestHandledEvent(request, response, startTime, failureCause);
		}
	}

最终调用DispatcherServlet的doService()方法,doService()方法中再调用核心的doDispatch()分派方法完全请求的处理。

关于DispatcherServlet的doDispatch()请参考:http://blog.csdn.net/yangshen_/article/details/53573271


DispatcherServlet 销毁

调用destroy()方法,该方法由FrameworkServlet实现。

	/**
	 * Close the WebApplicationContext of this servlet.
	 * 
	 * @see org.springframework.context.ConfigurableApplicationContext#close()
	 */
	@Override
	public void destroy() {
		getServletContext().log("Destroying Spring FrameworkServlet '" + getServletName() + "'");
		// Only call close() on WebApplicationContext if locally managed...
		if (this.webApplicationContext instanceof ConfigurableApplicationContext
				&& !this.webApplicationContextInjected) {
			((ConfigurableApplicationContext) this.webApplicationContext).close();
		}
	}


  • 7
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值