背景: 在分离式架构的项目中,前端和后端分离部署,往往导致前端向后端发起请求时遇到跨域问题。跨域问题会阻止前端获取后端的数据,因此需要对项目进行跨域配置。此外,项目中可能需要同时请求多个不同域名的接口,如何配置多域名请求也是一个重点。
本文将详细介绍如何通过后端注解 @CrossOrigin
解决跨域问题,并且结合前端的配置,确保项目顺利实现跨域与多域名请求。
在后端处理跨域时,可以通过全局跨域配置解决,也可以在特定的接口类上使用注解 @CrossOrigin
来灵活处理跨域请求。下面我们将通过注解的方式,允许特定接口处理跨域请求。
首先,在需要允许跨域访问的控制器类上添加 @CrossOrigin
注解。这个注解可以为接口指定允许的域名,以及指定允许的请求头等信息。
@RestController
// @CrossOrigin支持多个域名配置,允许多个前端同时请求接口。
// 例如: @CrossOrigin(origins = {"http://localhost:8080", "http://localhost:8081"}, allowedHeaders = "*")
@CrossOrigin(origins = "http://前端地址", allowedHeaders = "*")
public class AiMeowController {
@GetMapping("/aimeow/list")
public void list() {
// 实现获取数据的逻辑
}
}
注意: 避免在此类中使用
@RequestMapping
注解,因为它可能会影响跨域请求的处理。
通过这种方式,可以灵活地为特定的接口设置跨域访问权限,避免全局配置带来的不必要的安全风险。
在前端的跨域处理部分,除了需要指定后端服务地址外,还要确保请求库(如 axios
)能够正确发起请求并处理跨域响应。以下步骤将详细介绍如何在前端进行相关配置。
前端项目通常有不同的环境(如开发环境和生产环境),因此可以通过修改环境配置文件 .env.development
和 .env.production
来为每个环境指定后端服务地址。
# 指定后端接口服务的域名和端口
VUE_APP_API_SERVICE_URL='http://后端IP地址:端口'
不同环境下的文件分别管理开发和生产时的后端地址,以便前端在不同环境下都能正确请求数据。
request.js
为了使跨域请求顺畅并统一处理错误和请求拦截,我们可以仿照若依项目的 request.js
,编写一个新的请求文件。以下是实现的代码:
import axios from "axios";
import { Message } from "element-ui";
import { tansParams } from "@/utils/ruoyi";
import cache from "@/plugins/cache";
// 设置默认请求头
axios.defaults.headers["Content-Type"] = "application/json;charset=utf-8";
// 创建 axios 实例
const service = axios.create({
// 请求超时设置为10秒
timeout: 10000,
});
// 请求拦截器:用于防止重复提交和处理 GET 请求的参数
service.interceptors.request.use(
(config) => {
const isRepeatSubmit = (config.headers || {}).repeatSubmit === false;
// 处理 GET 请求参数
if (config.method === "get" && config.params) {
let url = config.url + "?" + tansParams(config.params);
url = url.slice(0, -1);
config.params = {};
config.url = url;
}
// 防止重复提交
if (!isRepeatSubmit && (config.method === "post" || config.method === "put")) {
const requestObj = {
url: config.url,
data: JSON.stringify(config.data),
time: new Date().getTime(),
};
const sessionObj = cache.session.getJSON("sessionObj");
if (sessionObj) {
const interval = 1000; // 设置请求时间间隔为1秒
if (
sessionObj.data === requestObj.data &&
requestObj.time - sessionObj.time < interval &&
sessionObj.url === requestObj.url
) {
const message = "请勿重复提交相同的数据";
console.warn(`[${sessionObj.url}]: ` + message);
return Promise.reject(new Error(message));
}
}
cache.session.setJSON("sessionObj", requestObj);
}
return config;
},
(error) => {
return Promise.reject(error);
}
);
// 响应拦截器:处理错误响应并提供友好提示
service.interceptors.response.use(
(res) => {
return res.data;
},
(error) => {
let { message } = error;
if (message === "Network Error") {
message = "后端服务无法连接";
} else if (message.includes("timeout")) {
message = "请求超时";
} else if (message.includes("Request failed with status code")) {
message = "接口返回异常,状态码:" + message.slice(-3);
}
Message({ message, type: "error", duration: 5000 });
return Promise.reject(error);
}
);
export default service;
在创建完请求库后,接下来可以为不同的后端接口创建独立的 API 调用文件。例如,下面的代码用于调用 AiMeow
接口:
import request from "@/utils/request";
const URL = process.env.VUE_APP_API_SERVICE_URL;
// 获取 AiMeow 列表
export function getAiMeowList() {
return request({
url: URL + "/aimeow/list",
method: "get",
});
}
这样,我们就可以在前端方便地调用跨域接口了。
调用第三方接口与引入本地 API 文件的方式相同。以下是调用 AiMeow
接口的示例代码:
import { getAiMeowList } from "@/api/aimeow";
export default {
methods: {
// 获取 AiMeow 列表数据
fetchAiMeowList() {
getAiMeowList().then((response) => {
console.log(response);
}).catch((error) => {
console.error(error);
});
}
}
};
通过这种方式,前端可以方便地发起跨域请求并获取后端数据。
通过以上配置,我们实现了在若依分离版项目中同时处理跨域问题和多域名接口请求。后端通过 @CrossOrigin
解决了跨域访问权限问题,而前端则通过修改环境配置文件和编写请求拦截器来实现跨域请求与错误处理,确保项目的跨域访问顺畅无阻。
powered by kaifamiao