如何在运行时管理两组属性?

时间:2017-01-05 15:22:37

标签: java spring spring-boot

我正在建立一个需要根据请求网址在两组属性之间切换的网络服务。我不确定哪种方法最适合处理。

我有一个具有yaml属性文件的Spring Boot应用程序。在属性文件中,结构看起来像这样;

optionA:
  foo:
    urls:
      - a
      - b
  bar:  
    something: hello

optionB:
  foo:
    urls:
      - x
      - y
  bar:  
    something: bye

optionAoptionB几乎都具有相同的属性,只有不同的值。

所以请求进来,我检查请求并决定是否需要optionA或optionB。

我一直试图让@ConfigurationProperties来处理这个问题,但这些属性会在启动时初始化,因此它不会是动态的。另一种可能性是我有两个配置类,每个选项一个但后来我的代码充满了检查以在两个类之间切换,这些类几乎完全相同,也不是很好。

任何有关如何最好地管理此事的最佳做法或建议都会受到赞赏,欢呼!

3 个答案:

答案 0 :(得分:2)

如果您没有太多选择,我会这样做:(刚刚用较小的配置制作示例)

<强> options.yml:

optionA:
  name: optionA
optionB:
  name: optionB

我为扩展程序创建了一个Option类:

public class Option {

    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

设置@ConfigurationProperties的两个Option类:(现在这些类都是空的,但您有机会对每个不同的选项更具体)

@Component
@ConfigurationProperties(prefix ="optionA", locations = "classpath:options.yml")
public class OptionA extends Option{
}
@Component
@ConfigurationProperties(prefix ="optionB", locations = "classpath:options.yml")
public class OptionB extends Option{
}

为了决定不同的选项,我创建了interface

public interface OptionService {

    Option findOption(boolean businessLogic);
}

在实现中,我注入了两个选项和业务逻辑的实现:(以一种简单的方式)

@Service
public class OptionServiceImpl implements OptionService {

    private OptionA optionA;
    private OptionB optionB;

    @Override
    public Option findOption(boolean businessLogic) {
        if(businessLogic){
            return getOptionA();
        } else {
            return getOptionB();
        }
    }

    public OptionA getOptionA() {
        return optionA;
    }

    @Autowired
    public void setOptionA(OptionA optionA) {
        this.optionA = optionA;
    }

    public OptionB getOptionB() {
        return optionB;
    }

    @Autowired
    public void setOptionB(OptionB optionB) {
        this.optionB = optionB;
    }
}

最后,您的控制器只需拨打OptionServiceImpl课程,并取消使用哪个选项:

@Controller
public class YourController {

    private OptionService optionServiceImpl;

    @RequestMapping("/")
    public String getIndex(){
        Option option = getOptionServiceImpl().findOption(true);
        System.out.println(option.getName());
        option = getOptionServiceImpl().findOption(false);
        System.out.println(option.getName());

        return "Hello World";
    }

    public OptionService getOptionServiceImpl() {
        return optionServiceImpl;
    }

    @Autowired
    public void setOptionServiceImpl(OptionService optionServiceImpl) {
        this.optionServiceImpl = optionServiceImpl;
    }
}

System.out.println的输出:

optionA
optionB

因此,决定应该使用哪个选项的业务逻辑不是if-else结构。您可以在界面及其实现中为decission创建规则。我认为您可以为更多控制器创建更多规则。

答案 1 :(得分:0)

您可以在application.properties中定义键值对。

其中key是Web服务名称,value是选项(属性列表)

使用@ConfigurationProperties

@ConfigurationProperties 
class Configuration {

    Map<String,Option> options; 

    // getters and setters
}

@Component
class ChooseServiceBasedConfiguration {

    @Autowired
    Configuration configuration;

    public void serviceMethod(String key ){
        //get appropriate properties of the web service
        configuration.getOptions().get(key);
    }    
}

基于Web服务,使用密钥获取所需的值。

答案 2 :(得分:0)

将您的yml更改为:

options:
  - name: optionA
    foo:
      urls:
        - a
        - b
    bar:  
      something: hello
  - name: optionB
    foo:
      urls:
        - x
        - y
    bar:  
      something: bye

添加Config类:

@Data
@ConfigurationProperties
@Configuration
public class MyConfig {

    private List<Option> options;
}

使用它:

@Component
public class UseConfig {

    @Autowired
    public UseConfig(final MyConfig config) {
        System.out.println(config.getOptions());
    }

}

结果:

[Option(name=optionA, foo=Foo(urls=[a, b]), bar=Bar(something=hello)), Option(name=optionB, foo=Foo(urls=[x, y]), bar=Bar(something=bye))]