本篇主要講解RestTemplate的基本使用,它是Spring提供的用來訪問Rest服務的客戶端,RestTmplate提供了不少便捷的方法,能夠大大提供開發效率,本篇只涉及基本使用,內部原理後續再展開java
RestTemplate是Spring提供的用於發送HTTP請求的客戶端工具,它遵循Restful原則,RestTemplate默認依賴JDK的Http鏈接工具HttpUrlConnection,你也能夠替換不一樣的源,好比OkHttp、Apache HttpComponents 等等。。正則表達式
在說RestTemplate以前,先介紹HttpMessageConverter,RestTemplate默認使用的轉化HttpMessageConverter去將Http消息轉換成POJO 或者 POJO轉化成Http消息。在建立RestTemplate的時候會默認添加一組HttpMessageConveter的實現。json
HttpMessageConverter源碼:app
public interface HttpMessageConverter<T> { //指示此轉換器是否能夠讀取給定的類。 boolean canRead(Class<?> clazz, [@Nullable](https://my.oschina.net/u/2896689) MediaType mediaType); //指示此轉換器是否能夠寫給定的類。 boolean canWrite(Class<?> clazz, [@Nullable](https://my.oschina.net/u/2896689) MediaType mediaType); //返回List<MediaType> List<MediaType> getSupportedMediaTypes(); //讀取一個inputMessage T read(Class<? extends T> clazz, HttpInputMessage inputMessage) throws IOException, HttpMessageNotReadableException; //往output message寫一個Object void write(T t, [@Nullable](https://my.oschina.net/u/2896689) MediaType contentType, HttpOutputMessage outputMessage) throws IOException, HttpMessageNotWritableException; }
RestTemplate中如何添加HttpMessageConverter的工具
構造器源碼:post
static { ClassLoader classLoader = RestTemplate.class.getClassLoader(); romePresent = ClassUtils.isPresent("com.rometools.rome.feed.WireFeed", classLoader); jaxb2Present = ClassUtils.isPresent("javax.xml.bind.Binder", classLoader); jackson2Present = ClassUtils.isPresent("com.fasterxml.jackson.databind.ObjectMapper", classLoader) && ClassUtils.isPresent("com.fasterxml.jackson.core.JsonGenerator", classLoader); jackson2XmlPresent = ClassUtils.isPresent("com.fasterxml.jackson.dataformat.xml.XmlMapper", classLoader); jackson2SmilePresent = ClassUtils.isPresent("com.fasterxml.jackson.dataformat.smile.SmileFactory", classLoader); jackson2CborPresent = ClassUtils.isPresent("com.fasterxml.jackson.dataformat.cbor.CBORFactory", classLoader); gsonPresent = ClassUtils.isPresent("com.google.gson.Gson", classLoader); jsonbPresent = ClassUtils.isPresent("javax.json.bind.Jsonb", classLoader); } public RestTemplate() { this.messageConverters.add(new ByteArrayHttpMessageConverter()); this.messageConverters.add(new StringHttpMessageConverter()); this.messageConverters.add(new ResourceHttpMessageConverter(false)); try { this.messageConverters.add(new SourceHttpMessageConverter<>()); } catch (Error err) { // Ignore when no TransformerFactory implementation is available } this.messageConverters.add(new AllEncompassingFormHttpMessageConverter()); if (romePresent) { this.messageConverters.add(new AtomFeedHttpMessageConverter()); this.messageConverters.add(new RssChannelHttpMessageConverter()); } if (jackson2XmlPresent) { this.messageConverters.add(new MappingJackson2XmlHttpMessageConverter()); } else if (jaxb2Present) { this.messageConverters.add(new Jaxb2RootElementHttpMessageConverter()); } if (jackson2Present) { this.messageConverters.add(new MappingJackson2HttpMessageConverter()); } else if (gsonPresent) { this.messageConverters.add(new GsonHttpMessageConverter()); } else if (jsonbPresent) { this.messageConverters.add(new JsonbHttpMessageConverter()); } if (jackson2SmilePresent) { this.messageConverters.add(new MappingJackson2SmileHttpMessageConverter()); } if (jackson2CborPresent) { this.messageConverters.add(new MappingJackson2CborHttpMessageConverter()); } this.uriTemplateHandler = initUriTemplateHandler(); }
從RestTemplate的構造器源碼中咱們能夠看到構造方法中 根據ClassUtils.isPresent判斷當前項目是否存在某些jar包向RestTemplate中添加不一樣的 HttpMessageConverter實現,Spring默認會添加 StringHttpMessageConverter , MappingJackson2XmlHttpMessageConverter等等ui
首先來看Get請求 RestTemplate提供了2種方法其中一種就是 getForObject()方法this
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)
客戶端 String url = "http://localhost:9999/testGetMethod"; String str = restTemplate.getForObject(url , String.class);、 服務端 @RequestMapping("/testGetMethod") public String testGetMethod(){ return "hello"; }
客戶端 String url = "http://localhost:9999/testGetMethod/{talk}/{name}"; //或者testGetMethod/{1}/{2} {裏面的參數無所謂,只是根據下面的Object... uriVariables 逐一綁定到上面{} 中去的} String str = restTemplate.getForObject(url , String.class,"hello" , "johnny"); 服務端 @RequestMapping("/testGetMethod/{talk}/{name}") public String testGetMethod(@PathVariable("talk") String talk , @PathVariable("name") String name){ log.info("【{} : {}】" , talk , name); return "hello"; }
說明{} http://localhost:9999/testGetMethod/{talk}/{name} 裏面的參數名稱無所謂,只是根據下面的Object... uriVariables 逐一綁上去的,具體綁定源碼請看 DefaultUriBuilderFactory的fromUriString方法內部是根據正則表達式進行綁定的,最終將返回 URI,URI的string屬性 就是綁定後要訪問的路徑 google
//不早了 先寫這麼多吧 明天把下面的補齊 ,先去睡覺了!!! //繼續補齊。。url
String url = "http://localhost:9999/testGetMethod/{talk}/{name}"; Map<String,String> map = new HashMap<>(); map.put("talk" , "hello"); map.put("name" , "johnny"); String str = restTemplate.getForObject(url , String.class,map);
能夠看出來是經過Map綁定參數的,這個和上面不同的是 map的key 必定要和 url中 {} 中的 保持一致 ,若是不一致會報錯
String url = "http://localhost:9999/testGetMethod/{talk}/{name}"; map.put("talk2" , "hello");
源碼
RestTemplate 提供的Get請求的第二種方法 ,基本和getForObject一致 ,就是返回類型不一樣,它是在getForObject返回的基礎上再包裝了一層 ResponseEntity 用於包含Http請求的所有信息
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){}
String url = "http://localhost:9999/testGetMethodForEntity/"; ResponseEntity<Student> responseEntity = restTemplate.getForEntity(url , Student.class); responseEntity.getStatusCode(); responseEntity.getHeaders(); responseEntity.getBody(); log.info("【responseEntity : {}】" , responseEntity);
String url = "http://localhost:9999/testGetMethodForEntity/{name}/{age}"; ResponseEntity<Student> responseEntity = restTemplate.getForEntity(url , Student.class , "johnny" , "23"); log.info("【responseEntity : {}】" , responseEntity);
String url = "http://localhost:9999/testGetMethodForEntity/{name}/{age}"; Map<String,String> map = new HashMap<>(); map.put("name","johnny"); map.put("age" , "23"); ResponseEntity<Student> responseEntity = restTemplate.getForEntity(url , Student.class ,"map"); log.info("【responseEntity : {}】" , responseEntity);
可是,一般狀況下咱們並不想要Http請求的所有信息,只須要相應體便可.對於這種狀況,RestTemplate提供了 getForObject() 方法用來只獲取 響應體信息. getForObject 和 getForEntity 用法幾乎相同,指示返回值返回的是 響應體,省去了咱們 再去 getBody() .
public <T> T postForObject(String url, @Nullable Object request, Class<T> responseType, Object... uriVariables) throws RestClientException {} public <T> T postForObject(String url, @Nullable Object request, Class<T> responseType, Map<String, ?> uriVariables) throws RestClientException {} public <T> T postForObject(URI url, @Nullable Object request, Class<T> responseType) throws RestClientException {}
客戶端代碼: String url = "http://localhost:9999/testPostMethodForObject"; Student student = new Student(); student.setName("johnny"); student.setAge("23"); String msg = restTemplate.postForObject(url , student , String.class); 服務端代碼: @RequestMapping("/testPostMethodForObject") public String testGetMethodForEntity(@RequestBody Student student){ log.info("【studeng: {}】" , student); return "success"; }
public <T> T postForObject(String url, @Nullable Object request, Class<T> responseType, Object... uriVariables) throws RestClientException {} public <T> T postForObject(String url, @Nullable Object request, Class<T> responseType, Map<String, ?> uriVariables) throws RestClientException {} public <T> T postForObject(URI url, @Nullable Object request, Class<T> responseType) throws RestClientException {}
@RequestMapping("/testPostMethodForEntity") public void testPostMethodForEntity(){ String url = "http://localhost:9999/testPostMethodForEntity"; Student student = new Student(); student.setName("johnny"); student.setAge("23"); ResponseEntity<String> responseEntity = restTemplate.postForEntity(url , student , String.class); log.info(responseEntity.getBody()); }
能夠看出來postForEntity和postForObject 幾乎同樣。
惟有 ResponseExtractor<T> 不一樣
HttpMessageConverterExtractor.extractData()方法
ResponseEntityResponseExtractor.extractData()方法
本篇主要講解RestTemplate的基本的 Get Post 的用法,簡單的涉及了一點源碼,其實內部源碼不少 很深 包括和解析url模板 綁定參數的 UriBuilderFactory UriTemplateHandler 等等 , 建議去跟着跑一遍會更加熟悉 用起來也更加輕鬆。
我的博客系統:https://www.askajohnny.com 歡迎訪問! 本文由博客一文多發平臺 OpenWrite 發佈!