SpringMVC-CROS
Spring-MVC 跨域
CrossOrigin 注解
- 通过注解设置跨域 demo 如下
|
|
-
切入点:
-
org.springframework.web.servlet.handler.AbstractHandlerMethodMapping#registerHandlerMethod
org.springframework.web.servlet.handler.AbstractHandlerMethodMapping.MappingRegistry#register
方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
/** * 注册方法 将controller 相关信息存储 * * @param mapping 请求地址 * @param handler 处理类 * @param method 函数 */ public void register(T mapping, Object handler, Method method) { // 上锁 this.readWriteLock.writeLock().lock(); try { // 创建 HandlerMethod , 通过 handler 创建处理的对象(controller) HandlerMethod handlerMethod = createHandlerMethod(handler, method); assertUniqueMethodMapping(handlerMethod, mapping); // 设置值 this.mappingLookup.put(mapping, handlerMethod); // 获取url List<String> directUrls = getDirectUrls(mapping); for (String url : directUrls) { // 设置 this.urlLookup.add(url, mapping); } String name = null; if (getNamingStrategy() != null) { name = getNamingStrategy().getName(handlerMethod, mapping); addMappingName(name, handlerMethod); } /** * 跨域设置 * {@link org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping#initCorsConfiguration(Object, Method, RequestMappingInfo)} **/ CorsConfiguration corsConfig = initCorsConfiguration(handler, method, mapping); if (corsConfig != null) { this.corsLookup.put(handlerMethod, corsConfig); } this.registry.put(mapping, new MappingRegistration<>(mapping, handlerMethod, directUrls, name)); } finally { // 开锁 this.readWriteLock.writeLock().unlock(); } }
-
-
着重查看**
CorsConfiguration
**初始化方法org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping#initCorsConfiguration
|
|
信息截图:
updateCorsConfig
- 该方法对原有的配置信息做补充
|
|
最终解析结果
-
解析完成后放入
corsLookup
对象中 类:org.springframework.web.servlet.handler.AbstractHandlerMethodMapping
1 2 3
if (corsConfig != null) { this.corsLookup.put(handlerMethod, corsConfig); }
xml 配置方式
|
|
-
mvc
标签解析类:org.springframework.web.servlet.config.MvcNamespaceHandler
,这个类对 Spring 配置文件中的<mvc:xxx>
标签做了解析设定,如这次我们的关注点**CORS
**1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
public class MvcNamespaceHandler extends NamespaceHandlerSupport { /** * 初始化一些SpringMvc 的解析类 */ @Override public void init() { // 注解驱动 registerBeanDefinitionParser("annotation-driven", new AnnotationDrivenBeanDefinitionParser()); // 默认的 servlet 处理器 registerBeanDefinitionParser("default-servlet-handler", new DefaultServletHandlerBeanDefinitionParser()); // 拦截器 registerBeanDefinitionParser("interceptors", new InterceptorsBeanDefinitionParser()); // 资源 registerBeanDefinitionParser("resources", new ResourcesBeanDefinitionParser()); // 视图控制器 registerBeanDefinitionParser("view-controller", new ViewControllerBeanDefinitionParser()); // 重定向视图控制器 registerBeanDefinitionParser("redirect-view-controller", new ViewControllerBeanDefinitionParser()); registerBeanDefinitionParser("status-controller", new ViewControllerBeanDefinitionParser()); // 视图解析器 registerBeanDefinitionParser("view-resolvers", new ViewResolversBeanDefinitionParser()); // tiles 处理器 registerBeanDefinitionParser("tiles-configurer", new TilesConfigurerBeanDefinitionParser()); registerBeanDefinitionParser("freemarker-configurer", new FreeMarkerConfigurerBeanDefinitionParser()); registerBeanDefinitionParser("groovy-configurer", new GroovyMarkupConfigurerBeanDefinitionParser()); registerBeanDefinitionParser("script-template-configurer", new ScriptTemplateConfigurerBeanDefinitionParser()); // 跨域处理 registerBeanDefinitionParser("cors", new CorsBeanDefinitionParser()); } }
CorsBeanDefinitionParser
类图
解析
- 实现BeanDefinitionParser 接口的都有一个parse方法直接看方法.
- 通过查看我们可以知道最终目的获取 xml 标签中的属性,对 CorsConfiguration进行初始化,最后 Spring 中注册
|
|
-
属性截图
- 可以看出这个是我们的第一个跨域配置的信息
-
注册方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
public static RuntimeBeanReference registerCorsConfigurations( @Nullable Map<String, CorsConfiguration> corsConfigurations, ParserContext context, @Nullable Object source) { // 判断是否包含跨域bean(beanName:mvcCorsConfigurations) if (!context.getRegistry().containsBeanDefinition(CORS_CONFIGURATION_BEAN_NAME)) { RootBeanDefinition corsDef = new RootBeanDefinition(LinkedHashMap.class); corsDef.setSource(source); corsDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE); if (corsConfigurations != null) { corsDef.getConstructorArgumentValues().addIndexedArgumentValue(0, corsConfigurations); } context.getReaderContext().getRegistry().registerBeanDefinition(CORS_CONFIGURATION_BEAN_NAME, corsDef); // 注册组件,并且通知监听器 context.registerComponent(new BeanComponentDefinition(corsDef, CORS_CONFIGURATION_BEAN_NAME)); } else if (corsConfigurations != null) { // 注册bean BeanDefinition corsDef = context.getRegistry().getBeanDefinition(CORS_CONFIGURATION_BEAN_NAME); corsDef.getConstructorArgumentValues().addIndexedArgumentValue(0, corsConfigurations); } return new RuntimeBeanReference(CORS_CONFIGURATION_BEAN_NAME); }
-
CorsConfiguration
- 跨域信息
|
|
处理请求
-
请求处理的一部分,前置后置都还有其他处理,这里只对跨域请求进行说明
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
@Override @Nullable 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 = obtainApplicationContext().getBean(handlerName); } HandlerExecutionChain executionChain = getHandlerExecutionChain(handler, request); if (logger.isTraceEnabled()) { logger.trace("Mapped to " + handler); } else if (logger.isDebugEnabled() && !request.getDispatcherType().equals(DispatcherType.ASYNC)) { logger.debug("Mapped to " + executionChain.getHandler()); } // 判断是否为跨域请求 if (CorsUtils.isCorsRequest(request)) { CorsConfiguration globalConfig = this.corsConfigurationSource.getCorsConfiguration(request); // 当前请求的跨域配置 CorsConfiguration handlerConfig = getCorsConfiguration(handler, request); CorsConfiguration config = (globalConfig != null ? globalConfig.combine(handlerConfig) : handlerConfig); executionChain = getCorsHandlerExecutionChain(request, executionChain, config); } return executionChain; }
判断是否跨域
org.springframework.web.cors.CorsUtils#isCorsRequest
|
|
获取跨域信息
|
|
跨域拦截器创建
|
|
跨域拦截器
|
|
DefaultCorsProcessor
- 经过跨域拦截器 **
CorsInterceptor
**之后会调用
|
|
模拟请求
GET http://localhost:9999/json
Origin: localhost
变量截图
- 原文作者:知识铺
- 原文链接:https://index.zshipu.com/geek/post/code/docs/Spring/SpringMVC/SpringMVC-CROS/
- 版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 4.0 国际许可协议进行许可,非商业转载请注明出处(作者,原文链接),商业转载请联系作者获得授权。
- 免责声明:本页面内容均来源于站内编辑发布,部分信息来源互联网,并不意味着本站赞同其观点或者证实其内容的真实性,如涉及版权等问题,请立即联系客服进行更改或删除,保证您的合法权益。转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。也可以邮件至 sblig@126.com