In the design of REST interface, using RestTemplate for interface testing is a common method, but during use, due to the numerous methods and parameters, many students have confused the differences between form submission and Payload submission methods. Moreover, the interface design is different from the submission methods used by traditional browsers. Various errors often occur, such as 405 errors, or the submitted data cannot be obtained at all. The error samples are as follows:
Exception in thread "main" org.springframework.web.client.HttpClientErrorException: 405 Method Not Allowed
at org.springframework.web.client.DefaultResponseErrorHandler.handleError(DefaultResponseErrorHandler.java:63)
at org.springframework.web.client.RestTemplate.handleResponse(RestTemplate.java:700)
at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:653)
at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:613)
at org.springframework.web.client.RestTemplate.exchange(RestTemplate.java:531)
1. Submit using the exchange method
Exchange can execute both POST methods and GETs, so it is the most widely used and the usage is as follows:
String url = "http://localhost/mirana-ee/app/login";RestTemplate client = new RestTemplate();HttpHeaders headers = new HttpHeaders();// Please do not change this submission method easily. In most cases, the submission method is form submission headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);// Encapsulate parameters, do not replace them with Map and HashMap, otherwise the parameters cannot be passed MultiValueMap<String, String> params= new LinkedMultiValueMap<String, String>();// also supports Chinese params.add("username", "username");params.add("password", "123456");HttpEntity<MultiValueMap<String, String>> requestEntity = new HttpEntity<MultiValueMap<String, String>>(params, headers);// Execute HTTP request ResponseEntity<String> response = client.exchange(url, HttpMethod.POST, requestEntity, String.class);// Output result System.out.println(response.getBody());2. Submit with postForEntity
postForEntity is a simplification of exchange, and only requires the reduction of the HttpMethod.POST parameter, as follows:
// The above code is exactly the same // You only need to replace the exchange method ResponseEntity<String> response = client.postForEntity(url, requestEntity, String.class);
3. About the difference between form submission and Payload submission
In the Controller method parameters, if you change "@ModelAttribute" to "@RequestBody" annotation, the submission method at this time is Payload method. The code example is as follows:
// Please note that @RequestBody annotation @RequestMapping(value="/login", method=RequestMethod.POST, consumptions="application/json")// Never add @ModelAttribute, otherwise it will be overwritten, as follows // public Account getAccount(@RequestBody@ModelAttribute Account account)public Account getAccount(@RequestBody Account account) { account.setVersion(new Date()); return account;}Once again, don’t add “@ModelAttribute” again, because its priority is relatively high, the system will use form to parse the submitted content.
For Payload method, the submitted content must be String, and the header must be set to "application/json". The example is as follows:
// Request address String url = "http://localhost/mirana-ee/app/login";RestTemplate client = new RestTemplate();// Be sure to set headerHttpHeaders headers = new HttpHeaders();headers.setContentType(MediaType.APPLICATION_JSON_UTF8);// Convert the submitted data to String// It is best to get ObjectMapperObjectMapper mapper through bean injection = new ObjectMapper();Map<String, String> params= Maps.newHashMap();params.put("username", "Inter");params.put("password", "123456");String value = mapper.writeValueAsString(params);HttpEntity<String> requestEntity = new HttpEntity<String>(value, headers);// Execute HTTP request ResponseEntity<String> response = client.postForEntity(url, requestEntity, String.class);System.out.println(response.getBody());If the content is not submitted in String mode, the following error will definitely appear:
Exception in thread "main" org.springframework.web.client.HttpClientErrorException: 400 Bad Request
at org.springframework.web.client.DefaultResponseErrorHandler.handleError(DefaultResponseErrorHandler.java:63)
at org.springframework.web.client.RestTemplate.handleResponse(RestTemplate.java:700)
at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:653)
at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:613)
at org.springframework.web.client.RestTemplate.postForEntity(RestTemplate.java:407)
Finally, it should be emphasized that the request parameters cannot be obtained through @RequestBody. If the code on the above server is changed to the following format, you will definitely not get the data, but the opposite is true for form submission.
@RequestMapping(value="/login", consumers="application/json", method=RequestMethod.POST)public Account getAccount(@RequestBody Account account, HttpServletRequest request) { // You must not get the parameter value System.out.println(request.getParameter("username")); account.setVersion(new Date()); return account;}4. Structure of HttpEntity
HttpEntity is an encapsulation of HTTP requests, which contains two parts, header and body. The header is used to set the request header, and the body is used to set the request body, so its constructor is as follows:
// value is the request body// header is the request header HttpEntity<String> requestEntity = new HttpEntity<String>(value, headers);
5. HttpEntity and uriVariables
In the use of RestTemplate, HttpEntity is used to pass specific parameter values, while uriVariables is used to format the Http address instead of the address parameters. The correct usage is as follows:
// Add formatting parameters pathString url = "http://localhost/mirana-ee/app/{path}";// Prepare formatting parameters Map<String, String> varParams = Maps.newHashMap();varParams.put("path", "login");// Other codes are omitted // Format the submission address ResponseEntity<String> response = client.postForEntity(url, requestEntity , String.class, varParams);6. Notes on HttpMessageConverter
In many examples online, I found that many people have added custom HttpMessageConverter to handle Payload submissions, as follows:
// There is no need to client.getMessageConverters().add(new MappingJackson2HttpMessageConverter()); client.getMessageConverters().add(new StringHttpMessageConverter());
Then, after I checked the source code and debugged, I found that RestTemplate has built-in 7 types of HttpMessageConverters, as follows:
1. org.springframework.http.converter.ByteArrayHttpMessageConverter
2. org.springframework.http.converter.StringHttpMessageConverter
3. org.springframework.http.converter.ResourceHttpMessageConverter
4. org.springframework.http.converter.xml.SourceHttpMessageConverter
5. org.springframework.http.converter.support.AllEncompassingFormHttpMessageConverter
6. org.springframework.http.converter.xml.Jaxb2RootElementHttpMessageConverter
7. org.springframework.http.converter.json.MappingJackson2HttpMessageConverter
“`
in conclusion
RestTemplate can greatly simplify the difficulty of submitting form data and comes with the function of automatically converting JSON data. However, only by understanding the composition structure of HttpEntity (header and body) and understanding the differences with uriVariables, can we truly understand its usage.
The above is all the content of this article. I hope it will be helpful to everyone's learning and I hope everyone will support Wulin.com more.