当前位置: 首页 > 知识库问答 >
问题:

可以使用属性启用/禁用spring boot@RestController吗?

骆嘉石
2023-03-14

给定一个带有RestController的“标准”spring boot应用程序,例如

@RestController
@RequestMapping(value = "foo", produces = "application/json;charset=UTF-8")
public class MyController {
    @RequestMapping(value = "bar")
    public ResponseEntity<String> bar(
        return new ResponseEntity<>("Hello world", HttpStatus.OK);
    }
}

如果/除非某个应用程序属性存在/不存在,是否有注释或技术可以阻止endpoint启动。

注意:测试方法内部的属性并分解不是解决方案,因为endpoint将存在。

我不关心粒度:即只启用/禁用一个方法或整个类都可以。

因为概要文件不是属性,所以通过概要文件进行控制并不能解决我的问题。

共有3个答案

姜博
2023-03-14

在某些情况下,@ConditionalOnXXX无法工作,例如,依赖另一个bean实例来检查条件。(XXXCondition类无法调用bean)。

在这种情况下,请在Java配置文件中注册控制器。

请参阅源代码(Spring webmvc 5.1.6):

org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping.isHandler(Class<?>)
 
       @Override
       protected boolean isHandler(Class<?> beanType) {
              return (AnnotatedElementUtils.hasAnnotation(beanType, Controller.class) ||
                           AnnotatedElementUtils.hasAnnotation(beanType, RequestMapping.class));
       }

应该在类型级别为控制器bean添加@RequestMapping注释。请参见:

@RequestMapping // Make Spring treat the bean as request handler
public class MyControllerA implements IMyController {
    @RequestMapping(path = { "/path1" })
    public .. restMethod1(...) {
  ........
    }
}

@RequestMapping // Make Spring treat the bean as request handler
public class MyControllerB implements IMyController {
    @RequestMapping(path = { "/path1" })
    public .. restMethod1(...) {
  ........
    }
}

@Configuration
public class ControllerConfiguration {

    /**
     *
     * Programmatically register Controller based on certain condition.
     *
     */
    @Bean
    public IMyController myController() {
        IMyController controller;
        if (conditionA) {
            controller = new MyControllerA();
        } else {
            controller = new MyControllerB();
        }
        return controller;
    }
}
郭和硕
2023-03-14

在此添加此问题和另一个问题。

这是我的答案:

我实际上会使用@ReFresScope Bean,然后当您想在运行时停止Rest Controller时,您只需要将所述控制器的属性更改为false。

SO的链接引用在运行时更改属性。

以下是我的工作代码片段:

@RefreshScope
@RestController
class MessageRestController(
    @Value("\${message.get.enabled}") val getEnabled: Boolean,
    @Value("\${message:Hello default}") val message: String
) {
    @GetMapping("/message")
    fun get(): String {
        if (!getEnabled) {
            throw NoHandlerFoundException("GET", "/message", null)
        }
        return message
    }
}

使用过滤器还有其他选择:

@Component
class EndpointsAvailabilityFilter @Autowired constructor(
    private val env: Environment
): OncePerRequestFilter() {
    override fun doFilterInternal(
        request: HttpServletRequest,
        response: HttpServletResponse,
        filterChain: FilterChain
    ) {
        val requestURI = request.requestURI
        val requestMethod = request.method
        val property = "${requestURI.substring(1).replace("/", ".")}." +
                "${requestMethod.toLowerCase()}.enabled"
        val enabled = env.getProperty(property, "true")
        if (!enabled.toBoolean()) {
            throw NoHandlerFoundException(requestMethod, requestURI, ServletServerHttpRequest(request).headers)
        }
        filterChain.doFilter(request, response)
    }
}

My Github解释如何在运行时禁用

隗锐进
2023-03-14

我使用ConditionalOnExpression找到了一个简单的解决方案:

@RestController
@ConditionalOnExpression("${my.controller.enabled:false}")
@RequestMapping(value = "foo", produces = "application/json;charset=UTF-8")
public class MyController {
    @RequestMapping(value = "bar")
    public ResponseEntity<String> bar(
        return new ResponseEntity<>("Hello world", HttpStatus.OK);
    }
}

加上这个注释,除非我有

my.controller.enabled=true

在我的application.properties文件中,控制器根本不会启动。

您还可以使用更方便的:

@ConditionalOnProperty("my.property")

其行为与上述完全相同;如果属性存在并且为true,则组件将启动,否则不会启动。

 类似资料:
  • 问题内容: 给定带有的“标准” Spring Boot应用程序,例如 是否存在一种注释或技术,可 在 /除非存在/不存在某个应用程序属性的情况下完全阻止端点启动。 注意:测试方法内部的属性并爆炸不是解决方案,因为端点将存在。 我不在乎粒度:即仅启用/禁用方法或整个类都可以。 由于配置文件不是属性,因此通过配置文件进行控制无法解决我的问题。 问题答案: 我发现使用一个简单的解决方案: 加上这个注释,

  • 我可以使用启用/禁用整个,例如: 以下配置工作正常。但我需要对该控制器进行更细粒度的控制,并启用/禁用对其中某些方法的访问,例如: 正如您可能看到的,我已经将添加到方法,但这种方法不起作用,并且在启用的情况下,即使属性在我的中不存在,也会启用方法。 在这种情况下如何正确启用/禁用方法?

  • 是否可以以编程方式控制以启用或禁用它?我不想只是在每个方法中编写代码来执行某种 我见过这个问题,但这只适用于启动时。我真正需要的是允许我多次启用或禁用控制器的东西。 我想过不同的方法,但不知道哪些在Spring可行。 实际上控制容器(在我的例子中是jetty),因此对该特定endpoint的请求被禁用。 以某种方式控制<code>RequestMappingHandlerMapping</code

  • 我正在使用SpringBoot和@JmsListener从同一个QManager中的多个队列中检索IBM MQ消息。到目前为止,我可以得到没有任何问题的消息。但也有可能出现这样的情况,我不得不暂时停止使用其中一个队列中的MSG。它不一定是动态的。 我没有使用任何自定义ConnectionFactory方法。需要时,我想在application.properties中进行配置更改,以禁用特定的队列消

  • 我想使用而不使用。我们有一个与Spring现有的项目,但我有麻烦配置没有。 当我使用@EnableZuulProxy注释时,出现以下错误: 原因:org。springframework。豆。工厂UnsatifiedPendencyException:创建名为“org”的bean时出错。springframework。云netflix。祖尔。ZuulProxyConfiguration”:通过字段“

  • 我在src/main/resources下创建了2个文件: 应用程序。属性 第一个具有从env变量中获取值的属性,而后者具有固定值。 根据这里的具体情况,我以这样的方式推出了Spring靴: 然而,不会产生任何影响,并且应用程序是局部的。属性似乎被忽略。 有什么提示吗?