ssh与ajax结合之json异常:org.apache.struts2.json.JSONException

30 篇文章 0 订阅
24 篇文章 0 订阅

在ssh和ajax结合实现异步传输时,经常会出现的一个问题是,json格式的数据从后台传递到页面后无法解析,下面的data即是回调函数中参数,在页面断点后会看到data接收到的是下面一堆数据,其实是异常信息。

------------------------------------------------------------------------------------------

data
"<html>
<head>
    <title>Struts Problem Report</title>
    <style>
     pre {
      margin: 0;
         padding: 0;
     }    
    </style>
</head>
<body>
    <h2>Struts Problem Report</h2>
    <p>
    Struts has detected an unhandled exception:
    </p>
<div id="exception-info">
<table>
    <tr>
        <td><strong>Messages</strong>:</td>
        <td>
            <ol>
                        <li>Positioned Update not supported.</li>
                        <li>java.lang.reflect.InvocationTargetException</li>
                        <li>org.apache.struts2.json.JSONException: java.lang.reflect.InvocationTargetException</li>
                        <li>org.apache.struts2.json.JSONException: org.apache.struts2.json.JSONException:java.lang.reflect.InvocationTargetException</li>
                        <li>org.apache.struts2.json.JSONException: org.apache.struts2.json.JSONException: org.apache.struts2.json.JSONException: java.lang.reflect.InvocationTargetException</li>
            </ol>
        </td>
    </tr>
    <tr>
        <td><strong>File</strong>:</td>
        <td>com/mysql/jdbc/SQLError.java</td>
    </tr>
    <tr>
        <td><strong>Line number</strong>:</td>
        <td>1,055</td>
    </tr>    
</table>
</div>
<div id="stacktraces">
<hr />
<h3>Stacktraces</h3>
<div class="stacktrace" style="padding-left: 0em">
    <strong>org.apache.struts2.json.JSONException: org.apache.struts2.json.JSONException: org.apache.struts2.json.JSONException: org.apache.struts2.json.JSONException: org.apache.struts2.json.JSONException: java.lang.reflect.InvocationTargetException</strong>
    <div>
    <pre>
    org.apache.struts2.json.JSONWriter.bean(JSONWriter.java:243)
    org.apache.struts2.json.JSONWriter.process(JSONWriter.java:165)
    org.apache.struts2.json.JSONWriter.value(JSONWriter.java:131)
    org.apache.struts2.json.JSONWriter.write(JSONWriter.java:99)
    org.apache.struts2.json.JSONUtil.serialize(JSONUtil.java:112)
    org.apache.struts2.json.JSONResult.execute(JSONResult.java:198)    com.opensymphony.xwork2.DefaultActionInvocation.executeResult(DefaultActionInvocation.java:362)    com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:266)    com.opensymphony.xwork2.interceptor.DefaultWorkflowInterceptor.doIntercept(DefaultWorkflowInterceptor.java:165)    com.opensymphony.xwork2.interceptor.MethodFilterInterceptor.intercept(MethodFilterInterceptor.java:87)    com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:237)    com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:237)    com.opensymphony.xwork2.interceptor.ParametersInterceptor.doIntercept(ParametersInterceptor.java:195)    com.opensymphony.xwork2.interceptor.MethodFilterInterceptor.intercept(MethodFilterInterceptor.java:87)    com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:237)    com.opensymphony.xwork2.interceptor.ParametersInterceptor.doIntercept(ParametersInterceptor.java:195)    com.opensymphony.xwork2.interceptor.MethodFilterInterceptor.intercept(MethodFilterInterceptor.java:87)    com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:237)        org.apache.struts2.interceptor.FileUploadInterceptor.intercept(FileUploadInterceptor.java:235)
    com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:237)
    com.opensymphony.xwork2.interceptor.ExceptionMappingInterceptor.intercept(ExceptionMappingInterceptor.java:176)
    com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:237)
    org.apache.struts2.impl.StrutsActionProxy.execute(StrutsActionProxy.java:52)
    org.apache.struts2.dispatcher.Dispatcher.serviceAction(Dispatcher.java:488)
    org.apache.struts2.dispatcher.ng.ExecuteOperations.executeAction(ExecuteOperations.java:77)
    org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter.doFilter(StrutsPrepareAndExecuteFilter.java:91)
    org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
    org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
    org.springframework.orm.hibernate3.support.OpenSessionInViewFilter.doFilterInternal(OpenSessionInViewFilter.java:198)
    org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:76)    org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)    org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)    org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
    org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:293)
    org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:859)
    org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:602)
    org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:489)
    java.lang.Thread.run(Unknown Source)
    </pre>
    </div>
