之二—用jsonRPC打通B/S的任督二脉"/>
实现通用的CRUD之二—用jsonRPC打通B/S的任督二脉
B/S应用需要解决的一个重要问题是:如何在B/S之间传递数据。同样是采用HTTP协议,当时传递的内容形式已经从最初的平面型的form参数提交,发展为结构型的WebRPC调用。其中DWR、Web Service和JsonRPC是最常见的实现。
WebRPC的基本思路如下:在B端和S端分别实现对象及方法的序列化和反序列化,一个典型的调用过程如下:
- B端实参调用方法
- WebRPC在B端序列化方法和实参对象
- HTTP传输序列化数据到S端
- S端反序列化方法和实参对象
- S端调用服务方法运算,获得运算结果
- WebRPC在S端序列化运算结果
- HTTP传输序列化数据到B端
- WebRPC在B端反序列化运算结果,获得B端对象
看起来很完美,但并没有解决全部问题,应用中经常遇到的场景是:只需要对数据库表中的部分而不是全部字段进行操作。即:我们需要对象部分属性的序列化和反序列化。实现这个目标有两种思路:一是hack现有的WebRPC,使其支持部分属性序列化。另一种思路则是:引入一个中间形态以承载部分属性对象。本文采用的是第二种思路。
对该形态的用java描述如下
/*** object部分属性的map形式* @author chen4w**/
public class BObj {//从数据库获得的原始状态public static final char ACTION_ORIG = 'O';//新增对象public static final char ACTION_ADD = 'A';//已设置为删除状态public static final char ACTION_REMOVE='R';//经过了修改public static final char ACTION_UPDATE='U';//用于新增的默认对象public static final char ACTION_DEFAULT='D';//多表按顺序的类名private String[] cns;/*** 属性数组*/private HashMap<String,Object> items;/*** 动作标识*/private char action;public char getAction(){return action;}public void setAction(char action){this.action=action;}public String[] getCns(){return cns;}public void setCns(String[] cname){thiss=cname;}public HashMap<String,Object> getItems(){return items;}public void setItems(HashMap<String,Object> fmap){this.items=fmap;}}
可以看出,描述中包含了如下几类信息:
cns——对象类名(O/R mapping映射的POJO),采用数组是考虑到多表联合查询
action——对象自描述的状态,新增/删除/更新/初始。
Items——对象的部分属性集合
以此类作为中间形态,我们不难写出完整对象与之转换的方法。然后利用WebRPC,编写出一个以该类作为参数的通用的数据库CRUD方法。
以jsonRPC为B/S双向序列化协议,编写服务方法如下:
static public Object handle(char method,HashMap<String, Object> rm,String sn,HttpServletRequest request) throws Exception {// TODO Auto-generated method stubif(sn==null || sn.trim().equals(""))sn = DEFAULTHANDLER;//session检查 为空且非登录请求/*if(method!=METHOD_LOGIN){throw new ServletException(Info.ERR_INVALID_SESSION); }*///如果存在before回调String cn = "";String[] cns= (String[])rm.get("cns");if(cns!=null){cn = cns[0];}//根据HHUtil中对sn+method的事务要求,采用编程决定是否启动事务管理Integer transanctionMode = hhutil.getTransactionMode(sn,method);PlatformTransactionManager transactionManager=null;TransactionStatus transactionStatus=null;if(transanctionMode!=null){transactionManager=(PlatformTransactionManager)Cfg.getBean("transactionManager"); TransactionDefinition transactionDefinition=new DefaultTransactionDefinition(transanctionMode); transactionStatus=transactionManager.getTransaction(transactionDefinition);}try{IHandleHook hcb = hhutil.getHandleHook(sn, method, cn);if(hcb!=null)hcb.beforeHandle(method,rm,request);Object result= getHandleImpl(sn).handle(method,rm,request);//如果存在after回调if(hcb!=null)hcb.afterHandle(method, rm, request, result);if(transactionManager!=null)transactionManagermit(transactionStatus);return result;}catch(Exception e){e.printStackTrace();if(transactionManager!=null)transactionManager.rollback(transactionStatus);throw e;}}
该方法处理调用的前后的切面,允许在默认处理前后便携特殊处理。另外,允许将多个调用封装为一个事务。
进一步编写数据库CRUD操作的服务作为一个handle实例。
附件说明如下:
BObj.java——对象的部分属性形态
Handler.java——jsonRPC调用的总入口,负责调用前后特殊逻辑调度和事务处理
HDDefault.java——负责数据库通用操作的服务
HDUtil——数据库操作辅助工具类
<!--EndFragment-->
更多推荐
实现通用的CRUD之二—用jsonRPC打通B/S的任督二脉
发布评论