RestTemplate 是从 Spring3.0 开始支持的一个 http 请求工具,这个请求工具是 Spring 自带的,与 Spring Boot 和 Spring Cloud 都无关。
RestTemplate 提供了常见的 REST 请求方法模板,如 GET、POST、PUT、DELETE 请求以及一些通用的请求执行方法 exchange 和 execute 方法。
RestTemplate 本身实现了 RestOperations 接口,而在 RestOperations 接口中,定义了常见 RESTful 操作,这些操作在 RestTemplate 中都得到了很好的实现。
GET
首先,在 provider 中定义一个 hello2 接口:
@GetMapping("/hello2")
public String hello2(String name){
return "hello" +name;
}
接下来,在 consumer 中去访问这个接口,也就是调用 RestTemplate 中的 GET 请求。
可以看到,在 RestTemplate 中,关于 GET 请求,一共有两大类方法:
这两大类方法实际是重载的,唯一不同的,就是返回值类型。
-
getForObject 返回的是一个对象,这个对象就是服务端返回的具体值。
-
getForEntity 返回的是一个 ResponseEntity,这个 ResponseEntity 中除了服务端返回的具体数据外,还保留了 http 响应头的数据。
@GetMapping("/hello4")
public void hello4(){
String s1 = restTemplate.getForObject("http://provider/hello?name={1}", String.class, "youlinwei");
System.out.println(s1);
ResponseEntity<String> responseEntity = restTemplate.getForEntity("http://provider/hello", String.class, "youlinwei");
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("----------- header ----------");
for (String s: keySet){
System.out.println(s + ":" + headers.get(s));
}
}
POST
首先在 provider 中提供两个 POST 接口,同时,因为 POST 请求可能需要传递 JSON ,所以,这里我们创建一个普通的 Maven 项目作为 commons 模块,然后这个 commons 模块被 provider 和 consumer 共同引用,这样我们就可以方便的传递 JSON 了。
commons 模块创建成功后,首先在 commons 模块中添加 User 对象,然后该模块分别被 provider 和 consumer 引用,即在 provider/pom.xml 和 consumer/pom.xml 中添加如下依赖:
<dependency>
<groupId>com.example</groupId>
<artifactId>commons</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
然后,我们在 provider 中提供两个 POST 接口:
// 以 key-value 形式传参
@PostMapping("/user1")
public User addUser1(User user){
return user;
}
// 以 json 形式传参
@PostMapping("/user2")
public User addUser2(@RequestBody User user){
return user;
}
这里定义了两个 User 添加的方法,两个方法代表了两种不同的传参方式。第一种方法是以 key-value 形式传参,第二种是以 json 形式传参。
定义完成后,接下来,我们在 commons 中调用这两个 POST 接口。
如上图,RestTemplate 的 POST 方法和前面的 GET 方法很像。只是多出来一个 postForLocation 方法。
这里,我们先使用 postForObject ,然后再看看 postForLocation。
@GetMapping("/hello6")
public void hello6(){
LinkedMultiValueMap<Object, Object> map = new LinkedMultiValueMap<>();
map.add("username","you");
map.add("password","123");
map.add("id",11);
// 以 key-value 形式传参
User user = restTemplate.postForObject("http://provider/user1", map, User.class);
System.out.println(user);
// 以 json 形式传参
user.setId(12);
user = restTemplate.postForObject("http://provider/user2", user, User.class);
System.out.println(user);
}
如果 postForObject 方法的第二个参数 MultiValueMap ,则参数是以 key-value 形式传递;如第二个参数是普通对象,则参数是以 json 形式来传递的。
最后再看看 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 ,否则 postForLocation 无效。
注意,重定向的地址,一定要写出绝对路径。
@GetMapping("/hello7")
public void hello7(){
LinkedMultiValueMap<Object, Object> map = new LinkedMultiValueMap<>();
map.add("username","you");
map.add("password","123");
map.add("id",11);
URI uri = restTemplate.postForLocation("http://provider/register", map);
String s = restTemplate.getForObject(uri, String.class);
System.out.println(s);
}
调用 postForLocation 方法,返回的是 uri ,这个 uri 就是重定向的地址,拿到 uri 之后,就可以直接发送新的请求了。
每天学习一点点,每天进步一点点。