前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >SpringBoot跨域及后端解决方案

SpringBoot跨域及后端解决方案

作者头像
框架师
发布2021-08-05 11:41:48
4.1K0
发布2021-08-05 11:41:48
举报
文章被收录于专栏:墨白的Java基地墨白的Java基地

什么是跨域?

  • 一个网页向另一个不同域名/不同协议/不同端口的网页请求资源,这就是跨域。
  • 跨域原因产生:在当前域名请求网站中,默认不允许通过ajax请求发送其他域名。

CROS常见header

Access-Control-Allow-Origin:http://somehost.com 表示允许http://somehost.com发起跨域请求

Access-Control-Max-Age:86400 表示在86400秒内不需要再发送预校验请求。

Access-Control-Allow-Methods: GET,POST,PUT,DELETE 表示允许跨域请求的方法。

Access-Control-Allow-Headers: content-type 表示允许跨域请求包含content-type

模拟跨域

后台代码

新建一个SpringBoot项目,添加如下依赖,版本随意,我自己是2.5.2版本

  • pom.xml 文件
代码语言:javascript
复制
<!-- springboot版本,2.5.2 -->
<parent>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-parent</artifactId>
   <version>2.5.2</version>
   <relativePath/> <!-- lookup parent from repository -->
</parent>
<!-- 添加 web -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- 添加 lombok 简化实体类 -->
<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
</dependency>
  • 创建一个实体类
代码语言:javascript
复制
/**
 * Software:IntelliJ IDEA 2021.1.1 x64
 * Author: https://www.mobaijun.com
 * Date: 2021/7/6 16:16
 * ClassName:GoodsDo
 * 类描述: 商品实体类
 */
@Data
public class GoodsDo {
    /**
     * 商品id
     */
    private Long id;
    /**
     * 商品名称
     */
    private String name;
    /**
     * 商品价格
     */
    private String price;
    /**
     * 商品图片
     */
    private String pic;
}
  • 服务层接口
代码语言:javascript
复制
import com.mobai.pojo.GoodsDo;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;

/**
 * Software:IntelliJ IDEA 2021.1.1 x64
 * Author: https://www.mobaijun.com
 * Date: 2021/7/6 16:17
 * ClassName:GoodsService
 * 类描述:商品实现类
 */
@Service
public class GoodsService {
    /**
     * 获取商品列表
     */
    public List<GoodsDo> getGoodsList() {
        // 模拟从数据库查询出的结果返回
        List<GoodsDo> goodsList = new ArrayList<GoodsDo>();
        GoodsDo goods = new GoodsDo();
        goods.setId(1L);
        goods.setName("苹果");
        goods.setPic("apple.jpg");
        goods.setPrice("3.5");
        goodsList.add(goods);
        return goodsList;
    }
}
  • 控制器接口
代码语言:javascript
复制
import com.mobai.pojo.GoodsDo;
import com.mobai.service.GoodsService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;

/**
 * Software:IntelliJ IDEA 2021.1.1 x64
 * Author: https://www.mobaijun.com
 * Date: 2021/7/6 16:17
 * ClassName:GoodsController
 * 类描述:
 */
@RestController
public class GoodsController {

    @Autowired
    private GoodsService goodsService;

    /**
     * 遵循Restful规范的接口
     * 请求地址:http://127.0.0.1:8080/goods
     */
    @GetMapping("/goods")
    public List<GoodsDo> getList() {
        return goodsService.getGoodsList();
    }
}

前端代码

新建一个文件夹,创建goods.html文件,编写如下请求代码:

代码语言:javascript
复制
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>商品请求测试</title>
    <!-- Bootstrap 核心 CSS 文件 -->
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/css/bootstrap.min.css"
          integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
