当前位置: 首页 > 编程日记 > 正文

Spring MVC中DispatcherServlet理解总结(1)

DispatcherServlet在web.xml中的配置

<context-param><!--默认配置文件为/WEB-INF/[servlet名字]-servlet.xml--><param-name>contextConfigLocation</param-name><param-value>WebApplicationContext的上下文配置</param-value>
</context-param>
<!--在启动Web 容器时,自动装配Spring的配置信息-->
<listener><listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<servlet><servlet-name>SpringMVC</servlet-name><servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class><!--此处没有配置contextConfigLocation,默认用WebApplicationContext的上下文配置--><init-param><param-name>contextConfigLocation</param-name><param-value>classpath:/spring/spring-mvc.xml</param-value></init-param></servlet><servlet-mapping><servlet-name>SpringMVC</servlet-name><url-pattern>请求映射</url-pattern>
</servlet-mapping>
复制代码
  • context-param中contextConfigLocation参数,指定用于加载Bean的配置文件,比如加载除Web层的DAO、Service等
  • servlet的init-param中contextConfigLocation参数,指定用于初始化Spring Web MVC框架上下文的配置文件。如果没有配置,默认用context-param中contextConfigLocation参数配置文件
  • ContextLoaderListener作用:在启动Web 容器时,自动装配Spring的配置信息。
    • ContextLoaderListener初始化的上下文加载的Bean是对于整个应用程序共享的;
    • DispatcherServlet初始化的上下文只加载Web相关组件,如Controller、HandlerMapping、HandlerAdapter等等

DispatcherServlet初始化顺序

继承体系:DispatcherServlet->FrameworkServlet->HttpServletBean->HttpServlet

  • 第一步:调用HttpServletBean的init()方法,将始化参数设置到该组件上
public abstract class HttpServletBean extends HttpServlet implements EnvironmentAware{@Overridepublic final void init() throws ServletException {//......//1、将配置文件中的contextConfigLocation初始化参数等设置到该组件,如设置FrameworkServlet的contextConfigLocation属性try {PropertyValues pvs = new ServletConfigPropertyValues(getServletConfig(), this.requiredProperties);// 扩展阅读BeanWrapperBeanWrapper bw = PropertyAccessorFactory.forBeanPropertyAccess(this);ResourceLoader resourceLoader = new ServletContextResourceLoader(getServletContext());bw.registerCustomEditor(Resource.class, new ResourceEditor(resourceLoader, this.environment));initBeanWrapper(bw);bw.setPropertyValues(pvs, true);}catch (BeansException ex) {//…………省略其他代码}//2、提供给子类初始化的扩展点,该方法由FrameworkServlet覆盖initServletBean();if (logger.isDebugEnabled()) {logger.debug("Servlet '" + getServletName() + "' configured successfully");}}//…………省略其他代码private static class ServletConfigPropertyValues extends MutablePropertyValues {public ServletConfigPropertyValues(ServletConfig config, Set<String> requiredProperties) throws ServletException {Set<String> missingProps = requiredProperties != null && !requiredProperties.isEmpty() ? new HashSet(requiredProperties) : null;// 读取servlet的init-param中contextConfigLocation参数Enumeration en = config.getInitParameterNames();while(en.hasMoreElements()) {String property = (String)en.nextElement();Object value = config.getInitParameter(property);this.addPropertyValue(new PropertyValue(property, value));if (missingProps != null) {missingProps.remove(property);}}}}
}
复制代码

扩展阅读BeanWrapper:[blog.csdn.net/u012410733/…]

