स्प्रिंग रेस्टेमप्लेट मापदंडों के साथ मिलता है


266

मुझे एक RESTकॉल करना है जिसमें कस्टम हेडर और क्वेरी पैरामीटर शामिल हैं। मैं HttpEntityसिर्फ हेडर (कोई शरीर नहीं) के साथ सेट करता हूं , और मैं इस RestTemplate.exchange()विधि का उपयोग करता हूं :

HttpHeaders headers = new HttpHeaders();
headers.set("Accept", "application/json");

Map<String, String> params = new HashMap<String, String>();
params.put("msisdn", msisdn);
params.put("email", email);
params.put("clientVersion", clientVersion);
params.put("clientType", clientType);
params.put("issuerName", issuerName);
params.put("applicationName", applicationName);

HttpEntity entity = new HttpEntity(headers);

HttpEntity<String> response = restTemplate.exchange(url, HttpMethod.GET, entity, String.class, params);

यह dispatcher servletएक हैंडलर के अनुरोध को हल करने में असमर्थ होने के साथ क्लाइंट के अंत में विफल रहता है । डिबग किए जाने पर, ऐसा लगता है कि अनुरोध पैरामीटर नहीं भेजे जा रहे हैं।

जब मैं POSTएक अनुरोध निकाय और कोई क्वेरी पैरामीटर का उपयोग करके एक्सचेंज करता हूं तो यह ठीक काम करता है।

क्या किसी के पास कोई विचार है?

जवाबों:


480

URL / पाथ / परम / आदि को आसानी से हेरफेर करने के लिए, आप स्प्रिंग के UriCompordsBuilder वर्ग का उपयोग कर सकते हैं । यह क्लीनर है जो मैन्युअल रूप से स्ट्रैटनिंग करता है और यह आपके लिए URL एन्कोडिंग का ध्यान रखता है:

HttpHeaders headers = new HttpHeaders();
headers.set("Accept", MediaType.APPLICATION_JSON_VALUE);

UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(url)
        .queryParam("msisdn", msisdn)
        .queryParam("email", email)
        .queryParam("clientVersion", clientVersion)
        .queryParam("clientType", clientType)
        .queryParam("issuerName", issuerName)
        .queryParam("applicationName", applicationName);

HttpEntity<?> entity = new HttpEntity<>(headers);

HttpEntity<String> response = restTemplate.exchange(
        builder.toUriString(), 
        HttpMethod.GET, 
        entity, 
        String.class);

10
महान टिप। बस के लिए बदल exchangeगया getForEntity: restTemplate.getForEntity(builder.build().encode().toUri(), String.class);सादगी के लिए।
फर्नांडो एम। पिनहेइरो

12
@ फर्नांडो.पिनहिरो: आप सही हैं, लेकिन यदि आप प्रतिक्रिया में एक सामान्य प्रकार की उम्मीद कर रहे हैं, तो आपको उपयोग करने exchangeऔर प्रदान करने की आवश्यकता है ParameterizedTypeReference। उदाहरण को और सरल बनाया जा सकता है, फिर भी इसे बदल builder.build().encode().toUri()दिया जाएगा builder.toUriString()
मिर्ज़मास्टर

@Christophe L क्या आप दिखा सकते हैं कि मैं सर्वर स्ट्रिंग में ये स्ट्रिंग पैरामीटर कैसे प्राप्त कर सकता हूं ??
KJEjava48

3
यूआरआई प्राप्त करने के लिए एक शॉर्टकट है: बस कॉल करेंbuilder.toUriString()
माइकल पीफेल

UriCompordsBuilder के लिए स्प्रिंग डॉक्स । गाइड UriCompordsBuilder के
चाको मैथ्यू

179

UriVariables को क्वेरी स्ट्रिंग में भी विस्तारित किया जाता है। उदाहरण के लिए, निम्नलिखित कॉल दोनों के लिए मूल्यों का विस्तार करेगा, खाता और नाम:

