1. 程式人生 > >呼叫第三方介面獲取資料寫入資料庫

呼叫第三方介面獲取資料寫入資料庫

系統框架: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);
}

之前做了顏色標記的,不知道為什麼釋出以後就變成了一個個大黑塊,都不知道重點在哪了,第一次做這種,湊合看吧。