  • 第二步:FrameworkServlet通过initServletBean()进行Web上下文初始化
public abstract class FrameworkServlet extends HttpServletBean {private String contextConfigLocation;// servlet的init-param中contextConfigLocation参数@Overrideprotected final void initServletBean() throws ServletException {......try {//1、初始化Web上下文this.webApplicationContext = initWebApplicationContext();//2、提供给子类初始化的扩展点initFrameworkServlet();}......}protected WebApplicationContext initWebApplicationContext() {//ROOT上下文(ContextLoaderListener加载的)WebApplicationContext rootContext =  WebApplicationContextUtils.getWebApplicationContext(getServletContext());WebApplicationContext wac = null;if (this.webApplicationContext != null) {// 1、在创建该Servlet注入的上下文wac = this.webApplicationContext;if (wac instanceof ConfigurableWebApplicationContext) {ConfigurableWebApplicationContext cwac = (ConfigurableWebApplicationContext) wac;if (!cwac.isActive()) {if (cwac.getParent() == null) {cwac.setParent(rootContext);}configureAndRefreshWebApplicationContext(cwac);}}}if (wac == null) {//2、查找已经绑定的上下文wac = findWebApplicationContext();}if (wac == null) {//3、如果没有找到相应的上下文,并指定父亲为ContextLoaderListenerwac = createWebApplicationContext(rootContext);}if (!this.refreshEventReceived) {//4、刷新上下文(执行一些初始化)onRefresh(wac);}if (this.publishContext) {// Publish the context as a servlet context attribute.String attrName = getServletContextAttributeName();getServletContext().setAttribute(attrName, wac);//省略部分代码}return wac;}
}
复制代码
  • 第三步:FrameworkServlet通过onRefresh()方法配置前端控制器
public class DispatcherServlet extends FrameworkServlet {private static final Properties defaultStrategies;// 默认策略,具体见DispatcherServlet.propertiesprivate MultipartResolver multipartResolver;private LocaleResolver localeResolver;private ThemeResolver themeResolver;private List<HandlerMapping> handlerMappings;private List<HandlerAdapter> handlerAdapters;private List<HandlerExceptionResolver> handlerExceptionResolvers;private RequestToViewNameTranslator viewNameTranslator;private FlashMapManager flashMapManager;private List<ViewResolver> viewResolvers;//实现子类的onRefresh()方法,该方法委托为initStrategies()方法。@Overrideprotected void onRefresh(ApplicationContext context) {initStrategies(context);}//初始化默认的Spring Web MVC框架使用的策略(如HandlerMapping)protected void initStrategies(ApplicationContext context) {initMultipartResolver(context);//文件上传解析initLocaleResolver(context);//本地化解析initThemeResolver(context);//主题解析initHandlerMappings(context);//请求到处理器的映射initHandlerAdapters(context);//处理器包装为适配器,从而支持多种类型的处理器initHandlerExceptionResolvers(context);//处理器异常解析initRequestToViewNameTranslator(context);//将请求URL映射为逻辑视图名initViewResolvers(context);//把逻辑视图名解析为具体的ViewinitFlashMapManager(context);// ???}/*** 文件上传解析器**/private void initMultipartResolver(ApplicationContext context){this.multipartResolver = (MultipartResolver)context.getBean("multipartResolver", MultipartResolver.class);}/*** 本地化解析**/private void initLocaleResolver(ApplicationContext context){this.localeResolver = (LocaleResolver)context.getBean("localeResolver", LocaleResolver.class);}/*** 主题解析**/private void initThemeResolver(ApplicationContext context){this.themeResolver = (LocaleResolver)context.getBean("themeResolver", ThemeResolver.class);}/*** 处理器解析,比如BeanNameUrlHandlerMapping,SimpleUrlHandlerMapping等**/private void initHandlerMappings(ApplicationContext context){this.handlerMappings = null;if (this.detectAllHandlerMappings) {// 获取IOC容器中实现了HandlerMapping接口的对象Map<String, HandlerMapping> matchingBeans = BeanFactoryUtils.beansOfTypeIncludingAncestors(context, HandlerMapping.class, true, false);if (!matchingBeans.isEmpty()) {this.handlerMappings = new ArrayList(matchingBeans.values());AnnotationAwareOrderComparator.sort(this.handlerMappings);}} else {HandlerMapping hm = (HandlerMapping)context.getBean("handlerMapping", HandlerMapping.class);this.handlerMappings = Collections.singletonList(hm);}if (this.handlerMappings == null) {// 获取默认的处理解析器this.handlerMappings = this.getDefaultStrategies(context, HandlerMapping.class);}}/*** 初始化适配器**/private void initHandlerAdapters(ApplicationContext context) {this.handlerAdapters = null;if (this.detectAllHandlerAdapters) {// 获取IOC容器中实现了HandlerAdapter接口的对象Map<String, HandlerAdapter> matchingBeans = BeanFactoryUtils.beansOfTypeIncludingAncestors(context, HandlerAdapter.class, true, false);if (!matchingBeans.isEmpty()) {this.handlerAdapters = new ArrayList(matchingBeans.values());AnnotationAwareOrderComparator.sort(this.handlerAdapters);}} else {HandlerAdapter ha = (HandlerAdapter)context.getBean("handlerAdapter", HandlerAdapter.class);this.handlerAdapters = Collections.singletonList(ha);}if (this.handlerAdapters == null) {// 获取默认的适配器this.handlerAdapters = this.getDefaultStrategies(context, HandlerAdapter.class);}}/*** 初始化异常解析器**/private void initHandlerExceptionResolvers(ApplicationContext context) {this.handlerExceptionResolvers = null;if (this.detectAllHandlerExceptionResolvers) {Map<String, HandlerExceptionResolver> matchingBeans = BeanFactoryUtils.beansOfTypeIncludingAncestors(context, HandlerExceptionResolver.class, true, false);if (!matchingBeans.isEmpty()) {this.handlerExceptionResolvers = new ArrayList(matchingBeans.values());AnnotationAwareOrderComparator.sort(this.handlerExceptionResolvers);}} else {HandlerExceptionResolver her = (HandlerExceptionResolver)context.getBean("handlerExceptionResolver", HandlerExceptionResolver.class);this.handlerExceptionResolvers = Collections.singletonList(her);}if (this.handlerExceptionResolvers == null) {// 获取默认的适配器this.handlerExceptionResolvers = this.getDefaultStrategies(context, HandlerExceptionResolver.class);}}/*** 将请求URL映射为逻辑视图名**/private void initRequestToViewNameTranslator(ApplicationContext context) {try {this.viewNameTranslator = (RequestToViewNameTranslator)context.getBean("viewNameTranslator", RequestToViewNameTranslator.class);} catch (NoSuchBeanDefinitionException var3) {this.viewNameTranslator = (RequestToViewNameTranslator)this.getDefaultStrategy(context, RequestToViewNameTranslator.class);}}/*** 初始化视图解析器**/private void initViewResolvers(ApplicationContext context) {this.viewResolvers = null;if (this.detectAllViewResolvers) {// 获取IOC容器中实现了ViewResolver接口的对象Map<String, ViewResolver> matchingBeans = BeanFactoryUtils.beansOfTypeIncludingAncestors(context, ViewResolver.class, true, false);if (!matchingBeans.isEmpty()) {this.viewResolvers = new ArrayList(matchingBeans.values());AnnotationAwareOrderComparator.sort(this.viewResolvers);}} else {ViewResolver vr = (ViewResolver)context.getBean("viewResolver", ViewResolver.class);this.viewResolvers = Collections.singletonList(vr);}if (this.viewResolvers == null) {// 获取默认的适配器this.viewResolvers = this.getDefaultStrategies(context, ViewResolver.class);}}
}
复制代码

相关文章:

功能点度量方法介绍

功能点度量方法是利用软件需求分析度量软件规模。 软件需求分析包括&#xff1a;软件功能需求分析、软件性能需求分析 在需求分析阶段可以利用数据流图和用例图对软件规模进行度量&#xff0c;分别对应功能点度量与用例点度量方法 1.功能点度量方法的分类 第三种 IFPUG是我…

微软2014校园招聘笔试试题

转载请标明出处&#xff0c;原文地址&#xff1a;http://blog.csdn.net/hackbuteer1/article/details/121908071、Which statement(s) is(are) correct about thread and process&#xff1f;Select all that apply.(5 Points) A、Threads share the same address space of the…

vi(vim)快捷键小记

1、前言 vi是“visual interface”的缩写&#xff0c;vim是vi IMproved(增强版的vi)。总结一下自己平时常用的vim快捷键&#xff0c;当是忘记也好&#xff0c;后续会不定期更新。 2、vim 快捷键 快捷键说明vi[m] file打开[新建]文件命令模式可以移动光标、删除字符等h,j,k,l左…

Premiere Pro2.0用DebugMode2.3搭桥小日本4.0输出图解

看图说话&#xff0c;不懂的多试试看首先明确几点&#xff1a;1。3个软件&#xff1a;Premiere Pro2.0、DebugMode&#xff08;帧服务器&#xff09;、小日本&#xff08;TMPGEnc 4.0 XPress&#xff09;2。渲染过程是在小日本中完成&#xff0c;与DebugMode无关&#xff0c;De…

用例点度量方法介绍

用例点度量方法分为6个步骤&#xff0c;分别是 step 1:计算未调整前的角色(执行者)权重 将角色按照复杂程度分为3类&#xff0c;具体如下 则本例中 UAW1121329 计算未调整前的用例权重UUC 有三种评估用例复杂程度的方法&#xff0c;具体如下 以下是用例权重评估表(普通那…

NYOJ——街区最短路径问题

街区最短路径问题 时间限制&#xff1a;3000 ms | 内存限制&#xff1a;65535 KB难度&#xff1a;4描述一个街区有很多住户&#xff0c;街区的街道只能为东西、南北两种方向。住户只可以沿着街道行走。各个街道之间的间隔相等。用(x,y)来表示住户坐在的街区。例如&#xff08…

Git 中常用的 4 个命令

使用 Git 进行版本管理时&#xff0c;肯定不只做提交&#xff0c;有时候也会需要回退修改&#xff0c;并且在回退的基础上进行重新提交&#xff0c;这时候有几个常用的命令就需要用到了&#xff0c;下面分别做介绍。 1、查看提交日志 首先&#xff0c;我们查看当前提交记录的命…

7月17日 晴

小懒猫&#xff0c;太阳晒PP拉Mua转载于:https://www.cnblogs.com/loverain/archive/2008/07/17/1244992.html

AS更改初始布局遇到的问题

将所有的simple.xml.ftl的内容都改成 <?xml version"1.0" encoding"utf-8"?> <LinearLayout xmlns:android"http://schemas.android.com/apk/res/android"android:layout_width"match_parent"android:layout_height"…

android Json解析详解

JSON的定义&#xff1a; 一种轻量级的数据交换格式&#xff0c;具有良好的可读和便于快速编写的特性。业内主流技术为其提供了完整的解决方案&#xff08;有点类似于正则表达式 &#xff0c;获得了当今大部分语 言的支持&#xff09;&#xff0c;从而可以在不同平台间进行数据交…

[二]Java虚拟机 jvm内存结构 运行时数据内存 class文件与jvm内存结构的映射 jvm数据类型 虚拟机栈 方法区 堆 含义...

前言简介 class文件是源代码经过编译后的一种平台中立的格式 里面包含了虚拟机运行所需要的所有信息,相当于 JVM的机器语言 JVM全称是Java Virtual Machine ,既然是虚拟机,他终归要运行在物理机上 在操作系统中体现出来的也就是一个进程 操作系统会给他分配资源,割一块内存作为…

import android.support.v7.widget.RecyclerView失败

换成 androidx.recyclerview.widget.RecyclerView 参考文章 https://blog.csdn.net/u013183608/article/details/89428611/

CrackMe_001

本系列文章的目的是从一个没有任何经验的新手的角度(其实就是我自己)&#xff0c;一步步尝试将160个CrackMe全部破解&#xff0c;如果可以&#xff0c;通过任何方式写出一个类似于注册机的东西。 其中&#xff0c;文章中按照如下逻辑编排&#xff08;解决如下问题&#xff09;&…

用javascript实现的纵版飞行射击游戏—《天机》

花了一个半月的时间用javascript完成了这款web版飞行射击游戏&#xff0c;游戏效果接近一般的客户端游戏&#xff0c;不过对机器的要求稍微高点点&#xff0c;主要是CPU&#xff0c;最好在1.5GHZ以上&#xff0c;不然可能会比较卡&#xff0c;支持IE、FF、Opera、safari。 用ja…

对分组交换(packet switching)高效迅速灵活可靠四个优点的理解

1.什么是分组&#xff1f; 通信过程中要发送的整块数据被称为一个报文(message)&#xff0c;报文被划分为一个个更小的等长数据段&#xff0c;每个数据段前加入一些由必要的控制信息组成的首部后&#xff0c;就构成了一个分组。分组是在互联网中传送的数据单元(长报文&#xff…

06、ActivationDeactivation

1、将App.xaml中的StartupUri"MainWindow.xaml"删除。 2、使用NuGet安装Prism.Wpf、Prism.Core、Prism.Unity。 3、添加类“Bootstrapper”&#xff0c;编辑如下&#xff1a; 1 using System;2 using System.Collections.Generic;3 using System.Linq;4 using System…

Git 学习笔记一

Git的基本配置和使用 一、git add ;git commit;git commit -a(默认跟踪修改直接提交(不包括新文件))。 二、tig命令 查看修改记录的前端工具&#xff0c;方面查看修改记录。相当于git log –p。 三、git config --global alias.ci "commit -a -v"添加命令别名&#x…

vb 取得计算机名及目录

Public gCompName 取得计算机名及Windows目录 Dim i% Dim c$ Dim cSql As String Dim cProduct As String c Space(256) i GetComputerName(c, 256) gCompName Trim(c) gCompName Left(gCompName, Len(gCompName) - 1) 读取MAC地址 Dim…

速率单位和信息量单位区分

网络技术钟的速率指的是数据的传送速率&#xff0c;也称为数据率或比特率。 单位是bit/s 比特每秒 也写作b/s 或bps(bit per second) 当数据率较高时 常常在bit/s前面加一个字母&#xff0c;如 k 10^3 M 10^6 G 10^9 T 10^12 P 10^15 …… 数据量往往用字节B作为度量单位…

python 自动生成C++代码 (代码生成器)

python 代码自动生成的方法 &#xff08;代码生成器&#xff09; 遇到的问题 工作中遇到这么一个事&#xff0c;需要写很多C的底层数据库类&#xff0c;但这些类大同小异&#xff0c;无非是增删改查&#xff0c;如果人工来写代码&#xff0c;既费力又容易出错&#xff1b;而借用…

WPF实用指南二:移除窗体的图标

原文:WPF实用指南二&#xff1a;移除窗体的图标WPF没有提供任何功能来移除窗体上的icon图标。一般的做法是设置一个空白的图标&#xff0c;如下图1: 这种做法在窗体边框与标题之间仍然会保留一片空白。比较好的做法是使用Win32API提供的函数来移除这个图标。使用如下的代码&…

什么是EAI?

什么是EAI(enterprise application integration)企业应用集成? EAI是将基于各种不同平台、用不同方案建立的异构应用集成的一种方法和技术。EAI通过建立底层结构&#xff0c;来联系横贯整个企业的异构系统、应用、数据 源等&#xff0c;完成在企业内部的 ERP、CRM、SCM、数据库…

C# 中的委托和事件

引言 委托 和 事件在 .Net Framework中的应用非常广泛&#xff0c;然而&#xff0c;较好地理解委托和事件对很多接触C#时间不长的人来说并不容易。它们就像是一道槛儿&#xff0c;过了这个槛的人&#xff0c;觉得真是太容易了&#xff0c;而没有过去的人每次见到委托和事件就觉…

零代价修复海量服务器的内核缺陷——UCloud内核热补丁技术揭秘

下述为UCloud资深工程师邱模炯在InfoQ架构师峰会上的演讲——《UCloud云平台的内核实践》中非常受关注的内核热补丁技术的一部分。给大家揭开了UCloud云平台内核技术的神秘面纱。 如何零代价修复海量服务器的Linux内核缺陷&#xff1f; 对于一个拥有成千上万台服务器的公司&…

软件工程技术基础-(软件复用技术)

软件可重用问题&#xff0c;包括源程序代码重用、静态库重用和组建重用。 源程序代码重用是直接将其他项目或系统开发完成的代码复制过来&#xff0c;直接使用。 限制源程序代码重用技术使用的关键因素是要考虑代码的语言实现&#xff0c;以及源代码 公开可能带来的知识产权问题…

Parcelable与Serializable的比较

Parcel: Android中的序列化方式&#xff0c;可用于跨进程传输 Parcelable 进程间 如&#xff1a;想从一个第三方app拿进程回来 Serializable 进程内

20140725 快速排序时间复杂度 sTL入门

1、快速排序的时间复杂度(平均时间复杂度为) 数组本身就有序时&#xff0c;效果很差为O(n^2) 2、STl入门 &#xff08;1&#xff09; C内联函数(inline)和C中宏(#define)区别 内联函数有类型检查&#xff0c;宏定义没有&#xff1b;C编程尽量使用内联函数 template <class T…

小编带你进入强如 Disruptor 也发生内存溢出?

前言OutOfMemoryError 问题相信很多朋友都遇到过&#xff0c;相对于常见的业务异常&#xff08;数组越界、空指针等&#xff09;来说这类问题是很难定位和解决的。 本文以最近碰到的一次线上内存溢出的定位、解决问题的方式展开&#xff1b;希望能对碰到类似问题的同学带来思路…

数据库反规范设计

< DOCTYPE html PUBLIC -WCDTD XHTML StrictEN httpwwwworgTRxhtmlDTDxhtml-strictdtd> 反规范化设计 为了提升性能而使用反规范化设计 常用方法&#xff1a; A、在多个表中存储某个字段的副本 B、在父表中存储汇总值 C、将活动数据和历史数据分开存储 D、应用程序本地缓…