Spring Boot @RestController使用属性启用/禁用方法

12

我可以使用@ConditionalOnProperty来启用/禁用整个@RestController,例如:

@RestController
@ConditionalOnProperty(name = "com.example.api.controller.decision.DecisionController.enabled", havingValue = "true")
@RequestMapping("/v1.0/decisions")
public class DecisionController {
}
以下配置可正常工作。但我需要更细粒度地控制此控制器并启用/禁用其中某些方法的访问权限,例如:
@RestController
@ConditionalOnProperty(name = "com.example.api.controller.decision.DecisionController.enabled", havingValue = "true")
@RequestMapping("/v1.0/decisions")
public class DecisionController {

    @ConditionalOnProperty(name = "com.example.api.controller.decision.DecisionController.create.enabled", havingValue = "true")
    @PreAuthorize("isAuthenticated()")
    @RequestMapping(method = RequestMethod.POST)
    public DecisionResponse create(@Valid @RequestBody CreateDecisionRequest request, Authentication authentication) {
        ...
    }

}

如您所见,我已将@ ConditionalOnProperty 添加到 create 方法中,但此方法无效,并且如果启用了 DecisionController ,即使在我的 application.properties 中不存在 com.example.api.controller.decision.DecisionController.create.enabled 属性, create 方法也会被启用。

在这种情况下,如何正确启用/禁用 create 方法?


只是好奇:使用案例是什么?为什么要禁用某些方法? - JB Nizet
@JBNizet 我有一个核心项目(Maven模块),定义了核心端点和方法。此外,我还有特定于项目的Maven子模块,将上述核心模块作为依赖项包含在内。根据业务需求和子模块项目中的配置,我需要隐藏一些从核心项目继承的核心功能(某些方法)。现在我可以隐藏整个控制器,但我需要更精细的控制。 - alexanoid
2
最简单的方法可能是使用过滤器,拦截对特定URL / HTTP方法的请求,并在禁用时返回404。 - JB Nizet
1
这个回答解决了您的问题吗?Spring Boot @RestController可以使用属性进行启用/禁用吗? - Amit G
2个回答

8

您可以使用aop来阻止方法执行并向用户返回某些状态。在此处,我使用注释标记/识别已禁用的方法。如果您想根据属性中的某些值禁用,可以向该注释添加属性。例如,您可以添加相同的属性名称和havingvalue,并查找那些属性等等...

@Retention(RUNTIME)
@Target(METHOD)
public @interface DisableMe {}

方面:

@Aspect
@Component
public class DisableCertainAPI {

  @Autowired private HttpServletResponse httpServletResponse;

  @Pointcut(" @annotation(disableMe)")
  protected void disabledMethods(DisableMe disableMe) {
    // disabled methods pointcut
  }

  @Around("disabledMethods(disableMe)")
  public void dontRun(JoinPoint jp, DisableMe disableMe) throws IOException {
    httpServletResponse.sendError(HttpStatus.NOT_FOUND.value(), "Not found");
  }
}

并且准确的方法:

 @DisableMe
 @GetMapping(...)
 public ResponseEntity<String> doSomething(...){
  logger.info("recieved a request");
 }

您会看到如下响应:
{
  "timestamp": "2019-11-11T16:29:31.454+0000",
  "status": 404,
  "error": "Not Found",
  "message": "Not found",
  "path": "/xyz/...."
}

1
不幸的是,@ConditionalOnProperty注释不能用于单个@RequestMapping方法。作为解决方法,您可以将所需的映射移动到单独的控制器bean中。

http://dolszewski.com/spring/feature-toggle-spring-boot/

我希望这篇文章能够对那些有同样问题的人提供帮助。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接