restTemplate.exchange("http://my-rest-url.org/rest/account/{account}?name={name}",
    HttpMethod.GET,
    httpEntity,
    clazz,
    "my-account",
    "my-name"
);

इसलिए वास्तविक अनुरोध url होगा

http://my-rest-url.org/rest/account/my-account?name=my-name

अधिक जानकारी के लिए HierarchicalUriCompords.expandInternal (UriTemplateVariables) देखें। वसंत का संस्करण 3.1.3 है।



2
और RestTemplate उदाहरण बनाते समय, आप यह निर्दिष्ट कर सकते हैं कि DefaultUriTemplateHandler (स्प्रिंग 5 से पहले) या DefaultUriBuilderFactory (स्प्रिंग 5+) को निर्दिष्ट करके उन क्वेरी पैरामीटर मानों का विस्तार कैसे किया जाएगा। यह उपयोगी है जब आप अतिरिक्त वर्ण जैसे (?,), आदि को सांकेतिक शब्दों में बदलना चाहते हैं
स्टीफन रूडोल्फ

मेरे URL में 10+ पैरामीटर हैं, हर चर को सूचीबद्ध करने के बजाय ऑब्जेक्ट / मैप के साथ समान प्राप्त करने का कोई तरीका? मैं UriComponentsBuilderया तो इसका उपयोग नहीं कर सकता क्योंकि यह प्रत्येक अनुरोध के लिए एक अलग मीट्रिक बनाने के लिए पैदा कर रहा हैMicrometer
डग

@ डग - RestTemplateमें या तो मानों की स्थिति सरणी ( Object... uriVariables) या नामित मानों का नक्शा ( ) निर्दिष्ट करने की समानांतर विधियां हैं Map<String, ?> uriVariables। नक्शा संस्करण की तरह ध्वनि आप क्या चाहते है: restTemplate.exchange(url, HttpMethod.GET, httpEntity, clazz, urlVariablesMap)
एम। जस्टिन

42

चूंकि UriComponentsBuilderURL बनाने के लिए उपयोग करने के बजाय कम से कम स्प्रिंग 3, (जो कि थोड़ा वर्बोज़ है), कई के RestTemplateतरीकों मापदंडों के लिए रास्ते में प्लेसहोल्डर (न सिर्फ स्वीकारexchange )।

प्रलेखन से:

कई RestTemplateविधियों में से एक के रूप में एक URI टेम्पलेट और URI टेम्पलेट चर को स्वीकार करता हैString varar के , या के रूप में Map<String,String>

Stringवरग के साथ उदाहरण के लिए :

restTemplate.getForObject(
   "http://example.com/hotels/{hotel}/rooms/{room}", String.class, "42", "21");

या एक के साथ Map<String, String>:

Map<String, String> vars = new HashMap<>();
vars.put("hotel", "42");
vars.put("room", "21");

restTemplate.getForObject("http://example.com/hotels/{hotel}/rooms/{room}", 
    String.class, vars);

संदर्भ: https://docs.spring.io/spring/docs/current/spring-framework-reference/integration.html#rest-resttemplate-uri

यदि आप JavaDoc को RestTemplate"URI टेम्प्लेट" के लिए देखते हैं और खोजते हैं, तो आप देख सकते हैं कि आप किन तरीकों से प्लेसहोल्डर का उपयोग कर सकते हैं।


35

ठीक है, इसलिए मैं एक बेवकूफ हूं और मैं url मापदंडों के साथ क्वेरी मापदंडों को भ्रमित कर रहा हूं। मैं थोड़े उम्मीद कर रहा था कि बदसूरत संगृहीत स्ट्रिंग के बजाय मेरे क्वेरी मापदंडों को आबाद करने का एक अच्छा तरीका होगा लेकिन हम हैं। यह केवल सही मापदंडों के साथ URL बनाने का मामला है। यदि आप इसे स्ट्रिंग स्प्रिंग के रूप में पास करते हैं तो यह आपके लिए एन्कोडिंग का भी ध्यान रखेगा।


क्या यह आपके काम आया ? मैंने UriCompordsBuilder का उपयोग करने के समान दृष्टिकोण का पालन किया, लेकिन लक्ष्य URL पर, जब मैं एक request.getAttribute () करता हूं, तो मैं अशक्त हो जाता हूं।
यतिरिगन

47
मुझे गंभीरता से समझ नहीं आ रहा है कि इस उत्तर में ग्रीन टिक क्यों है।
प्रदीप

7
क्योंकि वह ओपी है
कल्पेश सोनी

तो आपका समाधान क्या है? धन्यवाद!
रेमंड चेन

18

मैं कुछ इसी तरह का प्रयास कर रहा था, और रोबोस्पाइस उदाहरण ने मुझे इसे काम करने में मदद की :

HttpHeaders headers = new HttpHeaders();
headers.set("Accept", "application/json");

HttpEntity<String> request = new HttpEntity<>(input, createHeader());

String url = "http://awesomesite.org";
Uri.Builder uriBuilder = Uri.parse(url).buildUpon();
uriBuilder.appendQueryParameter(key, value);
uriBuilder.appendQueryParameter(key, value);
...

String url = uriBuilder.build().toString();

HttpEntity<String> response = restTemplate.exchange(url, HttpMethod.GET, request , String.class);

15
    String uri = http://my-rest-url.org/rest/account/{account};

    Map<String, String> uriParam = new HashMap<>();
    uriParam.put("account", "my_account");

    UriComponents builder = UriComponentsBuilder.fromHttpUrl(uri)
                .queryParam("pageSize","2")
                        .queryParam("page","0")
                        .queryParam("name","my_name").build();

    HttpEntity<String> requestEntity = new HttpEntity<>(null, getHeaders());

    ResponseEntity<String> strResponse = restTemplate.exchange(builder.toUriString(),HttpMethod.GET, requestEntity,
                        String.class,uriParam);

    //final URL: http://my-rest-url.org/rest/account/my_account?pageSize=2&page=0&name=my_name

RestTemplate: UriCompords (URI चर और अनुरोध पैरामीटर) का उपयोग करके गतिशील URI का निर्माण करें


6

क्वेरी मापदंडों के एक स्ट्रिंग के लिए एक हैश मैप का रूपांतरण:

Map<String, String> params = new HashMap<>();
params.put("msisdn", msisdn);
params.put("email", email);
params.put("clientVersion", clientVersion);
params.put("clientType", clientType);
params.put("issuerName", issuerName);
params.put("applicationName", applicationName);

UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(url);
for (Map.Entry<String, String> entry : params.entrySet()) {
    builder.queryParam(entry.getKey(), entry.getValue());
}

HttpHeaders headers = new HttpHeaders();
headers.set("Accept", "application/json");

HttpEntity<String> response = restTemplate.exchange(builder.toUriString(), HttpMethod.GET, new HttpEntity(headers), String.class);

3

मैं अलग दृष्टिकोण लेता हूं, आप सहमत हो सकते हैं या नहीं, लेकिन मैं संकलित जावा कोड के बजाय .properties फ़ाइल से नियंत्रित करना चाहता हूं

अनुप्रयोग के अंदर। फ़ाइल

endpoint.url = https: // yourHost / resource? requestParam1 = {0} और requestParam2 = {1}

