一、引言
最后一篇是easyui与struts传递数据。拖了好多天,因为一直没想好怎么写。这部分代码参考了一个开源项目,很早之前写的,具体是哪个我也忘了。例子是easyui+ssh全注解+maven。刚开始笔记想写easyui+ssh+maven完整的,发现内容太多,作为easyui的系列笔记,加上ssh全注解和maven的内容似乎跑题了。
本篇笔记重点介绍如何写action以便于easyui交换数据。其他的部分如感兴趣,可以从我git@osc里面名称为mis项目下载完整代码。项目zip包下载地址为:
http://git.oschina.net/ooad/mis/repository/archive?ref=master
二、SSH必要说明
尽管后台部分本篇不涉及,但是有些内容还是交代一下。
1. 数据库表
示例数据还是之前的客户数据。mysql建表脚本如下:
1
2
3
4
5
6
7
8
9
10
|
DROP
TABLE
IF EXISTS `customer`;
CREATE
TABLE
`customer` (
`ID`
int
(11)
NOT
NULL
AUTO_INCREMENT,
`CUSTOMERNO`
varchar
(36)
NOT
NULL
,
`CUSTOMERNAME`
varchar
(36)
NOT
NULL
,
`TELEPHONE`
varchar
(36)
DEFAULT
NULL
,
`ADDRESS`
varchar
(100)
DEFAULT
NULL
,
PRIMARY
KEY
(`ID`),
UNIQUE
KEY
`CUSTOMERNO` (`CUSTOMERNO`)
) ENGINE=InnoDB AUTO_INCREMENT=22
DEFAULT
CHARSET=utf8;
|
2 实体类
实体类Customer属性必须与easyui中列名称必须相同,否则无法对应。
3. 服务类
Action代码会有调用service层,CustomerService接口名称及作用如下:
添加客户saveCustomer(Customer customer)
修改用户 updateCustomer(Customer customer)
删除用户 deleteCustomer(int id)
列出所有用户并支持分页和排序List<Customer> findAllCustomer(int page, int rows, String sort, String order)
得到客户总数int getTotal()
4.控制类
控制层代码采用了注解方式,因此项目需要添加struts2-convention-plugin.jar依赖。
三、Action基类
我们必须清楚两个问题:(1) easyui如果要显示后台的数据,必须向action发出请求。因此action需要接收并处理easyui传递过来的参数。(2)easyui只能认识json,所以后台获取的对象或集合必须转换成json格式。这两个问题都需要在action里进行解决。
为了方便编写action,写了一个封装easyui页面参数的action基类BaseAction,并能实现对象转json,其他Action需继承该类。该类代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
|
public
class
BaseAction
extends
ActionSupport{
protected
int
page =
1
;
protected
int
rows =
20
;
protected
String sort;
protected
String order;
protected
int
id;
public
void
writeJson(
int
total,List list) {
try
{
Map<String, Object> maps =
new
HashMap<String, Object>();
maps.put(
"rows"
, list);
maps.put(
"total"
, total);
String json = JSON.toJSONString(maps);
ServletActionContext.getResponse().setContentType(
"text/html;charset=utf-8"
);
ServletActionContext.getResponse().getWriter().write(json);
ServletActionContext.getResponse().getWriter().flush();
}
catch
(IOException e) {
logger.debug(ExceptionUtil.getExceptionMessage(e));
}
}
public
void
writeJson(Object object) {
try
{
String json = JSON.toJSONString(object);
ServletActionContext.getResponse().setContentType(
"text/html;charset=utf-8"
);
ServletActionContext.getResponse().getWriter().write(json);
ServletActionContext.getResponse().getWriter().flush();
}
catch
(IOException e) {
logger.debug(ExceptionUtil.getExceptionMessage(e));
}
//此处省略了setter和getter
}
|
对该段代码解释:
1. 分页与排序
为了实现分页,action必须接收easyui的两个参数page和rows,page为页数,rows为每页记录数。
但是在数据库进行分页查找操作是需要指定的参数为第一条记录数和最后一条记录数,因此涉及转换问题。
这个转换可以再action层转换,也可以在dao层转换。
本笔记采用后者。这样目的以便让easyui与action交互更为清晰。此处以Hibernate条件查询为例,dao层基类BaseDao处理分页代码为:
1
2
|
criteria.setFirstResult((page-
1
) * rows);
criteria.setMaxResults(rows);
|
这样,在Service层查询分页查找客户的方法findAllCustomer(int page, int rows, String sort, String order)直接用这两个参数。
为了实现字段排序,则需接收sort和order两个参数。sort指定排序字段,order指定升降序
方案同前,BaseDao中支持排序代码如下:
1
2
3
4
5
6
|
if
(
"asc"
.equals(order)) {
criteria.addOrder(Order.asc(sort));
}
else
{
criteria.addOrder(Order.desc(sort));
}
}
|
2 对象转json
对象转json需要用到工具,Struts本身自带一个json插件。本笔记使用了阿里巴巴的fastjson工具,其实用法都差不多,据说fastjson性能强很多。
Fastjson API入口类是com.alibaba.fastjson.JSON,常用的序列化操作都可以在JSON类上的静态方法直接完成。
Api如下:
public static final String toJSONString(Object object); // 将JavaBean序列化为JSON文本
参考笔记6,要让datagrid显示数据,远程传递或本地读取的json数据格式如下:
1
2
3
4
|
{
"total"
: ,
"rows"
:[
{……},
{…....}
]}
|
需要提醒的是,这里的rows不是前面的每页记录数rows,这是后台向前台传递的。此处rows实际为数据集合,也就是java对象集合转换后的json。easyui为什么非得用一样的名字呢?
所以此处封装了一个writeJson(int total,List list)的方法,子类action中如果需要将List集合转成json在datagrid中显示就调用该方法。
为了提高可用性,本笔记会将后台操作的结果在前台通过消息提示框显示。写了一个向前台传递消息或数据的类(我竟然也照搬命名为Json,晕掉。此Json非彼Json,容易造成误解,应该改成Result,与前篇easyui的代码中的result相呼应),代码如下:
1
2
3
4
5
6
|
public
class
Json
implements
java.io.Serializable {
private
boolean
success =
false
;
private
String msg =
""
;
private
Object obj =
null
;
//此处省略setter和getter
}
|
因此,基类中还封装了一个writeJson(object)方法可用来将其转换成json。
四、CustomerAction类
代码有点长,如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
|
@Controller
@Action
(value =
"customer"
, results = {
@Result
(name =
"customer"
, location =
"/page/ /customer.jsp"
) })
public
class
CustomerAction
extends
BaseAction
implements
ModelDriven<Customer> {
@Autowired
private
CustomerService customerService;
public
Customer customer =
new
Customer();
/**
* 得到数据列表
*/
public
void
grid(){
int
total = customerService.getTotal();
List<Customer> list = customerService.findAllCustomer(page, rows, sort, order);
writeJson(total,list);
}
/**
* 添加操作
*/
public
void
add(){
Json result =
new
Json();
try
{
customerService.saveCustomer(customer);
result.setSuccess(
true
);
result.setMsg(
"添加客户成功"
);
}
catch
(Exception e) {
result.setMsg(
"添加客户失败"
);
}
writeJson(result);
}
/**
* 修改操作
*/
public
void
edit() {
Json result =
new
Json();
try
{
customerService.updateCustomer(customer);
result.setSuccess(
true
);
result.setMsg(
"修改客户成功"
);
result.setSuccess(
true
);
}
catch
(Exception e) {
result.setMsg(
"添加客户失败"
);
}
writeJson(result);
}
/**
* 删除操作
*/
public
void
remove() {
Json result =
new
Json();
try
{
customerService.deleteCustomer(customer.getId());
result.setSuccess(
true
);
result.setMsg(
"删除客户成功"
);
}
catch
(Exception e) {
result.setMsg(
"删除客户失败"
);
}
writeJson(result);
}
@Override
public
Customer getModel() {
return
customer;
}
}
|
说明如下:
(1) @Controller注解这是一个action,不需要再写配置文件了。
(2) @Action(value = "customer", results = { @Result(name = "customer", location = "/page/ /customer.jsp") })
这一长串是干嘛的呢?因为没有配置文件了。此处定义action的名字为customer,对应页面为某路径下的customer.jsp。
(3) 客户控制器(CustomerAction) 继承了基类BaseAction,从而可以接收easyui参数并实现json转换。
(4) 该控制器还实现了Struts的ModelDriven这个接口,并覆写了getModel()。以前还真不知道struts还有这个接口,参考之后发现真心好方便。
Action不用去写vo的setter,直接把easyui中的字段值赋值进入了实例化的customer对象中。爽歪歪!
当然前提条件是表单控件名称必须与实体类中的属性名相同,否则..........
(5) 为了在客户端消息提示操作结果,实例化Json(再次恶心下自己,真心命名不好)对象,把消息内容赋值进去,并调用writejson方法转成json在前台显示。
五、customer.jsp
很简单,把前面笔记的customer.html后缀改成jsp,在<html>前面加上下面这一段就可以了:
1
2
3
4
|
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%
String contextPath = request.getContextPath();
%>
|
需要强调的是,使用了注解的action,访问地址有了一些变化,规则为:action名!方法名.action
比如datagrid需要显示数据,需将本地读取url :datagridData.json改成从action中读取,url:customer!grid.action,即调用CustomerAction中的grid()方法得到数据。
grid()实现代码重复下:
1
2
3
4
5
|
public
void
grid(){
int
total = customerService.getTotal();
List<Customer> list = customerService.findAllCustomer(page, rows, sort, order);
writeJson(total,list);
}
|
相信看到这,逻辑你已经清楚了。
运行界面和之前没什么变化,只是数据换成了从后台读取。另外,增删改等操作、分页、排序都可以使用了。