1. 程式人生 > >【SSH網上商城專案實戰07】Struts2和Json的整合

【SSH網上商城專案實戰07】Struts2和Json的整合

 

 

轉自:https://blog.csdn.net/eson_15/article/details/51332758  

上一節我們完成了DataGrid顯示jason資料,但是沒有和後臺聯絡在一起,只是單純地顯示了我們自己弄的json資料,這一節我們將json和Struts2整合,打通EasyUI和Struts2之間的互動。

1. json環境的搭建
        json環境搭建很簡單,匯入json的jar包即可,如下:
--------------------- 
作者:eson_15 
來源:CSDN 
原文:https://blog.csdn.net/eson_15/article/details/51332758?utm_source=copy 
版權宣告:本文為博主原創文章,轉載請附上博文連結!

2. 完善Action
        在DataGrid控制元件中有個屬性是url,可以指定請求資料的url地址,在上一節我們將這個地址直接設定成了一個具體的json檔案,這裡我們將這個url設定成一個action,如url:'category_queryJoinAccount.action',表示會去請求categoryAction的queryJoinAccount方法(文章最後會給出query.jsp的程式碼)。所以我們需要去完成categoryAction中的queryJoinAccount方法。

        在Struts2和json整合前,我們先看一下之前顯示一次json資料都發了哪些請求:

因為type是Category類的一個屬性,我們在BaseAction中已經實現了ModelDriven<Category>介面,所以這個type會被封裝到model中,我們不需要管它,可以通過model來獲取,但是EasyUI自動發過來的page和rows引數我們需要自己獲取了,所以我們可以在BaseModel中增加兩個成員變數page和rows並實現get和set方法,最後還要考慮一點,這些引數都獲得了後,我們根據這些引數去資料庫中查詢資料,那麼我們查出來的資料放到哪呢?而且還要打包成json格式發到前臺才能被DataGrid顯示。我們先不考慮將查詢到的資料如何打包成json格式,我們先考慮把這些資料放到一個地方,很自然的想到了使用Map,因為json格式的資料就是key-value形式的。想到這裡,我們繼續完善BaseAction:

複製程式碼
 1 @Controller("baseAction")
 2 @Scope("prototype")
 3 public class BaseAction<T> extends ActionSupport implements RequestAware,SessionAware,ApplicationAware,ModelDriven<T> {
 4  
 5     //page和rows和分頁有關,pageMap存放查詢的資料,然後打包成json格式用的
 6     //page和rows實現get和set方法,pageMap只需要實現get方法即可,因為pageMap不是接收前臺引數的,是讓struts獲取的
 7     protected Integer page;
 8     protected Integer rows;
 9     protected Map<String, Object> pageMap = null;//讓不同的Action自己去實現
10         //省略get和set方法……
11     
12     /******************* 下面還是原來BaseAction部分 *************************/
13     //service物件
14     @Resource
15     protected CategoryService categoryService;
16     @Resource
17     protected AccountService accountService;
18  
19     //域物件
20     protected Map<String, Object> request;
21     protected Map<String, Object> session;
22     protected Map<String, Object> application;
23         
24     @Override
25     public void setApplication(Map<String, Object> application) {
26         this.application = application;
27     }
28     @Override
29     public void setSession(Map<String, Object> session) {
30         this.session = session;
31     }
32     @Override
33     public void setRequest(Map<String, Object> request) {
34         this.request = request;
35     }
36     
37     //ModelDriven
38     protected T model;
39     @Override
40     public T getModel() {
41         ParameterizedType type = (ParameterizedType)this.getClass().getGenericSuperclass();
42         Class clazz = (Class)type.getActualTypeArguments()[0];
43         try {
44             model = (T)clazz.newInstance();
45         } catch (Exception e) {
46             throw new RuntimeException(e);
47         }    
48         return model;
49     }
50 }
複製程式碼

  好,完善了BaseCategory後,我們可以寫categoryAction中的queryJoinAccount方法了,我們將categoryAction中原來的方法全刪掉,因為那些都是之前搭建環境時候測試用的,都不用了,現在真正開始專案程式碼了:

複製程式碼
 1 @Controller("categoryAction")
 2 @Scope("prototype")
 3 public class CategoryAction extends BaseAction<Category> {
 4     
 5     public String queryJoinAccount() {
 6  
 7         //用來儲存分頁的資料
 8         pageMap = new HashMap<String, Object>();
 9         
10         //根據關鍵字和分頁的引數查詢相應的資料。這個方法我們在Service中寫過了,當時完成級聯查詢
11         List<Category> categoryList = categoryService.queryJoinAccount(model.getType(), page, rows);
12         pageMap.put("rows", categoryList); //儲存為JSON格式,從上一節的json檔案可以看出,一個key是total,一個key是rows,這裡先把rows存放好
13         //根據關鍵字查詢總記錄數
14         Long total = categoryService.getCount(model.getType()); //這個方法沒寫,我們等會兒去Service層完善一下
15 //        System.out.println(total);
16         pageMap.put("total", total); //儲存為JSON格式,再把total存放好
17  
18         return "jsonMap";
19     }
20 }
複製程式碼

這樣Action我們就寫好了,現在Action拿到前臺傳來的引數,然後根據引數查詢了指定type的總記錄數,以及指定type的所有商品,並且按照json中指定的key(即total和rows)進行存放,放在HashMap中了,之後只要將這個HashMap中的資料打包成json格式傳送到前臺就可以被DataGrid顯示了。我們先把這個HashMap放這,先去完善了Service層的程式碼後,再來打包這個HashMap中的資料。

 

3. 完善categoryService
        從上面的categoryAction中可知,需要在categoryService中增加一個getCount方法,並且要在具體實現類中實現好,實現如下:

複製程式碼
 1 //CategoryService介面
 2 public interface CategoryService extends BaseService<Category> {
 3     //查詢類別資訊,級聯管理員
 4     public List<Category> queryJoinAccount(String type, int page, int size); //使用類別的名稱查詢
 5     //根據關鍵字查詢總記錄數
 6     public Long getCount(String type);
 7 }
 8  
 9 //CategoryServiceImpl實現類
10 @SuppressWarnings("unchecked")
11 @Service("categoryService")
12 public class CategoryServiceImpl extends BaseServiceImpl<Category> implements CategoryService {
13  
14     @Override
15     public List<Category> queryJoinAccount(String type, int page, int size) {
16         String hql = "from Category c left join fetch c.account where c.type like :type";
17         return getSession().createQuery(hql)
18                 .setString("type", "%" + type + "%")
19                 .setFirstResult((page-1) * size) //從第幾個開始顯示
20                 .setMaxResults(size) //顯示幾個
21                 .list();
22     }
23  
24     @Override
25     public Long getCount(String type) {
26         String hql = "select count(c) from Category c where c.type like :type";
27         return (Long) getSession().createQuery(hql)
28             .setString("type", "%" + type + "%")
29             .uniqueResult(); //返回一條記錄:總記錄數
30     }
31 }
複製程式碼

到現在為止,這個資料庫中資料的獲取這條路就打通了,前面兩步完成了從前臺-->資料庫-->取資料,接下來就開始打包HashMap中存放的資料,然後發給前臺了。

 

4. 配置struts.xml
        在struts.xml中通過配置就可以完成對指定資料的打包,我們先看一下struts.xml中的配置:

複製程式碼
 1 <struts>
 2     
 3     <constant name="struts.devMode" value="true" />
 4     
 5     <package name="shop" extends="json-default"><!-- jason-default繼承了struts-default -->
 6     
 7         <global-results>
 8             <result name="aindex">/WEB-INF/main/aindex.jsp</result>
 9         </global-results>
