java - 限制客户端仅使用从 yml 文件创建的配置列表中的一个配置

标签 java spring-boot yaml

在我的 Spring Boot 应用程序中,我有包含以下内容的 application.yml 配置文件

config:
gateways:
    -
        id: 'g0'
        nbrInputs: 128
        nbrOutputs: 128
    -
        id: 'g1'
        nbrInputs: 128
        nbrOutputs: 128

配置类:

 @Configuration
 @ConfigurationProperties(prefix="config")
 @EnableConfigurationProperties
 public class GatewayConfig
 {
     List<Gateway> gateways = new ArrayList<Gateway>();

     public List<Gateway> getGatewayList(){
          return gateways;
     }

     public static class Gateway
     {
       private String id;
       private int nbrInputs;
       private int nbrOutputs;

       // Getters and Setters
       // ...
      }
 }

我想向客户端公开这些网关,但希望允许一个网关仅用于一个客户端类(clientA 或 clientB)。

为此,我编写了一个 Mapper 类来根据客户端提供的 ID 将客户端实现映射到网关。

@Component
public class MapGatewaytoClasses{
     @Autowired
     private GatewayConfig gc;

     @Autowired
     private ApplicationContext ac;

     @PostConstruct
     public void init(){
          List<Gateway> lg = gc.getGatewayList();
          Map<String, Object> beans = applicationContext.getBeansWithAnnotation(Myannotation.class);

          for (Map.Entry<String,Object> entry : beans.entrySet()) {
               for(Gateway g: lg){
                   Client c = (Client)entry.getValue();
                    if(c.getId().equalsIgnoreCase(g.getId())){
                            c.setGateway(g);
                    }
               }
          }
     }
}

public abstract client{
    protected String id;
    public String getId() {
       return id;
    }
}

现在新客户端必须扩展此客户端才能使用。

@Component
@Myannotation
public class clientA extends Client {         
     Gateway gateway;
     public A(){
         id="g0";
     }
     public void setGateway(Gateway gateway){
         this.gateway = gateway;
     }
}

@Component
@Myannotation
public class clientB extends Client{
     Gateway gateway;
     public B(){
         id="g1";
     }

     public void setGateway(Gateway gateway){
         this.gateway = gateway;
     }
}

我应该如何限制 clientA 和 clientB 不使用相同的网关 ID。 他们可以使用任何网关,但不应该使用相同的网关。 或者是否有任何其他更好的方法将 clientA 或 clientB 与网关映射

最佳答案

在编译时,这些类的客户端无法知道 id/gateway 是否已被使用。
当您将网关关联到客户端对象时,它只能在运行时被发现:

 @PostConstruct
 public void init(){
      List<Gateway> lg = gc.getGatewayList();
      Map<String, Object> beans = applicationContext.getBeansWithAnnotation(Myannotation.class);

      for (Map.Entry<String,Object> entry : beans.entrySet()) {
           for(Gateway g: lg){
               Client c = (Client)entry.getValue();
                if(c.getId().equalsIgnoreCase(g.getId())){
                        c.setGateway(g);
                }
           }
      }
 }

这个时候,已经晚了。因此,作为解决方法,您可以为声明相同网关 ID 的客户端禁用或重新分配一个新网关。

Is there any other better way to map clientA or clientB with gateways

是的,客户端不直接耦合到网关的方式 而是在服务器将客户端关联到满足其要求的网关的地方。
这个想法是在服务器端提供一个网关池。
从客户端来看,客户端不指定他们将使用哪个网关,而是只指定他们对所需网关容量的要求,除了网关 ID 之外的所有内容:

config:

gateways:
    -
        id: 'g0'
        nbrInputs: 128
        nbrOutputs: 128
    -
        id: 'g1'
        nbrInputs: 64
        nbrOutputs: 64

client-gateway:
    -
        nbrInputs: 128
        nbrOutputs: 128
    -
        nbrInputs: 64
        nbrOutputs: 64 

服务器的角色是在运行时为每个声明的需要网关的客户端分配一个网关。 它可能应该在 init() 方法中完成。
这是一个给出想法的例子:

 @PostConstruct
 public void init(){
     Map<String, Object> beans = applicationContext.getBeansWithAnnotation(Myannotation.class);

     for (Map.Entry<String,Object> entry : beans.entrySet()) {
               Client c = (Client) entry.getValue();
               Optional<Gateway> gateway = findMatchingGateway(c);
               if (gateway.isPresent()){
                     c.setGateway(g);
                     gc.getGatewayList()
                       .removeIf(o->o.getId()==g.getId())
               )
               else {
                     // handle the not found case
               }


           }
     }
 } 


private Optional<Gateway> findMatchingGateway(Client client){
    return 
      gc.getGatewayList()
        .stream()
        .filter(g.nbrInputs() == client.getNbrInputs())
        .findAny();
}

关于java - 限制客户端仅使用从 yml 文件创建的配置列表中的一个配置,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57391142/

相关文章:

Java随机插入集合

java - 我在 springboot 中使用拦截器,但出现错误:

java - 如何使用 spring boot 读取 yaml 文件然后在 localhost 中显示结果?

java - Swing 应用程序的 Junit 测试用例

java - 有没有什么提示和技巧可以让 rhino 运行得更快?

java - 从动态库调用 jni 时 JVM 堆内存不足

json - @RequestBody无法与@JsonProperty一起使用

Spring Boot 2 - 基于过滤器的 JWT Spring Security 实现中的 403 而不是 401

linux - 如何在多行而不是单行输出上打印 linux 组名

java - PyYaml 到 SnakeYaml --- AWT-EventQueue- 0"Can' t 为标签 :yaml. org,2002:java/object 构造一个 java 对象: