SSH里面使用jQuery的ajax


今天我真的很興奮!在我的SSH項目中用jQuery的異步傳輸成功了,經過一天多的奮戰,大工告成!

我的項目需求是在javascript中向我的controller(即:action)中傳輸form表單數據,傳輸到action的任意需要的方法中,處理完結果在返回給jQuery,顯示出來。

在其中,我遇到了好多問題(初次使用),但是呢,都慢慢的解決了!下面看一下我的項目:

1、首先在jsp頁面中我寫了javascript,如下:

 1 <script type="text/javascript" src="./js/jquery-1.10.2.js"></script>
 2 <script type="text/javascript">
 3 function mySearch(){
 4     var queryStr = "";
 5     var mydata = $("#myform").serialize();
 6     var url = "cwgl_searchByConditions";
 7     $.post(url,mydata,searchListCallBackFun,'json');
 8 };
 9 function searchListCallBackFun(data){
10     alert("進入回調函數");
11     alert(data.gshts);
12     $.each(data.gshts,function(index,gsht){
13         $("#gsht").append(
14                 "<tr><td>" + gsht.gsmc + "</td><td>" + gsht.dabh + "</td><td>" 
15                 + gsht.gshtbh + "</td><td>" + gsht.kh.khxm + "</td><td>"
16                 + gsht.kh.qc + "</td><td>" + gsht.khjhhkje + "</tr>"
17         );
18     });
19 };
View Code

在這里我是用的是jQuery的serialize()對我的表單進行序列化,形成形如{}的數據傳輸給action,之后struts2能夠很好的識別這種數據類型並轉化為對應的對象,這個不需要我們考慮,接下來是對action處理結果的返回,返回數據時我也遇到了很多問題,如:Class org.apache.struts2.json.JSONWriter can not access a member of class org.hibernate.persister.entity.AbstractEntityPersister$3 with modifiers "public";

這個問題是由於在我的action中有這樣的數據:private CwglService cwglService;這個接口是在Spring的管理下的,json無法取得,但是,我們也不需要這個接口,我所需要的只是返回的數據!因此在我的struts.xml配置里有了這樣的配置:<param name="excludeProperties">cwglService</param>排除接口。

另外的一個問題是:org.apache.struts2.json.JSONException: java.lang.reflect.InvocationTargetException是Hibernate的懶加載引起的。一定是你傳遞的數據中有引用類型的數據采用了懶加載機制,這個問題待會在下面有我看到的,覺得比較好,粘在了下面;

在我的struts.xml配置如下:

1 <package name="default" extends="struts-default,json-default">
2     <action name="cwgl_*" class="com.action.CwglAction" method="{1}">
3         <result name="ajysgl_lb" type="json">
4             <param name="excludeProperties">cwglService</param>
5                <param name="ignoreHierarchy">false</param>
6                <param name="excludeNullProperties">true</param>
7         </result>
8     </action>
9 </package>
View Code

之后就可以自如的使用jQuery與action的交互了!

處理問題時,見到比較好的解釋copy如下:

在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中加載完畢,不能使用懶加載模式。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM