RestTemplate详解
一:get
之前实验中我们已经使用过RestTemplate去实现服务访问了,我们现在可以仔细研究下这个对象针对几种不同请求类型和参数类型的服务调用实现
依旧是我们刚才的实验,参与者有 Eureka Server(服务注册中心),product(服务调用者)、user(服务提供者)
启动服务如上
现在product中调用服务提供者的代码如下:
访问结果:
这里我们调用的方法是:
User user=restTemplate.getForObject("http://USER/user/"+String.valueOf(id),User.class);
关于restTemplate提供的主要方法,get方式的请求主要包含以下的两种,其一就是我们使用的getForObject,还有一种为getForEntity
首先我们来看getForEntity,官方重载函数有以下:
public <T> ResponseEntity<T> getForEntity(String url, Class<T> responseType, Object... uriVariables){}
public <T> ResponseEntity<T> getForEntity(String url, Class<T> responseType, Map<String, ?> uriVariables){}
public <T> ResponseEntity<T> getForEntity(URI url, Class<T> responseType){}
参数说明:
1:请求的URL地址
2: Class responseType 规定封装为某种需要的对象类型
3:Object… uriVariables 参数列表-可以多个也可以封装成一个map信息传递
该方法的返回值都为ResponseEntity,其中主要存储了http的几个重要元素,例如请求状态码的枚举类型Httpstatus、其父类HttpEntity中还存储着头信息等重要属性
方法调用如下:
public User getUserById(@PathVariable("id") long id){
//User user=restTemplate.getForObject("http://USER/user/"+String.valueOf(id),User.class);
ResponseEntity<User> responseEntity= restTemplate.getForEntity("http://USER/user/{id}"+String.valueOf(id),User.class,id);
System.out.println("---------------------------------------------------");
System.out.println(responseEntity);
System.out.println("---------------------------------------------------");
User user=responseEntity.getBody();
return user;
}
现在去访问:
我们发现依旧是正常访问,但是我们来看后台打印结果值
<200,com.bigsoft.bigsoftproduct.pojo.User@358c78bd,[Content-Type:"application/json", Transfer-Encoding:"chunked", Date:"Thu, 07 May 2020 06:04:39 GMT", Keep-Alive:"timeout=60", Connection:"keep-alive"]>
我们发现这里打印信息比较全面(和浏览器控制台打印的差不多)
反过头再看我们的另外个主要的方法getForObject 官方定义如下:
public <T> T getForObject(String url, Class<T> responseType, Object... uriVariables){}
public <T> T getForObject(String url, Class<T> responseType, Map<String, ?> uriVariables)
public <T> T getForObject(URI url, Class<T> responseType)
其实我们发现和上边方法重载一样的,都是地址+type+参数的形式
我们修改我们的代码如下:
@Autowired
private RestTemplate restTemplate;
@GetMapping("product/user/{id}")
public User getUserById(@PathVariable("id") long id){
User user=restTemplate.getForObject("http://USER/user/{id}"+String.valueOf(id),User.class,id);
return user;
}
访问服务:
我们发现也能正常访问
其实以上的两个方法区别就在于,一个直接帮你绑定成你需要的对象,另外一个返回了更多的访问信息
二:post
关于post请求RestTemplate也提供了全面的方法供我们调用
1:postForEntity
这个方法不管名字和用法其实和get中的getForEntity也非常相似,主要重载如下:
public <T> ResponseEntity<T> postForEntity(String url, @Nullable Object request, Class<T> responseType, Object... uriVariables)
public <T> ResponseEntity<T> postForEntity(String url, @Nullable Object request, Class<T> responseType, Map<String, ?> uriVariables) throws RestClientException
public <T> ResponseEntity<T> postForEntity(URI url, @Nullable Object request, Class<T> responseType) throws RestClientException
我们看到参数也非常相似,主要使用的前两种也是url+type+参数的组合拳,下边我们的做一个具体的测试,首先在user服务提供节点新增addUser方法
这里为了测试返回了一段文字,现实中千万不要这么做
代码如下:
@PostMapping("/addUser")
public String addUser(@RequestBody User user){
System.out.println(user);
return "add--------"+user+"-----------success";
}
然后在product节点中通过去调用该方法,具体调用如下:
@PostMapping("product/addUser")
public String addUser(){
User user=new User();
user.setUserId(10086L);
user.setUserName("user1");
user.setUserPwd("admin");
ResponseEntity<String> resp=restTemplate.postForEntity("http://USER/addUser",user,String.class);
System.out.println(resp);
return "add--------"+user+"-----------success";
}
这里restTemplate.postForEntity("http://USER/addUser",user,String.class);
三个参数分别代表了路径、参数类型、期待返回类型
我们使用postman 测试,测试结果如下:
我们再来看看后台打印的ResponseEntity
<200,add--------User{userId=10086, userName=‘user1’, userPwd=‘admin’}-----------success,[Content-Type:“text/plain;charset=UTF-8”, Content-Length:“82”, Date:“Wed, 13 May 2020 06:17:58 GMT”, Keep-Alive:“timeout=60”, Connection:“keep-alive”]>
这样就完成了我们的post请求调用,我们这里修改一句上边的代码:
System.out.println(resp.getBody());
这次我们直接获取它的body信息,我们可以看到如下,这次的打印结果如下
add--------User{userId=10086, userName=‘user1’, userPwd=‘admin’}-----------success
这里其实body中的类容就是我们在这调用的时候规定了返回值为string类型,所以body中指存在了user节点返回的值
和get相似的是post除了有postForEntity方法也存在postForObject方法,一样的是,postForEntity返回的是整个response 信息,而postForObject 只是返回我们泛型中规定的信息
通过这两个方法我们就能使用ribbon去调用微服务各个节点了