当前位置: 首页 / 技术干货 / 正文
SpringMVC源码解析(三)

2023-03-09

处理器 映射器 bean   

  3 处理器映射器HandlerMapping

  HandlerMapping接口负责根据request请求找到对应的Handler处理器及Interceptor拦截器,并将它们封装在HandlerExecutionChain对象中,返回给中央调度器。

  其常用的实现类有两种:

  BeanNameUrlHandlerMapping

  SimpleUrlHandlerMapping

  3.1 BeanNameUrlHandlerMapping

  BeanNameUrlHandlerMapping处理器映射器会根据请求的url与Spring容器中定义的处理器bean的name属性值进行匹配,从而在Spring容器中找到处理器bean实例。

<!-- 注册处理器映射器 -->
<bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"></bean>
<!-- 注册处理器 -->
<bean name="/hello" class="com.cy.controller.HelloController"></bean>

  打开类的源码,从BeanNameUrlHandlerMapping处理器映射器的方法中可以看出,对于处理器的bean的名称,必须以“/”开头,否则无法加入到urls数组中。

public class BeanNameUrlHandlerMapping extends AbstractDetectingUrlHandlerMapping {

/**
* 检查给定bean的名称和别名的URL,以“/”开头。
*/
@Override
protected String[] determineUrlsForHandler(String beanName) {
List<String> urls = new ArrayList<>();
if (beanName.startsWith("/")) {
urls.add(beanName);
}
String[] aliases = obtainApplicationContext().getAliases(beanName);
for (String alias : aliases) {
if (alias.startsWith("/")) {
urls.add(alias);
}
}
return StringUtils.toStringArray(urls);
}

}

  使用BeanNameUrlHandlerMapping处理器映射器有两点明显不足:

  处理器bean的id为一个url请求路径,而不是bean的名称,有些不伦不类。

  处理器bean的定义与请求url绑定在了一起,若出现多个url请求同一个处理器的情况,就需要在Spring容器中配置多个该处理器类的bean标签,这将导致容器会创建多个该处理器类实例。

<!-- 注册处理器映射器 -->
<bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"></bean>
<!-- 注册处理器:为一个处理器绑定多个请求url -->
<bean name="/hello" class="com.cy.controller.HelloController"></bean>
<bean name="/world" class="com.cy.controller.HelloController"></bean>

  3.2 SimpleUrlHandlerMapping

  SimpleUrlHandlerMapping处理器映射器,不仅可以将url与处理器的定义分离,还可以对url进行统一映射管理。

  SimpleUrlHandlerMapping处理器映射器会根据请求的url与Spring容器中定义的处理器映射器子标签的key属性进行匹配。匹配上后,再将该key的value值与处理器bean的id值进行匹配,从而在Spring容器中找到处理器bean。

<!-- 注册处理器映射器方式2:SimpleUrlHandlerMapping实现类 -->
<bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<!-- 方式1:通过mappings属性为同一个处理器绑定多个url请求,二选一 -->
<property name="mappings">
<props>
<prop key="/hello.do">helloController</prop>
<prop key="/world.do">helloController</prop>
</props>
</property>
<!-- 方式2:通过mappings属性为同一个处理器绑定多个url请求,二选一 -->
<property name="urlMap">
<map>
<entry key="/hello.action" value="helloController"/>
<entry key="/world.action" value="helloController"/>
</map>
</property>
</bean>
<!-- 注册处理器 -->
<bean id="helloController" class="com.cy.controller.HelloController"></bean>

<!-- 注册处理器映射器方式1:BeanNameUrlHandlerMapping实现类 -->
<!-- <bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"></bean> -->
<!-- <bean name="/hello" class="com.cy.controller.HelloController"></bean> -->
<!-- <bean name="/world" class="com.cy.controller.HelloController"></bean> -->

  3.3 HandlerMapping源码分析

  HandlerMapping的调用过程见下:

org.springframework.web.servlet.DispatcherServlet(类):
-- void doService(HttpServletRequest request, HttpServletResponse response)
-- doDispatch(request, response)
-- void doDispatch(HttpServletRequest request, HttpServletResponse response)
-- getHandler(processedRequest, false)
-- HandlerExecutionChain getHandler(HttpServletRequest request, boolean cache)
-- getHandler(request)
-- HandlerExecutionChain getHandler(HttpServletRequest request)
-- hm.getHandler(request)

org.springframework.web.servlet.HandlerMapping(接口):
-- HandlerExecutionChain getHandler(HttpServletRequest request)

org.springframework.web.servlet.handler.AbstractHandlerMapping(抽象类 implements HandlerMapping):
-- HandlerExecutionChain getHandler(HttpServletRequest request)
-- getHandlerExecutionChain(handler, request)
-- HandlerExecutionChain getHandlerExecutionChain(Object handler, HttpServletRequest request)

好程序员公众号

  • · 剖析行业发展趋势
  • · 汇聚企业项目源码

好程序员开班动态

More+
  • HTML5大前端 <高端班>

    开班时间:2021-04-12(深圳)

    开班盛况

    开班时间:2021-05-17(北京)

    开班盛况
  • 大数据+人工智能 <高端班>

    开班时间:2021-03-22(杭州)

    开班盛况

    开班时间:2021-04-26(北京)

    开班盛况
  • JavaEE分布式开发 <高端班>

    开班时间:2021-05-10(北京)

    开班盛况

    开班时间:2021-02-22(北京)

    开班盛况
  • Python人工智能+数据分析 <高端班>

    开班时间:2021-07-12(北京)

    预约报名

    开班时间:2020-09-21(上海)

    开班盛况
  • 云计算开发 <高端班>

    开班时间:2021-07-12(北京)

    预约报名

    开班时间:2019-07-22(北京)

    开班盛况
IT培训IT培训
在线咨询
IT培训IT培训
试听
IT培训IT培训
入学教程
IT培训IT培训
立即报名
IT培训

Copyright 2011-2023 北京千锋互联科技有限公司 .All Right 京ICP备12003911号-5 京公网安备 11010802035720号