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 }