前后端分离项目跨域问题解决方案总结

前言

本文将讲解前后端项目中跨域问题的常见解决方案,其中后端基于SpringBoot,前端使用了jQueryaxios等框架用于实战代码的讲解。本文将不涉及跨域的解释和SpringBoot等框架,或者是Nginx的使用,将主要讲解前后端分离项目中跨域问题的解决,不过如果你遇到了问题,也欢迎一起交流学习。

跨域解决

  • JSONP方式

    这种方式只能用于Get请求,因此如果需要以Post请求方式获取数据,则可以先看后面CORS解决方式,以下就讲解两种基于JSONP原理的解决方案,首先先看后端的接口:

    @RestController
    @RequestMapping("/api/customer")
    public class HelloController {
          
          
    
        @GetMapping("/getAllCustomerInfo")
        public String getAllCustomerInfo() {
          
          
            // 返回的数据必须包含在 getAllCustomerInfo() 字符串中
            // 以便在返回到前端后,可以自动执行回调函数,获取数据
            // getAllCustomerInfo() 与前端的回调函数名对应
            return "getAllCustomerInfo(" + getCustomerList() + ")";
        }
    
        private String getCustomerList() {
          
          
            List<Customer> list = new ArrayList<>(Arrays.asList(
                    new Customer(1, "张三", "123456"),
                    new Customer(2, "李四", "654321"),
                    new Customer(3, "王五", "123123")
            ));
            return new Gson().toJson(list);
        }
    
    }
    

    下面就来分别讲解以下两种方式的解决方案:

    1. js原生解决方案

      // 首先设置 src 并将结点添加到 <head> 中
      const script = document.createElement('script')
      script.src = 'http://localhost:8080/api/customer/getAllCustomerInfo'
      document.head.appendChild(script)
      
      // 回调函数名与接口中返回的名字对应
      const getAllCustomerInfo = res => {
              
              
      	console.table(res, ['id', 'username', 'password'])
      }
      

      通过以上设置就可以在Console中看到以下结果:

      image-20200915142859045

    2. jQueryajax解决方案

      // 记得需要引入 jQuery
      <script src="https://cdn.staticfile.org/jquery/1.10.0/jquery.js"></script>
      
      $.ajax({
              
               
      	url: 'http://localhost:8080/api/customer/getAllCustomerInfo', 
      	type: 'get', 
      	dataType: 'jsonp', 
      	jsonpCallback: "getAllCustomerInfo"
      })
      
      // 回调函数同上
      const getAllCustomerInfo = res => {
              
              
      	console.table(res, ['id', 'username', 'password'])
      }
      
  • CORS解决方案

    跨域资源共享(CORS) 是一种机制,它使用额外的 HTTP 头来告诉浏览器 让运行在一个 origin (domain) 上的Web应用被准许访问来自不同源服务器上的指定的资源。当一个资源从与该资源本身所在的服务器不同的域、协议或端口请求一个资源时,资源会发起一个跨域 HTTP 请求,详细解释请看链接

    1. 后端接口中进行设置

      通过利用CORS,我们在前端只需要利用正常的ajax请求方式即可,无需再设置回调函数,在这里我们使用了axios,在展示后端代码之前,我们先看后端代码的改变,为了区别于JSONP只能进行Get请求,我们这里将接口改成了Post

      @RestController
      @RequestMapping("/api/customer")
      public class HelloController {
              
              
      
          @PostMapping("/getAllCustomerInfo")
          public List<Customer> getAllCustomerInfo(HttpServletResponse response) {
              
              
              // 设置响应头
              response.setHeader("Access-Control-Allow-Origin", "*");
              // 不再需要将结果放在回调函数中
              return new ArrayList<>(Arrays.asList(
                      new Customer(1, "张三", "123456"),
                      new Customer(2, "李四", "654321"),
                      new Customer(3, "王五", "123123")
              ));
          }
      
      }
      

      然后前端代码直接使用ajax请求即可:

      // 首先需要引入 axios
      <script src="https://cdn.staticfile.org/axios/0.1.0/axios.js"></script>
      
      axios.post('http://localhost:8080/api/customer/getAllCustomerInfo')
      	.then(res => {
              
              
      		console.table(res, ['id', 'username', 'password'])
      	})
      
    2. Nginx反向代理

      关于反向代理的知识,这里不做详细解析,感兴趣的话,可以查看该链接。通过使用Nginx的反向代理,我们在后端接口中就可以去掉响应头的代码设置:

      @RestController
      @RequestMapping("/api/customer")
      public class HelloController {
              
              
      
          @PostMapping("/getAllCustomerInfo")
          public List<Customer> getAllCustomerInfo() {
              
              
              return new ArrayList<>(Arrays.asList(
                      new Customer(1, "张三", "123456"),
                      new Customer(2, "李四", "654321"),
                      new Customer(3, "王五", "123123")
              ));
          }
      
      }
      

      然后是nginx.conf中的修改:

      server {
              
              
      	# 监听80端口, 前端不再直接访问8080端口, 改为访问80端口即可
          listen       80;
          server_name  localhost;
      
          location / {
              
              
              root   html;
              # 添加头
              add_header Access-Control-Allow-Origin *;
              # 代理转发到8080后端端口
              proxy_pass http://localhost:8080;
              index  index.html index.htm;
          }
      }
      

      然后再将前端中访问的接口修改为80:

      // 首先需要引入 axios
      <script src="https://cdn.staticfile.org/axios/0.1.0/axios.js"></script>
      
      // 80为 http 默认端口,可省略
      axios.post('http://localhost/api/customer/getAllCustomerInfo')
                   .then(res => {
              
              
                      console.table(res, ['id', 'username', 'password'])
                   })
      

      然后开启Nginx服务器,Console中再次出现了我们想看到的结果:

      image-20200915150523876

总结

本文并没有包括跨域问题的所有解决方案,不过相信对于大部分的跨域问题,都已经可以解决了,本文在之后也可能会继续更新,讲解更多种解决跨域问题的方法,也欢迎各位一起交流学习。

猜你喜欢

转载自blog.csdn.net/qq_41698074/article/details/108600190