जावा कोड यहाँ जाता है, अगर आप एंडपॉइंट URL में .properties फ़ाइल में @PathVariable ({{)) या @RestestParam (yourURL? Key = value) इत्यादि है, तो ... लिख सकते हैं या लिख ​​सकते हैं? इस तरह से इसके गतिशील और भविष्य में एक बंद दुकान में कोड परिवर्तन की आवश्यकता नहीं है ...

मैं यहां वास्तविक कोड से अधिक विचार देने की कोशिश कर रहा हूं ... #RequestParam, और @PathVariable आदि के लिए प्रत्येक के लिए सामान्य विधि लिखने का प्रयास करें ... फिर जरूरत के अनुसार कॉल करें

  @Value("${endpoint.url}")
  private String endpointURL;
  // you can use variable args feature in Java
  public String requestParamMethodNameHere(String value1, String value2) {
    RestTemplate restTemplate = new RestTemplate();
    restTemplate
           .getMessageConverters()
           .add(new MappingJackson2HttpMessageConverter());

    HttpHeaders headers = new HttpHeaders();
    headers.set("Accept", MediaType.APPLICATION_JSON_VALUE);
    HttpEntity<String> entity = new HttpEntity<>(headers);

    try {
      String formatted_URL = MessageFormat.format(endpointURL, value1, value2);
      ResponseEntity<String> response = restTemplate.exchange(
                    formatted_URL ,
                    HttpMethod.GET,
                    entity,
                    String.class);
     return response.getBody();
    } catch (Exception e) { e.printStackTrace(); }

3

स्प्रिंग वेब में 4.3.6 मैं भी देखता हूं

public <T> T getForObject(String url, Class<T> responseType, Object... uriVariables)

इसका मतलब है कि आपको बदसूरत नक्शा बनाने की ज़रूरत नहीं है

तो अगर आपके पास यह url है

http://my-url/action?param1={param1}&param2={param2}

आप या तो कर सकते हैं

restTemplate.getForObject(url, Response.class, param1, param2)

या

restTemplate.getForObject(url, Response.class, param [])

2
public static void main(String[] args) {
         HttpHeaders httpHeaders = new HttpHeaders();
         httpHeaders.set("Accept", MediaType.APPLICATION_JSON_VALUE);
         final String url = "https://host:port/contract/{code}";
         Map<String, String> params = new HashMap<String, String>();
         params.put("code", "123456");
         HttpEntity<?> httpEntity  = new HttpEntity<>(httpHeaders); 
         RestTemplate restTemplate  = new RestTemplate();
         restTemplate.exchange(url, HttpMethod.GET, httpEntity,String.class, params);
    }

2

यदि आप RestTemplate के लिए गैर-पैरामीट्रिक पार्म्स को पास करते हैं, तो आपके पास पैरामीटरों को देखते हुए, हर एक अलग URL के लिए एक मेट्रिक्स होगा। आप पैरामीरीज़्ड यूआरएल का उपयोग करना चाहेंगे:

http://my-url/action?param1={param1}&param2={param2}

के बजाय

http://my-url/action?param1=XXXX&param2=YYYY

दूसरा मामला है जो आपको UriCompordsBuilder वर्ग का उपयोग करके मिलता है।

पहला व्यवहार लागू करने का एक तरीका निम्नलिखित है:

Map<String, Object> params = new HashMap<>();
params.put("param1", "XXXX");
params.put("param2", "YYYY");

String url = "http://my-url/action?%s";

String parametrizedArgs = params.keySet().stream().map(k ->
    String.format("%s={%s}", k, k)
).collect(Collectors.joining("&"));

HttpHeaders headers = new HttpHeaders();
headers.set("Accept", MediaType.APPLICATION_JSON_VALUE);
HttpEntity<String> entity = new HttpEntity<>(headers);

restTemplate.exchange(String.format(url, parametrizedArgs), HttpMethod.GET, entity, String.class, params);

0

अगर आपका url है http://localhost:8080/context path?msisdn={msisdn}&email={email}

फिर

Map<String,Object> queryParams=new HashMap<>();
queryParams.put("msisdn",your value)
queryParams.put("email",your value)

आपके द्वारा वर्णित के रूप में resttemplate विनिमय विधि के लिए काम करता है

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.