最近,業務須要在java服務端發起http請求,須要實現"GET","POST","PUT"等基本方法。因而想以 "HttpClient" 爲基礎,封裝基本實現方法。在github上面看到一個項目cn-umbrella/httpclientDemo,裏面實現簡單的 "GET","POST"。一方面,demo中實現的邏輯不能知足業務須要,同時實現過程當中,存在使用過時的類,代碼封裝不足等問題。也是我就從新封裝了httpclient-util,抱着你們相互學習的心態,將代碼上傳到github上面,相關連接,錯誤的地方歡迎你們指正。html
迴歸正題,下面講講工具類實現的基本思路。java
<dependency> <groupId>org.apache.httpcomponents</groupId> <artifactId>httpclient</artifactId> <version>4.5.2</version> </dependency> <!--httpmime主要用於構建multi-part/form-data 請求--> <dependency> <groupId>org.apache.httpcomponents</groupId> <artifactId>httpmime</artifactId> <version>4.5.2</version> </dependency>
/** * Do http request * @param request request object * @return response object */ public static Response doRequest(Request request)
其中,Request 封裝了請求參數,Response 封裝了返回內容。git
支持方法:"GET","OPTIONS","HEAD","POST","PUT","PATCH"。支持請求體: "application/x-www-form-urlencoded","json字符串","multipart/form-data"。github
Request的繼承關係 Request (沒有請求body的請求,支持方法:"GET", "OPTIONS", "HEAD") |---BaseEntityRequest (抽象類,定義有請求body的請求, 支持方法:"POST", "PUT", "PATCH") |--- UrlEncodedFormRequest (application/x-www-form-urlencoded) |--- JsonRequest (請求body爲json字符串) |--- MultiPartFormRequest (multipart/form-data)
同時,Request 支持使用 ssl/tls,使用request.setUseSSL(true);
設置便可。web
HttpEntity就是對應請求body相關實體對象。apache
任何實現具備請求body的請求,須要實現 BaseEntityRequest 如下方法json
/** * Get HttpEntity about request body * @return HttpEntity */ public abstract HttpEntity getEntity();
這個實現比較簡單,"K-V" 的形式,返回 UrlEncodedFormEntity,注意參數編碼。瀏覽器
@Override public HttpEntity getEntity() { List<NameValuePair> pairList = new ArrayList<>(params.size()); for (Map.Entry<String, Object> entry : params.entrySet()) { NameValuePair pair = new BasicNameValuePair(entry.getKey(), entry .getValue().toString()); pairList.add(pair); } return new UrlEncodedFormEntity(pairList, Charset.forName(getRequestCharset())); //參數編碼 }
請求body就是一個 "json字符串",返回一個StringEntity 實體便可。app
@Override public HttpEntity getEntity() { StringEntity stringEntity = new StringEntity(jsonObject.toString(), getRequestCharset()); //解決中文亂碼問題,須要注意編碼,如使用"utf-8" stringEntity.setContentEncoding(getResponseDefaultCharset()); stringEntity.setContentType(JSON_CONTENT_TYPE); return stringEntity; }
httpclient 類庫中不直接支持構造 "multi-part/form-data" ,須要引入 httpmime,並使用 MultipartEntityBuilder 構造請求body。若是是文件類型的參數對象,使用 FileBody 構建 part,不然,使用 StringBody,注意編碼。ide
@Override public HttpEntity getEntity() { try { Charset charset = CharsetUtils.get(getRequestCharset()); //使用瀏覽器兼容模式,而且設置編碼,防止文件名亂碼問題 MultipartEntityBuilder builder = MultipartEntityBuilder.create() .setMode(HttpMultipartMode.BROWSER_COMPATIBLE) .setCharset(charset); //編碼 parts.forEach((key, value) -> { if (null != value && value instanceof File) { //for file FileBody fileBody = new FileBody((File) value); builder.addPart(key, fileBody); } else { StringBody stringBody = new StringBody(null == value ? "" : value.toString() , ContentType.create(ContentType.TEXT_PLAIN.getMimeType(), charset)); //編碼 builder.addPart(key, stringBody); } }); return builder.build(); } catch (UnsupportedEncodingException e) { throw new RuntimeException("Charset '" + getRequestCharset() + "' is unsupported!"); } }
使用 https 過程當中,若是出現下述異常:
javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target at sun.security.ssl.Alerts.getSSLException(Alerts.java:192) at sun.security.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1949) at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:302) at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:296) ... Caused by: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:387) at sun.security.validator.PKIXValidator.engineValidate(PKIXValidator.java:292) at sun.security.validator.Validator.validate(Validator.java:260) at sun.security.ssl.X509TrustManagerImpl.validate(X509TrustManagerImpl.java:324) at sun.security.ssl.X509TrustManagerImpl.checkTrusted(X509TrustManagerImpl.java:229)
能夠參考個人上篇博文解決 java 使用ssl過程當中出現"PKIX path building failed:...,固然在包 com.xiaobenma020.http.cert 下面能夠找到類 InstallCert
關鍵步驟
% java InstallCert _web_site_hostname_ 顯示相關的證書信息 此時輸入'q' 則爲'退出', '1' 則將添加CA證書。 將新生成的 "jssecacerts" 移到"$JAVA_HOME/jre/lib/security"
@Test public void doResponse() throws Exception { UrlEncodedFormRequest request = new UrlEncodedFormRequest("https://xxx.com/login", RequestMethod.POST); //url form param request.addParam("loginId", "loginId"); request.addParam("password", "password"); //query string param request.addUrlParam("version", "v1"); //ssl request.setUseSSL(true); Response response = HttpClientUtil.doRequest(request); System.out.println(response.getResponseText()); //response text System.out.println(response.getCode()); //response code System.out.println(response.getHeader("Set-Cookie")); }