匿名內部類代理模式

項目中web網頁請求,action層返回的是同一個對象,WebApiBaseResult,並使用相同的異常處理

@RequestMapping(value="/path",method = RequestMethod.GET)
@ResponseBody
public WebApiBaseResult path(HttpSession httpSession
		,HttpServletRequest request
		,@RequestParam(value = "condition",required = false)String condition
		,@RequestParam(value = "keyword",required = false)String keyword){
	WebApiBaseResult result = new WebApiBaseResult();//web統一返回對象
	try{
		BaseUserModel  baseUser = (BaseUserModel) httpSession.getAttribute("currentUser");
		if(null == baseUser){
			throw new NotLogException("用戶登錄過期,請重新登錄");
		}
		//獲取session中的登錄公司的信息
		BaseCompanyModel baseCompany = (BaseCompanyModel)httpSession.getAttribute("currentCompany");
		//業務代碼
        ....................
        result.setData(data);//返回數據統一放在data裏
	}catch(NotLogException e){
		logger.error(MyRequestUtils.getParameterString());
		logger.error(e.getMessage(),e);
		result.setStatusCode(StatusCodeEnum.NOTLOG.getCode());
		result.setMessage(e.getMessage());
		return result;
	}catch(Exception e){
		logger.error(MyRequestUtils.getParameterString());
		logger.error(e.getMessage(),e);
		result.setStatusCode(StatusCodeEnum.COMMONERROR.getCode());
		result.setMessage(e.getMessage());
		return result;
	}
	return result;
}

所有的web請求都是如此處理的,雖然複製粘貼一下也不費什麼事,但是主管還是想複用一下,代碼看起來也清爽一點,於是我參考了一下過去項目的實現代碼,基本原理就是匿名函數和代理的編程思想的結合。

首先是寫一個接口,專門用來當匿名函數的

public interface BaseActionCallBack {
	WebApiBaseResult run() throws Exception;
}

就這麼簡單,也不用實現,是專門當匿名函數用的。

再寫一個代理類

public class BaseActionProxy {
	public static WebApiBaseResult commonWebAction(Logger logger, BaseActionCallBack action) {
		WebApiBaseResult result = null;
		try {
			result = action.run();
		} catch (NotLogException e) {
			result = new WebApiBaseResult();
			logger.error(MyRequestUtils.getParameterString());
			logger.error(e.getMessage(), e);
			result.setStatusCode(StatusCodeEnum.NOTLOG.getCode());
			result.setMessage(e.getMessage());
		} catch (Exception e) {
			result = new WebApiBaseResult();
			logger.error(MyRequestUtils.getParameterString());
			logger.error(e.getMessage(), e);
			result.setStatusCode(StatusCodeEnum.COMMONERROR.getCode());
			result.setMessage(e.getMessage());
		}
		return result;
	}
}

將上面寫的接口類當做參數傳進去,然後我還加了一個logger參數,打印異常用。

接着最開始的代碼就可以改造成這樣

@RequestMapping(value="/path",method = RequestMethod.GET)
@ResponseBody
public WebApiBaseResult path(HttpSession httpSession
		,HttpServletRequest request
		,@RequestParam(value = "condition",required = false)String condition
		,@RequestParam(value = "keyword",required = false)String keyword){
		return BaseActionProxy.commonWebAction(logger, new BaseActionCallBack() {
			@Override
			public WebApiBaseResult run() throws Exception {
				WebApiBaseResult result = new WebApiBaseResult();
				BaseUserModel  baseUser = (BaseUserModel) httpSession.getAttribute("currentUser");
				if(null == baseUser){
					throw new NotLogException("用戶登錄過期,請重新登錄");
				}
				//獲取session中的登錄公司的信息
				BaseCompanyModel baseCompany = (BaseCompanyModel)httpSession.getAttribute("currentCompany");
				//業務代碼
        		....................
        		result.setData(data);//返回數據統一放在data裏
				return result;
			}
		});
}

看起來是不是簡潔了很多,不過值得注意的是,匿名函數類裏面不能使用非finial的變量。java1.8比較智能一點,只要你沒有給變量賦值他就會視爲最終變量。這樣就會造成一些麻煩。比如分頁參數,因爲hibernate分頁是從0開始的,所以分頁參數傳進來後要減1,但是在匿名函數中就不能直接用了。

@RequestMapping(value="/path",method = RequestMethod.GET)
@ResponseBody
public WebApiBaseResult path(HttpSession httpSession
		,HttpServletRequest request
		,@RequestParam(value = "condition",required = false)String condition
		,@RequestParam(value = "keyword",required = false)String keyword
		,@RequestParam(value = "page",required = false)Integer page){
		    return BaseActionProxy.commonWebAction(logger, new BaseActionCallBack() {
			@Override
			public WebApiBaseResult run() throws Exception {
				WebApiBaseResult result = new WebApiBaseResult();
				BaseUserModel  baseUser = (BaseUserModel) httpSession.getAttribute("currentUser");
				if(null == baseUser){
					throw new NotLogException("用戶登錄過期,請重新登錄");
				}
				//獲取session中的登錄公司的信息
				BaseCompanyModel baseCompany = (BaseCompanyModel)httpSession.getAttribute("currentCompany");
				Integer p = 0;//頁碼數需要減1,但是匿名函數中不能改變變量,所以只能聲明一個新的變量
				if (page != null)
					p = page -1;
				PageParam pageInfo = new PageParam(p, size, pageFlag, sort);
				//業務代碼
        		....................
        		result.setData(data);//返回數據統一放在data裏
				return result;
			}
		});
}

只能聲明一個新的變量來接收,從這一點上看就不夠優雅了。相當於給代碼加了一個限制。。。其實還好,就是如果基本類型做更改需要聲明新變量接收,如果是對象,那麼還是能夠做更改的,就是其引用不能改變。

建議還是在action層中使用,然後把主要的業務代碼放到service層,action層只作爲傳遞參數的結構,這樣基本就不會出問題了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章