programing

모든 컨트롤러에 대해 기본 @RestController URI 접두사를 구성하는 방법은 무엇입니까?

css3 2023. 6. 19. 21:57

모든 컨트롤러에 대해 기본 @RestController URI 접두사를 구성하는 방법은 무엇입니까?

설할수를것을있(는)를 설정할 수 것을 알고 .server.contextPathapplication.properties루트 컨텍스트를 변경합니다.

또한 다음 예제(Groovy)와 같이 스프링 부트용 애플리케이션 구성에 추가 컨텍스트를 추가하여 루트 컨텍스트의 URL 매핑에 "/api"를 추가할 수 있습니다.

@Bean
ServletRegistrationBean dispatcherServlet() {
     ServletRegistrationBean reg = new ServletRegistrationBean(new DispatcherServlet(), "/")
        reg.name = "dispatcherServlet"
        reg.addInitParameter("contextConfigLocation", "")
        reg.addUrlMappings("/api/*")
        reg.loadOnStartup = 2
        reg
    }
}

보안 등을 위해 활용할 수 있는 웹 서비스 호출을 위한 별도의 기본 URI "/api"를 준비하려고 합니다.그러나 위의 접근 방식을 사용하면 웹 서비스 여부에 관계없이 "/" 또는 "/api"로 URI에 연결할 수 있으며 구체적인 구분은 제공되지 않습니다.

에게 할 수 더 있는 ?@RestController모든 컨트롤러에 /api/를 공식적으로 접두사로 붙일 필요 없이 구성을 사용할 수 있습니까?각 컨트롤러의 URI 앞에 수동으로 접두사를 붙여야 하는 경우 실수로 이를 생략하고 웹 서비스에 대한 보안 조치를 무시할 수 있습니다.

다음은 스택 오버플로에서 완전히 답변되지 않은 동일한 유형의 질문에 대한 참조입니다.

Spring Boot: RestController의 URL 접두사 구성

Github 문제는 현재 승인된 솔루션에 이어 동일한 문제를 해결합니다.

5에서는 Spring 5.1을 구현할 수 .WebMvcConfigurer 및오라드이버드를 재정의합니다.configurePathMatch와 같은 입니다.

@Configuration
@EnableWebMvc
public class WebConfig implements WebMvcConfigurer {

    @Override
    public void configurePathMatch(PathMatchConfigurer configurer) {
        configurer.addPathPrefix("/api",
                    HandlerTypePredicate.forAnnotation(RestController.class));
    }

}

이제모든것이▁the.@RestControllers을 가질 것입니다/api구성된 경로와 함께 접두사 경로로 사용됩니다.

공식 문서

