programing

2개의 MVC 구성을 사용한 스프링부트

telebox 2023. 4. 2. 10:19
반응형

2개의 MVC 구성을 사용한 스프링부트

JSON 뷰 구성에 Jackson을 사용하는 REST API를 갖춘 Spring Boot 앱을 가지고 있습니다.효과가 좋고 스프링 부츠의 장점을 모두 얻을 수 있습니다.

하지만 비슷한 REST API를 추가해야 하는데 설정이 다릅니다.예를 들어, JSON은 매우 다르게 보이기 때문에(예: JSON 어레이가 없음) 다른 Jackson 객체 매퍼 구성이 필요합니다.그것은 하나의 예에 불과하지만 꽤 많은 차이점이 있다.API마다 컨텍스트가 다릅니다(예: /api/current 및 /api/legacy).

이러한 다른 콘텍스트에 2개의 MVC 설정을 매핑하는 것이 이상적입니다.부팅 시 자동 배선을 포기하지 않아도 됩니다.

지금까지 접근한 것은 각각 독자적인 MVC 구성에 2개의 디스패처 서블릿을 사용하는 것뿐입니다만, 그 결과 Boot에서는 자동적으로 많은 것이 폐기되어 Boot을 사용하는 이유가 없어졌습니다.

앱을 여러 앱으로 분할할 수 없습니다.

"부팅으로 이 작업을 수행할 수는 없지만 모든 매직은 얻을 수 있습니다."라는 답변은 받아들일 수 있는 답변입니다.그래도 이 일을 처리할 수 있을 것 같은데요.

이를 실현하는 방법은 여러 가지가 있습니다.Id는 고객의 요건에 따라 REST API 버전을 관리하는 경우라고 말합니다.REST API를 버전화하는 방법에는 여러 가지가 있습니다.그 중 인기 있는 것은 버전 URL이나 코멘트 링크에 기재되어 있는 기타 기술입니다.URL 베이스의 어프로치는, 복수의 버전의 주소를 가지는 것을 목표로 하고 있습니다.

를 들어 V1의 경우:

/path/v1/resource

V2:

/path/v2/resource

이것들은 Spring MVC Controller bean에서 콜이 위임되는2개의 다른 메서드로 해결됩니다.

API 버전을 해결하기 위한 다른 옵션은 헤더를 사용하는 것입니다.이 방법으로는 버전에 따라 URL만 있고 여러 개의 메서드가 있습니다.예를 들어 다음과 같습니다.

/path/resource

헤더:

X-API-Version: 1.0

헤더:

X-API-Version: 2.0

또, 컨트롤러로 2개의 다른 조작으로 해결됩니다.

다음은 여러 버전의 나머지 버전을 처리할 수 있는 전략입니다.

위의 접근방식은 다음 예에서 잘 설명되어 있습니다.gt example

메모: 위는 스프링 부트 어플리케이션입니다.

두 접근법의 공통점은 지정된 유형의 인스턴스를 자동으로 JSON으로 정렬하기 위해 잭슨 JSON 라이브러리를 기반으로 서로 다른 POJOS가 필요하다는 것입니다.

에 「」가 되고 있는 을 전제로 하고 있습니다.@RestController [org.springframework.web.bind.annotation.RestController]

다른 JSON 매퍼 구성(즉, 다른 JSON 매퍼 구성)을 필요로 하는 경우 Spring 컨텍스트에 관계없이 시리얼화/디시리얼라이제이션에 다른 전략이 필요합니다.

