RestTemplate 操作详细笔记

it2024-10-04  34

RestTemplate介绍

spring3.0开始支持Http请求工具该工具与springboot或springcloud无关提供常见的REST请求模版 例如支持GET、PUT、POST、DELETE通用请求方法 --> exchange和execute实现RestOperations接口 该接口定义了常见的RESTful操作

1.GET操作

首先在provider中定义一个 hello2 接口:

@GetMapping("/hello2") public String hello2(String name){ return "hello "+name; }

接下来,我们在consumer去访问这个接囗,调用 RestTemplate中 的GET请求。 可以看到,在RestTemplate中,关于GET请求,一共有两大类方法:

这两大类方法实际上是重载的,唯一不同的,就是返回值类型。 getForObject返回的是一个对象,这个对象就是服务端返回的具体值。getForEntiey返回的是一个 ResponseEntity,这个ResponseEntity中除了服务端返回的具体数据外,还保留了Http应头的数据。

@GetMapping("/hello4") public void hello4(){ String s1 = restTemplate.getForObject("http://provider/hello2?name={1}",String.class,"javaone"); System.out.println(s1); ResponseEntity<String> responseEntity = restTemplate.getForEntity("http://provider/hello2", String.class, "javaone"); String body = responseEntity.getBody(); System.out.println("body:"+body); HttpStatus statusCode = responseEntity.getStatusCode(); System.out.println("HttpStatus:"+statusCode); int statusCodeValue = responseEntity.getStatusCodeValue(); System.out.println("statusCodeValue:"+statusCodeValue); HttpHeaders headers = responseEntity.getHeaders(); Set<String> keySet = headers.keySet(); System.out.println("---------headers--------"); for (String s : keySet) { System.out.println(s+":"+headers.get(s)+"///"); } }

 这里大家可以看到,getForObject直接拿到了服务的返回值,getForEntity不仅仅拿到服务的返回值, 还拿到http应的状态码。然后,后动 Eureka Server、provider以及consumer,访问consumer 中的 hello4 接囗,既可以看到请求结果。

看清楚两者的区别之舌,接下来看下两个各自的重载方法,getForObject 和 getForEntity 分别有三个重载方法,两者的三个重载方法基本都是一致的。所以,这里,我们主要看其中一种。三个重载方法, 其实代表了三种不同的传参方式。

@GetMapping("/hello5") public void hello5(){ String s1 = restTemplate.getForObject("http://provider/hello2?name={1}",String.class,"javatwo"); System.out.println("1:"+s1); HashMap<String, Object> map = new HashMap<>(); map.put("name","zhangsan"); s1 = restTemplate.getForObject("http://provider/hello2?name={name}", String.class,map); System.out.println("2:"+s1); try { String url = "http://provider/hello2?name="+ URLEncoder.encode("李四","UTF-8"); URI uri = URI.create(url); s1 = restTemplate.getForObject(uri, String.class); System.out.println("3:"+s1); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } }

小结:

getForObject和getForEntity返回值区别: getForObject返回一个对象(服务返回的具体值)getForEntity不仅返回具体数据 还可以返回状态码 头信息...getForObject和getForEntity 三种重载方式的类似 Object... --> 占位符 (?xxx={1}, xx.class, "xxxxx")Map<String, ?> --> 占位符为自定义key(name)需要提前声明map (?xxx={key}, xx.class, 返回的map)URI --> 字符串中包含中文的需要转码才能创建为URI 在被调用

 

2.POST操作

2.1准备工作

因为post请求可能是k/v或是json形式,需要提供2种接口,传参对象需要创建一个model, 为了以后方便使用直接新建一个普通的maven项目作为commons模块管理。

创建一个User类。

@Data @ToString public class User { private Integer id; private String name; private String nickName; }

然后provider和consumer分别引用commons模块依赖

<dependency> <groupId>com.example</groupId> <artifactId>commons</artifactId> <version>1.0-SNAPSHOT</version> </dependency>

