上一篇我们讲解了DispatcherServlet的url-pattern配置详解,今天我们来真正对SpringMVC进行配置式开发。
所谓配置式开发是指“处理器类是程序员自己定义的、实现了特定接口的类,然后在SpringMVC配置文件中对该类进行显式的,明确的注册”的开发方式。今天我们的开发还是将中央调度器的url-pattern配置成*.do。然后将springmvc.xml的静态资源访问先取消。

一、处理器映射器(BeanNameUrlHandlerMapping)
handlerMapping接口负责根据request请求找到对应的Handler处理器及Interceptor拦截器,并将它们封装在HandlerExecutionChain对象中,返回给中央调度器。其常用的实现类有两种:
1、BeanNameUrlHandlerMapping
2、SimpleUrlHandlerMapping

这里着重说明SimpleUrlHandlerMapping。BeanNameUrlHandlerMapping我们简单来看一下源码:

public class BeanNameUrlHandlerMapping extends AbstractDetectingUrlHandlerMapping {

    /**
* Checks name and aliases of the given bean for URLs, starting with "/".
*/
@Override
protected String[] determineUrlsForHandler(String beanName) {
List<String> urls = new ArrayList<String>();
if (beanName.startsWith("/")) {
urls.add(beanName);
}
String[] aliases = getApplicationContext().getAliases(beanName);
for (String alias : aliases) {
if (alias.startsWith("/")) {
urls.add(alias);
}
}
return StringUtils.toStringArray(urls);
} }

上方BeanNameUrlHandlerMapping类中只有一个方法determineUrlsForHandler()。该方法中把所有以斜杠开头的请求的BeanName都放到了一个名叫urls的List中。然后返回给了中央调度器。但是有一个弊端,比如我有两个请求都由一个Controller来处理,这时我们的springmvc.xml文件的配置方式如下:

<!-- 注册SpringMVC处理器 -->
<bean id="/my.do" class="cn.wechatbao.controller.MyController"></bean>
<bean id="/you.do" class="cn.wechatbao.controller.MyController"></bean>

这样Spring容器在创建MyController实例的时候,一次性创建了两个,而对于我们来说,其实一个实例就可以对两个或多个请求进行处理。所以我们继续来讲解SimpleUrlHandlerMapping方法。

二、处理器映射器(SimpleUrlHandlerMapping)
要使用SimpleUrlHandlerMapping我们需要将其注册到SpringMVC中,如图,我们在默认的处理器映射器中并没有发现该实现类。所以需要注册。

注册方式:(springmvc.xml如下)

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd"> <!-- 注册视图解析器 -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/" />
<property name="suffix" value=".jsp" />
</bean> <bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="mappings">
<props>
<prop key="/my.do">myController</prop>
<prop key="/you.do">myController</prop>
<prop key="/he.do">myController</prop>
</props>
</property>
<!--
这种方式也可以实现多个请求交由一个Controller处理的需求
<property name="urlMap">
<map>
<entry key="/my.do" value="myController"></entry>
<entry key="/you.do" value="myController"></entry>
<entry key="/he.do" value="myController"></entry>
</map>
</property>
-->
</bean> <!-- 注册SpringMVC处理器 -->
<bean id="myController" class="cn.wechatbao.controller.MyController"></bean>
</beans>

注意:该种配置方式只针对多个请求用一个Controller处理才使用。

三、处理器映射器源码分析
1、当客户端发送请求到达中央调度器(DispatcherServlet)时,DispatcherServlet首先进入到doService方法在doService()方法里,对request设计一些属性,然后又进入到了doDispatch()方法,在doDispatch()方法里,我们着重来看以下代码:

// Determine handler for the current request.
mappedHandler = getHandler(processedRequest);

2、从doDispatch()方法又进入了一个getHandler()的方法,如下

protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
for (HandlerMapping hm : this.handlerMappings) {
if (logger.isTraceEnabled()) {
logger.trace(
"Testing handler map [" + hm + "] in DispatcherServlet with name '" + getServletName() + "'");
}
HandlerExecutionChain handler = hm.getHandler(request);
if (handler != null) {
return handler;
}
}
return null;
}

在该方法中,使用了一个forEach循环,来循环所有的处理器映射器,根据每个处理器映射器(HandlerMapping)来获取与之对应的处理器执行链(HandlerExecutionChain)。

进入hm.getHandler(request);方法来看。
3、继续hm.getHandler(request);方法

@Override
public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
Object handler = getHandlerInternal(request);
if (handler == null) {
handler = getDefaultHandler();
}
if (handler == null) {
return null;
}
// Bean name or resolved handler?
if (handler instanceof String) {
String handlerName = (String) handler;
handler = getApplicationContext().getBean(handlerName);
} HandlerExecutionChain executionChain = getHandlerExecutionChain(handler, request);
if (CorsUtils.isCorsRequest(request)) {
CorsConfiguration globalConfig = this.corsConfigSource.getCorsConfiguration(request);
CorsConfiguration handlerConfig = getCorsConfiguration(handler, request);
CorsConfiguration config = (globalConfig != null ? globalConfig.combine(handlerConfig) : handlerConfig);
executionChain = getCorsHandlerExecutionChain(request, executionChain, config);
}
return executionChain;
}