Custom {를 하기 위한 Custom DeSerializer {CustomDeSerializer}를.JsonDeserializer<T> [com.fasterxml.jackson.databind.JsonDeserializer] ,에는deserialize()이치노

하다를 사용하세요.@JsonDeserialize(using = CustomDeSerializer.class)'POJO'입니다.

이렇게 하면 여러 JSON 체계를 서로 다른 직렬 제거기로 관리할 수 있습니다.

Combining Rest Versioning + Custom Serialization Strategy에 의해 여러 디스패처 Servlet 설정을 배선할 필요 없이 각 API를 자체 컨텍스트에서 관리할 수 있습니다.

어제의 코멘트와 @Ashoka Header 아이디어에 대해 자세히 설명하자면, 커스텀 미디어 타입에 2대의 Message Converter(레거시 및 현재)를 등록할 것을 제안합니다.다음과 같이 할 수 있습니다.

@Bean
MappingJackson2HttpMessageConverter currentMappingJackson2HttpMessageConverter() {
    MappingJackson2HttpMessageConverter jsonConverter = new MappingJackson2HttpMessageConverter();
    ObjectMapper objectMapper = new ObjectMapper();
    // set features
    jsonConverter.setObjectMapper(objectMapper);

    jsonConverter.setSupportedMediaTypes(Arrays.asList(new MediaType("json", "v2")));

    return jsonConverter;
}


@Bean
MappingJackson2HttpMessageConverter legacyMappingJackson2HttpMessageConverter() {
    MappingJackson2HttpMessageConverter jsonConverter = new MappingJackson2HttpMessageConverter();
    ObjectMapper objectMapper = new ObjectMapper();
    // set features
    jsonConverter.setObjectMapper(objectMapper);
    return jsonConverter;
}

컨버터의 1개의 커스텀미디어 타입에 주의해 주세요.

필요에 따라 대행 수신기를 사용하여 다음과 같이 @Ashoka에서 제안하는 버전헤더를 커스텀미디어 타입으로 변경할 수 있습니다.

public class ApiVersionMediaTypeMappingInterceptor extends HandlerInterceptorAdapter {
    @Override
    public boolean preHandle(HttpServletRequest request,
                             HttpServletResponse response, Object handler) throws Exception {
        try {
            if(request.getHeader("X-API-Version") == "2") {
                request.setAttribute("Accept:","json/v2");
            }
       .....
    }
}

이것이 당신이 찾고 있던 정확한 답은 아닐 수도 있지만, 영감을 줄 수도 있습니다.요격기는 이렇게 등록되어 있습니다.

할 수 「포토하다」를.DispatcherServletAutoConfiguration 작품, 파트, 등 나나 、 、 、 、 、 등슨등등.각 자식 컨텍스트에 대해 Servlet 및 Jackson/Multipart 등을 개별적으로 설정하고 부모 컨텍스트의 빈을 주입할 수 있습니다.

package test;

import static org.springframework.boot.autoconfigure.web.DispatcherServletAutoConfiguration.DEFAULT_DISPATCHER_SERVLET_BEAN_NAME;
import static org.springframework.boot.autoconfigure.web.DispatcherServletAutoConfiguration.DEFAULT_DISPATCHER_SERVLET_REGISTRATION_BEAN_NAME;

import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.context.embedded.ServletRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;
import org.springframework.web.servlet.DispatcherServlet;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;

@Configuration
@EnableAutoConfiguration(exclude = {
        Application.Context1.class,
        Application.Context2.class
})
public class Application extends WebMvcConfigurerAdapter {

    @Bean
    public TestBean testBean() {
        return new TestBean();
    }

    public static void main(String[] args) {
        final SpringApplicationBuilder builder = new SpringApplicationBuilder().parent(Application.class);
        builder.child(Context1.class).run();
        builder.child(Context2.class).run();
    }

    public static class TestBean {
    }

    @Configuration
    @EnableAutoConfiguration(exclude = {Application.class, Context2.class})
    @PropertySource("classpath:context1.properties")
    public static class Context1 {

        @Bean(name = DEFAULT_DISPATCHER_SERVLET_BEAN_NAME)
        DispatcherServlet dispatcherServlet() {
            DispatcherServlet dispatcherServlet = new DispatcherServlet();
            // custom config here
            return dispatcherServlet;
        }

        @Bean(name = DEFAULT_DISPATCHER_SERVLET_REGISTRATION_BEAN_NAME)
        ServletRegistrationBean dispatcherServletRegistration() {
            ServletRegistrationBean registration = new ServletRegistrationBean(dispatcherServlet(), "/test1");
            registration.setName(DEFAULT_DISPATCHER_SERVLET_BEAN_NAME);
            // custom config here
            return registration;
        }

        @Bean
        Jackson2ObjectMapperBuilder jackson2ObjectMapperBuilder(TestBean testBean) {
            System.out.println(testBean);
            Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder();
            // custom config here
            return builder;
        }
    }

    @Configuration
    @EnableAutoConfiguration(exclude = {Application.class, Context1.class})
    @PropertySource("classpath:context2.properties")
    public static class Context2 {

        @Bean(name = DEFAULT_DISPATCHER_SERVLET_BEAN_NAME)
        DispatcherServlet dispatcherServlet() {
            DispatcherServlet dispatcherServlet = new DispatcherServlet();
            // custom config here
            return dispatcherServlet;
        }

        @Bean(name = DEFAULT_DISPATCHER_SERVLET_REGISTRATION_BEAN_NAME)
        ServletRegistrationBean dispatcherServletRegistration() {
            ServletRegistrationBean registration = new ServletRegistrationBean(dispatcherServlet(), "/test2");
            registration.setName(DEFAULT_DISPATCHER_SERVLET_BEAN_NAME);
            // custom config here
            return registration;
        }

        @Bean
        Jackson2ObjectMapperBuilder jackson2ObjectMapperBuilder(TestBean testBean) {
            System.out.println(testBean);
            Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder();
            // custom config here
            return builder;
        }
    }
}

context1/2.properties에는 현재 """만 되어 있습니다.server.port=8080/8081, 그 의 모든 거기에 있는 할 수 있습니다.

는 다른 할 수 (예: "ypu" 입니다).dev ★★★★★★★★★★★★★★★★★」test를 참조해 주세요.

「」로 을 합니다.-Dspring.profiles.active=dev ★★★★★★★★★★★★★★★★★」-Dspring.profiles.active=test 속성 합니다.application-dev.properties ★★★★★★★★★★★★★★★★★」application-test.properties면 insideproperties디렉토리로 이동합니다.★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★

언급URL : https://stackoverflow.com/questions/34728814/spring-boot-with-two-mvc-configurations

반응형