</head>
<body>
<script>
    //初始化方法
    $(function () {
        var row = "";
        $.ajax({
            type: "GET",
            // 后端接口地址
            url: "http://127.0.0.1:8080/goods",
            dataType: "json",
            contentType: "application/json; charset=utf-8",
            success: function (res) {
                $.each(res, function (i, v) {
                    row = "<tr>";
                    row += "<td>" + v.id + "</td>";
                    row += "<td>" + v.name + "</td>";
                    row += "<td>" + v.price + "</td>";
                    row += "<td>" + v.pic + "</td>";
                    row += "</tr>";
                    $("#goodsTable").append(row);
                });
            },
            error: function (err) {
                console.log(err);
            }
        });
    });
</script>
</body>
</html>

如果在idea 或者 webStorm中可以直接点击右上角浏览器运行,会自动生成一个服务器和端口,打开浏览器控制台页面,查看请求信息:

has been blocked by CORS policy ,意味着被 CORS 策略阻塞了。我们的前端页面请求被 CORS 阻塞了,所以没成功获取到后端接口返回的数据。

CORS 跨域介绍

跨域实际上源自浏览器的同源策略,所谓同源,指的是协议、域名、端口都相同的源 (域)。浏览器会阻止一个域的 JavaScript 脚本向另一个不同的域发出的请求,这也是为了保护浏览器的安全。

在上面的例子中,发起请求的网页与请求资源的 URL 协议、域名、端口均不同,所以该请求就被浏览器阻止了。

CORS 的意思就是跨域资源共享,是一种允许跨域 HTTP 请求的机制,在这种情况下我们就要想办法实现 CORS 跨域了。

SpringBoot的Cors跨域设置

  • SpringBoot可以基于Cors解决跨域问题,Cors是一种机制,告诉我们的后台,哪边(origin )来的请求可以访问服务器的数据。
  • 全局配置类
  • 配置实例如下:
代码语言:javascript
复制
package com.mobai.config;

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

/**
 * Software:IntelliJ IDEA 2021.1.1 x64
 * Author: https://www.mobaijun.com
 * Date: 2021/7/7 10:55
 * ClassName:CorsConfig
 * 类描述: cors配置类
 */
// @Configuration
public class CorsConfig {

    @Bean
    public WebMvcConfigurer corsConfigurer() {
        return new WebMvcConfigurer() {
            // 重写父类提供的跨域请求处理的接口
            @Override
            public void addCorsMappings(CorsRegistry registry) {
                // 添加映射路径
                registry.addMapping("/**")
                        // 放行哪些原始域
                        .allowedOriginPatterns("*")
                        // 是否发送Cookie信息
                        .allowCredentials(true)
                        // 放行哪些原始域(请求方式)
                        .allowedMethods("GET", "HEAD", "POST", "PUT", "DELETE", "OPTIONS", "PATCH")
                        // 放行哪些原始域(头部信息)
                        .allowedHeaders("*")
                        // 暴露哪些头部信息(因为跨域访问默认不能获取全部头部信息)
                        .exposedHeaders("Header1", "Header2")
                        // 预请求的结果有效期,默认1800分钟,3600是一小时
                        .maxAge(3600);
            }
        };
    }
}

通过上面的配置类,实现了允许所有对该 Spring Boot 的请求跨域。此时再次打开网页,被跨域策略阻塞的提示消失,界面显示如下:

小插曲

如果你的springboot版本较低,在2.2以下,具体那个版本我没有试过,跨域配置需要将 .allowedOriginPatterns 替换成 .allowedOrigins,因为在新版本SpringBoot中,跨域配置将 .allowedOrigins 替换成 .allowedOriginPatterns

参考文章:

  1. (5条消息) When allowCredentials is true, allowedOrigins cannot contain the special value “*“ since that cannot_想望着太阳的博客-CSDN博客
  2. 浅谈SpringBoot的Cors跨域设置 - 云扬四海
  3. Spring Boot 跨域与前后端分离丨慕课网教程
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2021-07-07,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 什么是跨域?
  • CROS常见header
  • 模拟跨域
    • 后台代码
      • 前端代码
      • CORS 跨域介绍
      • SpringBoot的Cors跨域设置
      • 小插曲
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档