激情久久久_欧美视频区_成人av免费_不卡视频一二三区_欧美精品在欧美一区二区少妇_欧美一区二区三区的

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務器之家 - 編程語言 - Java教程 - 使用spring的restTemplate注意點

使用spring的restTemplate注意點

2022-03-03 11:05書生楊陽 Java教程

這篇文章主要介紹了使用spring的restTemplate注意點,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教

使用springrestTemplate注意點

spring的restTemplate可以向一個url發送請求并接收服務器端的響應信息。但在發請求時,會對請求的url值進行編碼再發送。

下面看spring的RestTemplate的源碼

restTemplate基本上發送請求的方法內部都會調用到execute()方法:

使用spring的restTemplate注意點

expand()方法的代碼如下:

使用spring的restTemplate注意點

encode()方法的代碼如下:

使用spring的restTemplate注意點

所以如果使用非spring的服務器接收時,需要進行解碼才能接收到RestTemplate發送的內容。(spring的服務器接收到參數時會自動進行一次解碼,所以使用restTemplate發送消息,Spring的服務器接收時不會出現問題)。

 

spring的RestTemplate使用指南

前言:現在restful接口越來越廣泛,而如今很多接口摒棄了傳統的配置復雜的webService開發模式,在java領域只需要很簡單的springMvc就可以聲明為一個控制器,再加上service層,就可以直接操作數據庫成為一個靈活的接口。

而我們請求接口的次數也會越來越多(最近我在和一個工具對接的時候,對方公司提供的接口全部由我們主動去調用),一般我們請求接口,都采用Apache Httpclient工具,這個工具穩定,既可以建立長連接,保持不錯的性能,而它唯一的不足就是使用起來麻煩多變,并且要很多層判斷處理,今天我要談的就是spring對httpClient的再封裝工具類,restTemplate,采用模板模式抽象出來的高效工具。

有點類似于jdbcTemplate,今天我們就來一步步揭開它的使用方法

一:restTemplate簡介

1.1:restTemplate的類結構

使用spring的restTemplate注意點

可以看出它繼承自HttpAccessor這個統一的處理器,然后再繼承自InterceptingHttpAccessor,這個攔截轉換器,最終RestTemplate實現了封裝httpClient的模板工具類

1.2:restTemplate的方法

Spring用于同步客戶端HTTP訪問的中心類。它簡化了與HTTP服務器的通信,并執行RESTful原則。它處理HTTP連接,使應用程序代碼提供URL,使用可能的模板變量,并提取結果。

注意:默認情況下,RestTemplate依賴于標準的JDK來建立HTTP連接。你可以切換使用不同的HTTP庫,如Apache HttpComponents,Netty和OkHttp通過setRequestFactory屬性。內部模板使用HttpMessageConverter實例將HTTP消息轉換為POJO和從POJO轉換。主要MIME類型的轉換器是默認注冊的,但您也可以注冊其他轉換器通過setMessageConverters

以下是http方法和restTempalte方法的比對映射,可以看出restTemplate提供了操作http的方法,其中exchange方法可以用來做任何的請求,一般我們都是用它來封裝不同的請求方式。

使用spring的restTemplate注意點

二:restTemplate的配置方法

2.1:在springboot中的配置

springboot是一款簡化傳統xml配置式的開發方式,主要采用注解的方式來代替傳統繁瑣的xml配置,接下來我們就用springboot提供的注解來配置restTemplate:

@Configuration
public class RestTemplateConfig {
  private static final Logger logger= LoggerFactory.getLogger(RestTemplateConfig.class);
  @Bean
  public RestTemplate restTemplate() {
      // 添加內容轉換器,使用默認的內容轉換器
      RestTemplate restTemplate = new RestTemplate(httpRequestFactory());
      // 設置編碼格式為UTF-8
      List<HttpMessageConverter<?>> converterList = restTemplate.getMessageConverters();
      HttpMessageConverter<?> converterTarget = null;
      for (HttpMessageConverter<?> item : converterList) {
          if (item.getClass() == StringHttpMessageConverter.class) {
              converterTarget = item;
              break;
          }
      }
      if (converterTarget != null) {
          converterList.remove(converterTarget);
      }
      HttpMessageConverter<?> converter = new StringHttpMessageConverter(StandardCharsets.UTF_8);
      converterList.add(1,converter);
      LOGGER.info("-----restTemplate-----初始化完成");
      return restTemplate;
  }
  @Bean
  public ClientHttpRequestFactory httpRequestFactory() {
      return new HttpComponentsClientHttpRequestFactory(httpClient());
  }
  @Bean
  public HttpClient httpClient() {
      // 長連接保持30秒
      PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(30, TimeUnit.SECONDS);
      //設置整個連接池最大連接數 根據自己的場景決定
      connectionManager.setMaxTotal(500);
      //同路由的并發數,路由是對maxTotal的細分
      connectionManager.setDefaultMaxPerRoute(500);
      //requestConfig
      RequestConfig requestConfig = RequestConfig.custom()
              //服務器返回數據(response)的時間,超過該時間拋出read timeout
              .setSocketTimeout(10000)
              //連接上服務器(握手成功)的時間,超出該時間拋出connect timeout
              .setConnectTimeout(5000)
              //從連接池中獲取連接的超時時間,超過該時間未拿到可用連接,會拋出org.apache.http.conn.ConnectionPoolTimeoutException: Timeout waiting for connection from pool
              .setConnectionRequestTimeout(500)
              .build();
      //headers
      List<Header> headers = new ArrayList<>();
      headers.add(new BasicHeader("User-Agent", "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.16 Safari/537.36"));
      headers.add(new BasicHeader("Accept-Encoding", "gzip,deflate"));
      headers.add(new BasicHeader("Accept-Language", "zh-CN"));
      headers.add(new BasicHeader("Connection", "Keep-Alive"));
      headers.add(new BasicHeader("Content-type", "application/json;charset=UTF-8"));
      return HttpClientBuilder.create()
              .setDefaultRequestConfig(requestConfig)
              .setConnectionManager(connectionManager)
              .setDefaultHeaders(headers)
              // 保持長連接配置,需要在頭添加Keep-Alive
              .setKeepAliveStrategy(new DefaultConnectionKeepAliveStrategy())
              //重試次數,默認是3次,沒有開啟
              .setRetryHandler(new DefaultHttpRequestRetryHandler(2, true))
              .build();
  }
}

首先解釋以下@configuration,它的主要作用就是在spring容器啟動的時候,初始化IOC,使用了這個注解,那么該類就會在spring啟動的時候,把@Bean注解標識的類進行依賴注入。@Bean理解的話,就好比在配置文件中配置<bean>.接下來就是在restTemplate的構造方法中添加httpRequest的工廠,使用連接池來優化http通信,默認使用長連接時間為30秒,再設置路由讓http連接定向到指定的IP,然后設置并發數。再就是設置請求配置的超時時間,為了防止請求時間過長而引起資源的過渡浪費。如果在超過設置的timeout還沒有數據返回,就直接斷開連接。headers是添加默認的請求頭,這里設置了傳送的格式為json,語言為中-英等等屬性。HttpClientBuilder.create設置請求頭到HttpClient,然后在設置保持的時間,重試的次數,注入給httpClient進行封裝。

在bean中的HttpMessageConverter,就是http信息轉換器,它的主要作用就是轉換和解析返回來的json數據,restTemplate默認使用jackson來作為底層的解析工具,而其它的比如Gson,fastjson等等第三方開源庫放在headers這個list中,如果要使用,可以通過以下代碼進行改變:

       this.restTemplate.getMessageConverters().clear();
      final List<HttpMessageConverter<?>> myHttpMessageConverter = new ArrayList<HttpMessageConverter<?>>();
       
      //自己實現的messgeConverter
      HttpMessageConverter<Object> messageConverter = new MyHttpMessageConverter<Object>();
      
      myHttpMessageConverter.add(messageConverter);
      
      this.restTemplate.setMessageConverters(myHttpMessageConverter);

三:restUtil工具類

restUtil就是通過包裝restTemplate暴露出面向外界的方法,通過高度封裝,可以隱藏內部細節,簡單使用,在使用它的時候,我們只需要傳入請求的url和對應的參數,然后就可以取到結果了。參數一般有兩種形式,一種是直接傳入json,另一種是key、value形式的,key/value形式的,可以直接使用execute方法,傳入url和請求的方法類型就可以了。在開頭看到了restTemplate基本上是支持所有http請求的,接下來的工具類就介紹一下post和get請求的主要封裝方法

