If you want to keep Spring Boot MVC features and you want to add additional MVC configuration (interceptors, formatters, view controllers, and other features), you can add your own @Configuration
class of type WebMvcConfigurer
but without @EnableWebMvc
. ->摘要自spring boot reference guide
通过spring官方说明明白可以通过WebMvcConfigurer实现额外的MVC配置。
@Configuration
public class ExampleConfig implements WebMvcConfigurer
{
@Override
public void addCorsMappings(CorsRegistry registry)
{
// 设置允许跨域的路径
registry.addMapping("/**")
// 设置允许跨域请求的域名
.allowedOrigins("*")
// 是否允许证书
.allowCredentials(true)
// 设置允许的方法
.allowedMethods("GET", "POST", "DELETE", "PUT")
// 设置允许的header属性
.allowedHeaders("*")
// 跨域允许时间
.maxAge(3600);
}
}
spring初始化时加载corsMapping的配置信息并注册到实现于IOC容器,具体实例以及信息封装:RequestMappingHandlerMapping -> corsConfigurationSource -> corsConfigurations
接口访问时,在DispatchServlet中doDispatch方法里,通过getHandler拿到HandlerExecutionChain,cors配置信息封装在HandlerExecutionChain实例中,在getHandler方法中的this.handlerMappings集合中可以看到之前注册的RequestMappingHandlerMapping。这里需要注意,请求访问的header头中需要包含Origin,因为在getHandler时会判断header中是否存在Origin,然后才包装cors配置信息。具体代码如下:
if (CorsUtils.isCorsRequest(request)) {
CorsConfiguration globalConfig = this.corsConfigurationSource.getCorsConfiguration(request);
CorsConfiguration handlerConfig = this.getCorsConfiguration(handler, request);
CorsConfiguration config = globalConfig != null ? globalConfig.combine(handlerConfig) : handlerConfig;
executionChain = this.getCorsHandlerExecutionChain(request, executionChain, config);
}
接着回到通过getHandler得到的mappedHandler对象处,往下可以看到执行了mappedHandler.applyPreHandle(processedRequest, response),而我们的cors配置封装在HandlerInterceptor数组中,这里通过调用interceptor的preHandle,通过调用链:CorsInterceptor.preHandle ->DefaultCorsProcessor.processRequest ->DefaultCorsProcessor.handleInternal 在这里将配置的cors信息写入response的header中完成跨域信息响应注入。
这块其实spring官方也有给出解释(摘要自CORS support in Spring Framework):
CORS requests (including preflight ones with an OPTIONS
method) are automatically dispatched to the various HandlerMapping
s registered. They handle CORS preflight requests and intercept CORS simple and actual requests thanks to a CorsProcessor implementation (DefaultCorsProcessor by default) in order to add the relevant CORS response headers (like Access-Control-Allow-Origin
). CorsConfiguration allows you to specify how the CORS requests should be processed: allowed origins, headers, methods, etc. It can be provided in various ways:
AbstractHandlerMapping#setCorsConfiguration()
allows to specify a Map
with several CorsConfiguration mapped on path patterns like /api/**
CorsConfiguration
by overriding AbstractHandlerMapping#getCorsConfiguration(Object, HttpServletRequest)
methodCorsConfigurationSource
interface (like ResourceHttpRequestHandler
now does) in order to provide a CorsConfiguration for each request.