日期:2014-05-16  浏览次数:20474 次

实现通用的CRUD之二—用jsonRPC打通B/S的任督二脉

?

B/S应用需要解决的一个重要问题是:如何在B/S之间传递数据。同样是采用HTTP协议,当时传递的内容形式已经从最初的平面型的form参数提交,发展为结构型的WebRPC调用。其中DWRWeb ServiceJsonRPC是最常见的实现。

WebRPC的基本思路如下:在B端和S端分别实现对象及方法的序列化和反序列化,一个典型的调用过程如下:

  1. B端实参调用方法
  2. WebRPCB端序列化方法和实参对象
  3. HTTP传输序列化数据到S
  4. S端反序列化方法和实参对象
  5. S端调用服务方法运算,获得运算结果
  6. WebRPCS端序列化运算结果
  7. HTTP传输序列化数据到B
  8. WebRPCB端反序列化运算结果,获得B端对象
  9. ?

看起来很完美,但并没有解决全部问题,应用中经常遇到的场景是:只需要对数据库表中的部分而不是全部字段进行操作。即:我们需要对象部分属性的序列化和反序列化。实现这个目标有两种思路:一是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){
		this.cns=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方法。

jsonRPCB/S双向序列化协议,编写服务方法如下:

?

	static public Object handle(char method,HashMap<String, Object> rm,String sn,
			HttpServletRequest request) throws Exception {
		// TODO Auto-generated method stub
		if(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,