@Component
public class RestUtil {
  @Autowired
  private  RestTemplate restTemplate;
  //一些自定義的請求頭參數
  public static final String supplierID="";
  public static final String interfacekey= "";
  /**
   * DLT專用執行方法
   * @param param 請求參數:可以添加一些常量請求值
   * @param url 訪問的url
   * @param method 請求的方法
   * @return
   */
  public String execute(Map<String,Object> param, String url, HttpMethod method){
      HttpHeaders headers = this.getDefaultHeader();
      Map<String,Object> requestor = this.getDefaultParam();
      param.put("requestor",requestor);
      param.put("supplierID",supplierID);
      HttpEntity<Map<String,Object>> requestEntity = new HttpEntity<>(param, headers);
      ResponseEntity<String> response = restTemplate.exchange(url,method, requestEntity, String.class);
      return response.getBody();
  }
  /**
   * 獲取默認的頭請求信息
   * @return
   */
  public HttpHeaders getDefaultHeader(){
      String timestamp = ""+System.currentTimeMillis();
      String signature = EncoderByMd5(supplierID + timestamp + interfacekey);
      HttpHeaders headers = new HttpHeaders();
      headers.add("signature", signature);
      headers.add("timestamp", timestamp);
      return headers;
  }
  /**
   * 獲取默認的參數
   * @return
   */
  public Map<String,Object> getDefaultParam(){
      Map<String,Object> defParam = new HashMap<>();
      defParam.put("invoker","xx");
      defParam.put("operatorName","xx");
      return defParam;
  }
  /**
   * 通過MD5加密
   * @param str
   * @return
   */
  public static String EncoderByMd5(String str){
      if (str == null) {
          return null;
      }
      try {
          // 確定計算方法
          MessageDigest md5 = MessageDigest.getInstance("MD5");
          BASE64Encoder base64en = new BASE64Encoder();
          // 加密后的字符串
          return base64en.encode(md5.digest(str.getBytes("utf-8"))).toUpperCase();
      } catch (NoSuchAlgorithmException | UnsupportedEncodingException e) {
          return null;
      }
  }
 
  /**
   * get請求
   * @param url 請求的url
   * @param jsonData 請求的json
   * @return
   */
  public String restGet(String url,String jsonData){
      return request(url, jsonData,HttpMethod.GET);
  }
  /**
   * @param url 請求的url
   * @param jsonData json數據
   * @param httpMethod
   * @return
   */
  private String request(String url, String jsonData,HttpMethod httpMethod) {
      ResponseEntity<String> response=null;
      try {
          if (Check.isEmpty(url)) {
              throw new IllegalArgumentException();
          }
          HttpEntity<String> requestEntity = new HttpEntity<String>(jsonData);
          response = restTemplate.exchange(url, httpMethod, requestEntity, String.class);
      }catch (Exception ex){
          ex.printStackTrace();
          return "";
      }
      return response.getBody().toString();
  }
  /**
   * Get請求獲取實體類
   * @param url 請求的url
   * @param responseType 返回的類型
   * @param parms 不限定個數的參數
   * @param <T> 泛型
   * @return
   */
  public <T> T getForEntity(String url,Class<T> responseType,Object... parms){
      return (T) restTemplate.getForEntity(url,responseType,parms);
  }
 /**
  * Get請求
  * @param url
  * @param parm
  * @return
   */
 public String get(String url,Map<String,Object> parm){
  return restTemplate.getForEntity(url,String.class,parm).getBody();
}
}

四:使用示例

4.1:首先我們用springBoot來搭建一個簡單的rest請求鏈接

我們來模擬一個請求,傳入年齡和性別、身高,計算出標準體重的接口,這段代碼比較簡單,我只給出示范代碼:

@SpringBootApplication
@RestController
public class HealApplication {
  @RequestMapping(value = "weight", method = RequestMethod.GET)
  public ResultModel getWeight(@RequestParam(value = "height", required = false) Integer height,   @RequestParam(value = "sex", required = false) Integer sex, @RequestParam(value = "age", required = false) Integer age) {
      if (height == null || age == null || sex == null || (!sex.equals(0) && !sex.equals(1))) {
          return new ResultModel(400, "缺少請求參數或者參數錯誤", 0d);
      }
      double condition = getStandardWeight(sex, age, height);
      return new ResultModel(200, "請求成功", condition);
  }
  /**
   * 獲取標準體重
   *
   * @param sex    性別 1:男  2:女
   * @param age    年齡
   * @param height
   * @return 體重(單位:kg)
   */
  public double getStandardWeight(int sex, int age, int height) {
      double weight = 0.0;
      switch (sex) {
          //男性
          case 1:
              if (age < 12 && age > 2) {
                  weight = age * 2 + 12;
              } else if (age > 12) {
                  weight = (height - 150) * 0.6 + 50;
              }
              break;
          case 0:
              if (age < 12 && age > 2) {
                  weight = age * 2 + 12;
              } else if (age > 12) {
                  weight = (height - 100) * 0.6 + 50;
              }
              break;
          default:
              weight = 0;
              break;
      }
      return weight;
  }

可以看到我們的控制器有個映射weight請求的方法,通過傳入年齡、身高、性別,就可以計算出標準體重,我們來啟動springBoot,先試著用瀏覽器訪問一下,可以看出如下結果:

使用spring的restTemplate注意點

使用spring的restTemplate注意點

4.2:為了表明接口是通的,我們再用postman來試一下,可以看到返回結果正確:

使用spring的restTemplate注意點

4.3:在springboot里引入testNg單元測試類,測試一下訪問這個鏈接的結果:

public class TestRestManager  extends OrderProviderApplicationTests {
  @Autowired
  private RestUtil restUtil;
  /**
   * 請求方法為GEt
   * @return
   */
  @Test
  private void  requestGet(){
      String url="http://localhost:8080/weight?age={age}&sex={sex}&height={height}";
      //組裝請求參數
      Map<String,Object> parmMap =new HashMap<String,Object>();
      parmMap.put("age",35);
      parmMap.put("sex",1);
      parmMap.put("height",178);
      String result = restUtil.get(url, parmMap);
      System.out.println(result);
  }
}

結果返回以下內容:

使用spring的restTemplate注意點

五:總結

本篇博客講述了RestTemplate的簡介,還有配置方法和使用示例,作為一款非常不錯的rest請求工具,屏蔽了復雜的HttpClient的實現細節,向外暴露出簡單、易于使用的接口,使得我們的開發工作越來越簡單、高效,更多的方法工具可以研究一下restTemplate的具體Api,打開源碼,一切都了如指掌。在平時的工作中,應該多發現這種工具類,從而來代替一些傳統的工具,對于提升工作效率有著突飛猛進的效果和不可言喻的方便。

以上為個人經驗,希望能給大家一個參考,也希望大家多多支持服務器之家。

原文鏈接:https://blog.csdn.net/Petershusheng/article/details/54236816

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 黄 色 免费网 站 成 人 | 久久在草 | 亚洲午夜免费电影 | 第四色成人网 | 久草导航| 亚洲第一视频在线 | 一区二区三区小视频 | 欧美精品国产综合久久 | 免费播放欧美毛片 | 精品成人av一区二区在线播放 | 久久蜜桃香蕉精品一区二区三区 | 欧洲a级片 | 人人舔人人射 | 久久国产成人精品国产成人亚洲 | 色播视频在线播放 | 日本在线视频一区二区三区 | 97风流梦电影 | 在线播放91 | 久久视频精品 | 成人免费一区二区 | 中文字幕在线视频网站 | av免费大全| 日韩理论电影网 | 天天好比网 | 免费国产在线视频 | 一本大道av | 大学生一级毛片在线视频 | 国产精品嘿咻嘿咻在线播放 | 奇米影视亚洲春色 | 色中色在线播放 | 高清一区二区在线观看 | 国产精品久久久久久久娇妻 | 黄色成人av在线 | 国产精品久久久久久久久久免 | 免费观看欧美一级片 | 黄色网址电影 | 操碰视频在线观看 | 在线观看中文字幕av | 原来神马影院手机版免费 | 成人性视频欧美一区二区三区 | 亚洲成人入口 |