Vue项目非proxy实现访问不同微服务

背景

最近做的一个项目,由于甲方的奇葩要求:

前端Vue项目打包部署不能用nginx代理,需要走甲方提供的SLB,在请求不同的微服务时,需要带上SLB指定的微服务端口,由甲方配置SLB匹配不同端口,负载到相应微服务。

在之前项目开发中,我们都是通过nginx去匹配不同的location去做,或者是后端直接使用的spring cloud gateway,前端只需要配置http-proxy-middleware 或者直接请求spring cloud gateway网关就行。

而这次甲方的需求,后端不能用spring cloud gateway,必须前端请求微服务前就告诉SLB需要请求哪个微服务,故而有了今天的这个实现方式,可能不是最优,但是解决了目前的燃眉之急。

思路

在调用后端接口前,类似于nginx,根据不同的location匹配设置不同的端口,动态拼接到URL上,再去请求后端,参考了axios用helper下边的 combineURLs.js

1
2
3
4
5
module.exports = function combineURLs(baseURL, relativeURL) {
return relativeURL
? baseURL.replace(/\/+$/, '') + '/' + relativeURL.replace(/^\/+/, '')
: baseURL;
};

实现

自己写一个类似的公共方法,每次请求之前,先拼接

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
//请求拼接方法
combineURLs(relativeURL) {
let baseURL = axios.defaults.baseURL;
let port;
if (relativeURL.startsWith("/system")) {
port = 8081;
}
if (relativeURL.startsWith("/mdm")) {
port = 8082;
}
if (relativeURL.startsWith("/integration")) {
port = 8083;
}
if (relativeURL.startsWith("/plan")) {
port = 8084;
}
if (relativeURL.startsWith("/analysis")) {
port = 8085;
}
return relativeURL
? baseURL.replace(/\/+$/, '') + ":" + port + "/" + relativeURL.replace(/^\/+/, '')
: baseURL;
}

然后在封装的axios请求之前,调用方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
// 根据环境变量进行接口区分
switch (process.env.NODE_ENV) {
case "dev":
axios.defaults.baseURL = 'http://localhost';
break;
case "pro":
axios.defaults.baseURL = 'http://10.16.160.160';//线上环境
break;
}

export default {
get(url, params = {}) {
//重点!!!请求前拼接,jurisdiction.js是自己封装公共方法的地方
url = jurisdiction.combineURLs(url)
return new Promise((resolve, reject) => {
axios.get(url, {
params
})
.then(response => {
if (response) {
resolve(response.data) // 成功
}
})
.catch(err => {
reject(err) // 失败
})
})
},
//post,put,delete类似
}

这样,在api里边,只需要写上不同的请求URL即可,如

1
2
3
4
5
export const Apis = {
logs: params => req.post("/system/logs/list", params),
users: params => req.post("/system/users/list", params),
productionLine: params => req.get(`/mdm/productionLine/${params}`)
}

跨域

这样实现了动态拼接,只需要后端配置上跨域支持就行了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {

/**
* 配置跨域信息
* @param registry
*/
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("*")
.allowCredentials(true)
.allowedMethods("GET", "POST", "DELETE", "PUT", "OPTIONS")
.allowedHeaders("*")
.maxAge(3600);
}
}

非前端开发,小小后端程序员,目前只能想到这种方式了。