RestTemplate介绍
调用远程服务时就必须使用HTTP客户端,主要有四种:JDK原生的URLConnection、Apache的Http Client、Netty的异步HTTP Client, Spring的RestTemplate。
解放了原先HttpClient的复杂提交,java中调用RESTful服务很典型的是使用HttpClient,对于常用的REST操作,这些方法属于低等级的操作。使用HttpClient我们需要自己封装Post请求,再根据响应的状态码判断从响应中获取header和body,有时候还需要自己做json转换。
Spring框架提供的RestTemplate类可用于在应用中调用rest服务,它简化了与http服务的通信方式,统一了RESTful的标准,封装了http链接, 我们只需要传入url及返回值类型即可。相较于之前常用的HttpClient,RestTemplate是一种更优雅的调用RESTful服务的方式。
在Spring应用程序中访问第三方REST服务与使用Spring RestTemplate类有关。RestTemplate类的设计原则与许多其他Spring *模板类(例如JdbcTemplate、JmsTemplate)相同,为执行复杂任务提供了一种具有默认行为的简化方法。
RestTemplate默认依赖JDK提供http连接的能力(HttpURLConnection),如果有需要的话也可以通过setRequestFactory方法替换为例如 Apache HttpComponents、Netty或OkHttp等其它HTTP library。
考虑到RestTemplate类是为调用REST服务而设计的,因此它的主要方法与REST的基础紧密相连就不足为奇了,后者是HTTP协议的方法:HEAD、GET、POST、PUT、DELETE和OPTIONS。例如,RestTemplate类具有headForHeaders()、getForObject()、postForObject()、put()和delete()等方法。
RestTemplate实现
RestTemplate包含以下几个部分:
- HttpMessageConverter 对象转换器
- ClientHttpRequestFactory 默认是JDK的HttpURLConnection
- ResponseErrorHandler 异常处理
- ClientHttpRequestInterceptor 请求拦截器
RestTemplate是spring的一个rest客户端,在spring-web这个包下,spring boot的依赖如下:
1 <dependency> 2 <groupId>org.springframework.boot</groupId> 3 <artifactId>spring-boot-starter-web</artifactId> 4 </dependency>
点进去可以看到spring-web
1 <dependency> 2 <groupId>org.springframework</groupId> 3 <artifactId>spring-web</artifactId> 4 <version>5.1.9.RELEASE</version> 5 </dependency>
所以如果在非spring的框架下直接引入spring-web这个包即可。
RestTemplate有三个实现
1 package org.springframework.web.client; 2 3 public class RestTemplate extends InterceptingHttpAccessor implements RestOperations { 4 5 ... 6 7 public RestTemplate() { 8 ... 9 } 10 11 public RestTemplate(ClientHttpRequestFactory requestFactory) { 12 ... 13 } 14 15 public RestTemplate(List<HttpMessageConverter<?>> messageConverters) { 16 ... 17 } 18 }
RestTemplate使用
新建一个SpringBoot Web工程,引入依赖spring-boot-starter-web
1 <dependency> 2 <groupId>org.springframework.boot</groupId> 3 <artifactId>spring-boot-starter-web</artifactId> 4 </dependency>
1、restTemplate获取字符串
REST API代码
1 @RequestMapping(value = "/employees", produces = MediaType.TEXT_HTML_VALUE, method = RequestMethod.GET) 2 public String getAllEmployeesHtml(Model model) 3 { 4 model.addAttribute("employees", employeeMapper.getEmps()); 5 return "employees"; 6 }
REST客户端代码
1 // 获取字符串 2 @Test 3 public void test01() { 4 String url = "http://localhost:8080/employees"; 5 String res1 = restTemplate.getForObject(url, String.class); 6 System.out.println("getForObject======" + res1); 7 }
2、使用RestTemplate的自定义HTTP标头
REST API代码
1 @RequestMapping(value = "/employees", produces = MediaType.APPLICATION_JSON_VALUE, method = RequestMethod.GET) 2 @ResponseBody 3 public List<Employee> getAllEmployeesJSON() 4 { 5 return employeeMapper.getEmps(); 6 }
REST客户端代码
// 使用RestTemplate的自定义HTTP标头 @Test public void test02(){ String url = "http://localhost:8080/employees"; HttpHeaders headers = new HttpHeaders(); headers.setAccept(Arrays.asList(MediaType.APPLICATION_JSON)); HttpEntity<String> entity = new HttpEntity<String>("parameters", headers); ResponseEntity<String> res2 = restTemplate.exchange(url, HttpMethod.GET, entity, String.class); System.out.println("exchange======" + res2); }
3、获取响应作为对象
REST API代码
1 @RequestMapping(value = "/employee/{id}", method = RequestMethod.GET) 2 @ResponseBody 3 public Employee get(@PathVariable("id") Integer id){ 4 return employeeMapper.getEmpById(id); 5 }
REST客户端代码
1 // 获取响应作为对象 2 @Test 3 public void test03(){ 4 String url = "http://localhost:8080/employee/1"; 5 6 Employee res3 = restTemplate.getForObject(url, Employee.class); 7 System.out.println("getForObject======" + res3); 8 } 9 10 // 获取响应作为对象,并获取响应对象状态 11 @Test 12 public void test033(){ 13 String url = "http://localhost:8080/employee/1"; 14 ResponseEntity<Employee> res3 = restTemplate.getForEntity(url, Employee.class); 15 System.out.println("getStatusCode======" + res3.getStatusCode()); 16 System.out.println("getForEntity======" + res3); 17 }
4、URL参数
REST API代码
1 @RequestMapping(value = "/employee/{id}", method = RequestMethod.GET) 2 @ResponseBody 3 public Employee get(@PathVariable("id") Integer id){ 4 return employeeMapper.getEmpById(id); 5 }
REST客户端代码
1 // URL参数 2 @Test 3 public void test04(){ 4 String url = "http://localhost:8080/employee/{id}"; 5 6 Map<String, String> params = new HashMap<String, String>(); 7 params.put("id", "1"); 8 Employee res4 = restTemplate.getForObject(url, Employee.class, params); 9 System.out.println("getForObject======" + res4); 10 }
5、HTTP POST方法
REST API代码
1 @RequestMapping(value = "/employee", method = RequestMethod.POST) 2 @ResponseBody 3 public String save(@RequestBody Employee employee){ 4 System.out.println("post ====" + employee); 5 return "success"; 6 }
REST客户端代码
1 // HTTP POST方法 2 @Test 3 public void test05(){ 4 String url = "http://localhost:8080/employee"; 5 6 Employee newEmployee = new Employee(-1, "小黑", "1", "test@email.com"); 7 String res5 = restTemplate.postForObject(url, newEmployee, String.class); 8 System.out.println("postForObject======" + res5); 9 }
6、HTTP PUT方法示例
REST API代码
1 @RequestMapping(value = "/employee", method = RequestMethod.PUT) 2 @ResponseBody 3 public String update(@RequestBody Employee employee){ 4 System.out.println("put ====" + employee); 5 return "success"; 6 }
REST客户端代码
1 // HTTP PUT方法示例 2 @Test 3 public void test06(){ 4 String url = "http://localhost:8080/employee"; 5 Employee newEmployee = new Employee(-1, "小黑", "1", "test@email.com"); 6 restTemplate.put(url, newEmployee); 7 }
7、HTTP DELETE方法示例
REST API代码
1 @RequestMapping(value = "/employee/{id}", method = RequestMethod.DELETE) 2 @ResponseBody 3 public String delete(@PathVariable("id") Integer id){ 4 System.out.println("delete ====" + id); 5 return "success"; 6 }
REST客户端代码
1 // HTTP DELETE方法示例 2 @Test 3 public void test07(){ 4 String url = "http://localhost:8080/employee/1"; 5 restTemplate.delete(url); 6 }