4、接下来又走到了HandlerExecutionChain executionChain = getHandlerExecutionChain(handler, request);这个方法。我们就不继续深究了。有兴趣的朋友可以自己再研究下去。我们得出的结论是经过了一系列的方法,最终返回给中央调度器一个HandlerExecutionChain对象。明白这个我们的目的就已经达到了。

《SpringMVC从入门到放肆》四、SpringMVC配置式开发(处理器映射器)的更多相关文章

  1. 4.SpringMVC 配置式开发-处理器映射器

    处理器映射器 HandlerMapping HandlerMapping 接口负责根据request请求找到对应的Handler处理器及Interceptor拦截器, 并将它们封装在HandlerEx ...

  2. 6.SpringMVC 配置式开发-处理器

    处理器除了实现Controller 接口外,还可以继承自一些其他的类,来完成一些特殊的功能 1.继承自AbstractController类 若处理器继承自AbstractController类,那么 ...

  3. 5.SpringMVC 配置式开发-处理器适配器

    处理器适配器HandlerAdapter 1.SimpleControllerHandlerAdapter(默认) 所有实现了 Controller 接口的处理器 Bean,均是通过SimpleCon ...

  4. SpringMVC的HandlerMapping(处理器映射器)

    SpringMvc有四种HandlerMapping:BeanNameUrlHandlerMapping ,SimpleUrlHandlerMapping,ControllerClassNameHan ...

  5. 【SpringMVC笔记】第三课 处理器映射器+处理器适配器

    第二课的例子中,在springmvc.xml中配置使用了第一种处理器映射器和处理器适配器,如下所示. <!-- 配置第一种处理器映射器 BeanNameUrlHandlerMapping --& ...

  6. springMVC三种处理器映射器

    1.配置处理器映射器,springmvc默认的处理器映射器BeanNameUrlHandlerMapping <bean class="org.springframework.web. ...

  7. 《SpringMVC从入门到放肆》八、SpringMVC注解式开发(基本配置)

    上一篇我们结束了配置式开发,配置式开发目前在企业中用的并不是很多,大部分企业都在使用注解式开发,所以今天我们就来学习注解式开发.所谓SpringMVC注解式开发是指,处理器是基于注解的类的开发方式.对 ...

  8. 《SpringMVC从入门到放肆》二、SpringMVC的执行流程及默认配置

    上一篇博文我们做了一个hello world的程序,并且已经成功的跑起来了.这一篇我们来深入的了解一下SpringMVC的执行流程以及一些其它的配置. 一.执行流程 来解释一下上图中的各个名词1.Di ...

  9. 《SpringMVC从入门到放肆》三、DispatcherServlet的url-pattern配置详解

    上一篇我们详细解释了一下SrpingMVC的执行流程以及一些默认的配置,在Spring的思想中,就是默认大于配置.今天我们来详细的研究一下DispatcherServlet的url-pattern配置 ...

随机推荐

  1. vs code调试console程序报错--preLaunchTask“build”

    网上有其他大神给出的建议是注释掉launch.json中的 "preLaunchTask": "build", 但是这种方式也会造成一个问题,就是再使用F5调试 ...

  2. 通过 kms 激活 office 2016

    1.管理员模式打开cmd,并切换到office的安装路径 注:office2016默认安装在C:\Program Files\Microsoft Office\Office16,激活其他office自 ...

  3. 【liferay】2、可配置portlet

    定义:edit和config模式一般没有使用,对于使用editor和config等模式的portlet,我们可以将他们称为可配置portlet. 我们先新建一个portlet项 添加可配置的控制元素, ...

  4. CentOS下 elasticsearch集群安装

    1.进入root目录并下载elasticsearch cd /root wget https://download.elastic.co/elasticsearch/elasticsearch/ela ...

  5. Ubuntu(Linux)下如何用源码文件安装软件

    在Ubuntu中附带了丰富的软件,这些软件一般使用图形化的自动方式(“添加/删除”或“新立得”)即可轻松安装,但是对于那些刚刚问世的新软件,Ubuntu的源中还未收录其中,这时我们就需要用到一种更通用 ...

  6. @Autowired内部实现原理

    @Autowiredprivate CustomerDao customerDao;        public void addCustomer() {        customerDao.add ...

  7. vue2.0表单事件的绑定

    v-model 1.input type="text" <template> <div id="app"> <label for= ...

  8. java 连接 postgresql

    最近公司用postgresql这个数据库,看网上说这个数据库还算好用,自己就用了一下,我就是用java连接了一下数据库. 其实每个数据库的连接方式大致相同,只是用到的驱动不同,用不同数据库只需要换不同 ...

  9. 为什么树莓派不会受到 Spectre 和 Meltdown 攻击

    最近爆出来的 Intel CPU 的底层漏洞可谓是影响巨大,过去20年的电脑都可能会受影响.前几天 Raspberry Pi 的官方 Twitter(@Raspberry_Pi) 转推了这篇文章,通过 ...

  10. phpstorm+wamp+xdebug配置php调试环境

    本篇文章主要是:教大家如果搭建一套phpstorm+wamp+xdebug调试php的环境现在大多数的程序员使用的调试方式一般都是echo, var_dump, file_put_contents等其 ...