Java RestTemplate remote call to pass parameters

Java RestTemplate remote call to pass parameters

Recently, when using Spring's RestTemplate tool class to request an interface, I found a pit in parameter passing, that is, when we encapsulate the parameters in the Map, the type of Map is selected. There are three main ways to implement RestTemplate post requests

  1. Call the postForObject method
  2. Use postForEntity method
  3. Call the exchange method

The main difference between the postForObject and postForEntity methods is that
you can set the header properties in the postForEntity method. When you need to specify the header property values, use the postForEntity method.

The exchange method is similar to postForEntity, but more flexible. Exchange can also call get, put, and delete requests. Use these three methods to call the post request to pass parameters. Map cannot be defined as the following two types (except when url uses placeholders for parameter passing)
Map<String, Object> paramMap = new HashMap<String, Object>();
Map<String, Object> paramMap = new LinkedHashMap<String, Object>();

After testing, I found that the parameters in these two maps could not be received by the background. This problem troubled me for two days. Finally, when I changed the Map type to LinkedMultiValueMap, the parameters were successfully passed to the background.
MultiValueMap<String, Object> paramMap = new LinkedMultiValueMap<String, Object>();
Note: HashMap is passed in the request body, and MultiValueMap is passed in the form.

After testing, the correct POST parameter passing method is as follows

public static void main(String[] args) {
        RestTemplate template = new RestTemplate();
        String url = "http://192.168.2.40:8081/channel/channelHourData/getHourNewUserData";
        // 封装参数,千万不要替换为Map与HashMap,否则参数无法传递
        MultiValueMap<String, Object> paramMap = new LinkedMultiValueMap<String, Object>();
        paramMap.add("dt", "20180416");
 
        // 1、使用postForObject请求接口
        String result = template.postForObject(url, paramMap, String.class);
        System.out.println("result1==================" + result);
 
        // 2、使用postForEntity请求接口
        HttpHeaders headers = new HttpHeaders();
        HttpEntity<MultiValueMap<String, Object>> httpEntity = new HttpEntity<MultiValueMap<String, Object>>(paramMap,headers);
        ResponseEntity<String> response2 = template.postForEntity(url, httpEntity, String.class);
        System.out.println("result2====================" + response2.getBody());
 
        // 3、使用exchange请求接口
        ResponseEntity<String> response3 = template.exchange(url, HttpMethod.POST, httpEntity, String.class);
        System.out.println("result3====================" + response3.getBody());
}

Supplement: POST parameter object

@Autowired
private RestTemplate restTemplate;
private String url="http://localhost:8080/users";
 
public Integer save(User user){
    Map<String,String> map = restTemplate.postForObject(url, user, Map.class);
    if(map.get("result").equals("success")){
        //添加成功
        return 1;
    }
    return -1;
}
 
 //这是访问的controller方法  
@RequestMapping(value = "users",method = RequestMethod.POST)
public Map<String,String> save(@RequestBody User user){
    Integer save = userService.save(user);
    Map<String,String> map=new HashMap<>();
    if(save>0){
        map.put("result","success");
        return map;
    }
    map.put("result","error");
    return map;
}

ps: The post request can also be passed as a placeholder (similar to get), but it does not look elegant. It is recommended to use the method in the text.
GET method of parameter transfer description
If it is a get request and you want to encapsulate the parameters into the map for transmission, the Map needs to use HashMap, and the URL needs to use placeholders, as follows:

public static void main(String[] args) {
        RestTemplate restTemplate2 = new RestTemplate();
        String url = "http://127.0.0.1:8081/interact/getData?dt={dt}&ht={ht}";
   
        // 封装参数,这里是HashMap
    Map<String, Object> paramMap = new HashMap<String, Object>();
    paramMap.put("dt", "20181116");
    paramMap.put("ht", "10");
 
    //1、使用getForObject请求接口
    String result1 = template.getForObject(url, String.class, paramMap);
    System.out.println("result1====================" + result1);
 
    //2、使用exchange请求接口
    HttpHeaders headers = new HttpHeaders();
    headers.set("id", "lidy");
    HttpEntity<MultiValueMap<String, Object>> httpEntity = new HttpEntity<MultiValueMap<String, Object>>(null,headers);
    ResponseEntity<String> response2 = template.exchange(url, HttpMethod.GET, httpEntity, String.class,paramMap);
    System.out.println("result2====================" + response2.getBody());
}

The delete() and put() methods provided by RestTemplate have no return value, but the interface I want to call has a return value. A lot of information on the Internet is written by calling the exchange() method to achieve it, but basically it does not give A complete example was given, which caused me to have a problem that the parameters could not be passed when referring to their code. I have solved the problem at present, and now I will share my solution

I also use the exchange() method to achieve this, but the url is particular about it. It needs to use the placeholder to
delete the request instance like using the exchange method to call the get request . The request method uses HttpMethod.DELETE (resultful style uses placeholders)

/**
 * 删除用户
 * @param id
 * @return
 */
public String delete(Long id) {
    StringBuffer url = new StringBuffer(baseUrl)
            .append("/user/delete/{id}");
 
    Map<String, Object> paramMap = new HashMap<>();
    paramMap.put("id", id);
 
    ResponseEntity<String > response = restTemplate.exchange(url.toString(), HttpMethod.DELETE, null, String .class, paramMap);
    String result = response.getBody();
 
    return result;
}

Supplement: resultful style direct splicing url