2.2 provider提供2个接口

// key/value形式传递 @PostMapping("/user1") public User addUser1(User user){ return user; } //json传递 @PostMapping("/user2") public User addUser2(@RequestBody User user){ return user; }

接下来,我们在consumer中调这两个POST接囗。

这里的post和前面的get很像,只是多出来了三个方法,就是postForLocation,另外,两个postForObject和postForEntiy和前面get基不一致,所以这里我们主要来看postForObject, 看完之后,我们再来看这个额外的postForLocation。

@GetMapping("/hello6") public void hello6(){ MultiValueMap<String, Object> map = new LinkedMultiValueMap<>(); map.add("username","javajava"); map.add("password","123456"); map.add("id",666); User user = restTemplate.postForObject("http://provider/user1", map, User.class); System.out.println("1:"+user); user.setId(888); user = restTemplate.postForObject("http://provider/user2", user, User.class); System.out.println("2:"+user); }

post参数到底是k/v 形式还是json形式,主要看第二个参数,如果第二个参数是 MultiValueMap,则参数是以k/v形来传递的。 如果是一个普通对象,则参数是以的son形式 传递。

最后再看看一下postForLocation。有的时候,当执行完一个post请求之后,立马要进行重定向, 一个非常常见的场景就是注册,注册是一个post请求,注册完成之后,立马重定向到登录页面去登录。对于这种场景,我们就可以便用postForLocation。

首先我们在 provider上提供一个用户注册接囗:

@Controller public class RegisterController { @PostMapping("/register") public String register(User user){ return "redirect:http://provider/loginPage?username="+user.getUsername(); } @GetMapping("/loginPage") @ResponseBody public String loginPage(String username){ return "loginPage:"+username; } }

 注意:

这里的post接口,响应一定是302,否则 postForLocaton 无效。重定向的地址,一定要写成绝对路径,不要写成相对路径,否则在consumer 中调用时会出问题 @GetMapping("/hello7") public void hello7() { MultiValueMap<String, Object> map = new LinkedMultiValueMap<>(); map.add("username", "javajava"); map.add("password", "123456"); map.add("id", 666); //这就是postForLocation,调用该方法返回的是一个Uri,Uri就是重定向的地址(里面包含重定向的参数),拿到Uri之后,就可以直接发送新的请求了 URI uri = restTemplate.postForLocation("http://provider/register", map); String s = restTemplate.getForObject(uri, String.class); System.out.println(s); }

3.PUT 

 首先在provider提供一个put接口:

@PutMapping("/user11") public void updateUser1(User user1){ //k/v形式 System.out.println(user1); } @PutMapping("/user12") public void updateUser2(@RequestBody User user2){ //json形式 System.out.println(user2); }

在consumer中调用该接口,和上面post类似:

@GetMapping("/hello8") public void hello8() { MultiValueMap<String, Object> map = new LinkedMultiValueMap<>(); map.add("username", "javajava"); map.add("password", "123456"); map.add("id", 666); restTemplate.put("http://provider/user11",map); User user = new User(); user.setId(98); user.setUsername("zhangsan"); user.setPassword("123456"); restTemplate.put("http://provider/user12",user); }

4.DELETE 

 首先在provider提供一个delete接口:

@DeleteMapping("/user13") public void deleteUser1(Integer id){ System.out.println(id); } @DeleteMapping("/user14/{id}") public void deleteUser2(@PathVariable Integer id){ System.out.println(id); }

 在consumer中调用这两个删除接口(delete中参数的传递,也支持map,这块实际上和get是一样的):

@GetMapping("/hello9") public void hello9() { restTemplate.delete("http://provider/user13?id={1}",99); restTemplate.delete("http://provider/user14/{1}",99); }

 示例代码地址:https://github.com/astronger/springcloud-simple-samples

 

 

 

 

 

 

最新回复(0)