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)
上一篇:SpringMVC源码解析(二)
下一篇:SpringMVC源码解析(四)
开班时间:2021-04-12(深圳)
开班盛况开班时间:2021-05-17(北京)
开班盛况开班时间:2021-03-22(杭州)
开班盛况开班时间:2021-04-26(北京)
开班盛况开班时间:2021-05-10(北京)
开班盛况开班时间:2021-02-22(北京)
开班盛况开班时间:2021-07-12(北京)
预约报名开班时间:2020-09-21(上海)
开班盛况开班时间:2021-07-12(北京)
预约报名开班时间:2019-07-22(北京)
开班盛况Copyright 2011-2023 北京千锋互联科技有限公司 .All Right 京ICP备12003911号-5 京公网安备 11010802035720号