Spring Boot 1.4.0 이후 이러한 문제를 해결할 수 있는 새로운 솔루션이 있습니다.RC1 (자세한 내용은 https://github.com/spring-projects/spring-boot/issues/5004) 참조)

Shahin ASkari 솔루션은 Auto 구성의 일부를 비활성화하므로 다른 문제가 발생할 수 있습니다.

다음 솔루션은 그의 아이디어를 받아들여 스프링 부트에 적절히 통합합니다.나의 경우 기본 경로 API가 있는 모든 RestController를 원했지만 루트 경로(예: Angular Webapp)와 함께 정적 콘텐츠를 제공합니다.

편집: 블로그 게시물에서 약간 개선된 버전으로 요약했습니다. https://mhdevelopment.wordpress.com/2016/10/03/spring-restcontroller-specific-basepath/ 을 참조하십시오.

@Configuration
public class WebConfig {

    @Bean
    public WebMvcRegistrationsAdapter webMvcRegistrationsHandlerMapping() {
        return new WebMvcRegistrationsAdapter() {
            @Override
            public RequestMappingHandlerMapping getRequestMappingHandlerMapping() {
                return new RequestMappingHandlerMapping() {
                    private final static String API_BASE_PATH = "api";

                    @Override
                    protected void registerHandlerMethod(Object handler, Method method, RequestMappingInfo mapping) {
                        Class<?> beanType = method.getDeclaringClass();
                        RestController restApiController = beanType.getAnnotation(RestController.class);
                        if (restApiController != null) {
                            PatternsRequestCondition apiPattern = new PatternsRequestCondition(API_BASE_PATH)
                                    .combine(mapping.getPatternsCondition());

                            mapping = new RequestMappingInfo(mapping.getName(), apiPattern,
                                    mapping.getMethodsCondition(), mapping.getParamsCondition(),
                                    mapping.getHeadersCondition(), mapping.getConsumesCondition(),
                                    mapping.getProducesCondition(), mapping.getCustomCondition());
                        }

                        super.registerHandlerMethod(handler, method, mapping);
                    }
                };
            }
        };
    }

}

또한 다음과 같이 WebMVC를 구성하여 동일한 결과를 얻을 수 있습니다.

@Configuration
public class PluginConfig implements WebMvcConfigurer {

public static final String PREFIX = "/myprefix";

@Override
public void configurePathMatch(PathMatchConfigurer configurer) {
    configurer.addPathPrefix(PREFIX, c -> c.isAnnotationPresent(MyCustomAnnotation.class));
}

}

  1. 시행하다WebMvcConfigurer아무렇게나@Configuration학급.
  2. 재정의configurePathMatch방법.
  3. 당신은 많은 유용한 것들을 할 수 있습니다.PathMatchConfigurer예를 들어, 술어 조건을 만족하는 여러 클래스의 접두사를 추가합니다.

문서화된 문제로 인해 Spring EL 옵션의 팬이 아니었으며 컨트롤러에서 접두사를 엄격하게 제어하기를 원했지만 개발자가 올바른 작업을 수행하는 것에 의존하고 싶지 않았습니다.

요즘은 더 좋은 방법이 있을지도 모르지만, 저는 이렇게 했습니다.부작용이 보이십니까, 저는 아직 부작용 검사 중입니다.

  1. 사용자 지정 주석을 정의합니다.
    이를 통해 개발자는 intapiVersion(), String resourceName()과 같은 입력된 특성을 명시적으로 제공할 수 있습니다.이러한 값은 나중에 접두사의 기본이 됩니다.
  2. 이 새 주석으로 주석이 달린 정지 컨트롤러
  3. 사용자 지정 요청 매핑 처리기 매핑 구현

RequestMappingHandlerMapping에서 사용자 지정 주석의 속성을 읽고 필요에 따라 최종 RequestMappingInfo를 수정할 수 있었습니다.다음은 몇 가지 코드 조각입니다.

@Configuration
public class MyWebMvcConfigurationSupport extends WebMvcConfigurationSupport {

    @Bean
    public RequestMappingHandlerMapping requestMappingHandlerMapping() {
        return new MyCustomRequestMappingHandlerMapping();
    }
}

그리고 MyCustomRequestMappingHandlerMapping에서 registerHandlerMethod를 덮어씁니다.

private class MyCustomRequestMappingHandlerMapping extends RequestMappingHandlerMapping {

    private Logger myLogger = LoggerFactory.getLogger(MyCustomRequestMappingHandlerMapping.class);

    public MyCustomRequestMappingHandlerMapping() {
        super();
    }

    @Override
    protected void registerHandlerMethod(Object handler, Method method, RequestMappingInfo mapping) {

        // find the class declaring this method
        Class<?> beanType = method.getDeclaringClass();

        // check for the My rest controller annotation
        MyRestController myRestAnnotation = beanType.getAnnotation(MyRestController.class);

        if (myRestAnnotation != null) {
            // this is a My annotated rest service, lets modify the URL mapping 

            PatternsRequestCondition oldPattern = mapping.getPatternsCondition();

            // create a pattern such as /api/v${apiVersion}/${resourceName}
            String urlPattern = String.format("/api/v%d/%s", 
                    myRestAnnotation.apiVersion(), 
                    myRestAnnotation.resourceName());

            // create a new condition
            PatternsRequestCondition apiPattern = 
                    new PatternsRequestCondition(urlPattern);

            // ask our condition to be the core, but import all settinsg from the old 
            // pattern
            PatternsRequestCondition updatedFinalPattern = apiPattern.combine(oldPattern);

            myLogger.info("re-writing mapping for {}, myRestAnnotation={}, original={}, final={}", 
                    beanType, myRestAnnotation, oldPattern, updatedFinalPattern);

            mapping = new RequestMappingInfo(
                    mapping.getName(),
                    updatedFinalPattern,
                    mapping.getMethodsCondition(),
                    mapping.getParamsCondition(),
                    mapping.getHeadersCondition(),
                    mapping.getConsumesCondition(),
                    mapping.getProducesCondition(),
                    mapping.getCustomCondition()
                    );
        }

        super.registerHandlerMethod(handler, method, mapping);
    }
}

주석 확인 논리를 중복하지 않고 매핑 경로만 변경하는 약간 덜 상세한 솔루션:

private static final String API_PREFIX = "api";

@Bean
WebMvcRegistrationsAdapter restPrefixAppender() {
    return new WebMvcRegistrationsAdapter() {
        @Override
        public RequestMappingHandlerMapping getRequestMappingHandlerMapping() {
            return new RequestMappingHandlerMapping() {
                @Override
                protected RequestMappingInfo getMappingForMethod(Method method, Class<?> handlerType) {
                    RequestMappingInfo mappingForMethod = super.getMappingForMethod(method, handlerType);
                    if (mappingForMethod != null) {
                        return RequestMappingInfo.paths(API_PREFIX).build().combine(mappingForMethod);
                    } else {
                        return null;
                    }
                }
            };
        }
    };
}

부작용

오류 컨트롤러도 /api/error 아래에 매핑되어 오류 처리가 중단됩니다(Dispatcher Servlet은 여전히 접두사 없이 /error!로 오류를 리디렉션합니다).

가능한 해결책은 위의 코드에 /api 접두사를 추가할 때 /error 경로를 건너뛰는 것입니다("if" 한 번 더).

누군가가 Spring MVC Jira에 문제를 제기했고 좋은 해결책을 생각해 냈는데, 지금 제가 사용하고 있습니다.이 방법은 각 RestController 파일에 있는 접두사에 Spring Expression Language를 사용하고 SpringBoot application.properties 파일에 있는 단일 속성을 참조하는 것입니다.

문제의 링크는 다음과 같습니다. https://jira.spring.io/browse/SPR-13882

언급URL : https://stackoverflow.com/questions/34801351/how-to-configure-a-default-restcontroller-uri-prefix-for-all-controllers