跨越问题产生原因:产生跨域问题的原因是浏览器的同源策略,所谓同源是指:域名,协议,端口相同。如果不同,将会出现跨域问题。

一、创建项目

我们创建两个项目,一个命名为provider提供服务,一个命名为consumer消费服务,第一个项目端口配置为8080,第二个项目端口配置为8081,然后在provider中提供一个接口,供consumer项目里访问。

provider项目:

接口代码示例如下:

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * @author qx
 * @date 2023/06/17
 * @desc 提供数据
 */
@RestController
public class HelloController {

    /**
     * 访问hello路径,返回hello字符串
     */
    @GetMapping("/hello")
    public String hello() {
        return "hello";
    }
}

consumer项目:

引入thymeleaf依赖,使用页面测试跨越问题。

<!--thymeleaf-->
<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>

消费者页面示例代码如下:

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;

/**
 * @author qx
 * @date 2023/06/17
 * @desc 消费者页面
 */
@Controller
public class IndexController {

    /**
     * 访问/index路径打开index.html页面
     */
    @GetMapping("/index")
    public String toIndex() {
        return "index";
    }

}

index.html页面代码如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<input type="button" onclick="btnClick()" value="click"/>
<script src="https://lib.baomitu.com/jquery/1.12.4/jquery.min.js"></script>
<script>
    function btnClick() {
        // 请求provider中的数据接口
        $.get('http://localhost:8080/hello', function (msg) {
            console.log(msg);
        });
    }
</script>
</body>
</html>

二、跨域问题产生

分别启动两个项目,点击consumer项目中index页面中的按钮。

SpringBoot中跨域问题的处理_spring

SpringBoot中跨域问题的处理_跨域_02

我们发现没有成功访问到数据,页面控制台遇到了跨域访问的异常提示。

三、解决跨域 

1.加@CrossOrigin注解

在provider项目的方法中加上@CrossOrigin注解,参数值为需要跨域访问的目标地址。

示例代码如下:

import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * @author qx
 * @date 2023/06/17
 * @desc 提供数据
 */
@RestController
public class HelloController {

    /**
     * 访问hello路径,返回hello字符串
     */
    @CrossOrigin(value = "http://localhost:8081/")
    @GetMapping("/hello")
    public String hello() {
        return "hello";
    }
}

表示这个方法可以接受来自http://localhost:8081/的请求,配置完成后重启provider项目,我们再次在consumer中发送请求,浏览器控制台不会报错,获取到了provider项目的数据。

SpringBoot中跨域问题的处理_spring_03

SpringBoot中跨域问题的处理_ide_04

2.跨域全局配置

在每个方法都加上@CrossOrigin很麻烦,我们在provider项目中通过在SpringMvc配置类中重写addCorsMappings实现全局的跨域配置。

示例代码如下:

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

/**
 * @author qx
 * @date 2023/06/17
 * @desc 全局跨域配置
 */
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**")
                .allowedOrigins("http://localhost:8081/")
                .allowedMethods("*")
                .allowedHeaders("*");
    }
}

/**表示本应用的所有方法都会去处理跨域请求。

allowedOrigins表示可以跨域的目标访问地址。

allowedMethods表示允许通过的数。

allowedHeaders表示允许的请求头。

这样配置之后,我们就不必在每个方法上都单独的跨域配置了。

我们把provider项目中的@CrossOrigin注解去掉,重新启动provider项目。

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * @author qx
 * @date 2023/06/17
 * @desc 提供数据
 */
@RestController
public class HelloController {

    /**
     * 访问hello路径,返回hello字符串
     */
    @GetMapping("/hello")
    public String hello() {
        return "hello";
    }
}

我们继续点击consumer项目中index页面上的请求按钮,成功获取到了数据。

SpringBoot中跨域问题的处理_ide_05

SpringBoot中跨域问题的处理_ide_06