尽管AJAX是Asynchronous Javascript and XML,但事实证明,在异步请求中传输XML格式的数据总让人觉得很麻烦。尽管在服务端XML的报文解析有广泛的工具支持,如JDOM, DOM4J等。但在客户端,用户需使用DOM来解析XML报文,才能获取需要的数据,并且由于XML报文在数据之外存在许多节点信息,因此传输的数据量相 对较大。如果仅使用普通文本的格式传输数据,又缺乏必要的数据结构。 JSON是Javascript Object Notation, 它是一种轻量级的数据结构。由于具有易于阅读,易于机器解析的特点,它非常适合于作为数据传输的格式,特别是对于客户端使用Javascript来解析的Web应用。 AJAX应用实现大体上分为服务端和客户端两部门,客户端若使用prototype的js库,能非常简单地实现AJAX请求和响应的获取。 prototype中的Form.serialize方法更能将表单中的所有字段序列化,作为发送给服务端的数据异步发送。在服务端,需要有一定的机制来 返回稳定格式的报文给客户端,并且这个响应的格式必须是易于客户端来解析的,JSON格式的报文是不错的选择。 在这里,我实现了一个基于JSON的服务端响应类,以满足上述的需求,服务端代码如下: package cn.ih.util.web; import java.util.HashMap; import java.util.LinkedHashMap; import java.util.Map; import javax.servlet.http.HttpServletResponse; import net.sf.json.JSONObject; import org.apache.commons.lang.StringUtils; /** *//** * * @author ih * */ public class JsonResponseUtils ...{ private static final String NODE_RESULT="result"; private static final String NODE_MESSAGE="message"; private static final String NODE_REASON="reason"; private static final String NODE_EXTRA_CONTENT="extraContent"; public static final String REASON_UNLOGON="unlogon"; public static final String REASON_ACCESS_DENY="accessDeny"; public static final String REASON_BIZ_CONSTRAINT="bizConstraint"; public static final String REASON_EXCEPTION="error"; /** *//** * 通过response返回到客户端 * @param response * @param responseContent * @throws Exception */ public static void outputResponse(HttpServletResponse response,String responseContent)throws Exception...{ response.getWriter().write(responseContent); } /** *//** * 返回json格式的报文 * @param result * @param message * @param reason * @param customerizedContent * @return */ @SuppressWarnings("unchecked") public static String generateResponse(boolean result,String message,String reason,Map customerizedContent)...{ Map map=new LinkedHashMap(); map.put(NODE_RESULT,result); if(StringUtils.isNotEmpty(message)) map.put(NODE_MESSAGE, message); if(StringUtils.isNotEmpty(reason)) map.put(NODE_REASON,reason); if(customerizedContent!=null) map.put(NODE_EXTRA_CONTENT, customerizedContent); return generateJsonObjectString(map); } /** *//** * 返回处理成功的报文 * @return */ public static String generateSuccessResponse()...{ return generateResponse(true, null, null, null); } /** *//** * 返回处理成功的报文,含成功提示信息和用户自定义内容 * @param message * @param customerizedContent * @return */ @SuppressWarnings("unchecked") public static String generateSuccessResponse(String message,Map customerizedContent)...{ return generateResponse(true, message, null, customerizedContent); } /** *//** * 返回处理成功的报文,含成功提示信息 * @param message * @return */ public static String generateSuccessResponse(String message)...{ return generateResponse(true, message, null, null); } /** *//** * 返回处理失败的报文, 原因为未登陆 * @param message * @return */ public static String generateUnlogonResponse(String message)...{ return generateResponse(false, message, REASON_UNLOGON, null); } /** *//** * 返回处理失败的报文, 原因为无权限 * @param message * @return */ public static String generateAccessDenyResponse(String message)...{ return generateResponse(false, message, REASON_ACCESS_DENY, null); } /** *//** * 返回处理失败的报文, 原因为业务限制 * @param message * @return */ public static String generateBizConstraintResponse(String message)...{ return generateResponse(false, message, REASON_BIZ_CONSTRAINT, null); } /** *//** * 返回处理失败的报文, 原因为系统异常 * @param message * @return */ public static String generateExceptionResponse(String message)...{ return generateResponse(false, message, REASON_EXCEPTION, null); } private static String generateJsonObjectString(Map map)...{ JSONObject jObj=new JSONObject(); jObj.putAll(map); return jObj.toString(); } public static void main(String[] args) ...{ System.out.println(generateSuccessResponse()); System.out.println(generateSuccessResponse("保存成功")); Map customerizedContent=new HashMap(); customerizedContent.put("newid", "101"); System.out.println(generateSuccessResponse("保存成功", customerizedContent)); System.out.println(generateUnlogonResponse("您尚未登陆")); System.out.println(generateAccessDenyResponse("您没有权限访问")); System.out.println(generateBizConstraintResponse("用户名不可重复")); System.out.println(generateExceptionResponse("数据库异常,请稍后再试")); } } 运行main后,将打印如下几种相同格式的报文,代表响应的不同种情况: {"result":true} {"message":"保存成功","result":true} {"extraContent":{"newid":"101"},"message":"保存成功","result":true} {"reason":"unlogon","message":"您尚未登陆","result":false} {"reason":"accessDeny","message":"您没有权限访问","result":false} {"reason":"bizConstraint","message":"用户名不可重复","result":false} {"reason":"error","message":"数据库异常,请稍后再试","result":false} Result属性代表这次处理的结果,只有true代表成功,false代表失败。 Message属性代表输出到客户端的打印信息。 Reason熟悉是对处理结果的解释,一般的业务系统有的情况基本上是unlogon未登陆,accessDeny访问拒绝,bizConstraint业务限制, error系统错误或异常。 extraContent用于输出额外的信息,比如在处理成功后客户端需要新生成纪录的主键,这时可以通过这个节点输出。 至于客户端的解析,由于是json格式的数据,非常简单地就能获取到报文中的数据。客户端代码如下: function submitForm(form)...{ var elemStr=Form.serialize(form); alert(elemStr); var url = "<c:url value="/multiActController.spr?action=jsonResponseSuccess"/>"; var mailAjax = new Ajax.Request(url,...{method: 'post',parameters:elemStr, onComplete: function(response)...{ var responseText=response.responseText; alert(responseText); var jobj=responseText.parseJSON(); alert(jobj.result+","+jobj.message+","+jobj.extraContent.name+","+jobj.extraContent.address+","+jobj.extraContent.sex); } } ); return false; } 附:服务端需要引入jsonlib;客户端需引入json.js和prototype1.5。