概述

这是一个Spring MVC助手类,用于集合应用所配置的HandlerMapping(url pattern和请求处理handler之间的映射)表,用于获取针对某个请求的如下信息 :

  1. getMatchableHandlerMapping(javax.servlet.http.HttpServletRequest)

    寻找能处理指定请求的HandlerMapping,如果找不到,返回null;如果找到的是一个MatchableHandlerMapping,则返回;如果找得到当并不是MatchableHandlerMapping,则抛出异常IllegalStateException

  2. getCorsConfiguration(javax.servlet.http.HttpServletRequest)

    获取针对指定请求的CORS配置,封装为CorsConfiguration。如果不存在相应配置,返回null

使用

  1. 作为CorsConfigurationSource使用
    // 配置类 WebMvcConfigurationSupport@Bean@Lazypublic HandlerMappingIntrospector mvcHandlerMappingIntrospector() {return new HandlerMappingIntrospector();}

源代码

源代码版本 Spring Web MVC 5.1.5.RELEASE


package org.springframework.web.servlet.handler;// 省略 importspublic class HandlerMappingIntrospectorimplements CorsConfigurationSource, ApplicationContextAware, InitializingBean {@Nullableprivate ApplicationContext applicationContext;@Nullableprivate List<HandlerMapping> handlerMappings;/*** Constructor for use with ApplicationContextAware.*/public HandlerMappingIntrospector() {}/*** Constructor that detects the configured {@code HandlerMapping}s in the* given {@code ApplicationContext} or falls back on* "DispatcherServlet.properties" like the {@code DispatcherServlet}.* @deprecated as of 4.3.12, in favor of {@link #setApplicationContext}*/@Deprecatedpublic HandlerMappingIntrospector(ApplicationContext context) {this.handlerMappings = initHandlerMappings(context);}/*** Return the configured HandlerMapping's.*/public List<HandlerMapping> getHandlerMappings() {return (this.handlerMappings != null ? this.handlerMappings : Collections.emptyList());}@Overridepublic void setApplicationContext(ApplicationContext applicationContext) {this.applicationContext = applicationContext;}// InitializingBean 接口约定的方法,用于获取容器中定义的所有类型为 HandlerMapping 的 bean,// 或者获取缺省定义的类型为 HandlerMapping 的 bean@Overridepublic void afterPropertiesSet() {if (this.handlerMappings == null) {Assert.notNull(this.applicationContext, "No ApplicationContext");this.handlerMappings = initHandlerMappings(this.applicationContext);}}/*** Find the {@link HandlerMapping} that would handle the given request and* return it as a {@link MatchableHandlerMapping} that can be used to test* request-matching criteria.* <p>If the matching HandlerMapping is not an instance of* {@link MatchableHandlerMapping}, an IllegalStateException is raised.* @param request the current request* @return the resolved matcher, or {@code null}* @throws Exception if any of the HandlerMapping's raise an exception*/@Nullablepublic MatchableHandlerMapping getMatchableHandlerMapping(HttpServletRequest request) throws Exception {Assert.notNull(this.handlerMappings, "Handler mappings not initialized");HttpServletRequest wrapper = new RequestAttributeChangeIgnoringWrapper(request);for (HandlerMapping handlerMapping : this.handlerMappings) {Object handler = handlerMapping.getHandler(wrapper);if (handler == null) {continue;}if (handlerMapping instanceof MatchableHandlerMapping) {return ((MatchableHandlerMapping) handlerMapping);}throw new IllegalStateException("HandlerMapping is not a MatchableHandlerMapping");}return null;}// 获取某个 request 请求对应的 CorsConfiguration// 1. 从 handlerMappings 中找到该请求对应的 handler, 形式为 HandlerExecutionChain;// 2. 检索 HandlerExecutionChain 中所有的 @Override@Nullablepublic CorsConfiguration getCorsConfiguration(HttpServletRequest request) {Assert.notNull(this.handlerMappings, "Handler mappings not initialized");HttpServletRequest wrapper = new RequestAttributeChangeIgnoringWrapper(request);for (HandlerMapping handlerMapping : this.handlerMappings) {HandlerExecutionChain handler = null;try {handler = handlerMapping.getHandler(wrapper);}catch (Exception ex) {// Ignore}if (handler == null) {continue;}if (handler.getInterceptors() != null) {for (HandlerInterceptor interceptor : handler.getInterceptors()) {if (interceptor instanceof CorsConfigurationSource) {return ((CorsConfigurationSource) interceptor).getCorsConfiguration(wrapper);}}}if (handler.getHandler() instanceof CorsConfigurationSource) {return ((CorsConfigurationSource) handler.getHandler()).getCorsConfiguration(wrapper);}}return null;}private static List<HandlerMapping> initHandlerMappings(ApplicationContext applicationContext) {// 获取容器中所有类型为 HandlerMapping 的 beanMap<String, HandlerMapping> beans = BeanFactoryUtils.beansOfTypeIncludingAncestors(applicationContext, HandlerMapping.class, true, false);if (!beans.isEmpty()) {List<HandlerMapping> mappings = new ArrayList<>(beans.values());AnnotationAwareOrderComparator.sort(mappings);return Collections.unmodifiableList(mappings);}// 容器中不存在类型为 HandlerMapping 的 bean,// 此时使用 initFallback 创建 DispatcherServlet.properties 文件中// 缺省定义的类型为 HandlerMapping 的 beanreturn Collections.unmodifiableList(initFallback(applicationContext));}private static List<HandlerMapping> initFallback(ApplicationContext applicationContext) {Properties props;String path = "DispatcherServlet.properties";try {Resource resource = new ClassPathResource(path, DispatcherServlet.class);props = PropertiesLoaderUtils.loadProperties(resource);}catch (IOException ex) {throw new IllegalStateException("Could not load '" + path + "': " + ex.getMessage());}String value = props.getProperty(HandlerMapping.class.getName());String[] names = StringUtils.commaDelimitedListToStringArray(value);List<HandlerMapping> result = new ArrayList<>(names.length);for (String name : names) {try {Class<?> clazz = ClassUtils.forName(name, DispatcherServlet.class.getClassLoader());// 使用容器创建 bean,该动作会使所创建的 bean 经历相应的生命周期处理,比如初始化,属性设置等等  Object mapping = applicationContext.getAutowireCapableBeanFactory().createBean(clazz);result.add((HandlerMapping) mapping);}catch (ClassNotFoundException ex) {throw new IllegalStateException("Could not find default HandlerMapping [" + name + "]");}}return result;}/*** Request wrapper that ignores request attribute changes.* 定义一个给当前 HandlerMappingIntrospector 使用的 HttpServletRequestWrapper,* 其方法 setAttribute 实现为空,主要是用于避免属性修改,也就是保持对所访问的 request 不做修改*/private static class RequestAttributeChangeIgnoringWrapper extends HttpServletRequestWrapper {public RequestAttributeChangeIgnoringWrapper(HttpServletRequest request) {super(request);}@Overridepublic void setAttribute(String name, Object value) {// Ignore attribute change...}}}

