【本人秃顶程序员】技巧分享丨spring的RestTemplate的妙用,你知道吗?
←←←←←←←←←←←← 快!點關注
為什么要使用RestTemplate?
隨著微服務的廣泛使用,在實際的開發中,客戶端代碼中調用RESTful接口也越來越常見。在系統的遺留代碼中,你可能會看見有一些代碼是使用HttpURLConnection來調用RESTful接口的,類似于下面這樣:
URL url = ... // 打開連接 HttpURLConnection conn = (HttpURLConnection) url.openConnection(); try {conn.setRequestMethod("POST");conn.setDoInput(true);conn.setDoOutput(true);conn.connect();// 發送數據...BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(conn.getOutputStream(), "utf-8"));bw.write(str);// 接收數據 ...BufferedReader br = new BufferedReader(new InputStreamReader(conn.getInputStream(), "utf-8"));String line = null;while ((line = br.readLine()) != null) {...} } finally {conn.disconnect(); } 復制代碼從上面的代碼可以看出,使用HttpURLConnection調用RESTful接口是比較麻煩的,假如要調用30個接口,每個接口都使用類似于上面的代碼 進行調用,那簡直是一場災難(寫這么多無聊的樣板代碼,內心絕對是崩潰的)。有人可能會想,將常用的RESTful操作(例如GET、POST、DELETE)封裝成工具類,再調用不是也可以嗎!這樣做確實可行,但是要封裝成通用的工具類不是那么簡單的(需要一定的經驗)。調用RESTful接口,還有另外一種選擇:Apache HttpComponents。雖然使用它發送HTTP請求確實挺方便的,但是使用它調用RESTful接口好像也挺麻煩的!
直到我遇到了RestTemplate,世界頓時都明亮了,腰也不酸了,腿也不疼了,一下子就對接好了10個RESTful接口。寫的代碼可能變成是這樣子的:
RestTemplate template = ... // 請求地址 String url = ... // 請求參數 UserParams request = ... // 執行POST請求 User u = template.postForObject(url, request, User.class); ... 復制代碼上面的調用代碼變的簡潔了很多,是不是很爽啊!RestTemplate是spring提供用來調用RESTful接口的類,里面提供了大量便捷的方法,如下:
執行不同的請求,只需找到這種請求方式所對應的方法就行,上例中的postForObject就是發送的POST請求。如果上面的請求沒有找到對應的方法,可以使用更加通用的exchange和execute方法。
RestTemplate的可擴展性也很強(下面列出比較常用的幾種方式):
RestTemplate的妙用
考慮這樣一個場景:假如說A部門開發的用戶相關的微服務接口,提供給B部門來使用,在使用時需要在請求頭中加入基本的認證頭信息,認證頭的格式如下:
Authorization=Basic {token} 復制代碼token的格式是:base64(username:password)。假如username是zfx,密碼是123,結果是先拼接用戶名和密碼:zfx:123,再用utf-8格式獲取其字節碼,進行base64編碼的結果為:emZ4OjEyMw==
假如要調用A部門的接口,根據id來獲取用戶的信息,代碼如下:
String userId = "11"; String url = "http://127.0.0.1:8080/v1/users/{id}";RestTemplate restTemplate = new RestTemplate();// 基本的認證頭信息 String username = "zfx"; String password = "123"; String token = Base64Utils.encodeToString((username + ":" + password).getBytes(StandardCharsets.UTF_8)); HttpHeaders headers = new HttpHeaders(); headers.add("Authorization", "Basic " + token); HttpEntity<Void> requestEntity = new HttpEntity<>(headers);ResponseEntity<User> exchange = restTemplate.exchange(url, HttpMethod.GET, requestEntity, User.class, userId); User result = exchange.getBody(); 復制代碼首先先創建RestTemplate的實例,在實際的開發中,最好不要每次都創建RestTemplate的實例,最好在spring中以單例的方式來配置,要使用的地方直接注入。用base64來編碼了用戶名和密碼,然后在請求頭中進行設置。restTemplate.exchange執行請求,并獲取返回的結果。上面的代碼其實并不難,但是這樣寫會不會有啥問題呢!假如說,叫你對接A部門的根據機構id來獲取機構信息的接口,你豈不是又要把上面的代碼再重新復制一下嗎?這樣不是很麻煩,代碼會很臃腫。
spring提供了ClientHttpRequestInterceptor這個類,適合用來處理這種情況,加入基本的認證頭信息,可以使用spring提供的這個類:BasicAuthorizationInterceptor。使用配置的方式來配置RestTemplate:
@Configuration public class RestTemplateConfig {@Value("${zfx.username}")private String username;@Value("${zfx.password}")private String password;@Bean("basicAuthRestTemplate")public RestTemplate createBasicAuthRestTemplate() {RestTemplate restTemplate = new RestTemplate();List<ClientHttpRequestInterceptor> interceptors = new ArrayList<>();interceptors.add(new BasicAuthorizationInterceptor(username, password));restTemplate.setInterceptors(interceptors);return restTemplate;}} 復制代碼上面的代碼在創建basicAuthRestTemplate時,會加入基本的認證頭信息的攔截器,來設置基本認證頭信息。
再次調用上面的接口時,代碼可以這樣寫:
@Autowired RestTemplate basicAuthRestTemplate; ... String userId = "11"; String url = "http://127.0.0.1:8080/v1/users/{id}"; User result = basicAuthRestTemplate.getForObject(url, User.class, userId); 復制代碼代碼一下子簡潔了這么多,假如說要調用根據機構id來獲取機構信息的接口呢?如下:
@Autowired RestTemplate basicAuthRestTemplate; ... String orgId = "11"; String url = "http://127.0.0.1:8080/v1/orgs/{id}"; Org result = basicAuthRestTemplate.getForObject(url, Org.class, orgId); 復制代碼代碼一下子簡潔了很多,對接這些接口的程序員不用再關心認證是怎么一回事,認證這件事對于他們完全是透明的,他們只需要專注于編寫他們自己的邏輯代碼就可以了。ClientHttpRequestInterceptor的實現也很簡單,代碼如下:
@Override public ClientHttpResponse intercept(HttpRequest request, byte[] body,ClientHttpRequestExecution execution) throws IOException {String token = Base64Utils.encodeToString((this.username + ":" + this.password).getBytes(StandardCharsets.UTF_8));request.getHeaders().add("Authorization", "Basic " + token);return execution.execute(request, body); } 復制代碼在intercept方法中加入了基本的認證頭信息。
假如說,有一天認證方式變了,改成OAuth2.0了,那么我們只需要實現自己的請求攔截器就行了,如下:
public class BearerAuthorizationInterceptimplements ClientHttpRequestInterceptor {@Overridepublic ClientHttpResponse intercept(HttpRequest request, byte[] body,ClientHttpRequestExecution execution) throws IOException {String token = 這些寫獲取token的邏輯;request.getHeaders().add("Authorization", "Bearer " + token);return execution.execute(request, body);}} 復制代碼然后配置restTemplate:
@Bean("bearerAuthRestTemplate")public RestTemplate createBearerAuthRestTemplate() {RestTemplate restTemplate = new RestTemplate();List<ClientHttpRequestInterceptor> interceptors = new ArrayList<>();interceptors.add(new BearerAuthorizationIntercept());restTemplate.setInterceptors(interceptors);return restTemplate;} 復制代碼那么只需要注入bearerAuthRestTemplate,就能使用他了:
@Autowired RestTemplate bearerAuthRestTemplate; ... String userId = "11"; String url = "http://127.0.0.1:8080/v1/users/{id}"; User result = bearerAuthRestTemplate.getForObject(url, User.class, userId); 復制代碼轉載于:https://juejin.im/post/5c8cba09e51d453e2762de2f
總結
以上是生活随笔為你收集整理的【本人秃顶程序员】技巧分享丨spring的RestTemplate的妙用,你知道吗?的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 网站计数器 web映射
- 下一篇: react项目打包后路径找不到,项目打开