匿名内部类代理模式
程序员文章站
2024-01-24 09:26:58
...
项目中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层只作为传递参数的结构,这样基本就不会出问题了。
完
下一篇: vue 使用 xe-ajax 异步请求