Spring Boot @RestController включает / отключает методы с использованием свойств

Я могу включить / отключить весь @RestController с помощью @ConditionalOnProperty, например:

@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 метод create также включен, даже если свойство com.example.api.controller.decision.DecisionController.create.enabled отсутствует в моем application.properties.

Как правильно включить / выключить метод create в этом случае?

Просто любопытно: каков вариант использования? Почему вы хотите отключить некоторые методы?

JB Nizet 08.04.2018 09:17

@JBNizet У меня есть основной проект (модуль Maven), который определяет основные конечные точки и методы. Кроме того, у меня есть подмодуль Maven для конкретного проекта, который включает упомянутый основной модуль в качестве зависимости. Исходя из бизнес-потребностей и конфигурации моего проекта подмодуля, мне нужно скрыть некоторые основные функции (некоторые методы), унаследованные от основного проекта. Прямо сейчас я могу скрыть весь контроллер, но мне нужен более детализированный элемент управления.

alexanoid 08.04.2018 09:22

Самый простой способ - это, вероятно, использовать фильтр и перехватывать запросы к определенным URL-адресам / методам HTTP и возвращать 404, если они отключены.

JB Nizet 08.04.2018 09:25
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
8
4
4 334
2

Ответы 2

Unfortunately, the @ConditionalOnProperty annotation can’t be used on a single @RequestMapping method. As a workaround, you can move the desired mapping to a separate controller bean.

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

Надеюсь, это поможет человеку, который зашел на эту страницу с тем же вопросом.

Вы также можете использовать aop, чтобы не продолжать выполнение метода и не возвращать пользователю некоторый статус. Я использую здесь аннотацию, чтобы отмечать / идентифицировать отключенные методы. Вы можете добавить атрибуты к этой аннотации, если хотите отключить на основе определенных значений в атрибутах. Например, вы можете добавить одно и то же имя свойства и имеющее значение, искать их и так далее ...

@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/...."
}

Другие вопросы по теме