10  
11         <!-- class對應的是Spring中配置該Action的id值,因為要交給Spring管理 -->
12         <action name="category_*" class="categoryAction" method="{1}">
13             <!-- 必須要先新增json包,然後上面繼承json-default -->
14             <result name="jsonMap" type="json">
15                 <!-- 要轉換成json物件的資料 -->
16                 <param name="root">pageMap</param>
17                 <!-- 配置黑名單,過濾不需要的選項 ,支援正則表示式
18                 json格式:{total:3,rows:[{account:{id:2,login:"user",name:"客服A",pass:"user"},hot:true,id:3,…}]}
19                 -->
20                 <param name="excludeProperties">
21                     <!-- rows[0].account.pass-->
22                                         <!-- 這裡顯示不了正則表示式, CSDN的一個bug,我接個圖放下面 -->
23                  </param>
24              </result>
25         </action>
26         
27         <action name="account_*" class="accountAction" method="{1}">
28             <result name="index">/index.jsp</result>
29         </action>
30         
31         <!-- 用來完成系統 請求轉發的action,所有的請求都交給execute-->
32         <action name="send_*_*" class="sendAction">
33             <result name="send">/WEB-INF/{1}/{2}.jsp</result>
34         </action>
35     </package>
36  
37 </struts>
複製程式碼

     從上面的配置可以看出,首先package要繼承json-default,因為json-default繼承了struts-default,因為在json的jar包裡有個struts2-json-plugin-2.3.24.1.jar,開啟即可看到裡面有個struts-plugin.xml,開啟即可看到json-default是繼承了struts-default:

 接下來我配置<result>,name是剛剛action返回的字串,type一定要配成json。然後就是result中的引數了,首先必須要配的就是name為root的引數,這個引數要配成剛剛需要轉換的HashMap物件,即我們定義的pageMap,有了這個引數的配置,struts才會將pageMap中的資料打包成json格式。然後就是配置黑名單,黑名單的意思就是告訴struts在打包的時候,哪些欄位不需要打包,比如管理員密碼之類的資訊,由上面註釋中的jason格式可以看出rows[0].account.pass表示密碼欄位,但是資料肯定不止一條,所以我們得用正則表示式來表示,這樣所有密碼都不會被打包到json中。

5. 修改query.jsp內容
             到此,我們已經將資料打包成了json格式了,接下來我們完善一下前臺query.jsp的內容就可以讓DataGrid正確顯示了:

複製程式碼
 1 <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
 2 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
 3 <html>
 4   <head>
 5     <%@ include file="/public/head.jspf" %>
 6     <script type="text/javascript">
 7         $(function(){
 8             $('#dg').datagrid({   
 9                 //url地址改為請求categoryAction
10                 url:'category_queryJoinAccount.action',
11                 loadMsg:'Loading......',
12                 queryParams:{type:''},//type引數,這裡不需要傳具體的type,因為我們要顯示所有的
13                 //width:300,
14                 fitColumns:true,
15                 striped:true,
16                 nowrap:true,
17                 singleSelect:true,
18                 pagination:true,
19                 rowStyler: function(index,row){
20                     console.info("index" + index + "," + row)
21                     if(index % 2 == 0) {
22                         return '';
23                     } else {
24                         return '';
25                     }
26                     
27                 },        
28                 frozenColumns:[[
29                     {field:'checkbox',checkbox:true},
30                     {field:'id',title:'編號',width:200}    //這裡的field欄位要和json資料中的一樣             
31                 ]],
32                 columns:[[                       
33                     {field:'type',title:'類別名稱',width:100, //欄位type
34                         formatter: function(value,row,index){
35                             return "<span title=" + value + ">" + value + "</span>";
36                         }
37                     },    
38                     {field:'hot',title:'熱賣',width:100,  //欄位hot
39                         formatter: function(value,row,index){
40                             if(value) { //如果是hot,該值為true,value是boolean型變數
41                                 return "<input type='checkbox' checked='checked' disabled='true'"; //勾選
42                             } else {
43                                 return "<input type='checkbox' disable='true'"; //不勾選
44                             }
45                         }
46                     },
47                     {field:'account.login',title:'所屬管理員',width:200, //account.login管理員登入名
48                         formatter: function(value,row,index){
49                             if(row.account != null && row.account.login != null) {
50                                 return row.account.login; //如果登入名不為空,顯示登入名
51                             } else {
52                                 return "此類別沒有管理員";
53                             }
54                     }    
55                     }
56                 ]]    
57             }); 
58         });
59     </script>
60   </head>
61   
62   <body>
63       <table id="dg"></table>
64   </body>
65 </html>
複製程式碼

6.  測試顯示結果

        最後我們測試一下DataGrid的顯示結果,如下:

        到這裡,我們成功整合了Struts2和json,現在可以和前臺傳輸json格式的資料了。

 

