隨筆-42  評(píng)論-578  文章-1  trackbacks-0

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

          其中,不管是從瀏覽器端(JS,Ajax,Jquery等)發(fā)送給服務(wù)器端,還是從服務(wù)器端(Struts的Action,Servlet等)發(fā)送回客戶端,都要識(shí)別一點(diǎn):發(fā)送的都應(yīng)該是JSON格式的字符串。

          下面,我們先來(lái)重寫登錄模塊中的loginform.jsp文件,原來(lái)的代碼,請(qǐng)看Struts 2.1.6 精簡(jiǎn)實(shí)例系列教程(2):用戶登錄模塊的實(shí)現(xiàn),現(xiàn)在修改的代碼如下:

          <%@ 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>登錄頁(yè)</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();    //獲取賬號(hào)
                      var password1 = $("input[name='password']").val();        //獲取密碼

                      
          var jsonUser = {loginName:loginName1, password:password1};    //JSON對(duì)象
                      
                      
          //注意:jsonUser.toString()這種方法錯(cuò)誤,javaScript中的toString是用于布爾型變量的,而應(yīng)用以下方法
                      var strUser = JSON.stringify(jsonUser);    //將JSON對(duì)象轉(zhuǎn)變成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";    //跳轉(zhuǎn)到后臺(tái)主頁(yè)
                      }

                  }

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

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

          </body>
          </html>

          關(guān)鍵的兩句是:

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

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

          第(2)句,相當(dāng)重要,通過(guò)JavaScript內(nèi)置對(duì)象JSON的stringify方法,將JSON對(duì)象轉(zhuǎn)換成字符串。因?yàn)椋覀儌魉徒o服務(wù)器端的要是JSON格式的字符串。

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

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

          回調(diào)函數(shù)(callback)是指服務(wù)器端成功發(fā)回時(shí),在JS端執(zhí)行的函數(shù)。最后一個(gè)參數(shù)“json”是返回?cái)?shù)據(jù)類型的一種,另外,還有”text”、“xml”等。而function callback函數(shù)體的內(nèi)容,大家看完LoginAction類后,自然會(huì)明白。

          好,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傳遞數(shù)據(jù)的載體
              public String getJson() {
                  
          return json;
              }

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


              
          /**
               * 登錄驗(yàn)證
               * 
          @throws Exception
               
          */

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

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

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

              
              
          /**
               * 向客戶端的JS發(fā)送字符串
               * 
          @param content 發(fā)送的內(nèi)容
               * 
          @throws IOException
               
          */

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

              
          }

           

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

          大家注意,在valid方法體中,引進(jìn)了org.json.JSONObject,這個(gè)類哪里來(lái)?請(qǐng)看:http://www.json.org/java/index.html,這里有幾個(gè)處理JSON數(shù)據(jù)常用的類:JSONObject.javaJSONArray.javaJSONStringer.javaJSONWriter.javaJSONTokener.javaJSONException.javaJSONString.java,將它們下載下來(lái),放到項(xiàng)目中,如下:

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

          網(wǎng)上有另一個(gè)JSON的類庫(kù):json-lib,大家也可下載使用一下,不過(guò),它要引進(jìn)幾個(gè)其他的jar包,詳細(xì)請(qǐng)見(jiàn)http://json-lib.sourceforge.net/。個(gè)人使用它的感受,也真有點(diǎn)郁悶,測(cè)試它時(shí),想找一個(gè)從JSON字符串轉(zhuǎn)換成JSON對(duì)象的方法,找了半天也沒(méi)找到。不過(guò),它對(duì)Java的Bean,Map,List等與JSONObject的互轉(zhuǎn)換做得還好。

          sendMsg方法,是從Struts的Action中調(diào)用回原生Servlet的response來(lái)向?yàn)g覽器端發(fā)送數(shù)據(jù)。

          還有一點(diǎn),大家應(yīng)該注意到,我們?cè)贚oginAction中寫的valid方法返回類型是void型的,跟我們以前做的返回“success”、”input”之類的String類型不同。當(dāng)我們通過(guò) “!valid”來(lái)方法它時(shí),它不作跳轉(zhuǎn),而是像我們平時(shí)Servlet中那種直接顯示HTML類似。這一點(diǎn)達(dá)成了Ajax與Struts的成功交互。而網(wǎng)上許多寫jsonplugin插件使用的文章,所調(diào)用的方法都是返回String類型,然后,再來(lái)個(gè)<result type=”json”>,那樣感覺(jué)挺麻煩的,不如直接讓Ajax發(fā)來(lái)的請(qǐng)求與void類型的方法交互,不直接爽快?

          好,讓我們運(yùn)行一下,看看效果吧:

          image

          image

          大家看看fireFox的debug的控制臺(tái)中顯示的:

          image

          image

          好,我們來(lái)輸入一個(gè)正確的賬號(hào)和密碼,如下:

          image

          點(diǎn)確定后,網(wǎng)頁(yè)就跳到了后臺(tái)主頁(yè)。

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

          關(guān)于Struts2,JSON,Jquery的話題,我們會(huì)在Struts2.1.6精簡(jiǎn)實(shí)例系列教程之外,繼續(xù)討論。



          本文原創(chuàng),轉(zhuǎn)載請(qǐng)注明出處,謝謝!http://www.aygfsteel.com/rongxh7(心夢(mèng)帆影JavaEE技術(shù)博客)
              

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

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

          那是因?yàn)闆](méi)有意義,只是發(fā)送數(shù)據(jù)而已,何必非要json格式的字符串,
          前臺(tái)需要將js對(duì)象格式化,后臺(tái)又得來(lái)解析,完全的無(wú)用功

            回復(fù)  更多評(píng)論
            
          # re: Struts 2.1.6 精簡(jiǎn)實(shí)例系列教程(6):重寫用戶登錄模塊(整合Jquery+JSON) 2009-09-01 11:46 | savage
          callback function should be:
          function callback(json){
          var user = eval('('+json+')');
          alert(json.msg);
          }  回復(fù)  更多評(píng)論
            
          # re: Struts 2.1.6 精簡(jiǎn)實(shí)例系列教程(6):重寫用戶登錄模塊(整合Jquery+JSON) 2009-09-01 14:02 | savage
          看你用的是ff
          ie8 對(duì)JSON.stringify支持不好,試一試!  回復(fù)  更多評(píng)論
            
          # re: Struts 2.1.6 精簡(jiǎn)實(shí)例系列教程(6):重寫用戶登錄模塊(整合Jquery+JSON) 2009-09-02 13:19 | haray
          我的action里怎么獲取不到客戶端傳過(guò)來(lái)的值呢?  回復(fù)  更多評(píng)論
            
          # re: Struts 2.1.6 精簡(jiǎn)實(shí)例系列教程(6):重寫用戶登錄模塊(整合Jquery+JSON) 2009-12-29 18:41 | maxthon
          博主能不能把這個(gè)每一講的代碼打包提供以下下載啊 萬(wàn)分感謝啊  回復(fù)  更多評(píng)論
            
          # re: Struts 2.1.6 精簡(jiǎn)實(shí)例系列教程(6):重寫用戶登錄模塊(整合Jquery+JSON) 2012-04-01 08:37 | wdw
          您好,為什么我的獲取不到返回信息呢?
          感覺(jué)是function callback(json)沒(méi)有執(zhí)行
          博主能不能把struts中action的配置發(fā)出來(lái)看看
          3q~~  回復(fù)  更多評(píng)論
            
          主站蜘蛛池模板: 惠安县| 眉山市| 九台市| 方城县| 兴安盟| 济阳县| 廉江市| 沙湾县| 临泽县| 彰化县| 甘德县| 师宗县| 廉江市| 老河口市| 漯河市| 望城县| 宜黄县| 克山县| 密云县| 武宣县| 松江区| 江油市| 庆安县| 荣昌县| 无棣县| 裕民县| 台州市| 绥江县| 镶黄旗| 昌黎县| 临沭县| 濮阳县| 满洲里市| 开封县| 邵东县| 巫山县| 衡南县| 句容市| 连江县| 海兴县| 搜索|