隨筆-42  評論-578  文章-1  trackbacks-0

          網上有許多關于Struts2與JSON的文章,Google加百度,查閱了許多,有各種各樣的做法。其中,大部分的文章都說要加進一個叫jsonplugin的插件,在Google Code可以下載。以前我有做過測試,也是用它,但著實麻煩,要讓Struts2的package繼承一個叫“json-default”的父package。網上的文章,大部分都是說從Struts的Action如何把JSON數據發送回瀏覽器端(Ajax),而我想要一個跟它們相反的過程(即從Ajax端發送數據到服務器端的Action并解析出來),卻找不到合適的答案。摸索了三個晚上,未果。今天終于讓我找到了思路。

          其中,不管是從瀏覽器端(JS,Ajax,Jquery等)發送給服務器端,還是從服務器端(Struts的Action,Servlet等)發送回客戶端,都要識別一點:發送的都應該是JSON格式的字符串。

          下面,我們先來重寫登錄模塊中的loginform.jsp文件,原來的代碼,請看Struts 2.1.6 精簡實例系列教程(2):用戶登錄模塊的實現,現在修改的代碼如下:

          <%@ page language="java" contentType="text/html; charset=UTF-8"
              pageEncoding
          ="UTF-8"
          %>
          <%@ taglib prefix="s" uri="/struts-tags" %>
          <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
          <html>
          <head>
          <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
          <title>登錄頁</title>
          <script type="text/javascript" src="js/jquery-1.3.2.min.js"></script>
          <script type="text/javascript">
              $(
          function(){

                  $(
          "#submit").click(function(){
                      
          var loginName1 = $("input[name='loginName']").val();    //獲取賬號
                      var password1 = $("input[name='password']").val();        //獲取密碼

                      
          var jsonUser = {loginName:loginName1, password:password1};    //JSON對象
                      
                      
          //注意:jsonUser.toString()這種方法錯誤,javaScript中的toString是用于布爾型變量的,而應用以下方法
                      var strUser = JSON.stringify(jsonUser);    //將JSON對象轉變成JSON格式的字符串,
                      
                      $.post(
          "login!valid.action"{json: strUser}, callback, "json");
                  }
          );

                  
          function callback(json){
                      alert(json.msg);    
          //顯示反饋信息
                      if(json.suc == 1){    //如果返回"登錄成功"
                          window.location.href = "admin/index.action";    //跳轉到后臺主頁
                      }

                  }

                  
              }
          );
          </script>
          </head>
          <body>

          <form action="login.action" method="post">
              賬號
          <input type="text" name="loginName"/><br/>
              密碼
          <input type="password" name="password"><br/>
              
          <input type="button" id="submit" value="登錄"/>
          </form>

          </body>
          </html>

          關鍵的兩句是:

          var jsonUser = {loginName:loginName1, password:password1};    (1)
          var strUser = JSON.stringify(jsonUser);                                         (2)

          第(1)句是組裝JSON對象,關于JSON對象的格式,建議大家到http://www.json.org/網站上學習一下,要驗證你寫的JSON對象是否正確,可在http://json.bloople.net/網站上驗證。上面寫的JSON對象其實是非常簡單的一種,jsonUser對象里有兩個屬性,分別是loginName和password,而表示這兩個屬性,用key-value的形式,loginName1和password1分別是接收表單中的賬號、密碼的值。

          第(2)句,相當重要,通過JavaScript內置對象JSON的stringify方法,將JSON對象轉換成字符串。因為,我們傳送給服務器端的要是JSON格式的字符串。

          $.post("login!valid.action", {json: strUser}, callback, "json");

          這一句,Jquery用POST方法向服務器端發送數據,login!valid.action是我們要發送到的目的URI,也即直達loginAction的valid方法。而{…}是我們要發送的數據(data),{json:strUser},其實也是一個JSON對象,Key:value的形式,大家注意,我們把strUser這個json串發過去,在Action那里接收時,要接收“json”這個變量,這個變量的值就是我們發送的strUser字符串。

          回調函數(callback)是指服務器端成功發回時,在JS端執行的函數。最后一個參數“json”是返回數據類型的一種,另外,還有”text”、“xml”等。而function callback函數體的內容,大家看完LoginAction類后,自然會明白。

          好,Show一下修改后的LoginAction.java,代碼如下:

          package cn.simple.action;

          import java.io.IOException;
          import javax.servlet.http.HttpServletResponse;
          import org.apache.struts2.ServletActionContext;
          import org.apache.struts2.convention.annotation.Result;
          import org.apache.struts2.convention.annotation.Results;
          import org.json.JSONObject;
          import cn.simple.manager.UserManager;
          import cn.simple.pojo.User;
          import com.opensymphony.xwork2.ActionSupport;

          //@Results({
          //    @Result(name="success", location="admin/index.action", type="redirect"),
          //    @Result(name="input", location="loginform.jsp", type="dispatcher")
          //})
          public class LoginAction extends ActionSupport {

              
          private String json;    //JSON字符串,JS與Action傳遞數據的載體
              public String getJson() {
                  
          return json;
              }

              
          public void setJson(String json) {
                  
          this.json = json;
              }


              
          /**
               * 登錄驗證
               * 
          @throws Exception
               
          */

              
          public void valid() throws Exception {
                  
                  JSONObject jsonObj 
          = new JSONObject(json);    //將JSON格式的字符串構造成JSON對象
                  String loginName = jsonObj.getString("loginName"); //獲取JSON對象中的loginName屬性的值
                  String password = jsonObj.getString("password");    //獲取JSON對象中的password屬性的值
                  
                  User user 
          = UserManager.selectUserByLoginName(loginName);    //查詢是否有用戶名存在

                  
          if(user==null){
                      
          //此時的JSON對象,有兩個屬性suc和msg,其中suc表示是否登錄成功的狀態
                      json = "{suc:0, msg:'用戶名不存在'}";    //構造JSON格式的字符串
                  }
           else if! password.equals(user.getPassword())){
                      json 
          = "{suc:0, msg:'密碼不正確!'}";
                  }
           else {
                      json 
          = "{suc:1, msg:'登錄成功!'}";
                  }

                  sendMsg(json);    
          //發送JSON格式的字符串回JS端
              }

              
              
          /**
               * 向客戶端的JS發送字符串
               * 
          @param content 發送的內容
               * 
          @throws IOException
               
          */

              
          public void sendMsg(String content) throws IOException{
                  HttpServletResponse response 
          = ServletActionContext.getResponse();
                  response.setCharacterEncoding(
          "UTF-8");
                  response.getWriter().write(content);
              }

              
          }

           

          我們說過了,JS與Action互相傳送的是JSON格式的字符串,故在LoginAction里,我們定義了private String json這個成員屬性及其getter和setter方法。

          大家注意,在valid方法體中,引進了org.json.JSONObject,這個類哪里來?請看:http://www.json.org/java/index.html,這里有幾個處理JSON數據常用的類:JSONObject.javaJSONArray.javaJSONStringer.javaJSONWriter.javaJSONTokener.javaJSONException.javaJSONString.java,將它們下載下來,放到項目中,如下:

          image 
          或者,打成jar包,放到項目lib目錄下。我們就可以使用JSON類庫提供給我們的方法了。

          網上有另一個JSON的類庫:json-lib,大家也可下載使用一下,不過,它要引進幾個其他的jar包,詳細請見http://json-lib.sourceforge.net/。個人使用它的感受,也真有點郁悶,測試它時,想找一個從JSON字符串轉換成JSON對象的方法,找了半天也沒找到。不過,它對Java的Bean,Map,List等與JSONObject的互轉換做得還好。

          sendMsg方法,是從Struts的Action中調用回原生Servlet的response來向瀏覽器端發送數據。

          還有一點,大家應該注意到,我們在LoginAction中寫的valid方法返回類型是void型的,跟我們以前做的返回“success”、”input”之類的String類型不同。當我們通過 “!valid”來方法它時,它不作跳轉,而是像我們平時Servlet中那種直接顯示HTML類似。這一點達成了Ajax與Struts的成功交互。而網上許多寫jsonplugin插件使用的文章,所調用的方法都是返回String類型,然后,再來個<result type=”json”>,那樣感覺挺麻煩的,不如直接讓Ajax發來的請求與void類型的方法交互,不直接爽快?

          好,讓我們運行一下,看看效果吧:

          image

          image

          大家看看fireFox的debug的控制臺中顯示的:

          image

          image

          好,我們來輸入一個正確的賬號和密碼,如下:

          image

          點確定后,網頁就跳到了后臺主頁。

          這樣,Ajax(Jquery)與Struts2.1.6的交互,通過JSON格式的字符串傳遞數據,這一實踐就完成了。有一點需要說明一下:本例中的JSON對象都是相對比較簡單,還有一些復雜的JSON對象,如{company:{building:”五角大樓”,employees:[{name:”tom”,age:21},{name:”marry”,age:18} ] } }。至于這些,該怎么處理呢?其實,處理方法也一樣的。只是在Action中調用JSON類庫的一些對象和方法,就能很好地處理。

          關于Struts2,JSON,Jquery的話題,我們會在Struts2.1.6精簡實例系列教程之外,繼續討論。



          本文原創,轉載請注明出處,謝謝!http://www.aygfsteel.com/rongxh7(心夢帆影JavaEE技術博客)
              

          posted on 2009-08-14 22:32 心夢帆影 閱讀(9461) 評論(10)  編輯  收藏 所屬分類: Struts2.1.6系列教程

          評論:
          # re: Struts 2.1.6 精簡實例系列教程(6):重寫用戶登錄模塊(整合Jquery+JSON) 2009-08-15 12:44 | 99讀書人
          圣誕節發生的糾紛  回復  更多評論
            
          # re: Struts 2.1.6 精簡實例系列教程(6):重寫用戶登錄模塊(整合Jquery+JSON)[未登錄] 2009-08-17 10:46 | ruislan
          建議你看看org.apache.struts2.interceptor.validation.JSONValidationInterceptor,那里有你的做法,至于不跳轉嘛用Action.NONE或者return null也是可以的,當然jsonplugin也提供了很好的途徑,而且我認為不應該直接用json-default(還有defaultStack)的配置,或者說本身就該定制自己的ajax的interceptor chain,和默認的Interceptor chain。  回復  更多評論
            
          # re: Struts 2.1.6 精簡實例系列教程(6):重寫用戶登錄模塊(整合Jquery+JSON) 2009-08-17 17:21 | 心夢帆影
          @ruislan
          好,非常感謝你提的建議!  回復  更多評論
            
          # re: Struts 2.1.6 精簡實例系列教程(6):重寫用戶登錄模塊(整合Jquery+JSON) 2009-08-18 20:40 | 開機
          頂,寫的很清楚很詳細。  回復  更多評論
            
          # re: Struts 2.1.6 精簡實例系列教程(6):重寫用戶登錄模塊(整合Jquery+JSON) 2009-08-26 11:18 | westlwt
          "網上的文章,大部分都是說從Struts的Action如何把JSON數據發送回瀏覽器端(Ajax),而我想要一個跟它們相反的過程(即從Ajax端發送數據到服務器端的Action并解析出來),卻找不到合適的答案"

          那是因為沒有意義,只是發送數據而已,何必非要json格式的字符串,
          前臺需要將js對象格式化,后臺又得來解析,完全的無用功

            回復  更多評論
            
          # re: Struts 2.1.6 精簡實例系列教程(6):重寫用戶登錄模塊(整合Jquery+JSON) 2009-09-01 11:46 | savage
          callback function should be:
          function callback(json){
          var user = eval('('+json+')');
          alert(json.msg);
          }  回復  更多評論
            
          # re: Struts 2.1.6 精簡實例系列教程(6):重寫用戶登錄模塊(整合Jquery+JSON) 2009-09-01 14:02 | savage
          看你用的是ff
          ie8 對JSON.stringify支持不好,試一試!  回復  更多評論
            
          # re: Struts 2.1.6 精簡實例系列教程(6):重寫用戶登錄模塊(整合Jquery+JSON) 2009-09-02 13:19 | haray
          我的action里怎么獲取不到客戶端傳過來的值呢?  回復  更多評論
            
          # re: Struts 2.1.6 精簡實例系列教程(6):重寫用戶登錄模塊(整合Jquery+JSON) 2009-12-29 18:41 | maxthon
          博主能不能把這個每一講的代碼打包提供以下下載啊 萬分感謝啊  回復  更多評論
            
          # re: Struts 2.1.6 精簡實例系列教程(6):重寫用戶登錄模塊(整合Jquery+JSON) 2012-04-01 08:37 | wdw
          您好,為什么我的獲取不到返回信息呢?
          感覺是function callback(json)沒有執行
          博主能不能把struts中action的配置發出來看看
          3q~~  回復  更多評論
            
          主站蜘蛛池模板: 祥云县| 石首市| 长沙县| 连平县| 汽车| 通辽市| 新宁县| 龙岩市| 邵东县| 荔波县| 临沭县| 仙桃市| 塔河县| 祁门县| 清苑县| 广南县| 怀宁县| 平遥县| 惠东县| 岱山县| 苍溪县| 涟水县| 贵阳市| 浪卡子县| 甘孜县| 大城县| 虎林市| 仁化县| 喀什市| 建平县| 南康市| 从江县| 临夏县| 青河县| 蓝田县| 杂多县| 曲水县| 华容县| 桦甸市| 泽普县| 江陵县|