轉自:https://blog.csdn.net/eson_15/article/details/51332758  

上一節我們完成了DataGrid顯示jason資料,但是沒有和後臺聯絡在一起,只是單純地顯示了我們自己弄的json資料,這一節我們將json和Struts2整合,打通EasyUI和Struts2之間的互動。

1. json環境的搭建
        json環境搭建很簡單,匯入json的jar包即可,如下:
--------------------- 
作者:eson_15 
來源:CSDN 
原文:https://blog.csdn.net/eson_15/article/details/51332758?utm_source=copy 
版權宣告:本文為博主原創文章,轉載請附上博文連結!

2. 完善Action
        在DataGrid控制元件中有個屬性是url,可以指定請求資料的url地址,在上一節我們將這個地址直接設定成了一個具體的json檔案,這裡我們將這個url設定成一個action,如url:'category_queryJoinAccount.action',表示會去請求categoryAction的queryJoinAccount方法(文章最後會給出query.jsp的程式碼)。所以我們需要去完成categoryAction中的queryJoinAccount方法。

        在Struts2和json整合前,我們先看一下之前顯示一次json資料都發了哪些請求:

因為type是Category類的一個屬性,我們在BaseAction中已經實現了ModelDriven<Category>介面,所以這個type會被封裝到model中,我們不需要管它,可以通過model來獲取,但是EasyUI自動發過來的page和rows引數我們需要自己獲取了,所以我們可以在BaseModel中增加兩個成員變數page和rows並實現get和set方法,最後還要考慮一點,這些引數都獲得了後,我們根據這些引數去資料庫中查詢資料,那麼我們查出來的資料放到哪呢?而且還要打包成json格式發到前臺才能被DataGrid顯示。我們先不考慮將查詢到的資料如何打包成json格式,我們先考慮把這些資料放到一個地方,很自然的想到了使用Map,因為json格式的資料就是key-value形式的。想到這裡,我們繼續完善BaseAction:

複製程式碼
 1 @Controller("baseAction")
 2 @Scope("prototype")
 3 public class BaseAction<T> extends ActionSupport implements RequestAware,SessionAware,ApplicationAware,ModelDriven<T> {
 4  
 5     //page和rows和分頁有關,pageMap存放查詢的資料,然後打包成json格式用的
 6     //page和rows實現get和set方法,pageMap只需要實現get方法即可,因為pageMap不是接收前臺引數的,是讓struts獲取的
 7     protected Integer page;
 8     protected Integer rows;
 9     protected Map<String, Object> pageMap = null;//讓不同的Action自己去實現
10         //省略get和set方法……
11     
12     /******************* 下面還是原來BaseAction部分 *************************/
13     //service物件
14     @Resource
15     protected CategoryService categoryService;
16     @Resource
17     protected AccountService accountService;
18  
19     //域物件
20     protected Map<String, Object> request;
21     protected Map<String, Object> session;
22     protected Map<String, Object> application;
23         
24     @Override
25     public void setApplication(Map<String, Object> application) {
26         this.application = application;
27     }
28     @Override
29     public void setSession(Map<String, Object> session) {
30         this.session = session;
31     }
32     @Override
33     public void setRequest(Map<String, Object> request) {
34         this.request = request;
35     }
36     
37     //ModelDriven
38     protected T model;
39     @Override
40     public T getModel() {
41         ParameterizedType type = (ParameterizedType)this.getClass().getGenericSuperclass();
42         Class clazz = (Class)type.getActualTypeArguments()[0];
43         try {
44             model = (T)clazz.newInstance();
45         } catch (Exception e) {
46             throw new RuntimeException(e);
47         }    
48         return model;
49     }
50 }
複製程式碼

  好,完善了BaseCategory後,我們可以寫categoryAction中的queryJoinAccount方法了,我們將categoryAction中原來的方法全刪掉,因為那些都是之前搭建環境時候測試用的,都不用了,現在真正開始專案程式碼了:

