interface HandlerMapping 用来描述请求(request) 和 处理(handler)的映射(map)
主要方法:HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception;
根据请求返回一个HandlerExecutionChain 对象,该对象包含handler和对应的拦截器链,获取该对象后,在DispatcherServlet的doDispatch中先执行拦截器预处理,然后执行handler ,然后执行拦截器后处理,最后根据返回的ModelAndView 生成视图返回
一、DispatcherServlet实例化时执行静态块加载默认的初始化信息保存在defaultStrategies属性里
static {
// Load default strategy implementations from properties file.
// This is currently strictly internal and not meant to be customized try {
ClassPathResource resource = new ClassPathResource(DEFAULT_STRATEGIES_PATH, DispatcherServlet.class);
defaultStrategies = PropertiesLoaderUtils.loadProperties(resource);
}
catch (IOException ex) {
throw new IllegalStateException("Could not load 'DispatcherServlet.properties': " + ex.getMessage());
}
}
配置文件:DispatcherServlet.properties
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
.......
在DispatcherServlet的IOC容器中没有配置HandlerMapping bean时使用这个配置文件中配置的HandlerMapping。
====================================================================
二、在DispatcherServlet实例创建后,web容器会调用父类HttpServletBean的ini()方法,在该方法中调用initServletBean(),
由子类FrameworkServlet实现,完成DispatcherServlet的IOC容器创建和初始化
protected final void initServletBean() throws ServletException {
...
//创建IOC容器,并初始化
this.webApplicationContext = initWebApplicationContext();
...
}
protected WebApplicationContext initWebApplicationContext() {
WebApplicationContext wac = findWebApplicationContext();
if (wac == null) {
// No fixed context defined for this servlet - create a local one.
WebApplicationContext parent =
WebApplicationContextUtils.getWebApplicationContext(getServletContext());
//创建实例
wac = createWebApplicationContext(parent);
}
if (!this.refreshEventReceived) {
//由子类 DispatcherServlet实现 onRefresh(wac);
}
.....
return wac;
}
在DispatcherServlet中重写了onRefresh
protected void onRefresh(ApplicationContext context) {
initStrategies(context);
}
protected void initStrategies(ApplicationContext context) {
initMultipartResolver(context);
initLocaleResolver(context);
initThemeResolver(context);
initHandlerMappings(context);
initHandlerAdapters(context);
initHandlerExceptionResolvers(context);
initRequestToViewNameTranslator(context);
initViewResolvers(context);
}
最终调用到initHandlerMappings(context)进行handlerMappings的初始化
private void initHandlerMappings(ApplicationContext context) {
this.handlerMappings = null;
//是否需要一起找出parent中配置的HandlerMapping的bean
if (this.detectAllHandlerMappings) {
//获取该容器以及所有parent容器中不重复的HandlerMapping类及其子类bean
Map<String, HandlerMapping> matchingBeans = BeanFactoryUtils.beansOfTypeIncludingAncestors(context, HandlerMapping.class, true, false);
if (!matchingBeans.isEmpty()) {
//如果配置了HandlerMapping类的bean,赋值给handlerMappings
this.handlerMappings = new ArrayList<HandlerMapping>(matchingBeans.values());
//排序实现了HandlerMapping接口,都要实现Ordered接口用来排序 OrderComparator.sort(this.handlerMappings);
}
}
else {
try {
//从该容器中根据bean的名字,找出名为handlerMapping的bean
HandlerMapping hm = context.getBean(HANDLER_MAPPING_BEAN_NAME, HandlerMapping.class);
this.handlerMappings = Collections.singletonList(hm);
}
catch (NoSuchBeanDefinitionException ex) {
// Ignore, we'll add a default HandlerMapping later.
}
}
if (this.handlerMappings == null) {
//如果在容器中没获取到,根据读取配置文件defaultStrategies的信息,创建默认的HandlerMapping的list
this.handlerMappings = getDefaultStrategies(context, HandlerMapping.class);
if (logger.isDebugEnabled()) {
logger.debug("No HandlerMappings found in servlet '" + getServletName() + "': using default");
}
}
}
protected <T> List<T> getDefaultStrategies(ApplicationContext context, Class<T> strategyInterface) {
String key = strategyInterface.getName();
String value = defaultStrategies.getProperty(key);
if (value != null) {
String[] classNames = StringUtils.commaDelimitedListToStringArray(value);
List<T> strategies = new ArrayList<T>(classNames.length);
for (String className : classNames) {
try {
Class clazz = ClassUtils.forName(className, DispatcherServlet.class.getClassLoader());
Object strategy = createDefaultStrategy(context, clazz);
strategies.add((T) strategy);
}
catch (ClassNotFoundException ex) {
throw new BeanInitializationException(
"Could not find DispatcherServlet's default strategy class [" + className +
"] for interface [" + key + "]", ex);
}
catch (LinkageError err) {
throw new BeanInitializationException(
"Error loading DispatcherServlet's default strategy class [" + className +
"] for interface [" + key + "]: problem with class file or dependent class", err);
}
}
return strategies;
}
else {
return new LinkedList<T>();
}
}
======================================================================
SimpleUrlHandlerMapping 实现:
首先在配置文件中定义
<bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="mappings">
<props>
<prop key="login.do">LoginAction</prop>
</props>
</property>
</bean>
SimpleUrlHandlerMapping 类中有这2个方法:
public void setMappings(Properties mappings) {
CollectionUtils.mergePropertiesIntoMap(mappings, this.urlMap);
}
public void setUrlMap(Map<String, ?> urlMap) {
this.urlMap.putAll(urlMap);
}
根据命名规则可以使用<property name="mappings">或<map name="urlMap">来配置映射。
SimpleUrlHandlerMapping 最上父类ApplicationObjectSupport 实现了ApplicationContextAware,当handlerMappings实例创建也就是调用getBean方法时,在AbstractAutowireCapableBeanFactory中
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args) {
//创建bean实例
if (instanceWrapper == null) {
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
.......
Object exposedObject = bean;
try {
//根据容器中注册的bean定义设值属性
populateBean(beanName, mbd, instanceWrapper);
if (exposedObject != null) {
//初始化方法调用
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
.......
}
在initializeBean方法中调用了ApplicationContextAwareProcessor的postProcessBeforeInitialization方法,在这个方法中调用了该类的invokeAwareInterfaces(bean);
private void invokeAwareInterfaces(Object bean) {
if (bean instanceof ResourceLoaderAware) {
((ResourceLoaderAware) bean).setResourceLoader(this.applicationContext);
}
if (bean instanceof ApplicationEventPublisherAware) {
((ApplicationEventPublisherAware) bean).setApplicationEventPublisher(this.applicationContext);
}
if (bean instanceof MessageSourceAware) {
((MessageSourceAware) bean).setMessageSource(this.applicationContext);
}
if (bean instanceof ApplicationContextAware) {
//容器调用实现了ApplicationContextAware接口的方法
((ApplicationContextAware) bean).setApplicationContext(this.applicationContext);
}
}
在SimpleUrlHandlerMapping中重写了该方法
@Override
public void initApplicationContext() throws BeansException {
super.initApplicationContext();
registerHandlers(this.urlMap);
}
protected void registerHandlers(Map<String, Object> urlMap) throws BeansException {
if (urlMap.isEmpty()) {
logger.warn("Neither 'urlMap' nor 'mappings' set on SimpleUrlHandlerMapping");
}
else {
for (Map.Entry<String, Object> entry : urlMap.entrySet()) {
String url = entry.getKey();
Object handler = entry.getValue();
if (!url.startsWith("/")) {
url = "/" + url;
}
if (handler instanceof String) {
handler = ((String) handler).trim();
}
//调用父类AbstractUrlHandlerMapping方法注册到该类的handlerMap中,在getHandler实现中使用这个map
registerHandler(url, handler);
}
}
}
AbstractUrlHandlerMapping中registerHandler方法:
分享到:
相关推荐
SpringMVC DispatcherServlet 初始化过程详解 DispatcherServlet 是 SpringMVC 框架中的核心组件,对于 SpringMVC 的请求处理和响应起着至关重要的作用。DispatcherServlet 的初始化过程是 SpringMVC 实现原理的...
在本文中,我们将深入探讨`DispatcherServlet`的初始化流程,这是SpringMVC的核心组件。`DispatcherServlet`扮演着中央调度者的角色,负责接收请求、解析请求信息,并调用合适的控制器进行业务逻辑处理。 首先,让...
SpringMVC DispatcherServlet重写、自定义拦截器拦截器源码
在 DispatcherServlet 的 init() 方法中,除了初始化 SpringIOC 容器外,还会初始化一些 SpringMVC 组件,包括: * MultipartResolver:处理multipart请求 * LocaleResolver:处理语言环境 * ThemeResolver:处理...
DispatcherServlet是SpringMVC的核心分发器,它实现了请求分发,是处理请求的入口,本篇将深入源码分析它的初始化过程。 首先,从DispatcherServlet的名称上可以看出它是一个Servlet,通过一张图来看一下它的实现...
同时,我们还指定了初始化参数contextConfigLocation,用于加载SpringMVC的配置文件spring-mvc.xml。 二、SpringMVC的配置文件 在SpringMVC的配置文件spring-mvc.xml中,我们需要配置controller的扫描路径和视图...
1. **加载配置**:`DispatcherServlet`会在初始化阶段读取配置文件(如`servlet-context.xml`),通过`WebApplicationContext`加载Bean定义。这个过程中,你可以自定义拦截器、视图解析器、异常处理器等关键组件。 ...
DispatcherServlet的初始化流程涉及多个步骤,通过org.springframework.web.servlet.FrameworkServlet#initWebApplicationContext 方法初始化WebApplicationContext,然后调用onRefresh方法进行refresh操作。...
总结,SpringMVC的处置流程始于Web应用的初始化,包括ContextLoaderListener加载根上下文和DispatcherServlet初始化子上下文。接着,DispatcherServlet负责接收和分发请求,通过HandlerMapping找到处理器,...
SpringMVC URL 与 Controller 方法初始化源码流程 Visio 文档 文档可以直接通过Visio进行编辑,方便二次修改、学习
在SpringMVC中 所有的请求都由dispatcherServlet处理(url-pattern配置的是/),当配置文件中有对静态资源的处理 时候 ,先匹配 welcome-file-list 中的文件,依次查找,找到了就 返回,如果没有找到就继续匹配到...
SpringMVC URL 与 Controller 方法初始化源码流程 Visio 文档 文档可以直接通过Visio进行编辑,方便二次修改、学习
SpringMVC中的DispatcherServlet在初始化时,会创建一个属于自己的ApplicationContext,我们通常称之为子容器。这个子容器负责处理与SpringMVC相关的bean,如Controller、ViewResolver、HandlerMapping等。...
03springmvc注解驱动开发的servlet3.0初始化配置类.avi
在`hou_job_springmvc2`或`hou_spring_mvc2`项目中,你可能会找到对应的配置文件(如`web.xml`),里面会定义DispatcherServlet的初始化参数。 2. **配置文件**:SpringMVC的配置通常在XML文件(如`servlet-context...
首先,Spring会初始化并管理所有组件,包括SpringMVC的DispatcherServlet、Controller以及Hibernate的SessionFactory。然后,当用户发起HTTP请求时,DispatcherServlet捕获请求并转发给相应的Controller。Controller...
这些文件定义了DispatcherServlet的初始化参数,控制器的映射,视图解析器等。 3. **@Controller注解**:标记在类上,表示该类为SpringMVC的控制器,处理来自客户端的请求。控制器中的方法通过@RequestMapping注解...
`web.xml`是应用的部署描述符,用于配置前端控制器DispatcherServlet和SpringMVC的初始化参数。`spring-servlet.xml`是SpringMVC的核心配置文件,用于定义处理器映射器、视图解析器以及其他Bean。 **3. 最少的Jar包...