今天分享下我专为ajax访问封装的action基类,依然用的全注解方式,主要使用基于泛型的模板模式实现;先来看下类头吧
@Results({ // 返回Action堆栈内所有对象 ignoreHierarchy=false(取消父子分离,将父类的属性也作为json传递) // excludeNullProperties 排除为null的对象 // excludeProperties 排除指定属性 @Result(name = "jsonall", type = "json", params = { "excludeNullProperties", "true"}) }) @SuppressWarnings("serial") public abstract class JsonBaseAction<T extends BaseEntity> extends ActionSupport { // 需要子类实现的查询列表方法 public abstract void searchList(Page page) throws ServiceException; // 查询明细 public abstract void searchEntity() throws ServiceException; // 删除 public abstract void deleteEntity() throws ServiceException; // 新增或修改 public abstract void addOrUpdEntity() throws ServiceException; public abstract void setEntity();
首先他是一个泛型抽象类,子类需要传参一个BaseEntity的派生类,同时子类还需要实现查询列表,查询单个,删除,新增修改这几个抽象方法.还定义了一个Result注解,他的作用是当action方法返回"jsonall"时,会把当前action上下文中所有的属性转成json数据返回给web端,excludeNullProperties:true就是过滤掉值为null的属性
然后再来看其他代码
// 返回所有josn的字符串 public static final String JSON = "jsonall"; // json返回执行结果 private boolean success = true; // json返回执行信息 private String msg; private Integer start; private Integer limit; private Long totalProperty; protected void putResult(boolean success, String msg) { this.setSuccess(success); this.setMsg(msg); } public JsonBaseAction(){ setEntity(); } // 查询的集合 protected List<T> searchList = null; // 明细实体 也是作为参数的载体 protected T entity; public String query() { Page p = new Page(); if(limit!=null) p.setPageSize(limit); if(start!=null) p.setCurrentPage(start); try { searchList(p); totalProperty = p.getCount(); } catch (ServiceException e) { this.setSuccess(false); this.setMsg(e.getMessage()); } catch (Exception e){ this.setSuccess(false); this.setMsg(e.getMessage()); e.printStackTrace(); } if (this.success) { this.setMsg("查询成功"); } return JSON; } public String find() { try { searchEntity(); } catch (ServiceException e) { this.setSuccess(false); this.setMsg(e.getMessage()); } if (this.success) { this.setMsg("查询成功"); } return JSON; } public String save(){ try { addOrUpdEntity(); } catch (ServiceException e) { this.setSuccess(false); this.setMsg(e.getMessage()); } if (this.success) { this.setMsg("保存成功"); } return JSON; } public String delete(){ try { deleteEntity(); } catch (ServiceException e) { this.setSuccess(false); this.setMsg(e.getMessage()); } if (this.success) { this.setMsg("删除成功"); } return JSON; }
基类定义了常用的属性包括success(操作是否成功)msg(操作结果信息)limit start(分页条件)totalProperty(查询总条数) 比较重要的是 entity和searchList两个属性,他们都是泛型类型的,他们在程序执行中既承担参数的载体又作为结果的返回,比如通过用户名查用户信息时,前台会传递entity.name到entity属性,后台会把查询到的entity信息赋值个entity,这一切都是泛型在控制节奏.对于前端来讲节省了很多规范成本.基类还定义了常用的增删改方法,注意这些方法都是直接对外访问的(可以看下web架构2convention插件),子类只负责实现业务,具体的接口和逻辑都在这个基类完成,比如分页功能基类会把用户端的参数封装成一个page对象传递个子类,一个很典型的模板模式列子.看到这里如果你还看不出其中的好处那确实有点跟不上节奏了,基类定义的 success msg entity searchList对于web端都是统一的,调用任何模块的返回值都是这些属性,查列表信息就从searchList获取,明细信息就从entity取 操作是否成功就从success取等等,而且对web端来说封装公共的grid的插件也变的容易的多,再来看看子类,代码会变的清爽的多
package cn.sdh.action; import java.util.List; import org.apache.struts2.convention.annotation.Namespace; import org.springframework.beans.factory.annotation.Autowired; import cn.sdh.common.Page; import cn.sdh.common.base.JsonBaseAction; import cn.sdh.common.exception.ServiceException; import cn.sdh.entity.Role; import cn.sdh.service.RoleService; import cn.sdh.utils.MyJsonUtil; @Namespace("/") @SuppressWarnings("serial") public class RoleAction extends JsonBaseAction<Role> { @Autowired private RoleService roleService; @Override public void searchList(Page page) { try { searchList = roleService.query(entity); } catch (ServiceException e) { this.putResult(false, e.getMsg()); } } @Override public void searchEntity() { try { roleService.findById(entity); } catch (ServiceException e) { this.putResult(false, e.getMsg()); } } @Override public void deleteEntity() { try { String [] idsarr = getMsg().split(","); roleService.deletes(idsarr); } catch (ServiceException e) { this.putResult(false, e.getMsg()); } } @Override public void addOrUpdEntity() { @SuppressWarnings("unchecked") List<Role> roleList = MyJsonUtil.getObjectsByJson(getMsg(), Role.class); try { roleService.saves(roleList); } catch (ServiceException e) { this.putResult(false, e.getMsg()); } } /** * 保存角色拥有的权限 * @return */ public String saveRolePermission(){ try { roleService.saveRolePermission(entity.getId(), getMsg()); this.putResult(true, "保存成功"); } catch (ServiceException e){ this.putResult(false, e.getMsg()); } return JSON; } @Override public void setEntity() { entity = new Role(); } }
这是一个关于角色的action,它传递给基类的泛型是Role,它实现了增删改查那几个方法而且不用关心返回值,同时它也可以有自己的方法saveRolePermission,拿searchList方法来说当web端通过role!query.action访问(convention插件)的时候,会先走到基类的,然后通过基类访问该类的searchList方法对searchList进行赋值,然后统一返回给web端,最后展示下我在Extjs4中封装的公共的Stroe,因为属性的约定让事情变的非常简单
Ext.define("app.base.store", { extend : "Ext.data.Store", pageSize:50, sorters: [{ property: 'id', direction: 'DESC' }], constructor : function(config){ this.proxy = { type:'ajax', reader : { type:'json', root:"searchList", totalProperty:'totalProperty' }, actionMethods: { read: 'POST' }, url : config.url }; this.model = config.model; this.listeners = { load : function(s,r,f,o,e){ if(!f){ app.alert("查询失败"); } } }; this.callParent(); } });