SolonGateway传送门solon.noear.org/article/211
创建Solon项目
命名Gateway
1.引入依赖
<!-- nacos注册中心 -->
<dependency>
<groupId>org.noear</groupId>
<artifactId>nacos2-solon-cloud-plugin</artifactId>
</dependency>
<!-- 微服务扩展插件 提供基于服务名的http调用-这里主要实现转发功能 -->
<dependency>
<groupId>org.noear</groupId>
<artifactId>solon.cloud.httputils</artifactId>
</dependency>
2.创建网关
package com.superb.gateway.config;
import com.superb.common.core.enums.SuperbCode;
import com.superb.common.core.model.Result;
import com.superb.common.utils.HeadersUtils;
import com.superb.common.utils.StringUtils;
import com.superb.gateway.handler.AfterHandler;
import com.superb.gateway.handler.HeaderHandler;
import org.noear.solon.annotation.Component;
import org.noear.solon.annotation.Mapping;
import org.noear.solon.cloud.utils.http.HttpUtils;
import org.noear.solon.core.NvMap;
import org.noear.solon.core.handle.Context;
import org.noear.solon.core.handle.Gateway;
import org.smartboot.http.common.enums.HttpMethodEnum;
/**
* gateway网关
* @Mapping("/**") 匹配网关所有请求
* https://solon.noear.org/article/212
* @Author: ajie
* @CreateTime: 2024-07-29 08:54
*/
@Mapping("/**")
@Component
public class GatewayConfig extends Gateway {
@Override
protected void register() {
// 处理异常
after(new AfterHandler());
// 添加服务转发
add(Nav.class);
}
public static class Nav {
//没有加印射值时,将做为默认处理 //当只有默认处理时,将接收所有请求
@Mapping
public Object def(Context ctx) throws Throwable {
//检测请求,并尝试获取接口服务名
String serverName = ctx.pathMap("/{serverName}/**").get("serverName");
// 如果没有与之对应的子服务,那么抛出异常
if (serverName == null) {
ctx.setHandled(true);
ctx.render(Result.error(SuperbCode.AUTH_404));
return ctx;
}
// 仅支持GET和POST请求
if (!HttpMethodEnum.GET.getMethod().equals(ctx.method()) && !HttpMethodEnum.POST.getMethod().equals(ctx.method())) {
ctx.setHandled(true);
ctx.render(Result.error("请求异常:不被允许的请求'"+ ctx.method() +"'"));
return ctx;
}
// 获取服务真实路径 -- 获取url参数,解决转发参数丢失问题
String params = ctx.queryString();
String servicePath = ctx.path().substring(serverName.length() + 1);
if (StringUtils.isNotBlank(params)) {
servicePath = servicePath + "?" + params;
}
NvMap nvMap = ctx.headerMap();
// 追加gateway请求头,可以到子服务中判断是否由gateway转发
nvMap.put("solon-gateway", "superb-gateway");
//转发请求(分布式的特点:转发到别处去)//使用服务名转发,即是用“负载均衡”了
return HttpUtils.http(serverName, servicePath).headers(nvMap).bodyJson(ctx.body()).execAsBody(ctx.method());
}
}
}
3.负载均衡
package com.superb.gateway.config;
import org.noear.solon.annotation.Bean;
import org.noear.solon.annotation.Configuration;
import org.noear.solon.cloud.impl.CloudLoadStrategy;
import org.noear.solon.cloud.impl.CloudLoadStrategyDefault;
import org.noear.solon.cloud.impl.CloudLoadStrategyIpHash;
/**
* 注册负载均衡器
* <a href="https://solon.noear.org/article/478">了解 LoadBalance</a>
* @Author: ajie
* @CreateTime: 2024-07-29 09:21
*/
@Configuration
public class CloudLoadBalanceConfig {
@Bean
public CloudLoadStrategy loadStrategy() {
// 返回负载均衡策略 提供:默认为轮询、ip希哈
return new CloudLoadStrategyDefault();
}
}
4.处理异常
package com.superb.gateway.handler;
import com.superb.common.core.enums.SuperbCode;
import com.superb.common.core.exception.SuperbException;
import com.superb.common.core.model.Result;
import com.superb.common.utils.AuthDataScopeUtils;
import com.superb.common.utils.HeadersUtils;
import org.noear.solon.core.handle.Context;
import org.noear.solon.core.handle.Handler;
/**
* 请求结束处理
* 出现异常情况
* @Author: ajie
* @CreateTime: 2024-07-29 11:23
*/
public class AfterHandler implements Handler {
@Override
public void handle(Context ctx) throws Throwable {
Throwable errors = ctx.errors;
if (errors != null) {
ctx.setHandled(true);
if (errors instanceof SuperbException ee) {
ctx.render(Result.error(ee.getCode(), ee.getMessage()));
} else if (errors instanceof IllegalStateException ee){
String message = ee.getMessage();
String str = "No service address found";
if (message.contains(str)) {
ctx.render(Result.failure("请检查服务["+ message.substring(str.length() + 1) +"]是否启动!"));
} else {
ctx.render(Result.failure(errors.getMessage()));
}
} else {
ctx.render(Result.failure(errors.getMessage()));
}
}
}
}
至此,SolonGateway就算搭建完成了