
在使用struts 2框架开发web应用时,我们经常需要通过ajax技术与后端进行异步数据交互,尤其是在前后端分离或部分数据动态加载的场景。当后端action处理完业务逻辑后,通常会返回json格式的数据给前端。然而,有时尽管后端看似输出了json字符串,前端ajax请求却可能进入error回调函数,并报告“parse error”或无法正确解析json数据。
最初的代码尝试通过ServletActionContext.getResponse().getWriter().write(obj.toJSONString());直接将JSON字符串写入HTTP响应流,并期望Struts 2的json结果类型能识别并处理。同时,struts.xml中配置了<result type="json"></result>,且AJAX请求中设置了dataType:"json"。然而,这种组合导致了前端解析失败。
Struts 2的JSON插件(struts2-json-plugin)提供了一种声明式的方式来生成JSON响应。当你在struts.xml中配置<result type="json"></result>时,Struts 2并不会简单地将你手动写入响应流的内容作为JSON返回。相反,它的核心机制是:
因此,如果你在Action中直接使用ServletActionContext.getResponse().getWriter().write()来输出JSON,这会与JSON插件的自动序列化机制产生冲突。JSON插件在尝试序列化Action属性时,可能会发现没有需要序列化的内容(或者你手动写入的内容被覆盖/忽略),导致最终的响应不符合预期,或者前端在尝试解析一个并非由插件正确生成的JSON响应时出现错误。
要正确地通过Struts 2 JSON插件返回JSON数据,我们应该遵循其设计原则,即在Action中定义一个公共属性(通常是一个Map、List或自定义POJO),并通过其getter方法让JSON插件进行序列化。
以下是修改后的Action类示例:
import java.util.HashMap;
import java.util.Map;
import com.opensymphony.xwork2.ActionSupport;
public class PropertyTesting extends ActionSupport
{
// 定义一个Map类型的属性,用于存储需要返回的JSON数据
// 必须有公共的getter方法,JSON插件才能访问并序列化它
private Map<String, String> jsonResponseData;
// JSON插件会通过这个getter方法获取数据并序列化
public Map<String, String> getJsonResponseData() {
return jsonResponseData;
}
public String execute()
{
// 初始化Map并填充数据
jsonResponseData = new HashMap<>();
jsonResponseData.put("Name", "PersonName");
jsonResponseData.put("ID", "PersonID");
// 返回SUCCESS,让Struts 2根据struts.xml配置的json结果类型进行处理
return SUCCESS;
}
}关键改动点:
struts.xml的配置保持不变,因为它已经正确地使用了JSON插件。确保你的package继承了json-default,并且action的result类型是json。
<struts>
<constant name="struts.devMode" value="true"/>
<package name="WebTesting" extends="json-default">
<action name="PropertyTesting" class="org.testing.PropertyTesting" >
<!-- 指定结果类型为json,Struts 2 JSON插件将自动序列化Action的属性 -->
<result type="json"></result>
</action>
</package>
</struts> 配置说明:
前端的AJAX请求代码无需修改,因为它已经正确地指定了dataType:"json",这告诉jQuery期望服务器返回JSON数据并尝试解析。
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib uri="/struts-tags" prefix="s"%>
<html>
<head>
<meta charset="UTF-8">
<title>Property Testing</title>
</head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
<script type="text/javascript">
function invokeAjax()
{
$.ajax(
{
type:"POST",
url:"PropertyTesting",
dataType:"json", // 明确告诉jQuery期望JSON响应
success: function(responseText)
{
// 当服务器返回有效的JSON时,此函数将被调用
console.log(responseText);
// responseText 现在是一个JavaScript对象,可以直接访问其属性
console.log("Name: " + responseText.Name);
console.log("ID: " + responseText.ID);
},
error: function(errorResponse)
{
// 如果JSON解析失败或服务器返回错误状态码,此函数将被调用
console.log("Error:", errorResponse);
console.log("Status:", errorResponse.status);
console.log("Response Text:", errorResponse.responseText);
}
});
}
</script>
<body>
<button type="button" onclick="invokeAjax()" >Submit</button>
</body>
</html>现在,当invokeAjax()函数被调用时,jQuery会向PropertyTesting Action发送POST请求。Struts 2将执行PropertyTesting Action的execute()方法,填充jsonResponseData属性。随后,JSON插件会捕获jsonResponseData属性的值(通过getJsonResponseData()方法),将其序列化为JSON字符串,并以application/json的Content-Type返回给客户端。前端的jQuery AJAX请求就能成功解析这个JSON响应,并在success回调中处理数据。
解决Struts 2与AJAX集成时JSON响应解析失败的关键在于理解Struts 2 JSON插件的工作机制。它通过序列化Action中的公共属性来生成JSON响应,而不是依赖于Action手动写入响应流。通过在Action中定义一个带有公共getter方法的属性(如Map或自定义POJO)来承载需要返回的JSON数据,并配合正确的struts.xml配置,可以确保后端成功生成符合预期的JSON响应,前端AJAX也能顺利解析,从而实现高效可靠的前后端数据交互。
以上就是Struts 2与AJAX集成:JSON响应解析失败的排查与解决的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号