Spring Boot Sample 013之spring-boot-web-cors
一、环境
- Idea 2020.1
- JDK 1.8
- maven
二、目的
spring boot 异常处理controller实现方式
三、步骤
3.1、点击File -> New Project -> Spring Initializer,点击next
3.2、修改项目信息
3.3、选择Web依赖,选中Spring Web。可以选择Spring Boot版本,本次默认为2.3.0,点击Next
3.4、项目结构
四、添加文件
pom.xml文件
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.ouyushan</groupId> <artifactId>ouyushan-spring-boot-samples</artifactId> <version>0.0.1-SNAPSHOT</version> </parent> <groupId>org.ouyushan</groupId> <artifactId>spring-boot-web-cors</artifactId> <version>0.0.1-SNAPSHOT</version> <name>spring-boot-web-cors</name> <description>Cors project for Spring Boot</description> <properties> <java.version>1.8</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <scope>runtime</scope> <optional>true</optional> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> <exclusions> <exclusion> <groupId>org.junit.vintage</groupId> <artifactId>junit-vintage-engine</artifactId> </exclusion> </exclusions> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
GlobalCorsConfiguration.java
package org.ouyushan.springboot.web.cors.config; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.CorsRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; /** * @Description: 方式一:CORS全局设置 注入bean * @Author: ouyushan * @Email: ouyushan@hotmail.com * @Date: 2020/6/5 11:07 */ @Configuration public class GlobalCorsConfiguration { @Bean public WebMvcConfigurer corsConfiguration() { return new WebMvcConfigurer() { @Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/**") .allowedOrigins("*") .allowCredentials(true) .allowedMethods("GET", "POST", "DELETE", "PUT") .maxAge(3600); } }; } }
GlobalCorsConfigurationAdapter.java
package org.ouyushan.springboot.web.cors.config; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.CorsRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport; /** * @Description: 方式二:CORS全局设置 通过继承实现CORS全局设置 * @Author: ouyushan * @Email: ouyushan@hotmail.com * @Date: 2020/6/5 11:18 */ @Configuration public class GlobalCorsConfigurationAdapter extends WebMvcConfigurationSupport { @Override protected void addCorsMappings(CorsRegistry registry) { registry.addMapping("/**") .allowedOrigins("*") .allowCredentials(true) .allowedMethods("GET", "POST", "DELETE", "PUT") .maxAge(3600); } }
GlobalCorsConfigurationWithFilter.java
package org.ouyushan.springboot.web.cors.config; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.cors.CorsConfiguration; import org.springframework.web.cors.UrlBasedCorsConfigurationSource; import org.springframework.web.filter.CorsFilter; /** * @Description: 常规方法配置之后再使用自定义拦截器时跨域相关配置就会失效,该配置能解决此问题。 * 原因是请求经过的先后顺序问题,当请求到来时会先进入拦截器中,而不是进入Mapping映射中,所以返回的头信息中并没有配置的跨域信息。浏览器就会报跨域异常。 * @Author: ouyushan * @Email: ouyushan@hotmail.com * @Date: 2020/6/5 11:20 */ @Configuration public class GlobalCorsConfigurationWithFilter { private CorsConfiguration corsConfig() { CorsConfiguration corsConfiguration = new CorsConfiguration(); corsConfiguration.addAllowedOrigin("*"); corsConfiguration.addAllowedHeader("*"); corsConfiguration.addAllowedMethod("*"); corsConfiguration.setAllowCredentials(true); corsConfiguration.setMaxAge(3600L); return corsConfiguration; } @Bean public CorsFilter corsFilter() { UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); source.registerCorsConfiguration("/**", corsConfig()); return new CorsFilter(source); } }
# 示例四 spring-boot-cors * 对应例子:https://github.com/ouyushan/spring-boot/tree/master/spring-boot-samples/spring-boot-sample-logback * 对应文档:第26节 https://docs.spring.io/spring-boot/docs/2.1.3.RELEASE/reference/htmlsingle/ Web 开发经常会遇到跨域问题,解决方案有: jsonp, iframe,CORS 等等 CORS 与 JSONP 相比 1、 JSONP 只能实现 GET 请求,而 CORS 支持所有类型的 HTTP 请求。 2、 使用 CORS,开发者可以使用普通的 XMLHttpRequest 发起请求和获得数据,比起 JSONP 有更好的 错误处理。 3、 JSONP 主要被老的浏览器支持,它们往往不支持 CORS,而绝大多数现代浏览器都已经支持了 CORS 二、 在 spring MVC 中可以配置全局的规则,也可以使用@CrossOrigin 注解进行细粒度的配置 全局配置:方式一 ``` package org.ouyushan.spring.boot.web.cors.config; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.CorsRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; /** * @Description: 方式一:CORS全局设置 注入bean * @Author: ouyushan * @Email: ouyushan@hotmail.com * @Date: 2020/6/5 11:07 */ @Configuration public class GlobalCorsConfiguration { @Bean public WebMvcConfigurer corsConfiguration() { return new WebMvcConfigurer() { @Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/**") .allowedOrigins("*") .allowCredentials(true) .allowedMethods("GET", "POST", "DELETE", "PUT") .maxAge(3600); } }; } } ``` 全局配置:方式二 ``` package org.ouyushan.spring.boot.web.cors.config; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.CorsRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport; /** * @Description: 方式二:CORS全局设置 通过继承实现CORS全局设置 * @Author: ouyushan * @Email: ouyushan@hotmail.com * @Date: 2020/6/5 11:18 */ @Configuration public class GlobalCorsConfigurationAdapter extends WebMvcConfigurationSupport { @Override protected void addCorsMappings(CorsRegistry registry) { registry.addMapping("/**") .allowedOrigins("*") .allowCredentials(true) .allowedMethods("GET", "POST", "DELETE", "PUT") .maxAge(3600); } } ``` 使用方法一、二配置之后再使用自定义拦截器时跨域相关配置就会失效。 原因是请求经过的先后顺序问题,当请求到来时会先进入拦截器中,而不是进入Mapping映射中,所以返回的头信息中并没有配置的跨域信息。浏览器就会报跨域异常。 正确的解决跨域问题的方法时使用CorsFilter过滤器。代码如下: 全局配置:方式三 ``` package org.ouyushan.spring.boot.web.cors.config; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.cors.CorsConfiguration; import org.springframework.web.cors.UrlBasedCorsConfigurationSource; import org.springframework.web.filter.CorsFilter; /** * @Description: 常规方法配置之后再使用自定义拦截器时跨域相关配置就会失效,该配置能解决此问题。 * 原因是请求经过的先后顺序问题,当请求到来时会先进入拦截器中,而不是进入Mapping映射中,所以返回的头信息中并没有配置的跨域信息。浏览器就会报跨域异常。 * @Author: ouyushan * @Email: ouyushan@hotmail.com * @Date: 2020/6/5 11:20 */ @Configuration public class GlobalCorsConfigurationWithFilter { private CorsConfiguration corsConfig() { CorsConfiguration corsConfiguration = new CorsConfiguration(); corsConfiguration.addAllowedOrigin("*"); corsConfiguration.addAllowedHeader("*"); corsConfiguration.addAllowedMethod("*"); corsConfiguration.setAllowCredentials(true); corsConfiguration.setMaxAge(3600L); return corsConfiguration; } @Bean public CorsFilter corsFilter() { UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); source.registerCorsConfiguration("/**", corsConfig()); return new CorsFilter(source); } } ```