可以使用属性启用/禁用弹簧启动@RestController吗?

时间:2015-04-30 02:56:36

标签: java spring spring-boot application-settings

给出带有@RestController的“标准”弹簧启动应用程序,例如

@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);
    }
}

是否有注释或技术阻止端点 at all 如果/除非某个应用程序属性存在/不存在。

注意:测试方法内的属性并且爆炸不是解决方案,因为端点将存在。

我不关心粒度:即启用/禁用方法或整个类都很好。

由于个人资料不是属性,因此通过个人资料进行控制无法解决我的问题。

4 个答案:

答案 0 :(得分:59)

我找到了一个使用@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",则组件启动,否则不启动。

答案 1 :(得分:0)

在这个问题和另一个问题here.

中添加

这是我的答案:

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

SO的link引用运行时更改的属性。

以下是我的工作代码段:

@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 explaining how to disable at runtime

答案 2 :(得分:0)

在某些情况下,@ 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 hanlder
public class MyControllerA {
    @RequestMapping(path = { "/path1" })
    public .. restMethod1(...) {
  ........
    }
}

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

@Configuration
public class ControllerConfiguration {

    /**
     *
     * Programmingly register Controller based on certain condition.
     *
     */
    @Bean
    public IMyController myController() {
        IMyController controller;
        if (conditionA) {
            cntroller = new MyControllerA();
        } else {
            controller = new MyControllerB();
        }
        return controller;
    }
}

答案 3 :(得分:-1)

我认为此问题来自以下事实:您针对不同的环境使用了不同的application.properties文件。在这种情况下,您可以使用spring配置文件并将配置单独配置到带有配置文件名称后缀的不同文件中,例如:

application.properties:

spring.profiles.active=@activatedProperties@

application-local.properties:

 //some config

application-prod.properties:

//some config

然后在构建参数中,您可以通过添加选项来指定要构建的环境:

-Dspring.profiles.active= //<-put here profile local or prod

然后在您的应用程序中,您可以通过添加

启用/禁用任何spring bean。
@Profile("put here profile name")

例如:

@RestController
@Profile("local")
@RequestMapping("/testApi")
public class RestForTesting{

//do some stuff

}

现在,仅当我运行使用

创建的版本时,我的RestForTesting才会创建

-Dspring.profiles.active=local