前言:這是我的第一篇博文,是我對現在一些接口調用的梳理,寫的不好,請見諒。
序:接口無非就是“你調用別人的接口”和“別人調用你的接口”,我會對這兩種情況分別的理一下我的思路。
准備:我使用的是HttpClient,它的特性是實現了Http全部的方法和支持HTTPS協議,是一種比較純凈的JAVA語言。
一、“你調用別人的接口”:
我這里提供的方法是POST和GET的方法.
使用HttpClient發送請求、接收響應很簡單,一般需要如下幾步即可。
1. 創建HttpClient對象。
2. 創建請求方法的實例,並指定請求URL。如果需要發送GET請求,創建HttpGet對象;如果需要發送POST請求,創建HttpPost對象。
3. 如果需要發送請求參數,我使用的是List<NameValuePair>,采用鍵值對的形式
4. 釋放連接。無論執行方法是否成功,都必須釋放連接
來個代碼進行討論把,我會在代碼里面進行詳細的講解,這里主要是post和get的方法.
1.先來一個常量類:
/*************************************************接口部分**************************************************/ /** * 請求正常 */ public static final int SUCCESS = 200; /** * 請求參數有誤 */ public static final int PARAMETER_EXCEPTION = 400; /** * 認證失敗 */ public static final int AUTHENTICATION_FAILED = 401; /** * 請求地址錯誤或不存在 */ public static final int ADDRESS_EXCEPTION = 404; /** * 請求地址錯誤或不存在 */ public static final int SERVER_EXCEPTION = 500; /** * 接口狀態碼判斷 */ public static String putThrowException(int statusCode) { String e = ""; if(PARAMETER_EXCEPTION == statusCode) { e = "請求參數有誤"; }else if(AUTHENTICATION_FAILED == statusCode) { e = "認證失敗"; }else if(ADDRESS_EXCEPTION == statusCode) { e = "請求地址錯誤或不存在"; }else if(SERVER_EXCEPTION == statusCode) { e = "服務器狀態異常"; } return e; } /** * Token元素 */ public static final String USERNAME = "tianxun"; public static final String PASSWORD = "123456"; public static final String token = "dGlhbnh1biUzQTEyMzQ1Ng==";
2.接口類:
package cn.tisson.bycs.utils; import java.io.IOException; import java.io.UnsupportedEncodingException; import java.net.URLEncoder; import java.net.UnknownHostException; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.net.ssl.SSLException; import org.apache.commons.httpclient.HttpException; import org.apache.http.Consts; import org.apache.http.HttpEntity; import org.apache.http.HttpEntityEnclosingRequest; import org.apache.http.HttpRequest; import org.apache.http.NameValuePair; import org.apache.http.NoHttpResponseException; import org.apache.http.client.HttpRequestRetryHandler; import org.apache.http.client.config.RequestConfig; import org.apache.http.client.entity.UrlEncodedFormEntity; import org.apache.http.client.methods.CloseableHttpResponse; import org.apache.http.client.methods.HttpGet; import org.apache.http.client.methods.HttpPost; import org.apache.http.client.protocol.HttpClientContext; import org.apache.http.client.utils.URIUtils; import org.apache.http.client.utils.URLEncodedUtils; import org.apache.http.conn.ConnectTimeoutException; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClients; import org.apache.http.message.BasicNameValuePair; import org.apache.http.protocol.HttpContext; import org.apache.http.util.EntityUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.apache.commons.codec.binary.Base64; import cn.tisson.bycs.cst.Constants; /** * 接口常用工具類 * @author zahngrh * */ public class serviceUtils { private static final Logger logger = LoggerFactory.getLogger(serviceUtils.class); /** * Base64加密Token * @return * @throws UnsupportedEncodingException */ public static String getBase64() throws UnsupportedEncodingException { String str = Constants.USERNAME+":"+Constants.PASSWORD; final byte[] textByte = str.getBytes("UTF-8"); String result= Base64.encodeBase64String(textByte); return result; } public static void main(String[] args) throws UnsupportedEncodingException { System.out.println(getBase64()); } /** * 設置超時重試 */ public static HttpRequestRetryHandler myRetryHandler = new HttpRequestRetryHandler() { @Override public boolean retryRequest(IOException exception,int executionCount,HttpContext context) { System.out.println("............................第"+executionCount+"次重試"); if (executionCount >= 3) { return false; }else if(exception instanceof UnknownHostException || exception instanceof ConnectTimeoutException || !(exception instanceof SSLException) || exception instanceof NoHttpResponseException) { return true; } HttpClientContext clientContext = HttpClientContext.adapt(context); HttpRequest request = clientContext.getRequest(); boolean idempotent = !(request instanceof HttpEntityEnclosingRequest); if (idempotent) { //如果請求被認為是等冪,則重試 return true; } return false; } }; /** * 接口請求工具類 */ public static Map<String,String> requestResult(Map<String,String> map,String putType,String url) throws HttpException, IOException { CloseableHttpResponse response = null; int statusCode = 0; // 狀態碼 String content =""; // 返回結果 Map<String,String> resultMap = new HashMap(); // 創建httpclient對象 CloseableHttpClient httpClient = HttpClients.createDefault(); // 設置參數 List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(); for(String key:map.keySet()) { nameValuePairs.add(new BasicNameValuePair(key,map.get(key).toString())); } String str = EntityUtils.toString(new UrlEncodedFormEntity(nameValuePairs,Consts.UTF_8)); // 設置超時時間 RequestConfig requestConfig = RequestConfig.custom() .setSocketTimeout(5000) .setConnectTimeout(5000) .setConnectionRequestTimeout(5000) .build(); if(putType != null && "post".equals(putType)){ // 請求URL地址 HttpPost httpPost = new HttpPost(url); httpPost.setEntity(new UrlEncodedFormEntity(nameValuePairs,Consts.UTF_8)); // 設置Token httpPost.setHeader("token",Constants.token); httpPost.setConfig(requestConfig); httpClient = HttpClients.custom().setRetryHandler(serviceUtils.myRetryHandler).build(); try { response = httpClient.execute(httpPost); // 接收狀態碼 statusCode = response.getStatusLine().getStatusCode(); } catch (Exception e) { e.printStackTrace(); } }else if(putType != null && "get".equals(putType)) { // 請求URL地址 HttpGet httpGet = new HttpGet(url+"?"+str); // 設置Token httpGet.setHeader("token",Constants.token); httpGet.setConfig(requestConfig); httpClient = HttpClients.custom().setRetryHandler(serviceUtils.myRetryHandler).build(); try { response = httpClient.execute(httpGet); // 接收狀態碼 statusCode = response.getStatusLine().getStatusCode(); } catch (Exception e) { e.printStackTrace(); } } // 判斷狀態碼 if (Constants.SUCCESS == statusCode) { HttpEntity entity = response.getEntity(); content = EntityUtils.toString(entity, "utf-8"); logger.info(content); } else { //logger.error("狀態碼:"+Constants.putThrowException(statusCode)); } resultMap.put("statusCode", String.valueOf(statusCode)); resultMap.put("result", content); try { // 釋放client httpClient.close(); } catch (IOException e) { logger.error("http接口調用異常:url is::" + url, e); } return resultMap; } }
3.對於接口類的調用:
/**
*根據業務使用接口,對返回值進行自我的調整
**/
public static void main(String[] args) throws HttpException, IOException { Map<String,String> paraMap = new HashMap(); paraMap.put("type", "1"); System.out.println(serviceUtils.requestResult(paraMap, "post", "https://api.apiopen.top/musicRankingsDetails")); }
一、“別人調用你的接口”:
別人調用你的接口,你需要:
1.token的驗證(業務需求)的返回
2.參數的驗證的返回
3.內部錯誤的返回
4.正確結果的返回
這時候你需要先寫一個"情況返回的類"對各種錯誤信息和正確信息的返回
1.處理類
package cn.tisson.bycs.utils.exception; import com.alibaba.fastjson.JSONException; import com.alibaba.fastjson.JSONObject; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.web.bind.MissingServletRequestParameterException; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.bind.annotation.ResponseStatus; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; import java.util.HashMap; import java.util.Hashtable; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; import javax.servlet.http.HttpServletRequest; @ControllerAdvice public class GlobalExceptionHandler { private static final Logger logger = LoggerFactory.getLogger(GlobalExceptionHandler.class); /** * <p>判斷參數是否為空</p></br> * <p>如果為空,返回resultCode=400和具體信息,</p></br> * <p>如果不為空,則返回resultCode=0。</p> * @Title: isEmpty * @Description: TODO * @param @param param * @param @return * @return Hashtable<String,Object> * @throws * @author zhangrh */ public Hashtable<String, Object> isEmpty(Map<String, Map<String, String>> param) { Hashtable<String, Object> resultHt = new Hashtable<String, Object>(); int resultCode = 0; List<Map<String, String>> list = new ArrayList<>(); Set<String> set = param.keySet(); Iterator<String> iterator = set.iterator(); while(iterator.hasNext()) { String paramName = iterator.next(); Map<String, String> m = param.get(paramName); Set<String> s = m.keySet(); Iterator<String> iter = s.iterator(); while(iter.hasNext()) { String describe = iter.next(); if(m.get(describe) == null || "".equals(m.get(describe))) { resultCode = 400; Map<String, String> detail = new HashMap<>(); detail.put("objectName", paramName); detail.put("defaultMessage", describe); detail.put("error", describe + "不能為空"); list.add(detail); } } } if(resultCode == 400) { resultHt.put("resultMsg", "請求參數有誤"); resultHt.put("detail", list); } resultHt.put("resultCode", resultCode); return resultHt; } /** * 接口有參數未傳 */ @ExceptionHandler(value = MissingServletRequestParameterException.class) @ResponseBody public JSONObject missActionParam(HttpServletRequest req, List<Map<String, Object>> list) throws Exception { return makeErrorObj("參數異常", "400", req, null, list); } /** * 服務器內部錯誤 */ @ExceptionHandler(value = NullPointerException.class) @ResponseBody public JSONObject error(HttpServletRequest req) throws Exception { Map<String,Object> resultMap = new HashMap<>(); return makeErrorObj("服務器內部錯誤", "500",req, resultMap, null); } /** * token驗證錯誤 */ @ExceptionHandler(value = NullPointerException.class) @ResponseBody public JSONObject tokenException(HttpServletRequest req,Map<String,Object> resultMap) throws Exception { return makeErrorObj("token驗證失敗","401", req,resultMap, null); } /** * 正常執行 */ @ResponseBody public JSONObject success(HttpServletRequest req,Map<String,Object> resultMap){ return makeErrorObj("執行成功","200", req,resultMap, null); } /** * 構造錯誤信息 * * @param msg 錯誤描述 * @param e 異常信息 * @return */ @ResponseBody private JSONObject makeErrorObj(String msg,String status, HttpServletRequest req,Map<String,Object> resultMap, List<Map<String, Object>> list) { JSONObject obj = new JSONObject(); // 日期格式化 SimpleDateFormat sdf =new SimpleDateFormat("yyyy-MM-dd HH:mm:ss" ); String timestamp = sdf.format(new Date()); if("200".equals(status)) { for(String key : resultMap.keySet()) { obj.put(key,resultMap.get(key)); } }else { obj.put("errors", list); obj.put("status", status); obj.put("msg", msg); obj.put("path", req.getRequestURL()); obj.put("timestamp", timestamp); } return obj; } }
2.寫一個Controller方法,讓別人調用我的接口
@SuppressWarnings({ "unchecked" })
@RequestMapping(value = "/queryCheckPassengers", method = { RequestMethod.GET }) //這個一個get請求的方法,如果是post== RequestMethod.POST @ResponseBody public JSONObject queryCheckPassengers(HttpServletRequest request,HttpServletResponse response,Map<String, String> resultMap)throws Exception{ // 驗證token String tokenStr = request.getHeader("token"); if(!Constants.token.equals(tokenStr)) { response.setStatus(401); return new GlobalExceptionHandler().tokenException(request, new HashMap<String, Object>()); } try{ Map<String, Map<String, String>> pMap = new HashMap<>(); Map<String, String> m = new HashMap<>(); //數據 String flightNum = request.getParameter("flightNum"); //航班號 String flightDate = request.getParameter("flightDate"); //航班日期,格式YYYY-MM-DD String passengerCheckInNumber = request.getParameter("passengerCheckInNumber"); //值機序號 String flightBoardingCode = request.getParameter("flightBoardingCode"); //始發地(城市名稱、3字碼) m.put("航班號", flightNum); pMap.put("flightNum", m); m = new HashMap<>(); m.put("航班日期", flightDate); pMap.put("flightDate", m); m = new HashMap<>(); m.put("值機序號", passengerCheckInNumber); pMap.put("passengerCheckInNumber", m); m = new HashMap<>(); m.put("始發地", flightBoardingCode); pMap.put("flightBoardingCode", m); Hashtable<String, Object> ht = new GlobalExceptionHandler().isEmpty(pMap); if(ht.get("resultCode").toString().equals("400")) { response.setStatus(400); return new GlobalExceptionHandler().missActionParam(request, (List<Map<String, Object>>)ht.get("detail")); }else {
//這里是你需要返回的信息 Map<String, Object> result = checkActionTypeStub.queryCheckPassengers(flightNum, flightDate, passengerCheckInNumber, flightBoardingCode); response.setStatus(200); return new GlobalExceptionHandler().success(request, result); } }catch (Exception e) { response.setStatus(500); e.printStackTrace(); return new GlobalExceptionHandler().error(request); } }
說明:別人調用你的接口,有提供一個api的和提供一個controller的方式,這里是提供一個controller的方式,你需要的是提供IP和端口,加上你的類名和方法名
例:http://172.16.31.199:8080/passton/queryCheckPassengers
總結:在這里就是對我的一些對接口的應用了,初次寫作,還很潦草,就當是我的一次記錄吧。