呼叫第三方介面獲取資料寫入資料庫
阿新 • • 發佈:2018-11-11
系統框架:springboot(和框架沒有什麼太大關係,僅記錄一下)
呼叫路徑:controller→service
第三方介面:http://xx.xxx.com:9905/api/list?transtime=20181017105600&token=abcdefghijklmn
請求引數:{"data":"{\"xxx\":\"\",\"xx\":\"\",\"xxxx\":\"\",\"pageindex\":1}"}
(注:因為有些公司的後臺是用.net寫的,所以java給它傳資料要像上面那麼傳,即包兩層,json裡面套json,且有斜槓;如果不是.net的話,就不用這麼封裝,具體請求方法看對方的要求)
一 controller層
@ApiOperation("資料抓取") @ApiImplicitParam(name = "ImportListInput",value = "輸入引數",required = true,dataType = "ImportListInput") @PostMapping("interface") @ResponseBody @PreAuthorize("isAuthenticated()") public Output getQualityLevel(@Valid @RequestBody ImportListInput importListInput)throws Exception { return mdmElianImportListService.getImportList(importListInput); }
importListInput 為向第三方介面傳送的請求引數,該介面的請求方式為POST,故,後面需要將我們輸入的值轉為json資料包傳送
二 service層
public static final String ESB_ElIAN_XXX_EXCHANGE = "elian.xxx.exchange";//下面同步用到
private static final Logger logger = LoggerFactory.getLogger(MdmElianDataStandardService.class);
public Output getImportList(ImportListInput importListInput) throws IOException, YaolingException, ParseException { //獲取token (獲取token也是呼叫第三方提供的介面獲取的,方法與下面記錄的類似,不作贅述) String str = mdmElianGetTokenService.getToken(); JSONObject oj = new JSONObject(str.toString()); String errorcode = oj.get("errorcode").toString(); if (ObjectUtils.isEmpty(errorcode)) { //單起一個執行緒 (當第三方的資料量過大時,需要起一個執行緒,以防止超時而造成的資料獲取不全,應該有更好的優化方法,如執行緒 //池之類的,暫不會;執行緒的使用程式碼用粉色標出) Thread ts = new Thread(new Runnable() { @Override public void run() { JSONObject oj1 = new JSONObject(str.toString()); String data = oj1.get("data").toString(); JSONObject oj2 = new JSONObject(data.toString()); String token = oj2.get("token").toString(); int pageindex; if ((Integer) mdmElianImportListInput.getPageindex() == null||mdmElianImportListInput.getPageindex() ==0) { pageindex = 1; } else { pageindex = mdmElianImportListInput.getPageindex(); } //得到long型別當前時間 long l = System.currentTimeMillis(); //new日期物件 Date date = new Date(l); //轉換提日期輸出格式 SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMddHHmmss"); SimpleDateFormat dateFormat1 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); SimpleDateFormat dateFormat2 = new SimpleDateFormat("yyyyMMdd"); String time = dateFormat.format(date);//按要求生成請求url中的第一個引數transtime並與格式化為url示例中的樣子 while (true) { 《--完整的請求示例從這裡開始--》 //new一個JSONObject格式的引數inner將我們傳入的引數轉為json格式 JSONObject inner = new JSONObject(); //把我們傳進來的引數分別賦值給inner中的各個引數, //這些引數名要和請求包的引數名一致,畢竟這是傳給對方的資料,如果和對方要求的 //引數名不一致,那麼我們也拿不到資料 inner.put("xxx", importListInput.getDrugname()); inner.put("xx", importListInput.getCompanysceng()); inner.put("xxxx", importListInput.getEndTime()); inner.put("pageindex", pageindex); // 這裡引數是包裝了兩層的 //再new一個JSonObject型別的引數param,把上面的inner放到param中,實現兩層包裝,因為對方後臺用的.net,所以包兩層。具體包裝幾層,看介面要求,有的可能只一層就好了 JSONObject param = new JSONObject(); param.put("data", inner.toString()); //拼接請求的url,把url+transtime+token拼接在一起 String url = "http://xx.xxx.com:9905/api/importlist?transtime=" + time + "&token=".concat(token); //定義一個JSONObject型別的rets用於接收返回的JSON資料 JSONObject rets = null; try { //呼叫第三方介面,並傳引數給對方,jsonPost方法在最後面附上 rets = DataDownloadUtil.jsonPost(url, param.toString()); } catch (IOException e) { e.printStackTrace(); } //如果返回結果中errorcode為空,即請求成功(具體看對方怎麼標識錯誤資訊,有的可能不用errorcode,所以不可直接生搬硬套此程式碼) String errorCode = (String) rets.get("errorcode") if (ObjectUtils.isEmpty(errorCode)) { //呼叫成功 JSONArray jsonArray = rets.getJSONArray("data"); //用一個集合接收返回的json資料中的data的值,遍歷集合,取出資料 for (int i = 0, len = jsonArray.length(); i < len; i++) { JSONObject jsonObject2 = (JSONObject) jsonArray.get(i); //定義一個接受類importList,將接收的資料寫進資料庫 ImportList importList = new ImportList(); //jsonObject2.get("x_x").toString()中的“x_x”要和實際返回的json資料中的欄位名一致,否則可能會出現找不到欄位的錯誤提示 importList.setXx(jsonObject2.get("x_x").toString()); importList.setXxx(jsonObject2.get("x_xx").toString()); importList.setXxxx(jsonObject2.get("x_xxx").toString()); importList.setDrugnameeng(jsonObject2.get("drugnameeng").toString()); //如果存在時間類的資料,且自己的資料庫中設計時將時間欄位的型別設定為了datetime,那麼在接收時要進行轉換,將string型的資料轉為date型的資料存入資料庫 SimpleDateFormat sdfs = new SimpleDateFormat("yyyy-MM-dd"); try { importList.setLisencecodedate(sdfs.parse(jsonObject2.get("date").toString())); } catch (ParseException e) { e.printStackTrace(); } //儲存此條資料,框架是springboot,所以有Repository。不要生搬硬套程式碼 importListRepository.save(importList); // } // 同步到xxxx平臺,用不到就不用寫了 rabbitTemplate.convertAndSend(CommonConstant.ESB_ElIAN_XXX_EXCHANGE,CommonConstant.UPDATE, importList); } } else { try { throw new YaolingException(errorCode); } catch (YaolingException e) { e.printStackTrace(); } } logger.debug("傳過去的pageindex值:[{}]", pageindex); //控制檯做監控,看是否資料正確翻頁 //json資料中的null和一般的null不同,判斷的時候要注意,不能用==null之類的 if (rets.isNull("nextpage")) { logger.debug("返回的nextpage值為null,抓取結束"); break; } logger.debug("返回的nextpage值:[{}]", (Integer) rets.get("nextpage")); //請求資料時,我們要告訴對方要第幾頁的資料,所以會傳一個pageindex值過去,對方返回給我們資料時,會給我們一個nextpage值,如果這個值不為null或者“ ”就說明下一頁還有資料,我們要把nextpage值賦值給pageindex繼續傳過去獲取下一頁的值,寫進資料庫,迴圈往復直至nextpage為null或者“”,這也就是上面為什麼要用while迴圈的原因 pageindex = (Integer) rets.get("nextpage"); logger.debug("下一次要傳的pageindex值:[{}]", pageindex); //至此,一條資料的獲取、存入結束 } //while 《--一個完整的請求及獲取資料到寫入資料庫到此結束--》 }//執行緒 });//執行緒 ts.start(); //啟動執行緒 } else { throw new YaolingException(errorcode); } return new Output(); }
(請求的程式碼是用“《-- --》《-- --》”包起來的部分,上面獲取token之後,藍色之前的程式碼都是為了藍色程式碼中的url中的token做服務的,所以不用太在意。)
jsonPost方法
protected JSONObject jsonPost(String urls, String text) throws IOException {
//建立一個HttpClient最新版的實現類CloseableHttpClient
CloseableHttpClient httpClient = HttpClients.createDefault();
//建立post方法請求物件,並把拼接好的地址url賦值給它的請求引數urls
HttpPost httpPost = new HttpPost(urls);
//設定報文頭為Content-Type。具體格式看實際需求,我只知道如果請求的資料包為raw時,用Content-Type
httpPost.setHeader("Content-Type", "application/json");
//設定引數到請求物件中
httpPost.setEntity(new StringEntity(text));
//執行請求操作,並拿到結果(同步阻塞)。(括號裡的同步阻塞我也不知道什麼意思,之後知道了再補上)
CloseableHttpResponse response = httpClient.execute(httpPost);
//獲取結果實體
HttpEntity entity = response.getEntity();
//看返回狀態是否正常,正常則把獲取到的json字串返回給呼叫者
int statue = response.getStatusLine().getStatusCode();
if (statue != HttpStatus.SC_OK) {
logger.error("http connect fail:{}", response.getStatusLine());
}
//返回結果
String result = EntityUtils.toString(entity, "utf-8");
return new JSONObject(result);
}
之前做了顏色標記的,不知道為什麼釋出以後就變成了一個個大黑塊,都不知道重點在哪了,第一次做這種,湊合看吧。