Spring Boot Sample 013之spring-boot-web-cors

懵懂的女人 提交于 2020-07-28 14:06:59

一、环境

  • 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);
    }
}

```

 

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!