</div>

------------------------------------------------------------------------------------------

那么,为什么会出现这个异常呢?

究其原因,竟然是Hibernate的懒加载引起的。一定是你传递的数据中有引用类型的数据采用了懒加载机制。

比如:我要从Action中向前台传送一个Collection<Menuitem>,通过get方法

public Collection<Menuitem> getMenuitemList() {
  return this.menuitemList;
 }

而其中Menuitem类型的数据结构是:

public class Menuitem {
 private Long mid;
 private Long pid;//父节点
 private String name;//树的节点的名称
 private Boolean isParent;//是否为父节点
 private String icon;//图标的路径
 private Boolean checked;//复选框是否被选中
 /**
  * 菜单权限与用户是多对多的关系
  */
 private Set<User> users;

//getter(),setter()方法

}

在映射文件Menuitem.hbm.xml中users属性的配置如下:

<set name="users" table="user_menuitem" inverse="true">
         <key column="mid"></key>
         <many-to-many column="uid" class="cn.myoa.domain.User"></many-to-many>
</set>

未设置lazy="false",则默认采用懒加载模式。

当中间表user_menuitem中没有数据时,ok,不会牵涉到use表,也就不存在懒加载问题,运行一切正常。

但是当user_menuitem表中有数据,且数据与所传送的Menuitem对象有关时,就会有问题了

因为懒加载,这样在Action中获取的Menuitem对象中的users属性中的set集合中会存在user对象的引用,但是user的信息其实并未加载,

只有当用到时,容器才再次发出sql请求进行加载,但是在json插件对menuitemList进行处理以转换成json格式时,Hibernate Session早已关闭,这样user信息便加载不成功,而它又无法对set集合中空的引用进行处理,所以便抛出了JSONException。

有人可能会有疑问,我在web.xml中配置了OpenSessionInViewFilter过滤器,为什么Session还会关闭呢!?

这个疑问问的好!!我也不知何故,在网上也没找到相关的解释,不知是不是ajax的XMLHttpRequest的问题,

总之,在struts2与ajax结合的过程中,OpenSessionInView模式不起作用了!请知道的朋友不吝赐教!

 

好!既然知道了问题的原因,那么解决方法就很明了了!

方法一:设置lazy="false",即对user不采用懒加载。如

         <set name="users" table="user_menuitem" inverse="true"lazy="false">
         <key column="mid"></key>
         <many-to-many column="uid" class="cn.myoa.domain.User"></many-to-many>
         </set>

          不过这时要注意在User对象中有没有其他对象的引用,用过有,也要设置为非懒加载模式。

方法二:忽略set<User> users 属性,(推荐使用)

          如果在前台页面不需要使用该属性的话,就不要把他传到前台去,设置方法是在其getter方法上加一注解: @JSON(serialize=false)

          @JSON(serialize=false)
          public Set<User> getUsers() {
                  return users;
          }

         这样json插件在转换数据时就会忽略该属性。

现在问题应该已经解决了!!

下面关于struts2和ajax的结合还有几点建议:

1、在页面用不到的数据最好不要传到前台(这也是之所以推荐第二种方法的原因,传的数据越大,效率越低不是吗!)

2、不是向前台传数据的方法最好不要以get开头,json插件会把所有get开头的方法当做属性,转为json格式数据

3、如果方法必须以get开头,然而又不是为了转为json格式,那么可以在该方法上加注解:@JSON(serialize=false)

4、需要传到前台的数据,一定要在dao中加载完毕,不能使用懒加载模式。

 

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值