轉自:http://blog.csdn.net/eson_15/article/details/51332758
上一節我們完成了DataGrid顯示jason數據,但是沒有和後臺聯繫在一起,只是單純地顯示了我們自己弄的json數據,這一節我們將json和Struts2整合,打通EasyUI和Struts2之間的交互。
1. json環境的搭建
json環境搭建很簡單,導入json的jar包即可,如下:
(注:json-lib-2.4的jar包下載地址:http://download.csdn.net/detail/eson_15/9514985 )
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:
- @Controller("baseAction")
- @Scope("prototype")
- public class BaseAction<T> extends ActionSupport implements RequestAware,SessionAware,ApplicationAware,ModelDriven<T> {
- //page和rows和分頁有關,pageMap存放查詢的數據,然後打包成json格式用的
- //page和rows實現get和set方法,pageMap只需要實現get方法即可,因爲pageMap不是接收前臺參數的,是讓struts獲取的
- protected Integer page;
- protected Integer rows;
- protected Map<String, Object> pageMap = null;//讓不同的Action自己去實現
- //省略get和set方法……
- /******************* 下面還是原來BaseAction部分 *************************/
- //service對象
- @Resource
- protected CategoryService categoryService;
- @Resource
- protected AccountService accountService;
- //域對象
- protected Map<String, Object> request;
- protected Map<String, Object> session;
- protected Map<String, Object> application;
- @Override
- public void setApplication(Map<String, Object> application) {
- this.application = application;
- }
- @Override
- public void setSession(Map<String, Object> session) {
- this.session = session;
- }
- @Override
- public void setRequest(Map<String, Object> request) {
- this.request = request;
- }
- //ModelDriven
- protected T model;
- @Override
- public T getModel() {
- ParameterizedType type = (ParameterizedType)this.getClass().getGenericSuperclass();
- Class clazz = (Class)type.getActualTypeArguments()[0];
- try {
- model = (T)clazz.newInstance();
- } catch (Exception e) {
- throw new RuntimeException(e);
- }
- return model;
- }
- }
@Controller("baseAction")
@Scope("prototype")
public class BaseAction<T> extends ActionSupport implements RequestAware,SessionAware,ApplicationAware,ModelDriven<T> {
//page和rows和分頁有關,pageMap存放查詢的數據,然後打包成json格式用的
//page和rows實現get和set方法,pageMap只需要實現get方法即可,因爲pageMap不是接收前臺參數的,是讓struts獲取的
protected Integer page;
protected Integer rows;
protected Map<String, Object> pageMap = null;//讓不同的Action自己去實現
//省略get和set方法……
/******************* 下面還是原來BaseAction部分 *************************/
//service對象
@Resource
protected CategoryService categoryService;
@Resource
protected AccountService accountService;
//域對象
protected Map<String, Object> request;
protected Map<String, Object> session;
protected Map<String, Object> application;
@Override
public void setApplication(Map<String, Object> application) {
this.application = application;
}
@Override
public void setSession(Map<String, Object> session) {
this.session = session;
}
@Override
public void setRequest(Map<String, Object> request) {
this.request = request;
}
//ModelDriven
protected T model;
@Override
public T getModel() {
ParameterizedType type = (ParameterizedType)this.getClass().getGenericSuperclass();
Class clazz = (Class)type.getActualTypeArguments()[0];
try {
model = (T)clazz.newInstance();
} catch (Exception e) {
throw new RuntimeException(e);
}
return model;
}
}
好,完善了BaseCategory後,我們可以寫categoryAction中的queryJoinAccount方法了,我們將categoryAction中原來的方法全刪掉,因爲那些都是之前搭建環境時候測試用的,都不用了,現在真正開始項目代碼了:
- @Controller("categoryAction")
- @Scope("prototype")
- public class CategoryAction extends BaseAction<Category> {
- public String queryJoinAccount() {
- //用來存儲分頁的數據
- pageMap = new HashMap<String, Object>();
- //根據關鍵字和分頁的參數查詢相應的數據。這個方法我們在Service中寫過了,當時完成級聯查詢
- List<Category> categoryList = categoryService.queryJoinAccount(model.getType(), page, rows);
- pageMap.put("rows", categoryList); //存儲爲JSON格式,從上一節的json文件可以看出,一個key是total,一個key是rows,這裏先把rows存放好
- //根據關鍵字查詢總記錄數
- Long total = categoryService.getCount(model.getType()); //這個方法沒寫,我們等會兒去Service層完善一下
- // System.out.println(total);
- pageMap.put("total", total); //存儲爲JSON格式,再把total存放好
- return "jsonMap";
- }
- }
@Controller("categoryAction")
@Scope("prototype")
public class CategoryAction extends BaseAction<Category> {
public String queryJoinAccount() {
//用來存儲分頁的數據
pageMap = new HashMap<String, Object>();
//根據關鍵字和分頁的參數查詢相應的數據。這個方法我們在Service中寫過了,當時完成級聯查詢
List<Category> categoryList = categoryService.queryJoinAccount(model.getType(), page, rows);
pageMap.put("rows", categoryList); //存儲爲JSON格式,從上一節的json文件可以看出,一個key是total,一個key是rows,這裏先把rows存放好
//根據關鍵字查詢總記錄數
Long total = categoryService.getCount(model.getType()); //這個方法沒寫,我們等會兒去Service層完善一下
// System.out.println(total);
pageMap.put("total", total); //存儲爲JSON格式,再把total存放好
return "jsonMap";
}
}
這樣Action我們就寫好了,現在Action拿到前臺傳來的參數,然後根據參數查詢了指定type的總記錄數,以及指定type的所有商品,並且按照json中指定的key(即total和rows)進行存放,放在HashMap中了,之後只要將這個HashMap中的數據打包成json格式發送到前臺就可以被DataGrid顯示了。我們先把這個HashMap放這,先去完善了Service層的代碼後,再來打包這個HashMap中的數據。3. 完善categoryService
從上面的categoryAction中可知,需要在categoryService中增加一個getCount方法,並且要在具體實現類中實現好,實現如下:
- //CategoryService接口
- public interface CategoryService extends BaseService<Category> {
- //查詢類別信息,級聯管理員
- public List<Category> queryJoinAccount(String type, int page, int size); //使用類別的名稱查詢
- //根據關鍵字查詢總記錄數
- public Long getCount(String type);
- }
- //CategoryServiceImpl實現類
- @SuppressWarnings("unchecked")
- @Service("categoryService")
- public class CategoryServiceImpl extends BaseServiceImpl<Category> implements CategoryService {
- @Override
- public List<Category> queryJoinAccount(String type, int page, int size) {
- String hql = "from Category c left join fetch c.account where c.type like :type";
- return getSession().createQuery(hql)
- .setString("type", "%" + type + "%")
- .setFirstResult((page-1) * size) //從第幾個開始顯示
- .setMaxResults(size) //顯示幾個
- .list();
- }
- @Override
- public Long getCount(String type) {
- String hql = "select count(c) from Category c where c.type like :type";
- return (Long) getSession().createQuery(hql)
- .setString("type", "%" + type + "%")
- .uniqueResult(); //返回一條記錄:總記錄數
- }
- }
//CategoryService接口
public interface CategoryService extends BaseService<Category> {
//查詢類別信息,級聯管理員
public List<Category> queryJoinAccount(String type, int page, int size); //使用類別的名稱查詢
//根據關鍵字查詢總記錄數
public Long getCount(String type);
}
//CategoryServiceImpl實現類
@SuppressWarnings("unchecked")
@Service("categoryService")
public class CategoryServiceImpl extends BaseServiceImpl<Category> implements CategoryService {
@Override
public List<Category> queryJoinAccount(String type, int page, int size) {
String hql = "from Category c left join fetch c.account where c.type like :type";
return getSession().createQuery(hql)
.setString("type", "%" + type + "%")
.setFirstResult((page-1) * size) //從第幾個開始顯示
.setMaxResults(size) //顯示幾個
.list();
}
@Override
public Long getCount(String type) {
String hql = "select count(c) from Category c where c.type like :type";
return (Long) getSession().createQuery(hql)
.setString("type", "%" + type + "%")
.uniqueResult(); //返回一條記錄:總記錄數
}
}
到現在爲止,這個數據庫中數據的獲取這條路就打通了,前面兩步完成了從前臺-->數據庫-->取數據,接下來就開始打包HashMap中存放的數據,然後發給前臺了。4. 配置struts.xml
在struts.xml中通過配置就可以完成對指定數據的打包,我們先看一下struts.xml中的配置:
- <struts>
- <constant name="struts.devMode" value="true" />
- <package name="shop" extends="json-default"><!-- jason-default繼承了struts-default -->
- <global-results>
- <result name="aindex">/WEB-INF/main/aindex.jsp</result>
- </global-results>
- <!-- class對應的是Spring中配置該Action的id值,因爲要交給Spring管理 -->
- <action name="category_*" class="categoryAction" method="{1}">
- <!-- 必須要先添加json包,然後上面繼承json-default -->
- <result name="jsonMap" type="json">
- <!-- 要轉換成json對象的數據 -->
- <param name="root">pageMap</param>
- <!-- 配置黑名單,過濾不需要的選項 ,支持正則表達式
- json格式:{total:3,rows:[{account:{id:2,login:"user",name:"客服A",pass:"user"},hot:true,id:3,…}]}
- -->
- <param name="excludeProperties">
- <!-- rows[0].account.pass-->
- <!-- 這裏顯示不了正則表達式, CSDN的一個bug,我接個圖放下面 -->
- </param>
- </result>
- </action>
- <action name="account_*" class="accountAction" method="{1}">
- <result name="index">/index.jsp</result>
- </action>
- <!-- 用來完成系統 請求轉發的action,所有的請求都交給execute-->
- <action name="send_*_*" class="sendAction">
- <result name="send">/WEB-INF/{1}/{2}.jsp</result>
- </action>
- </package>
- </struts>
<struts>
<constant name="struts.devMode" value="true" />
<package name="shop" extends="json-default"><!-- jason-default繼承了struts-default -->
<global-results>
<result name="aindex">/WEB-INF/main/aindex.jsp</result>
</global-results>
<!-- class對應的是Spring中配置該Action的id值,因爲要交給Spring管理 -->
<action name="category_*" class="categoryAction" method="{1}">
<!-- 必須要先添加json包,然後上面繼承json-default -->
<result name="jsonMap" type="json">
<!-- 要轉換成json對象的數據 -->
<param name="root">pageMap</param>
<!-- 配置黑名單,過濾不需要的選項 ,支持正則表達式
json格式:{total:3,rows:[{account:{id:2,login:"user",name:"客服A",pass:"user"},hot:true,id:3,…}]}
-->
<param name="excludeProperties">
<!-- rows[0].account.pass-->
<!-- 這裏顯示不了正則表達式, CSDN的一個bug,我接個圖放下面 -->
</param>
</result>
</action>
<action name="account_*" class="accountAction" method="{1}">
<result name="index">/index.jsp</result>
</action>
<!-- 用來完成系統 請求轉發的action,所有的請求都交給execute-->
<action name="send_*_*" class="sendAction">
<result name="send">/WEB-INF/{1}/{2}.jsp</result>
</action>
</package>
</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正確顯示了:
- <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
- <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
- <html>
- <head>
- <%@ include file="/public/head.jspf" %>
- <script type="text/javascript">
- $(function(){
- $('#dg').datagrid({
- //url地址改爲請求categoryAction
- url:'category_queryJoinAccount.action',
- loadMsg:'Loading......',
- queryParams:{type:''},//type參數,這裏不需要傳具體的type,因爲我們要顯示所有的
- //width:300,
- fitColumns:true,
- striped:true,
- nowrap:true,
- singleSelect:true,
- pagination:true,
- rowStyler: function(index,row){
- console.info("index" + index + "," + row)
- if(index % 2 == 0) {
- return 'background-color:#fff;';
- } else {
- return 'background-color:#ff0;';
- }
- },
- frozenColumns:[[
- {field:'checkbox',checkbox:true},
- {field:'id',title:'編號',width:200} //這裏的field字段要和json數據中的一樣
- ]],
- columns:[[
- {field:'type',title:'類別名稱',width:100, //字段type
- formatter: function(value,row,index){
- return "<span title=" + value + ">" + value + "</span>";
- }
- },
- {field:'hot',title:'熱賣',width:100, //字段hot
- formatter: function(value,row,index){
- if(value) { //如果是hot,該值爲true,value是boolean型變量
- return "<input type='checkbox' checked='checked' disabled='true'"; //勾選
- } else {
- return "<input type='checkbox' disable='true'"; //不勾選
- }
- }
- },
- {field:'account.login',title:'所屬管理員',width:200, //account.login管理員登錄名
- formatter: function(value,row,index){
- if(row.account != null && row.account.login != null) {
- return row.account.login; //如果登錄名不爲空,顯示登錄名
- } else {
- return "此類別沒有管理員";
- }
- }
- }
- ]]
- });
- });
- </script>
- </head>
- <body>
- <table id="dg"></table>
- </body>
- </html>
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<%@ include file="/public/head.jspf" %>
<script type="text/javascript">
$(function(){
$('#dg').datagrid({
//url地址改爲請求categoryAction
url:'category_queryJoinAccount.action',
loadMsg:'Loading......',
queryParams:{type:''},//type參數,這裏不需要傳具體的type,因爲我們要顯示所有的
//width:300,
fitColumns:true,
striped:true,
nowrap:true,
singleSelect:true,
pagination:true,
rowStyler: function(index,row){
console.info("index" + index + "," + row)
if(index % 2 == 0) {
return 'background-color:#fff;';
} else {
return 'background-color:#ff0;';
}
},
frozenColumns:[[
{field:'checkbox',checkbox:true},
{field:'id',title:'編號',width:200} //這裏的field字段要和json數據中的一樣
]],
columns:[[
{field:'type',title:'類別名稱',width:100, //字段type
formatter: function(value,row,index){
return "<span title=" + value + ">" + value + "</span>";
}
},
{field:'hot',title:'熱賣',width:100, //字段hot
formatter: function(value,row,index){
if(value) { //如果是hot,該值爲true,value是boolean型變量
return "<input type='checkbox' checked='checked' disabled='true'"; //勾選
} else {
return "<input type='checkbox' disable='true'"; //不勾選
}
}
},
{field:'account.login',title:'所屬管理員',width:200, //account.login管理員登錄名
formatter: function(value,row,index){
if(row.account != null && row.account.login != null) {
return row.account.login; //如果登錄名不爲空,顯示登錄名
} else {
return "此類別沒有管理員";
}
}
}
]]
});
});
</script>
</head>
<body>
<table id="dg"></table>
</body>
</html>
6. 測試顯示結果
最後我們測試一下DataGrid的顯示結果,如下:
到這裏,我們成功整合了Struts2和json,現在可以和前臺傳輸json格式的數據了。
相關閱讀:http://blog.csdn.net/column/details/str2hiberspring.html
整個項目的源碼下載地址:http://blog.csdn.net/eson_15/article/details/51479994