Solon+Gateway实现像SpringCloudGateway一样的转发网关!

SolonGateway传送门https://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就算搭建完成了

  • 4
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

阿࿆杰࿆

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值