.net 8 WepApi简易路由分配实现

前言:

最近看了很多路由,网关中间件,觉得嵌入比较麻烦,所以想在Admin中对多个系统的配置进行统一管理,不考虑中间件路由分发的情况下,通过restful Api携带系统标识clinetId,注入一个Fun来具体分配。

代码实现:

1.自定义统一接口:供各个子系统各自的具体实现

//定义统一接口
public interface IClientSecurityProxy
{
    //定义方法
    Task<ConfigurationBase> GetConfiguration(string clientId);
}

2.定义ClientSecurityProxyBase:保证各个系统可以只实现自己需要的,解耦

public class ClientSecurityProxyBase : IClientSecurityProxy
{
    //虚方法默认实现,实际供具体子系统具体实现
    public virtual Task<ConfigurationBase> GetConfiguration(string clientId)
    {
        throw new NotImplementedException();
    }
}

3.定义两个子系统,各自实现各自的逻辑

//A系统
public class AClientSecurityProxy : ClientSecurityProxyBase
{
    //A方法实现逻辑
    public override async Task<ConfigurationBase> GetConfiguration(string clientId)
    {
        return new ConfigurationBase()
        {
            configurations =new Dictionary<string, List<Config>>()
            {
                {"A",new List<Config>()}
            }
        };
    }
}


//B系统
public class BClientSecurityProxy: ClientSecurityProxyBase
{
    //B方法实现逻辑
    public override async Task<ConfigurationBase> GetConfiguration(string clientId)
    {
        return new ConfigurationBase()
        {
            configurations =new Dictionary<string, List<Config>>()
            {
                {"B",new List<Config>()}
            }
        };
    }
}

4.Program.cs注入两个单例的子系统实现:注意不要用<接口,实现类>方式注入

//注入各个子系统的具体代理实现
builder.Services.AddSingleton<AClientSecurityProxy>();
builder.Services.AddSingleton<BClientSecurityProxy>();

5.注入一个Func<string, IClientSecurityProxy>(): 供我们获取具体的实现类

//注入一个Fun,来判断属于那个系统
builder.Services.AddSingleton(sp =>new Func<string, IClientSecurityProxy>(c =>
{
    //判断是A系统就返回AClientSecurityProxy 
    if (isA(c))
        return sp.GetRequiredService<AClientSecurityProxy>();
    //判断是B系统就返回BClientSecurityProxy
    if (isB(c))
        return sp.GetRequiredService<BClientSecurityProxy>();
    throw new NotSupportedException($"Unsupported clientId:{c}.");
}));

6.定义判断系统Fun<string,bool>(): 区分是哪个系统,可自由添加,复杂的可以定义对象,或者元组来传递判断

//A系统判断依据
Func<string, bool> isA = clientId => clientId.EndsWith(".A", StringComparison.OrdinalIgnoreCase)
                                         || clientId.EndsWith(".axxx", StringComparison.OrdinalIgnoreCase)
                                         || clientId.Equals("A", StringComparison.OrdinalIgnoreCase)
                                         || clientId.Equals("a", StringComparison.OrdinalIgnoreCase);


//B系统判断依据
Func<string, bool> isB = clientId => clientId.EndsWith(".b", StringComparison.OrdinalIgnoreCase)
                                       || clientId.EndsWith(".bxx", StringComparison.OrdinalIgnoreCase)
                                       || clientId.Equals("B", StringComparison.OrdinalIgnoreCase)
                                       || clientId.Equals("b", StringComparison.OrdinalIgnoreCase);

7.Controller 注入Program.cs注入的Func<string, IClientSecurityProxy>()

[ApiController]
[Route("api/[controller]/[action]")]
public class ConfigurationController : ControllerBase
{
    //注入client工厂
    private readonly Func<string, IClientSecurityProxy> _clientProxyFactory;

    public ConfigurationController(Func<string, IClientSecurityProxy> clientProxyFactory)
    {
        _clientProxyFactory = clientProxyFactory;
    }
    
    //从路由中拿取系统标识,拿到具体系统的实现执行
    [HttpGet("{clientId}/getSetting")]
    public async Task<IActionResult> TestConfigurationAsync([FromRoute] string clientId)
    {
        var resp = await _clientProxyFactory(clientId).GetConfiguration(clientId);
        return Ok(resp);
    }
}

测试:

返回AClientSecurityProxy实例

 
执行AClientSecurityProxy的GetConfiguration()

以上就是文章的全部了。经测试,这种方式设计简单,方便扩展,prod环境实战表现不错,是一个推荐的实现方案,完整的demo在下文Github链接,如果对你有帮助的话麻烦点一下star !

完整Demo地址: 

GitHub Linked

  • 15
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值