DispatcherServlet以及其线程安全性

本文探讨了Spring MVC中的DispatcherServlet的线程安全性。DispatcherServlet在初始化时,其配置和映射关系已在同步代码块中完成,确保线程安全。尽管一些非静态final变量可能引发关注,但在初始化时的赋值操作保证了它们的可见性。文章还详细介绍了DispatcherServlet处理请求的流程,从ServletHolder.handle()到DispatcherServlet.doDispatch(),展示了请求如何被分发到合适的处理器。
摘要由CSDN通过智能技术生成

DispatcherServlet

探究到DispatcherServlet这个MVC中最重要的一个前端请求调度器时,突然考虑到了它本身的线程安全性,由此引入对DispatcherServlet的了解

首先是一个大概的MVC执行框图
在这里插入图片描述
看代码是spring-webmvc-4.3.17版本,首先看一下DispatcherServlet的继承结构
在这里插入图片描述
DispatcherServlet直接继承于FrameworkServlet,然后是HttpServletBean,再往上是HttpServlet直到GenericServlet定义了最基本的servlet标准。

我们知道在spring的托管下,所有的servlet在IOC容器初始化的时候都已经加载完毕,包含这个最重要的DispatcherServlet,作为web服务入口的前端控制器,所需要的参数都在web.xml中进行配置,它会拦截匹配规则的请求。

DispatcherServlet初始化

在这个继承体系下,当ServletWrappingController.afterPropertiesSet()初始化所有的Servlet时,会调用HttpServlet的init()方法进行初始化,实际调用的是DispatcherServlet.initStrategies()方法
在这里插入图片描述

protected void initStrategies(ApplicationContext context) {
   
        initMultipartResolver(context); //文件上传解析,如果请求类型是multipart将通过MultipartResolver进行文件上传解析;
        initLocaleResolver(context);    //本地化解析
        initThemeResolver(context);   //主题解析
        initHandlerMappings(context);   //通过HandlerMapping,将请求映射到处理器
        initHandlerAdapters(context);   //通过HandlerAdapter支持多种类型的处理器
        initHandlerExceptionResolvers(context); //如果执行过程中遇到异常将交给HandlerExceptionResolver来解析
        initRequestToViewNameTranslator(context); //直接解析请求到视图名
        initViewResolvers(context);      //通过ViewResolver解析逻辑视图名到具体视图实现
        initFlashMapManager(context);   //flash映射管理器
	}

在初始化的时候,DispatcherServlet已经持有了所有url对应的Controller的映射关系,方便后续将request中请求的url分发给适合的Controller。

DispatcherServlet线程安全?

其实这是主要想关注的点,DispatcherServlet请求调度器是否是线程安全的呢?

在web容器中对DispatcherServlet初始化的时候是放在Synchronized修饰的同步代码块中实现的,可以保证Servlet创建和初始化的时候是对线程可见的,因此可以保证DispatcherServlet调用initStrategies方法是可以把成员变量刷新到主存中的。但是值得注意的是在DispatcherServlet中有一些变量是未被static final修饰的,这不会引起线程不安全么

	/** Detect all HandlerMappings or just expect "handlerMapping" bean? */
	private boolean detectAllHandlerMappings = true;

	/** Detect all HandlerAdapters or just expect "handlerAdapter" bean? */
	private boolean detectAllHandlerAdapters = true;

	/** Detect all HandlerExceptionResolvers or just expect "handlerExceptionResolver" bean? */
	private boolean detectAllHandlerExceptionResolvers = true;

	/** Detect all ViewResolvers or just expect "viewResolver" bean? */
	private boolean detectAllViewResolvers = true;

	/** Throw a NoHandlerFoundException if no Handler was found to process this request? **/
	private boolean throwExceptionIfNoHandlerFound = false;

	/** Perform cleanup of request attributes after include request? */
	private boolean cleanupAfterInclude = true;

	/** MultipartResolver used by this servlet */
	private MultipartResolver multipartResolver;

	/** LocaleResolver used by this servlet */
	private LocaleResolver localeResolver;

	/** ThemeResolver used by this servlet */
	private ThemeResolver themeResolver;

	/** List of HandlerMappings used by this servlet */
	private List<HandlerMapping> handlerMappings;

	/** List of HandlerAdapters used by this servlet */
	private List<HandlerAdapter> handlerAdapters;

	/** List of HandlerExceptionResolvers used by this servlet */
	private List<HandlerExceptionResolver> handlerExceptionResolvers;

	/** RequestToViewNameTranslator used by this servlet */
	private RequestToViewNameTranslator viewNameTranslator;

	/** FlashMapManager used by this servlet */
	private FlashMapManager flashMapManager;

	/** List of ViewResolvers used by this servlet */
	private List<ViewResolver> viewResolvers;

但仔细查看这些变量的使用处,发现都是在initStrategies()初始化时调用的init方法中进行了赋值,这样就可以保证未被安全修饰符修饰的变量始终是可见的,尽管它们未被修饰,但是并不会影响到DispatcherServlet的可见性。为什么要这么写?特别是那几个未被修改的Boolean类型的参数,尚未得知。

DispatcherServlet处理(分发)请求

按照上一篇blog中所述的在filter过滤后请求到达DispatcherServlet,大概的流程是

ServletHolder.handle() ->

FrameworkServlet.service() -> FrameworkServlet.processRequest()

DispatcherServlet.doService() -> DispatcherServlet.doDispatch()

其中,FrameworkServlet定义了Servlet的service抽象处理流程

	/** FrameworkServlet
  */
	@Override
	protected 
  • 4
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值