Spring MVC : HandlerMappingIntrospector
概述
这是一个Spring MVC
助手类,用于集合应用所配置的HandlerMapping
(url pattern
和请求处理handler
之间的映射)表,用于获取针对某个请求的如下信息 :
getMatchableHandlerMapping(javax.servlet.http.HttpServletRequest)
寻找能处理指定请求的
HandlerMapping
,如果找不到,返回null
;如果找到的是一个MatchableHandlerMapping
,则返回;如果找得到当并不是MatchableHandlerMapping
,则抛出异常IllegalStateException
。getCorsConfiguration(javax.servlet.http.HttpServletRequest)
获取针对指定请求的
CORS
配置,封装为CorsConfiguration
。如果不存在相应配置,返回null
。
使用
- 作为
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相关推荐
- CORS跨域资源共享(二):详解Spring MVC对CORS支持的相关类和API【享学Spring MVC】
每篇一句 重构一时爽,一直重构一直爽.但出了问题火葬场 前言 上篇文章通过我模拟的跨域请求实例和结果分析,相信小伙伴们都已经80%的掌握了CORS到底是怎么一回事以及如何使用它.由于Java语言中的w ...
- Java之Spring mvc详解(非原创)
文章大纲 一.Spring mvc介绍 二.Spring mvc代码实战 三.项目源码下载 四.参考文章 一.Spring mvc介绍 1. 什么是springmvc springmvc是spri ...
- spring mvc 关键接口 HandlerMapping HandlerAdapter
HandlerMapping Spring mvc 使用HandlerMapping来找到并保存url请求和处理函数间的mapping关系. 以DefaultAnnotationHandle ...
- spring mvc 控制器方法传递一些经验对象的数组
由于该项目必须提交一个表单,其中多个对象,更好的方法是直接通过在控制器方法参数的数组. 因为Spring mvc框架在反射生成控制方法的參数对象的时候会调用这个类的getDeclaredConstru ...
- Spring MVC 4
Spring MVC 4 项目文件结构 pom.xml依赖 <properties><endorsed.dir>${project.build.directory}/endor ...
- java注解返回不同消息,Spring MVC Controller中的一个读入和返回都是JSON的方法如何获取javax.validation注解的异常信息...
Spring MVC Controller中的一个读入和返回都是JSON的方法怎么获取javax.validation注解的错误信息? 本帖最后由 LonelyCoder2012 于 2014-03- ...
- Spring MVC前后端的数据传输
本篇文章主要介绍了Spring MVC中如何在前后端传输数据. 后端 ➡ 前端 在Spring MVC中这主要通过Model将数据从后端传送到前端,一般的写法为: @RequestMapping(va ...
- 番外:Spring MVC环境搭建和Mybatis配置避坑篇
2019独角兽企业重金招聘Python工程师标准>>> web.xml引入对spring mvc的支持: spring-mvc配置spring-mvc: spring-mybatis ...
- spring mvc velocity 配置备忘
2019独角兽企业重金招聘Python工程师标准>>> Spring里面最重要的概念是IOC和AOP,还有两项很重要的模块是事务和MVC,对于IOC和AOP,我们要深究其源码实现,对 ...
最新文章
- php 自学 经验,学习PHP:PHP学习的几个问题经验总结
- ActiveMQ部署模式
- 现代软件工程 第六章 【敏捷流程】练习与讨论
- 接口500什么原因_80%小餐饮店几乎都“活“不过500天,为什么?都在这5个原因里...
- 虚拟机网络无法连接问题解决(超简单)
- 安卓第三阶段实训项目:基于网络乐库音乐播放器V1.0
- 使用“管道”与“应用程序生命周期”重构:可插拔模块
- matlab 编程——一些细节、常犯错误的汇总
- Jni开发(二)Linux运行java测试代码
- 算法导论2.3练习答案
- 数据结构(直接插入排序、希尔排序、直接选择排序、堆排序、冒泡排序、快速排序)
- 上网代理设置会被自动清空_关于代理被自动设置问题的排查
- 考研加油站系统的设计与实现
- 【Verilog】一、Verilog概述
- Django模型之Meta属性详解
- Java面向对象:Account类
- erp与计算机技术,基于mvc模式的erp系统研究与应用-计算机技术专业论文.docx
- python爬虫实战-爬取小说
- 用JQuery方法,将会计数字转换为大写
- 2022广西省安全员C证考试试题及答案
热门文章
- Idea 2020.1如何改变JetBrains Runtime(jbr)
- idea启动报错:Failed to create JVM. JVM Path: D:\Program Files\JetBrains\IntelliJ IDEA 2021.3.3\jbr\
- 大聪明教你学Java | 如何写出优雅的接口
- Python计算越南出线概率
- 彻底搞懂数据库中的超码,候选码,主码,主属性,非主属性,全码的区别
- 基于动画图解常用的机器学习算法
- 互联网金融产品移动前端发展简史
- Ubuntu 电脑下插入移动硬盘,显示不能挂载该硬盘
- 请问,你心里有B树吗??(B树添加、删除操作详细图解)
- shell 语句出错自动退出