項目總結之HttpURLConnection的disconnect的問題
HttpURLConnection的disconnect問題
項目需要存儲文件,但是由于使用百度云平臺的服務器,沒有文件寫權限,輾轉使用中間轉發(fā)的策略,將文件存儲在公司公網(wǎng)服務器上,通過云平臺的文件請求都轉發(fā)到文件服務器。
響應轉發(fā)過程中,總是得不到轉發(fā)的響應內容。
跟蹤發(fā)現(xiàn)獲取到的URLConnection的輸入流的available總是返回0,導致轉發(fā)響應內容為空。
調試發(fā)現(xiàn)把 URLConnection的disconnect()調用代碼注釋掉,能夠轉發(fā)成功。
/** ?? ? * 以http方式發(fā)送請求,并將請求響應內容以String格式返回 ?? ? * @param path ? ?請求路徑 ?? ? * @param method ?請求方法 ?? ? * @param body ? ?請求數(shù)據(jù) ?? ? * @return 返回響應的字符串 ?? ? */ ?? ?public static void httpRequestRediret(HttpServletResponse response,String fileName,String path, String method, String body) { ?? ??? ?HttpURLConnection conn = null; ?? ??? ?InputStream inputStream = null; ?? ??? ?try { ?? ??? ??? ?URL url = new URL(path); ?? ??? ??? ?conn = (HttpURLConnection) url.openConnection(); ?? ??? ??? ?conn.setDoOutput(true); ?? ??? ??? ?conn.setDoInput(true); ?? ??? ??? ?conn.setUseCaches(false); ?? ??? ??? ?conn.setRequestMethod(method); ?? ??? ??? ?if (null != body) { ?? ??? ??? ??? ?OutputStream outputStream = conn.getOutputStream(); ?? ??? ??? ??? ?outputStream.write(body.getBytes("UTF-8")); ?? ??? ??? ??? ?outputStream.close(); ?? ??? ??? ?} ?? ??? ??? ?//代理返回流信息 ?? ??? ??? ?inputStream = conn.getInputStream(); ?? ??? ??? ?response.setContentType(conn.getContentType()); ?? ??? ??? ?FileUtil.responseAttachment(fileName,inputStream, response); ?? ??? ?} catch (Exception e) { ?? ??? ??? ?logger.error(e); ?? ??? ?}finally{ ?? ??? ??? ?if(conn!=null){ ?? ??? ??? ??? ?conn.disconnect(); ?? ??? ??? ?} ?? ??? ?} ?? ?}
FileUtil轉發(fā)附件
/** ?? ? * Http響應內容為附件 ?? ? * @param file ?? ? * @param response ?? ? */ ?? ?public static void responseAttachment(String fileName ,InputStream in,HttpServletResponse response){ ?? ??? ?if(response==null||in==null||fileName==null){ ?? ??? ??? ?return; ?? ??? ?} ?? ??? ?BufferedInputStream bis = null; ?? ??? ?BufferedOutputStream bos = null; ?? ??? ?byte[] buff = new byte[1024]; ?? ??? ?int bytesRead; ?? ??? ?try{ ?? ??? ??? ?response.setHeader("Content-disposition", "attachment; filename=" ?? ??? ??? ??? ??? ?+ new String(fileName.getBytes("utf-8"), "ISO8859-1")); ?? ??? ??? ?response.setHeader("Content-Length", String.valueOf(in.available())); ?? ??? ??? ?bis = new BufferedInputStream(in); ?? ??? ??? ?bos = new BufferedOutputStream(response.getOutputStream()); ?? ??? ??? ?while (-1 != (bytesRead = bis.read(buff, 0, buff.length))) { ?? ??? ??? ??? ?bos.write(buff, 0, bytesRead); ?? ??? ??? ?} ?? ??? ?}catch(Exception e){ ?? ??? ??? ?e.printStackTrace(); ?? ??? ?}finally{ ?? ??? ??? ?if(bis!=null){ ?? ??? ??? ??? ?try { ?? ??? ??? ??? ??? ?bos.close(); ?? ??? ??? ??? ??? ?bis.close(); ?? ??? ??? ??? ?} catch (IOException e) { ?? ??? ??? ??? ??? ?e.printStackTrace(); ?? ??? ??? ??? ?} ?? ??? ??? ?} ?? ??? ?} ?? ?}
結論
URLConnection的響應流InputStream在沒有處理之前就關閉connection會導致該輸入流信息為空,getInputStream()的available總是為0。
猜測disconnection可能執(zhí)行了輸入流的關閉操作了。response響應頭如果不設置Content-Length,客戶端也能正確獲取到響應文件的。
網(wǎng)上看到一種說法說如果將輸入流關閉后,則對應的URLConnection也會自動關閉了。
還有一個問題是如果Connection沒有執(zhí)行disconnect()操作,會有什么后果呢?
HttpURLConnection解決Feign報400問題
問題描述
項目中使用Feign組件遠程調用問題記錄,本地代碼執(zhí)行正常,部署到服務器訪問調用不了遠程接口,報 feign.FeignException: status 400 reading,不太清楚是什么問題,分別用了httpclinet、resttemplate、feign,結果都失敗報同一個問題,明明本地運行正常,線上就不正常了呢?
原因分析
網(wǎng)上查了很多報錯的原因,但是都不符合,最后用了HttpURLConnection這個api 成功解決
解決方案
?? ?//post請求 ? ? public static <T> T doPost(String url, Object requestObj, Class<T> tClass) throws IOException { ? ? ? ? PrintWriter out = null; ? ? ? ? BufferedReader in = null; ? ? ? ? String result = ""; ? ? ? ? try { ? ? ? ? ? ? // 打開和URL之間的連接 ? ? ? ? ? ? HttpURLConnection conn = (HttpURLConnection) new URL(url).openConnection(); ? ? ? ? ? ? // 設置通用的請求屬性 ? ? ? ? ? ? conn.setRequestMethod("POST"); ? ? ? ? ? ? conn.setConnectTimeout(4 * 1000); ? ? ? ? ? ? conn.setRequestProperty("Content-Type", "application/json;charset=UTF-8"); ? ? ? ? ? ? // 發(fā)送POST請求必須設置如下兩行 ? ? ? ? ? ? conn.setDoOutput(true); ? ? ? ? ? ? conn.setDoInput(true); ? ? ? ? ? ? // 獲取URLConnection對象對應的輸出流 ? ? ? ? ? ? out = new PrintWriter(new OutputStreamWriter(conn.getOutputStream(), "utf-8")); ? ? ? ? ? ? out.println(JSON.toJSONString(requestObj)); ? ? ? ? ? ? // flush輸出流的緩沖 ? ? ? ? ? ? out.flush(); ? ? ? ? ? ? InputStream is = null; ? ? ? ? ? ? if (conn.getResponseCode() >= 400) { ? ? ? ? ? ? ? ? is = conn.getErrorStream(); ? ? ? ? ? ? } else { ? ? ? ? ? ? ? ? is = conn.getInputStream(); ? ? ? ? ? ? } ? ? ? ? ? ? // 定義BufferedReader輸入流來讀取URL的響應 ? ? ? ? ? ? in = new BufferedReader(new InputStreamReader(is,"utf-8")); ? ? ? ? ? ? String line; ? ? ? ? ? ? while ((line = in.readLine()) != null) { ? ? ? ? ? ? ? ? result += line; ? ? ? ? ? ? } ? ? ? ? } catch (Exception e) { ? ? ? ? ? ? System.out.println("發(fā)送 POST 請求出現(xiàn)異常!" + e); ? ? ? ? ? ? e.printStackTrace(); ? ? ? ? } ? ? ? ? //使用finally塊來關閉輸出流、輸入流 ? ? ? ? finally { ? ? ? ? ? ? try { ? ? ? ? ? ? ? ? if (out != null) { ? ? ? ? ? ? ? ? ? ? out.close(); ? ? ? ? ? ? ? ? } ? ? ? ? ? ? ? ? if (in != null) { ? ? ? ? ? ? ? ? ? ? in.close(); ? ? ? ? ? ? ? ? } ? ? ? ? ? ? } catch (IOException ex) { ? ? ? ? ? ? ? ? ex.printStackTrace(); ? ? ? ? ? ? } ? ? ? ? } ? ? ? ? log.info("流獲取的對象:---"+result); ? ? ? ? T t = JSON.parseObject(result, tClass); ? ? ? ? return t; ? ? } ?? ?//get請求 ? ? public static JSONObject useGetMethod(String get_url){ ? ? ? ? try { ? ? ? ? ? ? Map<String,Object> result = new HashMap<String,Object>(); ? ? ? ? ? ? JSONObject jsonObject=null; ? ? ? ? ? ? URL url = new URL(get_url); ? ? ? ? ? ? HttpURLConnection connection = (HttpURLConnection) url.openConnection(); ? ? ? ? ? ? connection.setRequestMethod("GET"); ? ? ? ? ? ? //設置連接遠程服務器的超時時間 ? ? ? ? ? ? connection.setConnectTimeout(30000); ? ? ? ? ? ? //設置讀取遠程返回的數(shù)據(jù)時間 ? ? ? ? ? ? connection.setReadTimeout(30000); ? ? ? ? ? ? connection.connect(); ? ? ? ? ? ? int responseCode = connection.getResponseCode(); ? ? ? ? ? ? if (responseCode == HttpURLConnection.HTTP_OK) { ? ? ? ? ? ? ? ? StringBuffer str = new StringBuffer(); ? ? ? ? ? ? ? ? InputStream in = connection.getInputStream(); ? ? ? ? ? ? ? ? BufferedReader br = new BufferedReader(new InputStreamReader(in, "utf-8")); ? ? ? ? ? ? ? ? try{ ? ? ? ? ? ? ? ? ? ? String line = ""; ? ? ? ? ? ? ? ? ? ? while((line = br.readLine()) != null) { ? ? ? ? ? ? ? ? ? ? ? ? str.append(line); ? ? ? ? ? ? ? ? ? ? } ? ? ? ? ? ? ? ? } finally { ? ? ? ? ? ? ? ? ? ? br.close(); ? ? ? ? ? ? ? ? ? ? in.close(); ? ? ? ? ? ? ? ? } ? ? ? ? ? ? ? ? jsonObject = JSONObject.parseObject(str.toString()); // ? ? ? ? ? ? ? ?result.put("code", jsonObject.get("code")); // ? ? ? ? ? ? ? ?result.put("data", jsonObject.get("data")); ? ? ? ? ? ? }else{ // ? ? ? ? ? ? ? ?System.out.println("錯誤狀態(tài)碼:"+responseCode); // ? ? ? ? ? ? ? ?result.put("code", responseCode); // ? ? ? ? ? ? ? ?result.put("message", "異常"); ? ? ? ? ? ? } ? ? ? ? ? ? connection.disconnect(); ? ? ? ? ? ? return jsonObject; ? ? ? ? } catch (Exception e) { ? ? ? ? ? ? e.printStackTrace(); ? ? ? ? } ? ? ? ? return null; ? ? }
總結
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關文章
Spring Cloud Eureka服務治理的實現(xiàn)
服務治理是微服務框架中最為核心和基礎的模塊,它主要是用來實現(xiàn)各個微服務實例的自動化注冊與發(fā)現(xiàn)。這篇文章主要介紹了Spring Cloud Eureka服務治理的實現(xiàn),感興趣的小伙伴們可以參考一下2018-06-06java創(chuàng)建一個類實現(xiàn)讀取一個文件中的每一行顯示出來
下面小編就為大家?guī)硪黄猨ava創(chuàng)建一個類實現(xiàn)讀取一個文件中的每一行顯示出來的實例。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-01-01Mybatis-Plus中使用@DS注解動態(tài)選擇數(shù)據(jù)源的源碼解讀
這篇文章主要介紹了Mybatis-Plus中使用@DS注解動態(tài)選擇數(shù)據(jù)源的源碼解讀,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2023-07-07IntelliJ IDEA修改新建文件自動生成注釋的user名
今天小編就為大家分享一篇關于IntelliJ IDEA修改新建文件自動生成注釋的user名,小編覺得內容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧2018-10-10