Spring MVC : HandlerMappingIntrospector相关推荐

  1. CORS跨域资源共享(二):详解Spring MVC对CORS支持的相关类和API【享学Spring MVC】

    每篇一句 重构一时爽,一直重构一直爽.但出了问题火葬场 前言 上篇文章通过我模拟的跨域请求实例和结果分析,相信小伙伴们都已经80%的掌握了CORS到底是怎么一回事以及如何使用它.由于Java语言中的w ...

  2. Java之Spring mvc详解(非原创)

    文章大纲 一.Spring mvc介绍 二.Spring mvc代码实战 三.项目源码下载 四.参考文章 一.Spring mvc介绍 1. 什么是springmvc   springmvc是spri ...

  3. spring mvc 关键接口 HandlerMapping HandlerAdapter

    HandlerMapping  Spring mvc 使用HandlerMapping来找到并保存url请求和处理函数间的mapping关系.     以DefaultAnnotationHandle ...

  4. spring mvc 控制器方法传递一些经验对象的数组

    由于该项目必须提交一个表单,其中多个对象,更好的方法是直接通过在控制器方法参数的数组. 因为Spring mvc框架在反射生成控制方法的參数对象的时候会调用这个类的getDeclaredConstru ...

  5. Spring MVC 4

    Spring MVC 4 项目文件结构 pom.xml依赖 <properties><endorsed.dir>${project.build.directory}/endor ...

  6. java注解返回不同消息,Spring MVC Controller中的一个读入和返回都是JSON的方法如何获取javax.validation注解的异常信息...

    Spring MVC Controller中的一个读入和返回都是JSON的方法怎么获取javax.validation注解的错误信息? 本帖最后由 LonelyCoder2012 于 2014-03- ...

  7. Spring MVC前后端的数据传输

    本篇文章主要介绍了Spring MVC中如何在前后端传输数据. 后端 ➡ 前端 在Spring MVC中这主要通过Model将数据从后端传送到前端,一般的写法为: @RequestMapping(va ...

  8. 番外:Spring MVC环境搭建和Mybatis配置避坑篇

    2019独角兽企业重金招聘Python工程师标准>>> web.xml引入对spring mvc的支持: spring-mvc配置spring-mvc: spring-mybatis ...

  9. spring mvc velocity 配置备忘

    2019独角兽企业重金招聘Python工程师标准>>> Spring里面最重要的概念是IOC和AOP,还有两项很重要的模块是事务和MVC,对于IOC和AOP,我们要深究其源码实现,对 ...

最新文章

  1. php 自学 经验,学习PHP:PHP学习的几个问题经验总结
  2. ActiveMQ部署模式
  3. 现代软件工程 第六章 【敏捷流程】练习与讨论
  4. 接口500什么原因_80%小餐饮店几乎都“活“不过500天,为什么?都在这5个原因里...
  5. 虚拟机网络无法连接问题解决(超简单)
  6. 安卓第三阶段实训项目:基于网络乐库音乐播放器V1.0
  7. 使用“管道”与“应用程序生命周期”重构:可插拔模块
  8. matlab 编程——一些细节、常犯错误的汇总
  9. Jni开发(二)Linux运行java测试代码
  10. 算法导论2.3练习答案
  11. 数据结构(直接插入排序、希尔排序、直接选择排序、堆排序、冒泡排序、快速排序)
  12. 上网代理设置会被自动清空_关于代理被自动设置问题的排查
  13. 考研加油站系统的设计与实现
  14. 【Verilog】一、Verilog概述
  15. Django模型之Meta属性详解
  16. Java面向对象:Account类
  17. erp与计算机技术,基于mvc模式的erp系统研究与应用-计算机技术专业论文.docx
  18. python爬虫实战-爬取小说
  19. 用JQuery方法,将会计数字转换为大写
  20. 2022广西省安全员C证考试试题及答案

热门文章

  1. Idea 2020.1如何改变JetBrains Runtime(jbr)
  2. idea启动报错:Failed to create JVM. JVM Path: D:\Program Files\JetBrains\IntelliJ IDEA 2021.3.3\jbr\
  3. 大聪明教你学Java | 如何写出优雅的接口
  4. Python计算越南出线概率
  5. 彻底搞懂数据库中的超码,候选码,主码,主属性,非主属性,全码的区别
  6. 基于动画图解常用的机器学习算法
  7. 互联网金融产品移动前端发展简史
  8. Ubuntu 电脑下插入移动硬盘,显示不能挂载该硬盘
  9. 请问,你心里有B树吗??(B树添加、删除操作详细图解)
  10. shell 语句出错自动退出