如何使 REST 控制器以环境为条件?

Posted

技术标签:

【中文标题】如何使 REST 控制器以环境为条件?【英文标题】:How can I make a REST controller conditional on the environment? 【发布时间】:2019-10-14 09:08:54 【问题描述】:

我们有一个用例,我们希望在除生产环境之外的每个环境中启用一组端点。我们的想法是使用 Spring 的 Conditional annotation 的变体,仅在非生产环境中启用控制器,而不是为此用例实现自定义安全实现。

我们最初的尝试是通过注入指定环境类型(例如 dev、test、prod 等)的动态系统属性来使用 @ConditionalOnExpression,并将该属性与正则表达式进行匹配,但我们还没有能够以适合我们需求的方式正确解析 SpEL 表达式。

@RestController
@ConditionalOnExpression("$property.name matches ^((?!prod).)*$")
public class TestDataController

我们也考虑过使用@ConditionalOnProperty,但似乎没有办法让这个属性接受多个有效值。

@RestController
@ConditionalOnProperty(
        value = "property.name",
        havingValue = "value1" or "value2",
        matchIfMissing = true)
public class TestDataController

我们最后一次尝试是编写一个自定义类来扩展 Spring 的 Conditional 类以满足我们的需要。这目前可行,但它依赖于 Java 文件 I/O,我们希望尽可能避免这种情况。

有什么想法吗?

19 年 5 月 29 日更新

我们能够使用以下解决方案来解决我们的问题:

    按以下方式定义自定义条件:
public class NotInProductionCondition implements Condition 
    @Override
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) 
        final String env = context.getEnvironment().getProperty("property.name");
        if (env == null || env.isEmpty()) 
            return true;
        
        return !env.contains("prod");
    

    在我们的控制器上使用自定义条件:
@RestController
@Conditional(NotInProductionCondition.class)
public class TestDataController

【问题讨论】:

使用Profile注解。它在内部使用条件 谢谢,@EbrahimPasbani。这会奏效,但我们选择了不同的方法。请参阅上面的更新了解我们采用的方法。 没问题。是的,这种方法更好,更干净 【参考方案1】:

您可以使用@Profile 注解根据您的环境中设置的配置文件来实例化一个bean。

@RestController
@Profile("!prod")
class MyController 
  ...

如果您不在您的环境中使用配置文件,您很可能会使用某种类型的环境变量来指定环境名称,我想。你可以把它做成这样的弹簧配置文件

spring.profiles.active = $environmentName

【讨论】:

谢谢!这会奏效,但我们选择了不同的方法。有关我们采用的方法,请参阅问题的更新。

以上是关于如何使 REST 控制器以环境为条件?的主要内容,如果未能解决你的问题,请参考以下文章

如何在Angular 4中提供用户名和密码以使用具有oAuth安全性的rest控制器?

添加凭据以访问 REST 控制器

如何以 JSON 格式发送 Integer 值并在 REST Controller 中接收?

如何使导航栏背景颜色为clearColor?

如何在 Jmeter 中控制 REST API 的流/序列?

如何使我的键盘弹出窗口更加流畅,我的视图控制器以模态方式出现?