在处理 JSON 的过程中, 往往要面对着解析和转换 ,异常处理的问题 。
普通的处理流程 :
HttpClient client = new HttpClient();
String strUrl = CommonConstant.getBatchShowAssociationURL() + parm;
PostMethod method = new PostMethod(strUrl);
List<AssociationVO> associationList = new ArrayList<AssociationVO>();
try {
client.executeMethod(method);
} catch (HttpException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
String returnJson = "";
try {
returnJson = method.getResponseBodyAsString();// 返回json字符串值
String strJson = returnJson.replace("?(", "").replace(")", "").replace(";", "");
if (strJson.startsWith("{")) {
JSONObject jsonObject = JSONObject.fromObject(strJson);
String code = jsonObject.getString("code").toString();
if ("200".equals(code)) {
JSONArray jsonArray = JSONArray.fromObject(jsonObject.get("result"));
for (int i = 0, len = jsonArray.size(); i < len; i++) {
AssociationVO vo = new AssociationVO();
JSONObject jsonClub = jsonArray.getJSONObject(i);
vo.setId(Long.valueOf(jsonClub.get("id").toString()));
associationList.add(vo);
}
}
}
} catch (Exception e1) {
e1.printStackTrace();
} finally {
// 使用完成后要释放链接
method.releaseConnection();
}
这样的处理每次都要定义 处理方法, 负责打开和关闭流 ,
如果处理的是规则的接口,返回的数据都是相对固定的字段,可以考虑
利用自己定义的帮助类和接口实现的内部类,能够极大简化, 可以直接得到类。
首先是远程接口类, 调用得到JSON字串。。
public class RemoteRepositoryImpl implements RemoteRepository {
public String executePost(String url, Entity...requestBody) throws RemoteException {
PostMethod method = getPostMethod(url);
if (requestBody!=null && requestBody.length>0) {
method.setRequestBody(requestBody);
}
return execute(method);
}
protected PostMethod getPostMethod(String url) {
PostMethod method = new PostMethod(url);
method.getParams().setParameter(HttpMethodParams.SO_TIMEOUT, 5000); //设置 post 方法请求超时为 15 秒
method.setRequestHeader("Content-Type", "application/x-www-form-urlencoded;charset=utf-8");
return method;
}
public String execute(HttpMethodBase httpMethod) throws RemoteException {
HttpClient client = new HttpClient();
client.getHttpConnectionManager().getParams().setConnectionTimeout(5000);//设置 http 连接超时为 10 秒
String url = "";
long logT1 = System.currentTimeMillis();
try {
url = "" + httpMethod.getURI();
int sc = client.executeMethod(httpMethod);
if (sc != HttpStatus.SC_OK && sc!=HttpStatus.SC_CREATED && sc!=HttpStatus.SC_ACCEPTED) {
throw new RemoteException("remote service ERROR! methodstatus=[" + sc + "]" + url, "HttpStatus");
}
return httpMethod.getResponseBodyAsString();
} catch (URIException e) {
throw new RemoteException("URIException remote service ERROR!" + url, "URIException", e);
} catch (HttpException e) {
throw new RemoteException("HttpException remote service ERROR!" + url, "HttpException", e);
} catch (IOException e) {
throw new RemoteException("IOException remote service ERROR!" + url, "IOException", e);
} catch (RuntimeException e) {
throw new RemoteException("RuntimeException","RuntimeException" , e);
} finally {
httpMethod.releaseConnection();
long logT2 = System.currentTimeMillis();
if (logger.isInfoEnabled()) {
logger.info("Remote Time " + (logT2 - logT1) + " millisecounds:" + url);
}
}
}
}
在得到结果之后, 把返回字符串放到 JSON 包装类对象中去。
public class JSONWrapper {
protected JSONObject root;
private String json;
/**
* 构造
* @param json
*/
public JSONWrapper(String json) {
json = json.replaceAll("\\n", "");
this.json = json;
String validJson = (json);
if (validJson!=null) {
root = (JSONObject) JSONSerializer.toJSON((json));
}else {
root = new JSONObject(true);
}
}
private JSONWrapper(JSONObject json) {
this.json = "";
root = json;
}
/**
* 静态工厂
* @param json
* @return
*/
public static JSONWrapper valueOf(String json) {
return new JSONWrapper(json);
}
private static <E> List<E> getJavaList(Object bean, String path, ToJava<E> tojava){
Object p = getProperty(bean, path);
if (p==null) {
return Collections.emptyList();
}
if (!(p instanceof JSON)) {// TODO trycache
return Collections.emptyList();
// throw new RuntimeException("path 路径错误,请检查:[" + p + "]不是一个JSON对象");
}
JSON jo = (JSON) p;
List<E> res = new ArrayList<E>(jo.size());
Collection arr = (jo instanceof JSONObject) ? ((JSONObject) jo).values() : (JSONArray) jo;
JSONWrapper subWrapper = new JSONWrapper((JSONObject)null);
for (Object obj : arr) {
if (!(obj instanceof JSONObject)) {
logger.error("path 路径错误,请检查:[" + obj + "]不是一个JsonObject对象");
continue;
//throw new RemoteException("path 路径错误,请检查:[" + obj + "]不是一个JsonObject对象", "json");
}
if (((JSONObject) obj).isNullObject()) {
continue;
}
try {
subWrapper.root = (JSONObject) obj;
E o = tojava.toJava(subWrapper);
if (o!=null) {
res.add(o);
}
} catch (RuntimeException e) {
logger.error("取tojava异常");
//throw new RemoteException("取tojava异常", "json", e);
}
}
return res;
}
//根据路径得到 JSON 对象
private static Object getProperty(Object jo, String path) {
if (StringUtils.hasText(path)) {
for (String prop : path.split("\\.")) {
if (jo==null) {
return null;
}
if (jo instanceof JSONObject) {
jo = getJSONObject((JSONObject) jo, prop);
}
}
}
return jo;
}
protected static Object getJSONObject(JSONObject jo, String propName) {
return jo!=null && !jo.isNullObject()? jo.get(propName) : null;
}
}
通用的接口类 :
public interface ToJava<E>{
E toJava(JSONWrapper wrapper);
}
这样,就可以使用内部类来得到JSON中的数据了
public class BusinessCircleServiceImpl implements BusinessCircleService {
protected ToAssociationVO toAssociationVO = new ToAssociationVO();
//内部实现类
protected static class ToAssociationVO implements ToJava<AssociationVO> {
public AssociationVO toJava(JSONWrapper wrapper) {
AssociationVO vo = new AssociationVO();
vo.setId(wrapper.getLong("id", null));
vo.setTimeCreated(DateTimeUtils.formatPageDate(DateTimeUtils.parseFullDateTime(DateUtil
.getDateTimeByMillisecond(wrapper.getString("timeCreated", null)))));
return vo;
}
}
public List<AssociationVO> getRecommandList(int type, PaginationDto paginationDto) {
..................................
//调用代码:
try {
String strJson = remoteRepository.executeGet(CommonConstant.getBatchShowAssociationURL() + ids);
return JSONWrapper.valueOf(strJson).getJavaList("result", toAssociationVO);
} catch (RemoteException e) {
log.error("远程服务出错:" + CommonConstant.getBatchShowAssociationURL() + ids, e);
return Collections.EMPTY_LIST;
}
}
}