项目总结之HttpURLConnection的disconnect的问题
作者:毕小宝
这篇文章主要介绍了项目总结之HttpURLConnection的disconnect的问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
HttpURLConnection的disconnect问题
项目需要存储文件,但是由于使用百度云平台的服务器,没有文件写权限,辗转使用中间转发的策略,将文件存储在公司公网服务器上,通过云平台的文件请求都转发到文件服务器。
响应转发过程中,总是得不到转发的响应内容。
跟踪发现获取到的URLConnection的输入流的available总是返回0,导致转发响应内容为空。
调试发现把 URLConnection的disconnect()调用代码注释掉,能够转发成功。
/** * 以http方式发送请求,并将请求响应内容以String格式返回 * @param path 请求路径 * @param method 请求方法 * @param body 请求数据 * @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转发附件
/** * 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可能执行了输入流的关闭操作了。response响应头如果不设置Content-Length,客户端也能正确获取到响应文件的。
网上看到一种说法说如果将输入流关闭后,则对应的URLConnection也会自动关闭了。
还有一个问题是如果Connection没有执行disconnect()操作,会有什么后果呢?
HttpURLConnection解决Feign报400问题
问题描述
项目中使用Feign组件远程调用问题记录,本地代码执行正常,部署到服务器访问调用不了远程接口,报 feign.FeignException: status 400 reading,不太清楚是什么问题,分别用了httpclinet、resttemplate、feign,结果都失败报同一个问题,明明本地运行正常,线上就不正常了呢?
原因分析
网上查了很多报错的原因,但是都不符合,最后用了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"); // 发送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("发送 POST 请求出现异常!" + 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); //设置读取远程返回的数据时间 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("错误状态码:"+responseCode); // result.put("code", responseCode); // result.put("message", "异常"); } connection.disconnect(); return jsonObject; } catch (Exception e) { e.printStackTrace(); } return null; }
总结
以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。