2016-01-11 15 views
24

मेरे पास JSON व्यू कॉन्फ़िगरेशन के लिए जैक्सन का उपयोग करके एक आरईएसटी एपीआई के साथ एक स्प्रिंग बूट ऐप है। यह बहुत अच्छा काम करता है और मैं सभी स्प्रिंग बूट भलाई प्राप्त कर सकता हूं।दो एमवीसी कॉन्फ़िगरेशन के साथ स्प्रिंग बूट

हालांकि, मैं एक अतिरिक्त REST API कि समान है, लेकिन विभिन्न सेटिंग्स के साथ है जोड़ने की जरूरत है। उदाहरण के लिए, अन्य चीजों के साथ, इसे एक अलग जैक्सन ऑब्जेक्ट मैपर कॉन्फ़िगरेशन की आवश्यकता होती है क्योंकि JSON काफी अलग दिखाई देगा (उदा। कोई JSON सरणी नहीं)। यह सिर्फ एक उदाहरण है लेकिन कुछ अंतर हैं। प्रत्येक एपीआई में एक अलग संदर्भ होता है (उदा।/एपीआई/वर्तमान और/एपीआई/विरासत)।

आदर्श रूप में मैं दो MVC इन विभिन्न संदर्भों को मैप किया कॉन्फ़िगरेशन चाहते हैं, और बूट में चीजों का स्वत: तारों के किसी भी देने के लिए नहीं।

अब तक सब मैं पास पर प्राप्त कर लिया है दो डिस्पैचर का उपयोग कर अपने MVC config के साथ प्रत्येक servlets है, लेकिन उस बूट में परिणाम चीजें मैं स्वचालित रूप से और मूल रूप से प्राप्त की एक पूरी गुच्छा छोड़ने बूट उपयोग करने का कारण धरा ।

मैं एक साथ कई एप्लिकेशन में एप्लिकेशन को तोड़ने नहीं कर सकते।

जवाब "आप बूट के साथ ऐसा नहीं कर सकते हैं और अभी भी अपने सभी जादू मिल" एक अस्वीकार्य जवाब है। ऐसा लगता है कि यह इसे संभालने में सक्षम होना चाहिए।

+0

http://stackoverflow.com/questions/29096511/using-multiple-dispatcher-servlets-web-contexts-with-spring-boot - क्या आपने कोशिश की? – Rozart

+1

यहां भी: http: // stackoverflow।कॉम/प्रश्न/21630820/कॉन्फ़िगर-एकाधिक-सर्वलेट कंटेनर-सर्लेट-साथ-वसंत-बूट – atamanroman

+0

स्पष्टीकरण के लिए: उन्हें एक ही मूल संदर्भ में रहने की आवश्यकता है? तो एक ही सेम साझा करना? – atamanroman

उत्तर

4

इसे प्राप्त करने के कई तरीके हैं। आपकी आवश्यकता के आधार पर, आईडी कहता है कि यह आरईएसटी एपीआई संस्करणों का प्रबंधन करने का मामला है। आरईएसटी एपीआई संस्करण के कई तरीके हैं, कुछ लोकप्रिय संस्करण यूआरएल हैं और टिप्पणियों के लिंक में उल्लिखित अन्य तकनीकों हैं।

V1 के लिए उदाहरण के लिए::

/path/v1/resource 

और V2:

/path/v2/resource 

ये हल होगा यूआरएल के आधार दृष्टिकोण अधिक पता एक से अधिक संस्करण होने की दिशा में प्रेरित है स्प्रिंग एमवीसी कंट्रोलर बीन में 2 अलग-अलग तरीकों से, जिन पर कॉल प्रतिनिधिमंडल प्राप्त होते हैं।

एपीआई के संस्करणों को हल करने के लिए अन्य विकल्प हेडर का उपयोग करने के लिए, इस तरह से केवल यूआरएल, कई तरीकों संस्करण पर आधारित नहीं है। उदाहरण के लिए:

/path/resource 

हैडर:

X-API-Version: 1.0 

हैडर:

X-API-Version: 2.0 

यह भी नियंत्रक पर दो अलग-अलग अभियानों में समाधान हो जाएगा।

अब इन रणनीतियों आधारित है जिस पर कई बाकी संस्करणों से संभाला जा सकता है।

ऊपर दृष्टिकोण निम्नलिखित में अच्छी तरह से समझाया गया है: git example

ध्यान दें: ऊपर एक वसंत बूट अनुप्रयोग है।

इन दोनों दृष्टिकोणों में समानता यह है कि जेएसओएन में निर्दिष्ट प्रकार के स्वचालित प्रकार के मार्शल उदाहरणों के लिए जैक्सन जेएसओएन लाइब्रेरी के आधार पर अलग-अलग POJOS होने की आवश्यकता होगी।