複製程式碼
 1 @Controller("categoryAction")
 2 @Scope("prototype")
 3 public class CategoryAction extends BaseAction<Category> {
 4     
 5     public String queryJoinAccount() {
 6  
 7         //用來儲存分頁的資料
 8         pageMap = new HashMap<String, Object>();
 9         
10         //根據關鍵字和分頁的引數查詢相應的資料。這個方法我們在Service中寫過了,當時完成級聯查詢
11         List<Category> categoryList = categoryService.queryJoinAccount(model.getType(), page, rows);
12         pageMap.put("rows", categoryList); //儲存為JSON格式,從上一節的json檔案可以看出,一個key是total,一個key是rows,這裡先把rows存放好
13         //根據關鍵字查詢總記錄數
14         Long total = categoryService.getCount(model.getType()); //這個方法沒寫,我們等會兒去Service層完善一下
15 //        System.out.println(total);
16         pageMap.put("total", total); //儲存為JSON格式,再把total存放好
17  
18         return "jsonMap";
19     }
20 }
複製程式碼

這樣Action我們就寫好了,現在Action拿到前臺傳來的引數,然後根據引數查詢了指定type的總記錄數,以及指定type的所有商品,並且按照json中指定的key(即total和rows)進行存放,放在HashMap中了,之後只要將這個HashMap中的資料打包成json格式傳送到前臺就可以被DataGrid顯示了。我們先把這個HashMap放這,先去完善了Service層的程式碼後,再來打包這個HashMap中的資料。

 

3. 完善categoryService
        從上面的categoryAction中可知,需要在categoryService中增加一個getCount方法,並且要在具體實現類中實現好,實現如下:

複製程式碼
 1 //CategoryService介面
 2 public interface CategoryService extends BaseService<Category> {
 3     //查詢類別資訊,級聯管理員
 4     public List<Category> queryJoinAccount(String type, int page, int size); //使用類別的名稱查詢
 5     //根據關鍵字查詢總記錄數
 6     public Long getCount(String type);
 7 }
 8  
 9 //CategoryServiceImpl實現類
10 @SuppressWarnings("unchecked")
11 @Service("categoryService")
12 public class CategoryServiceImpl extends BaseServiceImpl<Category> implements CategoryService {
13  
14     @Override
15     public List<Category> queryJoinAccount(String type, int page, int size) {
16         String hql = "from Category c left join fetch c.account where c.type like :type";
17         return getSession().createQuery(hql)
18                 .setString("type", "%" + type + "%")
19                 .setFirstResult((page-1) * size) //從第幾個開始顯示
20                 .setMaxResults(size) //顯示幾個
21                 .list();
22     }
23  
24     @Override
25     public Long getCount(String type) {
26         String hql = "select count(c) from Category c where c.type like :type";
27         return (Long) getSession().createQuery(hql)
28             .setString("type", "%" + type + "%")
29             .uniqueResult(); //返回一條記錄:總記錄數
30     }
31 }
複製程式碼

到現在為止,這個資料庫中資料的獲取這條路就打通了,前面兩步完成了從前臺-->資料庫-->取資料,接下來就開始打包HashMap中存放的資料,然後發給前臺了。

 

4. 配置struts.xml
        在struts.xml中通過配置就可以完成對指定資料的打包,我們先看一下struts.xml中的配置:

複製程式碼
 1 <struts>
 2     
 3     <constant name="struts.devMode" value="true" />
 4     
 5     <package name="shop" extends="json-default"><!-- jason-default繼承了struts-default -->
 6     
 7         <global-results>
 8             <result name="aindex">/WEB-INF/main/aindex.jsp</result>
 9         </global-results>
