赞
踩
更多精彩请访问:http://www.gzdangfu.com
服务端项目中通过全局异常拦截器进行异常处理,但进行单元测试发现用java原生HttpURLConnection方法访问服务端时,无法读取到处理异常后的响应体中的内容,直接报错!在此记录下解决方案!
先看看发生报错时的代码如何写的:
抛出自定义错误的代码:
try {
service = (MoerService) SpringContextHolder.getBean(serviceImpl);
} catch (Exception e) {
throw new SystemException(ErrorMessageConstants.NOT_BEAN_ERROR);
}
/** * 全局异常拦截器 * * @Author --- * @Date: -- */ @ControllerAdvice public class GlobalExceptionHandler { private Logger logger = LoggerFactory.getLogger(GlobalExceptionHandler.class); /** * 拦截全局异常 */ @ExceptionHandler(Exception.class) @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR) @ResponseBody public Result exception(Exception e) { logger.error("异常错误:", e); return Result.fail(ErrorMessageConstants.ABNORMAL_ERROR); } /** * 拦截系统异常 */ @ExceptionHandler(SystemException.class) @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR) @ResponseBody public Result systemException(SystemException e) { logger.error("系统异常:", e); return Result.fail(e.getMessage()); } /** * 拦截业务异常 */ @ExceptionHandler(BussinessException.class) @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR) @ResponseBody public Result bussinessException(BussinessException e) { logger.error("业务异常:", e); return Result.fail(e.getMessage()); }
public static String postJsonParams(String requestUrl, String requestMethod, String params) { StringBuilder sb = new StringBuilder(); try { URL url = new URL(requestUrl);// 创建连接 HttpURLConnection connection = (HttpURLConnection) url .openConnection(); connection.setDoOutput(true); connection.setDoInput(true); connection.setUseCaches(false); connection.setInstanceFollowRedirects(true); connection.setRequestMethod(requestMethod); // 设置请求方式 connection.setRequestProperty("Accept", "application/json"); // 设置接收数据的格式 connection.setRequestProperty("Content-Type", "application/json"); // 设置发送数据的格式 connection.connect(); OutputStreamWriter out = new OutputStreamWriter( connection.getOutputStream(), "UTF-8"); // utf-8编码 out.append(params); out.flush(); out.close(); if (connection != null) { BufferedReader br = new BufferedReader(new InputStreamReader(connection.getInputStream(), "UTF-8")); String line = null; while ((line = br.readLine()) != null) { sb.append(line); sb.append("\r\n"); } br.close(); } connection.disconnect(); } catch (IOException e) { e.printStackTrace(); } return sb.toString(); }
当服务端抛出 SystemException() 时,会被异常拦截器 GlobalExceptionHandler 所处理,然后return
Result.fail(e.getMessage()),返回自定义友好错误提示;
但通过postJsonParams方法发起请求时,却无法获取服务端响应内容,报错信息如下:
java.io.IOException: Server returned HTTP response code: 500 for URL: http://localhost:8885/moerService/access
at sun.net.www.protocol.http.HttpURLConnection.getInputStream0(HttpURLConnection.java:1839)
at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1440)
at com.moerlong.service_authorize.util.HttpRequest.postJsonParams(HttpRequest.java:94)
at com.moerlong.service_authorize.controller.AccessController.test(AccessController.java:91)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:205)
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:133)
......
由错误信息可以看到:Server returned HTTP response code: 500,说明服务端响应码为500是错误的源头;
我们再看异常拦截器中的 @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR) 正好为response设置响应码为500,难道是这个问题?
之前通过HttpClient
发送请求时没遇到这种问题,难道是HttpURLConnection
API不能读取responseCode为500
时的响应体内容么?
再看读取响应体的方法:
if (connection != null) {
BufferedReader br = new BufferedReader(new InputStreamReader(connection.getInputStream(), "UTF-8"));
String line = null;
while ((line = br.readLine()) != null) {
sb.append(line);
sb.append("\r\n");
}
br.close();
}
我们是通过
connection.getInputStream()
方法获取输入流来读取响应体内容的!但这个API只能读取
responseCode=200
时的响应内容!我们翻阅
HttpURLConnection
的API文档,可以看到十分靠前的一个方法getErrorStream()
:
Returns the error stream if the connection failed but the server sent
useful data nonetheless.
原来通过这个方法我们才能获取到responseCode不为200
时(connection failed)
的响应内容(useful data)
!
public static String postJsonParams(String requestUrl, String requestMethod, String params) { StringBuilder sb = new StringBuilder(); try { URL url = new URL(requestUrl);// 创建连接 HttpURLConnection connection = (HttpURLConnection) url .openConnection(); connection.setDoOutput(true); connection.setDoInput(true); connection.setUseCaches(false); connection.setInstanceFollowRedirects(true); connection.setRequestMethod(requestMethod); // 设置请求方式 connection.setRequestProperty("Accept", "application/json"); // 设置接收数据的格式 connection.setRequestProperty("Content-Type", "application/json"); // 设置发送数据的格式 connection.connect(); OutputStreamWriter out = new OutputStreamWriter( connection.getOutputStream(), "UTF-8"); // utf-8编码 out.append(params); out.flush(); out.close(); if (connection != null) { InputStream inputStream = null; //根据responseCode来获取输入流,此处错误响应码的响应体内容也要获取(看服务端的返回结果形式决定) if (HttpURLConnection.HTTP_OK == connection.getResponseCode()) { inputStream = connection.getInputStream(); } else { inputStream = connection.getErrorStream(); } BufferedReader br = new BufferedReader(new InputStreamReader(inputStream, "UTF-8")); String line = null; while ((line = br.readLine()) != null) { sb.append(line); sb.append("\r\n"); } br.close(); } connection.disconnect(); } catch (IOException e) { e.printStackTrace(); } return sb.toString(); }
核心:
if (HttpURLConnection.HTTP_OK == connection.getResponseCode()) {
inputStream = connection.getInputStream();
} else {
inputStream = connection.getErrorStream();
}
根据
ResponseCode
来选择getInputStream/getErrorStream API
即可!
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。