//负责调用provider的方法,获取数据
@Autowired
private RestTemplate restTemplate;
//在provider端资源的路径
private String url="http://localhost:8080/details";   
 
public String deleteDetail(Integer id){
    ResponseEntity<String> response = restTemplate.exchange(url + "/" + id, HttpMethod.DELETE, null, String.class);
    String result = response.getBody();
    return result;
}
 
//被调用的controller方法
@ResponseBody
@RequestMapping(value = "details/{id}",method = RequestMethod.DELETE)
public String deleteDetail(@PathVariable Integer id){
    Integer integer = detailService.deleteDetail(id);
    if(integer>0){
        return "success";
    }
    return "error";
}

Placeholders can be used if the style is not resultful

private String url="http://localhost:8080/details?id={id}";
 
public String deleteDetail(Integer id){
         
        Map<String, Object> paramMap = new HashMap<>();
        paramMap.put("id", id);
        ResponseEntity<String > response = restTemplate.exchange(url.toString(), HttpMethod.DELETE, null, String .class, paramMap);
        String result = response.getBody();
        return result;
    }

Put request instance, the request method uses HttpMethod.PUT

/**
 * 更新用户基础信息
 * @param userInfoDTO
 * @return
 */
public String edit(UserInfoDTO userInfoDTO) {
    StringBuffer url = new StringBuffer(baseUrl)
            .append("/user/edit?tmp=1")
            .append("&id={id}")
            .append("&userName={userName}")
            .append("&nickName={nickName}")
            .append("&realName={realName}")
            .append("&sex={sex}")
            .append("&birthday={birthday}");
 
    Map<String, Object> paramMap = new HashMap<>();
    paramMap.put("userId", userInfoDTO.getId());
    paramMap.put("userName", userInfoDTO.getUserName());
    paramMap.put("nickName", userInfoDTO.getNickName());
    paramMap.put("realName", userInfoDTO.getRealName());
    paramMap.put("sex", userInfoDTO.getSex());
    paramMap.put("birthday", userInfoDTO.getBirthday());
 
    ResponseEntity<String > response = restTemplate.exchange(url.toString(), HttpMethod.PUT, null, String .class, paramMap);
    String result = response.getBody();
    return result;
 
}

Add the exchange() parameter object again:
    reference: https://www.cnblogs.com/jnba/p/10522608.html

//测试post的controller
@RequestMapping(value = "detailsPost",method = RequestMethod.POST)
public String test02(@RequestBody Detail detail){
    System.out.println("POST-"+detail);
    return "error";
}
//测试put的controller
@RequestMapping(value = "detailsPut",method = RequestMethod.PUT)
public String test03(@RequestBody Detail detail){
    System.out.println("PUT-"+detail);
    return "error";
}
//测试delete的controller
@RequestMapping(value = "detailsDelete",method = RequestMethod.DELETE)
public String test04(@RequestBody Detail detail){
    System.out.println("DELETE-"+detail);
    return "error";
}
 
 
//测试方法
public String test(){
    //put传递对象
    //String json = "{\"author\":\"zsw\",\"createdate\":1582010438846,\"id\":1,\"summary\":\"牡丹\",\"title\":\"菏泽\"}";
    //HttpHeaders headers = new HttpHeaders();
    //headers.setContentType(MediaType.APPLICATION_JSON);
    //HttpEntity<String> entity = new HttpEntity<>(json,headers);
    //ResponseEntity<String> resp = restTemplate.exchange("http://localhost:8080/detailsPut", HttpMethod.PUT, entity, String.class);
 
    //delete传递对象
    Detail detail=new Detail();
    detail.setId(1L);
    detail.setSummary("牡丹");
    detail.setTitle("菏泽");
    detail.setAuthor("zsw");
    detail.setCreatedate(new Timestamp(new Date().getTime()));
    HttpHeaders headers = new HttpHeaders();
    headers.setContentType(MediaType.APPLICATION_JSON);
    HttpEntity<Detail> entity = new HttpEntity<>(detail,headers);
    ResponseEntity<String> resp = restTemplate.exchange("http://localhost:8080/detailsDelete", HttpMethod.DELETE, entity, String.class);
 
    String result = resp.getBody();
    System.out.println(result);
    return result;
}

The delete request is the same as above, but get fails, and an error 400 is reported directly. It seems that get does not support this kind of parameter transfer. https://blog.belonk.com/c/http_resttemplate_get_with_body.htm The situation is the same as this big brother, but I didn't understand his solution, so if there are any big brothers, I would like to give some advice to my brother, I would be very grateful.

Exchange() can use placeholders to pass a single parameter:

 //post传递单参
//        ResponseEntity<String> resp = restTemplate.exchange("http://localhost:8080/detailsPostD?id={id}&name={name}", HttpMethod.POST, null, String.class,1,"zsw");
        //put传递单参
        Map<String,Object> map=new HashMap<>();
        map.put("id",1);
        map.put("name","zsw");
        ResponseEntity<String> resp = restTemplate.exchange("http://localhost:8080/detailsPutD?id={id}&name={name}", HttpMethod.PUT, null, String.class,map);

Common for get, post, put, and delete requests.

You can refer to the example on the spring official website, which is clear, direct and intuitive https://docs.spring.io/spring/docs/5.1.6.RELEASE/spring-framework-reference/integration.html#rest-template-multipart

Guess you like

Origin blog.csdn.net/Guesshat/article/details/109549440