Ajax请求数据提示org.apache.struts2.json.JSONException错误

2 篇文章 0 订阅
1 篇文章 0 订阅
使用Ajax请求Action中数据,网页提示“org.apache.struts2.json.JSONException”与“java.sql.SQLException: Positioned Update not supported.”错误,如图:
Ajax请求数据提示org.apache.struts2.json.JSONException错误 - lemmata - 联墨-Lemmata
 
笔者发现在程序中确实使用了Ajax与Action交互数据,web页面代码如下所示:
  
  
$(function() {
$.post("Inspection_ready.action", null, function(data) {
if (data.Clients.length != 0) {
for ( var i in data.Clients) {
$("<option value='"+data.Clients[i].cid+"'>" +data.Clients[i].cname + "</option>")
.appendTo($("#weituo"));
}
}
});
$("#weituo").change(function() {
$.post("Inspection_selectClientById.action", {
id : $("#weituo").val()
}, function(data) {
$("#simplename").val(data.Client.simplename);
$("#simplename1").val(data.Client.simplename);
});
})
}

Action中相应代码如下所示:
  
  
public String ready(){
datemap = new HashMap<String,Object>();
List<Client> clients = iinspection.getClientAll();
//集合对象用于封装返回的clients集合数据
datemap.put("Clients", clients);
return SUCCESS;
}
public String selectClientById() {
client = iinspection.selectBycid(id);
//datemap集合对象,用于封装返回的client数据
datemap.put("Client", client);
return SUCCESS;
}

Struts2配置文件struts.xml中的设置:
  
  
<action name="Inspection_*" class="inspectionAction" method="{1}">
<result  name="success"  type="json" >
<param name="root">datemap</param>
</result>
</action>

页面加载完毕后首先与服务器交互获取内容,用于为下拉列表初始化数据,当下拉列表切换选项时再与服务器交互根据选中内容检索数据,如图:
Ajax请求数据提示org.apache.struts2.json.JSONException错误 - lemmata - 联墨-Lemmata
但初次交互时并没有出现问题,可以成功返回clients集合,如图所示:
Ajax请求数据提示org.apache.struts2.json.JSONException错误 - lemmata - 联墨-Lemmata
 
说明Struts2的JSON插件可以成功根据集合自动生成JSON数据,但是当列表的change事件触发再次检索数据时,却发生了如题所述错误。
根据提问者描述,如果在Action类型之前添加“@Scope("prototype")”注解,程序出现错误,如果去除此项注解,程序可以正确运行,但返回的结果变为以下效果,如图:
Ajax请求数据提示org.apache.struts2.json.JSONException错误 - lemmata - 联墨-Lemmata
 
这与程序的执行流程不符,因为第二次change检索数据并没有调用ready方法返回clients数据,笔者在调试过程中发现以下关键点:
1. Action注解:
  
  
@Controller
@Scope("prototype")
public class InspectionAction extends ActionSupport 
2. Map注解:
  
  
@Resource
private Map<String,Object> datemap;
3. Map创建新对象:
  
  
datamap = new HashMap<String,Object>();
List<Client> clients = iinspection.getClientAll();

我们逐条分析:
1.@Scope注解的作用:表示交由Spring托管对象的作用域,默认情况下作用域为“singleton”,即每次发起请求,都获取Spring容器中相同的对象实例。而Scope取值“prototype”时,表示非单例,即每次发起请求都会创建新的对象。

去掉Action类型之前的“@Scope("prototype")”注解,表示采用Spring的默认设置,即单例模式,此时Action中的所有成员如果没有重新赋值,则保留默认状态,以此可以解释第二次返回结果中为何包含“clients”集合,是由于Action单例,其中的datemap集合常驻容器并未清空。

2.@Resource注解的作用:类中成员属性的自动装配,默认按照属性名称自动装配,如果找不到与名称匹配的bean,则按照类型进行装配。以此可以解释添加“@Scope("prototype")”注解,以非单例方式创建Action并调用selectClientById方法时,可以直接使用datemap对象,而没有抛出NullPointerException异常,是由于Spring自动装配了datemap,而不用手动new此对象。既然datemap可以直接使用,为何还会抛出“JSONException”,经过调试笔者发现,初次访问进入ready()方法时,datemap对象为HashMap<k,v>类型,如图:
Ajax请求数据提示org.apache.struts2.json.JSONException错误 - lemmata - 联墨-Lemmata 
 
而此二次访问进入selectClientById方法时,datemap为LinkedHashMap类型,如图:
Ajax请求数据提示org.apache.struts2.json.JSONException错误 - lemmata - 联墨-Lemmata

因此可以得出结论了, 问题的核心在于datemap = new HashMap<String,Object>();,初次访问时程序员手动构建datemap对象,第二次访问时使用了spring自动装配的datemap对象,默认数值不同,因此JSON无法封装。于是 决绝方案也可提出,无论是否对Action添加“@Scope("prototype")”注解,都不是造成本问题的核心原因,手动创建datemap对象才是核心原因,建议datemap之前不要添加注解,其属于此Action专有属性,无需在多个Action间共享,使用时手动开辟空间即可,不需要使用spring自动装配。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值