programing

속성을 사용하여 스프링부트 @RestController를 활성화/비활성화할 수 있습니까?

kakaobank 2023. 3. 28. 22:05
반응형

속성을 사용하여 스프링부트 @RestController를 활성화/비활성화할 수 있습니까?

'표준' 스프링 부트 어플리케이션과@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);
    }
}

특정 애플리케이션 속성이 존재하지 않는 경우 또는 존재하지 않는 경우 엔드포인트가 전혀 시작되지 않도록 하는 주석 또는 기술이 있습니까?

주의: 메서드 내의 속성을 테스트하고 폭발시키는 것은 엔드포인트가 존재하기 때문에 해결책이 아닙니다.

세세한 부분까지는 신경 쓰지 않습니다.즉, 메서드만 활성화/비활성화해도 상관없습니다.


프로파일은 속성이 아니기 때문에 프로파일을 통한 제어로는 문제가 해결되지 않습니다.

저는 다음 방법으로 간단한 해결책을 찾았습니다.@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"컴포넌트가 기동합니다.그렇지 않으면 기동하지 않습니다.

여기에 이 질문과 다른 질문을 추가합니다.

제 대답은 이렇습니다.

실제로 @RefreshScope 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

예를 들어 @ConditionalOnXX가 동작하지 않는 경우가 있습니다.예를 들어 상태를 체크하기 위해 다른 bean instance에 의존합니다.(XXXCondition 클래스는 bean을 호출할 수 없습니다.

이 경우 컨트롤러를 Java Configuration파일에 등록합니다.

소스 코드(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;
    }
}

이 질문은 환경마다 다른 application.properties 파일을 사용하고 있다는 사실에서 나온 것이라고 생각합니다.이 경우 스프링 프로파일과 설정을 프로파일 이름 서픽스를 붙여 다른 파일로 분리할 수 있습니다.다음은 예를 제시하겠습니다.

application.properties:

spring.profiles.active=@activatedProperties@

application-local.properties:

 //some config

application-module.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

}

이제 Rest For Testing은 다음 명령어를 사용하여 작성된 빌드를 실행하는 경우에만 생성됩니다.

-Dspring.profiles.active=local

언급URL : https://stackoverflow.com/questions/29958231/can-a-spring-boot-restcontroller-be-enabled-disabled-using-properties

반응형