आईई। यह मानते हुए कि कोड @RestController [org.springframework.web.bind.annotation.RestController]

का उपयोग करता है अब अगर आपकी आवश्यकता, विभिन्न JSON मैपर अर्थात विभिन्न JSON नक्शाकार विन्यास है तो भले ही वसंत संदर्भों आप क्रमबद्धता/डी-क्रमबद्धता के लिए एक अलग रणनीति की आवश्यकता होगी की।

इस मामले में, आप कोई कस्टम डी-Serializer {CustomDeSerializer} कि JsonDeserializer<T>[com.fasterxml.jackson.databind.JsonDeserializer] का विस्तार होगा और deserialize() में अपने कस्टम startegy लागू लागू करने के लिए की आवश्यकता होगी।

लक्ष्य POJO पर @JsonDeserialize(using = CustomDeSerializer.class) एनोटेशन का उपयोग करें।

इस तरह एकाधिक जेएसओएन योजनाओं को विभिन्न डी-सीरियलाइज़र के साथ प्रबंधित किया जा सकता है।

आराम संस्करण + कस्टम सीरियलाइजेशन रणनीति का संयोजन करके, प्रत्येक एपीआई को एकाधिक प्रेषक सर्वलेट कॉन्फ़िगरेशन को तार किए बिना अपने स्वयं के संदर्भ में प्रबंधित किया जा सकता है।

+0

जेएसओएन प्रारूप से परे प्रत्येक एपीआई के लिए एमवीसी कॉन्फ़िगरेशन में मतभेदों के लिए थोड़ा और कुछ है, लेकिन मुझे लगता है कि यह जवाब मुझे आपके द्वारा दी गई जानकारी की मात्रा के लिए समझ में आता है और यह एकमात्र वास्तविक उत्तर है जिसे मैंने इस प्रश्न पर प्राप्त किया है और मैंने दूसरों से पूछा है। आपको बक्षीस मिलती है ;-) धन्यवाद, और मैं आपकी समस्या के अन्य पहलुओं के लिए आपके उत्तर की भावना का उपयोग करूंगा। – SingleShot

-3

वसंत-बूट ypu में विभिन्न प्रोफाइल (जैसे dev और test) का उपयोग कर सकते हैं।

-Dspring.profiles.active=dev या -Dspring.profiles.active=test और विभिन्न गुणों का उपयोग के साथ

प्रारंभ आवेदन अपने properties निर्देशिका के अंदर application-dev.properties या application-test.properties नामित फ़ाइलें। वह समस्या कर सकता है।

+1

आपके उत्तर के लिए धन्यवाद। दुर्भाग्य से इस मुद्दे के साथ इसका कोई लेना-देना नहीं है जिसे मैं हल करने की कोशिश कर रहा हूं। – SingleShot

3

कल की मेरी टिप्पणी और @ अशोक हैडर विचार का विस्तार करते हुए मैं कस्टम मीडिया प्रकारों के लिए 2 संदेश कनवर्टर्स (विरासत और वर्तमान) को पंजीकृत करने का प्रस्ताव दूंगा। आप ऐसा कर सकते हैं:

@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; 
} 

कन्वर्टर्स में से किसी एक के लिए कस्टम मीडिया-प्रकार पर ध्यान दें।

आप चाहें, तो आप संस्करण-हेडर तो जैसे एक कस्टम मीडिया प्रकार के @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"); 
      } 
     ..... 
    } 
} 

यह सटीक उत्तर आप देख रहे थे नहीं हो सकता है , लेकिन शायद यह कुछ प्रेरणा प्रदान कर सकते हैं। एक इंटरसेप्टर like so पंजीकृत है।

+0

यह मुझे कुछ विचार देता है। मैं वास्तव में ग्राहकों को हेडर और पसंद जोड़ने के लिए नहीं बदल सकता, हालांकि मैं बेस यूआरएल को रोक सकता हूं और देख सकता हूं और फिर शीर्षलेख जोड़ सकता हूं या खुद को जोड़ सकता हूं। विचार के लिए धन्यवाद। – SingleShot

2

यदि आप प्रत्येक संदर्भ के लिए एक अलग बंदरगाह के साथ रह सकते हैं, तो आपको केवल DispatcherServletAutoConfiguration बीन्स को ओवरराइट करना होगा। बाकी सभी जादू कार्य, मल्टीपार्ट, जैक्सन इत्यादि। आप प्रत्येक बच्चे-संदर्भ के लिए सर्वलेट और जैक्सन/मल्टीपार्ट इत्यादि को अलग-अलग कॉन्फ़िगर कर सकते हैं और मूल संदर्भ के बीन इंजेक्ट कर सकते हैं।

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 होने के बावजूद आपको बच्चे के संदर्भों के लिए अन्य सभी वसंत गुण सेट कर सकते हैं।

संबंधित मुद्दे