10  
11         <!-- class對應的是Spring中配置該Action的id值,因為要交給Spring管理 -->
12         <action name="category_*" class="categoryAction" method="{1}">
13             <!-- 必須要先新增json包,然後上面繼承json-default -->
14             <result name="jsonMap" type="json">
15                 <!-- 要轉換成json物件的資料 -->
16                 <param name="root">pageMap</param>
17                 <!-- 配置黑名單,過濾不需要的選項 ,支援正則表示式
18                 json格式:{total:3,rows:[{account:{id:2,login:"user",name:"客服A",pass:"user"},hot:true,id:3,…}]}
19                 -->
20                 <param name="excludeProperties">
21                     <!-- rows[0].account.pass-->
22                                         <!-- 這裡顯示不了正則表示式, CSDN的一個bug,我接個圖放下面 -->
23                  </param>
24              </result>
25         </action>
26         
27         <action name="account_*" class="accountAction" method="{1}">
28             <result name="index">/index.jsp</result>
29         </action>
30         
31         <!-- 用來完成系統 請求轉發的action,所有的請求都交給execute-->
32         <action name="send_*_*" class="sendAction">
33             <result name="send">/WEB-INF/{1}/{2}.jsp</result>
34         </action>
35     </package>
36  
37 </struts>
複製程式碼

     從上面的配置可以看出,首先package要繼承json-default,因為json-default繼承了struts-default,因為在json的jar包裡有個struts2-json-plugin-2.3.24.1.jar,開啟即可看到裡面有個struts-plugin.xml,開啟即可看到json-default是繼承了struts-default:

 接下來我配置<result>,name是剛剛action返回的字串,type一定要配成json。然後就是result中的引數了,首先必須要配的就是name為root的引數,這個引數要配成剛剛需要轉換的HashMap物件,即我們定義的pageMap,有了這個引數的配置,struts才會將pageMap中的資料打包成json格式。然後就是配置黑名單,黑名單的意思就是告訴struts在打包的時候,哪些欄位不需要打包,比如管理員密碼之類的資訊,由上面註釋中的jason格式可以看出rows[0].account.pass表示密碼欄位,但是資料肯定不止一條,所以我們得用正則表示式來表示,這樣所有密碼都不會被打包到json中。

5. 修改query.jsp內容
             到此,我們已經將資料打包成了json格式了,接下來我們完善一下前臺query.jsp的內容就可以讓DataGrid正確顯示了:

複製程式碼
 1 <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
 2 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
 3 <html>
 4   <head>
 5     <%@ include file="/public/head.jspf" %>
 6     <script type="text/javascript">
 7         $(function(){
 8             $('#dg').datagrid({   
 9                 //url地址改為請求categoryAction
10                 url:'category_queryJoinAccount.action',
11                 loadMsg:'Loading......',
12                 queryParams:{type:''},//type引數,這裡不需要傳具體的type,因為我們要顯示所有的
13                 //width:300,
14                 fitColumns:true,
15                 striped:true,
16                 nowrap:true,
17                 singleSelect:true,
18                 pagination:true,
19                 rowStyler: function(index,row){
20                     console.info("index" + index + "," + row)
21                     if(index % 2 == 0) {
22                         return '';
23                     } else {
24                         return '';
25                     }
26                     
27                 },        
28                 frozenColumns:[[
29                     {field:'checkbox',checkbox:true},
30                     {field:'id',title:'編號',width:200}    //這裡的field欄位要和json資料中的一樣             
31                 ]],
32                 columns:[[                       
33                     {field:'type',title:'類別名稱',width:100, //欄位type
34                         formatter: function(value,row,index){
35                             return "<span title=" + value + ">" + value + "</span>";
36                         }
37                     },    
38                     {field:'hot',title:'熱賣',width:100,  //欄位hot
39                         formatter: function(value,row,index){
40                             if(value) { //如果是hot,該值為true,value是boolean型變數
41                                 return "<input type='checkbox' checked='checked' disabled='true'"; //勾選
42                             } else {
43                                 return "<input type='checkbox' disable='true'"; //不勾選
44                             }
45                         }
46                     },
47                     {field:'account.login',title:'所屬管理員',width:200, //account.login管理員登入名
48                         formatter: function(value,row,index){
49                             if(row.account != null && row.account.login != null) {
50                                 return row.account.login; //如果登入名不為空,顯示登入名
51                             } else {
52                                 return "此類別沒有管理員";
53                             }
54                     }    
55                     }
56                 ]]    
57             }); 
58         });
59     </script>
60   </head>
61   
62   <body>
63       <table id="dg"></table>
64   </body>
65 </html>
複製程式碼

6.  測試顯示結果

        最後我們測試一下DataGrid的顯示結果,如下:

        到這裡,我們成功整合了Struts2和json,現在可以和前臺傳輸json格式的資料了。