javaWEB SSM AOP+注解保存操作日志
2018-02-12 16:03
513 查看
本篇文章的诞生离不开这篇文章的作者:http://blog.csdn.net/czmchen/article/details/42392985。
*
* AOP记录操作&异常日志-切点类
* @see [相关类/方法]
* @since [产品/模块版本]
*/
@Aspect
@Component
public class SystemLogAspect
{
private static final Logger logger = LoggerFactory.getLogger(SystemLogAspect.class);
// 队列
private static BlockingQueue<Log> queue = new LinkedBlockingQueue<Log>();
// 缓存线程池
private static ExecutorService threadPool = Executors.newFixedThreadPool(3);
// 任务数
private static int taskSize = 6;
// 线程是否已启动
boolean isStartThread = false;
// 用来启动或停止线程
static boolean run = true;
@Autowired
private LogService logService;
@Autowired
private UserService userService;
// Service层切点
@Pointcut("@annotation(com.rzzl.wap.log.annotation.SystemServiceLog)")
public void serviceAspect()
{
}
// Controller层切点
@Pointcut("@annotation(com.rzzl.wap.log.annotation.SystemControllerLog)")
public void controllerAspect()
{
}
public static BlockingQueue<Log> getQueue()
{
return queue;
}
public static void setQueue(BlockingQueue<Log> queue)
{
SystemLogAspect.queue = queue;
}
public static boolean isRun()
{
return run;
}
public static void setRun(boolean run)
{
SystemLogAspect.run = run;
}
/**
*
* 返回通知 用于拦截Controller层记录用户的操作
* @param joinPoint 切点
* @param result 返回值
* @see [类、类#方法、类#成员]
*/
@AfterReturning(value = "controllerAspect()", returning = "result")
public void afterReturn(JoinPoint joinPoint, Object result)
{
// 请求的IP
User user = WebUtils.getSessionValue(LoginContact.SESSION_USER);
String params = "";
WebResult webResult = new WebResult();
webResult.setCode(FlagContact.BACK_SUCCESS);
try
{
if (WebResult.class.isInstance(result))
{
webResult = (WebResult)result;
}
String loginName = "";
InnnerBean innnerBean = getControllerMethodDescription(joinPoint);
Object[] arguments = innnerBean.getArguments();
String remark = innnerBean.getDescription();
Log log = new Log.Builder().type(LogTypes.type.operate)
.moduleType(innnerBean.getModuleType())
.operateCode(joinPoint.getSignature().getName())
.operateValue(innnerBean.getOperateValue())
.remark(remark)
.operateStatus(webResult.getCode().equals(FlagContact.BACK_SUCCESS) ? LogTypes.operateStatus.Y
: LogTypes.operateStatus.N)// 返回值1操作成功,否则失败
.method((joinPoint.getTarget().getClass().getName() + "." + joinPoint.getSignature().getName() + "()"))
.param(params)
.loginName(user.getAccountNo())
.fullName(user.getUserName())
.build();
// 放入队列
queue.put(log);
if (!isStartThread)
{
for (int i = 0; i < taskSize; i++)
{
threadPool.execute(new saveLogThread());
}
isStartThread = true;
}
}
catch (Exception e)
{
logger.error("异常信息:{}", e.toString());
}
}
/**
* 异常通知 用于拦截service层记录异常日志
* @param joinPoint
* @param e
* @see [类、类#方法、类#成员]
*/
@AfterThrowing(pointcut = "serviceAspect()", throwing = "e")
public void doAfterThrowing(JoinPoint joinPoint, Throwable e)
{
// 读取session中的用户
User user = WebUtils.getSessionValue(LoginContact.SESSION_USER);
String params = "";
try
{
if (joinPoint.getArgs() != null && joinPoint.getArgs().length > 0)
{
for (int i = 0; i < joinPoint.getArgs().length; i++)
{
params += JSONUtils.valueToString(joinPoint.getArgs()[i].toString()) + ";";
}
}
InnnerBean innnerBean = getServiceMthodDescription(joinPoint);
String loginName = "";
Log log =
new Log.Builder().type(LogTypes.type.exception)
.moduleType(innnerBean.getModuleType())
.operateCode(joinPoint.getSignature().getName())
.operateValue(innnerBean.getOperateValue())
.remark(innnerBean.getDescription())
.operateStatus(LogTypes.operateStatus.N)
.method(
(joinPoint.getTarget().getClass().getName() + "." + joinPoint.getSignature().getName() + "()"))
.param(params)
.exceptionDetail(e.toString())
.build();
// 放入队列
queue.put(log);
if (!isStartThread)
{
new Thread(new saveLogThread()).start();
isStartThread = true;
}
}
catch (Exception ex)
{
logger.error("异常信息:{}", ex.toString());
}
finally
{
logger.error("异常方法:{" + joinPoint.getTarget().getClass().getName() + "}异常代码:{"
+ joinPoint.getSignature().getName() + "}异常信息:{" + e.toString() + "}参数:{" + params + "}");
}
}
/**
* 获取注解中对方法的描述信息 用于service层注解
* @param joinPoint 切点
* @return 方法描述
* @throws Exception
* @see [类、类#方法、类#成员]
*/
@SuppressWarnings("rawtypes")
public static InnnerBean getServiceMthodDescription(JoinPoint joinPoint)
throws Exception
{
String targetName = joinPoint.getTarget().getClass().getName();
String methodName = joinPoint.getSignature().getName();
Object[] arguments = joinPoint.getArgs();
Class targetClass = Class.forName(targetName);
Method[] methods = targetClass.getMethods();
String moduleType = "";
String operateValue = "";
String description = "";
InnnerBean innnerBean = new InnnerBean(moduleType, operateValue, description);
for (Method method : methods)
{
if (method.getName().equals(methodName))
{
Class[] clazzs = method.getParameterTypes();
if (clazzs.length == arguments.length)
{
SystemServiceLog annotation = method.getAnnotation(SystemServiceLog.class);
moduleType = annotation.moduleType();
operateValue = annotation.operateValue();
description = annotation.description();
innnerBean = new InnnerBean(moduleType, operateValue, description);
break;
}
}
}
innnerBean.setArguments(arguments);
return innnerBean;
}
/**
* 获取注解中对方法的描述信息 用于Controller层注解
* @param joinPoint 切点
* @return 方法描述
* @throws Exception
* @see [类、类#方法、类#成员]
*/
@SuppressWarnings("rawtypes")
public static InnnerBean getControllerMethodDescription(JoinPoint joinPoint)
throws Exception
{
String targetName = joinPoint.getTarget().getClass().getName();
String methodName = joinPoint.getSignature().getName();
Object[] arguments = joinPoint.getArgs();
Class targetClass = Class.forName(targetName);
Method[] methods = targetClass.getMethods();
String moduleType = "";
String operateValue = "";
String description = "";
boolean firstParamName = false;
InnnerBean innnerBean = new InnnerBean(moduleType, operateValue, description);
for (Method method : methods)
{
if (method.getName().equals(methodName))
{
Class[] clazzs = method.getParameterTypes();
if (clazzs.length == arguments.length)
{
SystemControllerLog annotation = method.getAnnotation(SystemControllerLog.class);
moduleType = annotation.moduleType();
operateValue = annotation.operateValue();
description = annotation.description();
firstParamName = annotation.firstParamName();
innnerBean = new InnnerBean(moduleType, operateValue, description);
innnerBean.setFirstParamName(firstParamName);
break;
}
}
}
innnerBean.setArguments(arguments);
return innnerBean;
}
/**
*
* 内部类封装注入信息
* @see [相关类/方法]
* @since [产品/模块版本]
*/
static class InnnerBean
{
private String moduleType;// 模块代码
private String description;// 描述
private String operateValue;// 操作类型
private boolean firstParamName;
private Object[] arguments;
public InnnerBean(String moduleType, String operateValue, String description)
{
super();
this.moduleType = moduleType;
this.description = description;
this.operateValue = operateValue;
}
public String getOperateValue()
{
return operateValue;
}
public void setOperateValue(String operateValue)
{
this.operateValue = operateValue;
}
public String getModuleType()
{
return moduleType;
}
public void setModuleType(String moduleType)
{
this.moduleType = moduleType;
}
public String getDescription()
{
return description;
}
public void setDescription(String description)
{
this.description = description;
}
public Object[] getArguments()
{
return arguments;
}
public void setArguments(Object[] arguments)
{
this.arguments = arguments;
}
public boolean isFirstParamName()
{
return firstParamName;
}
public void setFirstParamName(boolean firstParamName)
{
this.firstParamName = firstParamName;
}
}
/**
*
* 异步保存日志
* @see [相关类/方法]
* @since [产品/模块版本]
*/
class saveLogThread implements Runnable
{
Lock lock = new ReentrantLock();
@Override
public void run()
{
try
{
while (run)
{
while (queue.size() != 0)
{
// 如果对插入顺序无要求,此处不需要同步可提升效率
lock.lock();
Log log = queue.take();
logService.insert(log);
lock.unlock();
}
Thread.sleep(3000);
}
}
catch (InterruptedException e)
{
logger.error("saveLogThread被唤醒:" + e.toString());
}
catch (Exception e)
{
logger.error("saveLogThread异常:" + e.toString());
}
}
}
}
*
* 操作日志&异常日志
* @see [相关类/方法]
* @since [产品/模块版本]
*/
public class Log implements Serializable
{
/**
* serialVersionUID
*/
private static final long serialVersionUID = 1L;
private static final String reqSource;// 请求来源,pc:pc端,wap:wap端 默认来源为pc
private static final String localAddr;// 服务器IP
private String ip;// 操作电脑ip
private String fullName;// 操作人员名字
private String loginName;// 操作人员登录账号
private Date operateDateTime;// 操作时间
private Date createDateTime;// 创建时间
private Long id;
private String type;// 日志类型,‘operate’:操作日志,‘exception’:异常日志
private String moduleType;// 模块代码
private String operateCode;// 操作代码
private String operateValue;// 操作类型
private String remark;// 操作备注(记录参数)
private String operateStatus;// 操作状态(成功与否Y\\N)
private String method;// 调用方法
private String param;// 方法的请求参数
private String exceptionDetail;// 异常信息
static{
reqSource = "wap";
localAddr = WebUtils.getLocalAddr();
}
public void init()
{
User user = WebUtils.getSessionValue(LoginContact.SESSION_USER);
ip = WebUtils.getRemoteIP();
loginName = user != null ? user.getAccountNo() : getLoginName();
fullName = user != null ? user.getUserName() : getFullName();
operateDateTime = new Date();
createDateTime = new Date();
}
public Log()
{
init();
}
public Log(Log origin)
{
init();
this.id = origin.id;
this.type = origin.type;
this.moduleType = origin.moduleType;
this.operateCode = origin.operateCode;
this.operateValue = origin.operateValue;
this.remark = origin.remark;
this.operateStatus = origin.operateStatus;
this.method = origin.method;
this.param = origin.param;
this.exceptionDetail = origin.exceptionDetail;
this.fullName = origin.fullName;
this.loginName = origin.loginName;
}
public String getIp()
{
return ip;
}
public void setIp(String ip)
{
this.ip = ip;
}
public String getFullName()
{
return fullName;
}
public void setFullName(String fullName)
{
this.fullName = fullName;
}
public String getLoginName()
{
return loginName;
}
public void setLoginName(String loginName)
{
this.loginName = loginName;
}
public Date getOperateDateTime()
{
return operateDateTime;
}
public void setOperateDateTime(Date operateDateTime)
{
this.operateDateTime = operateDateTime;
}
public Date getCreateDateTime()
{
return createDateTime;
}
public void setCreateDateTime(Date createDateTime)
{
this.createDateTime = createDateTime;
}
public Long getId()
{
return id;
}
public void setId(Long id)
{
this.id = id;
}
public String getType()
{
return type;
}
public void setType(String type)
{
this.type = type;
}
public String getModuleType()
{
return moduleType;
}
public void setModuleType(String moduleType)
{
this.moduleType = moduleType;
}
public String getOperateCode()
{
return operateCode;
}
public void setOperateCode(String operateCode)
{
this.operateCode = operateCode;
}
public String getOperateValue()
{
return operateValue;
}
public void setOperateValue(String operateValue)
{
this.operateValue = operateValue;
}
public String getRemark()
{
return remark;
}
public void setRemark(String remark)
{
this.remark = remark;
}
public String getOperateStatus()
{
return operateStatus;
}
public void setOperateStatus(String operateStatus)
{
this.operateStatus = operateStatus;
}
public String getMethod()
{
return method;
}
public void setMethod(String method)
{
this.method = method;
}
public String getParam()
{
return param;
}
public void setParam(String param)
{
this.param = param;
}
public String getExceptionDetail()
{
return exceptionDetail;
}
public void setExceptionDetail(String exceptionDetail)
{
this.exceptionDetail = exceptionDetail;
}
public String getLocalAddr()
{
return localAddr;
}
public static class Builder
{
private Log target;
public Builder()
{
target = new Log();
}
public Builder id(Long id)
{
target.id = id;
return this;
}
public Builder type(String type)
{
target.type = type;
return this;
}
public Builder moduleType(String moduleType)
{
target.moduleType = moduleType;
return this;
}
public Builder operateCode(String operateCode)
{
target.operateCode = operateCode;
return this;
}
public Builder operateValue(String operateValue)
{
target.operateValue = operateValue;
return this;
}
public Builder remark(String remark)
{
target.remark = remark;
return this;
}
public Builder operateStatus(String operateStatus)
{
target.operateStatus = operateStatus;
return this;
}
public Builder method(String method)
{
target.method = method;
return this;
}
public Builder param(String param)
{
target.param = param;
return this;
}
public Builder exceptionDetail(String exceptionDetail)
{
target.exceptionDetail = exceptionDetail;
return this;
}
public Builder loginName(String loginName)
{
target.loginName = loginName;
return this;
}
public Builder fullName(String fullName)
{
target.fullName = fullName;
return this;
}
public Log build()
{
return new Log(target);
}
}
}
* @ClassName: WebUtils
* @version 1.0
* @Desc: WebUtils
* @history v1.0
*/
public class WebUtils
{
/**
* 描述:获取request对象
* @return
*/
public static HttpServletRequest getRequest()
{
return ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
}
/**
* 描述:获取responce对象
* @return
*/
public static HttpServletResponse getResponse()
{
return ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getResponse();
}
/**
* 描述:获取session
* @return
*/
public static HttpSession getSession()
{
return getRequest().getSession();
}
/**
* 描述:设置session值
* @param key
* @param val
*/
public static <T> void setSessionValue(String key, T val)
{
getSession().setAttribute(key, val);
}
/**
* 描述:获取session值
* @param key
* @return
*/
@SuppressWarnings("unchecked")
public static <T> T getSessionValue(String key)
{
return (T) getSession().getAttribute(key);
}
/**
* 描述:移除session
* @param key
* @return
*/
@SuppressWarnings("unchecked")
public static <T> T removeSessionValue(String key)
{
Object obj = getSession().getAttribute(key);
getSession().removeAttribute(key);
return (T) obj;
}
/**
* 描述:获取客户端ip
* @param request
* @return
*/
public static String getRemoteIP(HttpServletRequest request)
{
String ip = request.getHeader("x-forwarded-for");
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip))
{
ip = request.getHeader("Proxy-Client-IP");
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip))
{
ip = request.getHeader("WL-Proxy-Client-IP");
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip))
{
ip = request.getRemoteAddr();
}
return ip.equals("0:0:0:0:0:0:0:1") ? "127.0.0.1" : ip;
}
/**
*
* 获得本机IP
* @return
* @throws Exception
* @see [类、类#方法、类#成员]
*/
public final static String getLocalAddr()
{
String hostAddress = "";
try
{
hostAddress = InetAddress.getLocalHost().getHostAddress();
}
catch (Exception e)
{
}
return hostAddress;
}
/**
* 描述:获取客户端ip
* @return
*/
public static String getRemoteIP()
{
HttpServletRequest request = getRequest();
return getRemoteIP(request);
}
}
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`reqSource` varchar(10) DEFAULT 'pc' COMMENT '请求来源,pc:pc端,wap:wap端 默认来源为pc',
`type` varchar(10) DEFAULT NULL COMMENT '日志类型,‘operate’:操作日志,‘exception’:异常日志',
`ip` varchar(20) NOT NULL COMMENT '操作电脑ip',
`fullName` varchar(50) NOT NULL COMMENT '操作人员名字',
`loginName` varchar(50) NOT NULL COMMENT '操作人员登录账号',
`moduleType` varchar(50) NOT NULL COMMENT '模块代码',
`operateCode` varchar(50) NOT NULL COMMENT '操作代码',
`operateValue` varchar(50) DEFAULT NULL COMMENT '操作类型',
`operateDateTime` datetime NOT NULL COMMENT '操作时间',
`createDateTime` datetime NOT NULL COMMENT '创建时间',
`remark` varchar(100) DEFAULT NULL COMMENT '操作备注(记录参数)',
`operateStatus` varchar(20) DEFAULT NULL COMMENT '操作状态(成功与否Y\\N)',
`localAddr` varchar(20) DEFAULT NULL COMMENT '服务器IP',
`method` varchar(100) DEFAULT NULL COMMENT '调用方法',
`param` varchar(2000) DEFAULT NULL COMMENT '方法的请求参数',
`exceptionDetail` varchar(1000) DEFAULT NULL COMMENT '异常信息',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3430 DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC;
前言
操作日志在javaWeb的业务系统中是在是太常见的功能了,主要记录用户再什么时间,什么位置进行了什么操作。如果每新增一个功能都要写一个插入代码的话,是非常不容易维护的。加一个字段就要在每个插入语句上加入这个字段。所以AOP+注解的优势就显现了出来,不仅如此,当我们有了这套代码以后,可以通用在该系统的wap端或者其他的系统中,不必修改太多的代码。针对日志这种实时性不是很高的功能,这里用了异步的方式进行,这样日志系统独立出来,不会影响业务。下面是我整理的代码,欢迎留下宝贵意见。这里再次感谢原作者提供良好的思路。代码
一、核心类
1.自定义注解 拦截Controller
/** * * 自定义注解 拦截Controller * @see [相关类/方法] * @since [产品/模块版本] */ @Target({ElementType.PARAMETER, ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface SystemControllerLog { String description() default "";//描述 String moduleType() default "";//模块代码 String operateValue() default "";//操作类型 boolean firstParamName() default false; }
2.自定义注解 拦截service
/** * * 自定义注解 拦截service * @see [相关类/方法] * @since [产品/模块版本] */ @Target({ElementType.PARAMETER, ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface SystemServiceLog { String description() default "";// 描述 String moduleType() default "";// 模块代码 String operateValue() default "";// 操作类型 }
3.AOP可以拦截到controller的配置
spring.xml中加入下面这句话<aop:aspectj-autoproxy proxy-target-class="true" />4.切点类
这里用的是返回通知,用来接收成功或失败。/***
* AOP记录操作&异常日志-切点类
* @see [相关类/方法]
* @since [产品/模块版本]
*/
@Aspect
@Component
public class SystemLogAspect
{
private static final Logger logger = LoggerFactory.getLogger(SystemLogAspect.class);
// 队列
private static BlockingQueue<Log> queue = new LinkedBlockingQueue<Log>();
// 缓存线程池
private static ExecutorService threadPool = Executors.newFixedThreadPool(3);
// 任务数
private static int taskSize = 6;
// 线程是否已启动
boolean isStartThread = false;
// 用来启动或停止线程
static boolean run = true;
@Autowired
private LogService logService;
@Autowired
private UserService userService;
// Service层切点
@Pointcut("@annotation(com.rzzl.wap.log.annotation.SystemServiceLog)")
public void serviceAspect()
{
}
// Controller层切点
@Pointcut("@annotation(com.rzzl.wap.log.annotation.SystemControllerLog)")
public void controllerAspect()
{
}
public static BlockingQueue<Log> getQueue()
{
return queue;
}
public static void setQueue(BlockingQueue<Log> queue)
{
SystemLogAspect.queue = queue;
}
public static boolean isRun()
{
return run;
}
public static void setRun(boolean run)
{
SystemLogAspect.run = run;
}
/**
*
* 返回通知 用于拦截Controller层记录用户的操作
* @param joinPoint 切点
* @param result 返回值
* @see [类、类#方法、类#成员]
*/
@AfterReturning(value = "controllerAspect()", returning = "result")
public void afterReturn(JoinPoint joinPoint, Object result)
{
// 请求的IP
User user = WebUtils.getSessionValue(LoginContact.SESSION_USER);
String params = "";
WebResult webResult = new WebResult();
webResult.setCode(FlagContact.BACK_SUCCESS);
try
{
if (WebResult.class.isInstance(result))
{
webResult = (WebResult)result;
}
String loginName = "";
InnnerBean innnerBean = getControllerMethodDescription(joinPoint);
Object[] arguments = innnerBean.getArguments();
String remark = innnerBean.getDescription();
Log log = new Log.Builder().type(LogTypes.type.operate)
.moduleType(innnerBean.getModuleType())
.operateCode(joinPoint.getSignature().getName())
.operateValue(innnerBean.getOperateValue())
.remark(remark)
.operateStatus(webResult.getCode().equals(FlagContact.BACK_SUCCESS) ? LogTypes.operateStatus.Y
: LogTypes.operateStatus.N)// 返回值1操作成功,否则失败
.method((joinPoint.getTarget().getClass().getName() + "." + joinPoint.getSignature().getName() + "()"))
.param(params)
.loginName(user.getAccountNo())
.fullName(user.getUserName())
.build();
// 放入队列
queue.put(log);
if (!isStartThread)
{
for (int i = 0; i < taskSize; i++)
{
threadPool.execute(new saveLogThread());
}
isStartThread = true;
}
}
catch (Exception e)
{
logger.error("异常信息:{}", e.toString());
}
}
/**
* 异常通知 用于拦截service层记录异常日志
* @param joinPoint
* @param e
* @see [类、类#方法、类#成员]
*/
@AfterThrowing(pointcut = "serviceAspect()", throwing = "e")
public void doAfterThrowing(JoinPoint joinPoint, Throwable e)
{
// 读取session中的用户
User user = WebUtils.getSessionValue(LoginContact.SESSION_USER);
String params = "";
try
{
if (joinPoint.getArgs() != null && joinPoint.getArgs().length > 0)
{
for (int i = 0; i < joinPoint.getArgs().length; i++)
{
params += JSONUtils.valueToString(joinPoint.getArgs()[i].toString()) + ";";
}
}
InnnerBean innnerBean = getServiceMthodDescription(joinPoint);
String loginName = "";
Log log =
new Log.Builder().type(LogTypes.type.exception)
.moduleType(innnerBean.getModuleType())
.operateCode(joinPoint.getSignature().getName())
.operateValue(innnerBean.getOperateValue())
.remark(innnerBean.getDescription())
.operateStatus(LogTypes.operateStatus.N)
.method(
(joinPoint.getTarget().getClass().getName() + "." + joinPoint.getSignature().getName() + "()"))
.param(params)
.exceptionDetail(e.toString())
.build();
// 放入队列
queue.put(log);
if (!isStartThread)
{
new Thread(new saveLogThread()).start();
isStartThread = true;
}
}
catch (Exception ex)
{
logger.error("异常信息:{}", ex.toString());
}
finally
{
logger.error("异常方法:{" + joinPoint.getTarget().getClass().getName() + "}异常代码:{"
+ joinPoint.getSignature().getName() + "}异常信息:{" + e.toString() + "}参数:{" + params + "}");
}
}
/**
* 获取注解中对方法的描述信息 用于service层注解
* @param joinPoint 切点
* @return 方法描述
* @throws Exception
* @see [类、类#方法、类#成员]
*/
@SuppressWarnings("rawtypes")
public static InnnerBean getServiceMthodDescription(JoinPoint joinPoint)
throws Exception
{
String targetName = joinPoint.getTarget().getClass().getName();
String methodName = joinPoint.getSignature().getName();
Object[] arguments = joinPoint.getArgs();
Class targetClass = Class.forName(targetName);
Method[] methods = targetClass.getMethods();
String moduleType = "";
String operateValue = "";
String description = "";
InnnerBean innnerBean = new InnnerBean(moduleType, operateValue, description);
for (Method method : methods)
{
if (method.getName().equals(methodName))
{
Class[] clazzs = method.getParameterTypes();
if (clazzs.length == arguments.length)
{
SystemServiceLog annotation = method.getAnnotation(SystemServiceLog.class);
moduleType = annotation.moduleType();
operateValue = annotation.operateValue();
description = annotation.description();
innnerBean = new InnnerBean(moduleType, operateValue, description);
break;
}
}
}
innnerBean.setArguments(arguments);
return innnerBean;
}
/**
* 获取注解中对方法的描述信息 用于Controller层注解
* @param joinPoint 切点
* @return 方法描述
* @throws Exception
* @see [类、类#方法、类#成员]
*/
@SuppressWarnings("rawtypes")
public static InnnerBean getControllerMethodDescription(JoinPoint joinPoint)
throws Exception
{
String targetName = joinPoint.getTarget().getClass().getName();
String methodName = joinPoint.getSignature().getName();
Object[] arguments = joinPoint.getArgs();
Class targetClass = Class.forName(targetName);
Method[] methods = targetClass.getMethods();
String moduleType = "";
String operateValue = "";
String description = "";
boolean firstParamName = false;
InnnerBean innnerBean = new InnnerBean(moduleType, operateValue, description);
for (Method method : methods)
{
if (method.getName().equals(methodName))
{
Class[] clazzs = method.getParameterTypes();
if (clazzs.length == arguments.length)
{
SystemControllerLog annotation = method.getAnnotation(SystemControllerLog.class);
moduleType = annotation.moduleType();
operateValue = annotation.operateValue();
description = annotation.description();
firstParamName = annotation.firstParamName();
innnerBean = new InnnerBean(moduleType, operateValue, description);
innnerBean.setFirstParamName(firstParamName);
break;
}
}
}
innnerBean.setArguments(arguments);
return innnerBean;
}
/**
*
* 内部类封装注入信息
* @see [相关类/方法]
* @since [产品/模块版本]
*/
static class InnnerBean
{
private String moduleType;// 模块代码
private String description;// 描述
private String operateValue;// 操作类型
private boolean firstParamName;
private Object[] arguments;
public InnnerBean(String moduleType, String operateValue, String description)
{
super();
this.moduleType = moduleType;
this.description = description;
this.operateValue = operateValue;
}
public String getOperateValue()
{
return operateValue;
}
public void setOperateValue(String operateValue)
{
this.operateValue = operateValue;
}
public String getModuleType()
{
return moduleType;
}
public void setModuleType(String moduleType)
{
this.moduleType = moduleType;
}
public String getDescription()
{
return description;
}
public void setDescription(String description)
{
this.description = description;
}
public Object[] getArguments()
{
return arguments;
}
public void setArguments(Object[] arguments)
{
this.arguments = arguments;
}
public boolean isFirstParamName()
{
return firstParamName;
}
public void setFirstParamName(boolean firstParamName)
{
this.firstParamName = firstParamName;
}
}
/**
*
* 异步保存日志
* @see [相关类/方法]
* @since [产品/模块版本]
*/
class saveLogThread implements Runnable
{
Lock lock = new ReentrantLock();
@Override
public void run()
{
try
{
while (run)
{
while (queue.size() != 0)
{
// 如果对插入顺序无要求,此处不需要同步可提升效率
lock.lock();
Log log = queue.take();
logService.insert(log);
lock.unlock();
}
Thread.sleep(3000);
}
}
catch (InterruptedException e)
{
logger.error("saveLogThread被唤醒:" + e.toString());
}
catch (Exception e)
{
logger.error("saveLogThread异常:" + e.toString());
}
}
}
}
二、定值类
日志系统中的定值
/** * * 日志系统中的定值 * * @see [相关类/方法] * @since [产品/模块版本] */ public interface LogTypes { /** * * 操作状态(成功与否Y\\N) * @see [相关类/方法] * @since [产品/模块版本] */ static interface operateStatus { // 成功 final String Y = "Y"; // 失败 final String N = "N"; } /** * * 日志类型 * @see [相关类/方法] * @since [产品/模块版本] */ static interface type { // 操作日志 final String operate = "operate"; // 异常日志 final String exception = "exception"; } /** * * 模块类型 * @see [相关类/方法] * @since [产品/模块版本] */ static interface moduleType { // 登录模块 final String LOGIN = "LOGIN"; // 项目模块 final String PROJECT = "PROJECT"; // 客户模块 final String CUSTOMER = "CUSTOMER"; // 用户模块 final String SYS_USER = "SYS_USER"; } /** * * 操作类型 * @see [相关类/方法] * @since [产品/模块版本] */ static interface operateValue { // 查询 final String select = "select"; // 登录 final String login = "login"; // 保存 final String save = "save"; // 新增 final String add = "add"; // 修改 final String edit = "edit"; // 删除 final String delete = "delete"; // 查看 final String view = "view"; // 修改密码 final String editPassword = "editPassword"; // 上传 final String upload = "upload"; // 下载 final String down = "down"; // 下载 final String packagedown = "packagedown"; } /** * * 保存描述的前缀 * 方便于批量修改该备注 * @see [相关类/方法] * @since [产品/模块版本] */ static interface Prefix { // 查询 final String savePrefix = "新增/编辑"; } }
三、实体类
1、日志实体
应用了Builder设计模式/***
* 操作日志&异常日志
* @see [相关类/方法]
* @since [产品/模块版本]
*/
public class Log implements Serializable
{
/**
* serialVersionUID
*/
private static final long serialVersionUID = 1L;
private static final String reqSource;// 请求来源,pc:pc端,wap:wap端 默认来源为pc
private static final String localAddr;// 服务器IP
private String ip;// 操作电脑ip
private String fullName;// 操作人员名字
private String loginName;// 操作人员登录账号
private Date operateDateTime;// 操作时间
private Date createDateTime;// 创建时间
private Long id;
private String type;// 日志类型,‘operate’:操作日志,‘exception’:异常日志
private String moduleType;// 模块代码
private String operateCode;// 操作代码
private String operateValue;// 操作类型
private String remark;// 操作备注(记录参数)
private String operateStatus;// 操作状态(成功与否Y\\N)
private String method;// 调用方法
private String param;// 方法的请求参数
private String exceptionDetail;// 异常信息
static{
reqSource = "wap";
localAddr = WebUtils.getLocalAddr();
}
public void init()
{
User user = WebUtils.getSessionValue(LoginContact.SESSION_USER);
ip = WebUtils.getRemoteIP();
loginName = user != null ? user.getAccountNo() : getLoginName();
fullName = user != null ? user.getUserName() : getFullName();
operateDateTime = new Date();
createDateTime = new Date();
}
public Log()
{
init();
}
public Log(Log origin)
{
init();
this.id = origin.id;
this.type = origin.type;
this.moduleType = origin.moduleType;
this.operateCode = origin.operateCode;
this.operateValue = origin.operateValue;
this.remark = origin.remark;
this.operateStatus = origin.operateStatus;
this.method = origin.method;
this.param = origin.param;
this.exceptionDetail = origin.exceptionDetail;
this.fullName = origin.fullName;
this.loginName = origin.loginName;
}
public String getIp()
{
return ip;
}
public void setIp(String ip)
{
this.ip = ip;
}
public String getFullName()
{
return fullName;
}
public void setFullName(String fullName)
{
this.fullName = fullName;
}
public String getLoginName()
{
return loginName;
}
public void setLoginName(String loginName)
{
this.loginName = loginName;
}
public Date getOperateDateTime()
{
return operateDateTime;
}
public void setOperateDateTime(Date operateDateTime)
{
this.operateDateTime = operateDateTime;
}
public Date getCreateDateTime()
{
return createDateTime;
}
public void setCreateDateTime(Date createDateTime)
{
this.createDateTime = createDateTime;
}
public Long getId()
{
return id;
}
public void setId(Long id)
{
this.id = id;
}
public String getType()
{
return type;
}
public void setType(String type)
{
this.type = type;
}
public String getModuleType()
{
return moduleType;
}
public void setModuleType(String moduleType)
{
this.moduleType = moduleType;
}
public String getOperateCode()
{
return operateCode;
}
public void setOperateCode(String operateCode)
{
this.operateCode = operateCode;
}
public String getOperateValue()
{
return operateValue;
}
public void setOperateValue(String operateValue)
{
this.operateValue = operateValue;
}
public String getRemark()
{
return remark;
}
public void setRemark(String remark)
{
this.remark = remark;
}
public String getOperateStatus()
{
return operateStatus;
}
public void setOperateStatus(String operateStatus)
{
this.operateStatus = operateStatus;
}
public String getMethod()
{
return method;
}
public void setMethod(String method)
{
this.method = method;
}
public String getParam()
{
return param;
}
public void setParam(String param)
{
this.param = param;
}
public String getExceptionDetail()
{
return exceptionDetail;
}
public void setExceptionDetail(String exceptionDetail)
{
this.exceptionDetail = exceptionDetail;
}
public String getLocalAddr()
{
return localAddr;
}
public static class Builder
{
private Log target;
public Builder()
{
target = new Log();
}
public Builder id(Long id)
{
target.id = id;
return this;
}
public Builder type(String type)
{
target.type = type;
return this;
}
public Builder moduleType(String moduleType)
{
target.moduleType = moduleType;
return this;
}
public Builder operateCode(String operateCode)
{
target.operateCode = operateCode;
return this;
}
public Builder operateValue(String operateValue)
{
target.operateValue = operateValue;
return this;
}
public Builder remark(String remark)
{
target.remark = remark;
return this;
}
public Builder operateStatus(String operateStatus)
{
target.operateStatus = operateStatus;
return this;
}
public Builder method(String method)
{
target.method = method;
return this;
}
public Builder param(String param)
{
target.param = param;
return this;
}
public Builder exceptionDetail(String exceptionDetail)
{
target.exceptionDetail = exceptionDetail;
return this;
}
public Builder loginName(String loginName)
{
target.loginName = loginName;
return this;
}
public Builder fullName(String fullName)
{
target.fullName = fullName;
return this;
}
public Log build()
{
return new Log(target);
}
}
}
2.返回结果实体
/** * @ClassName: WebResult * @version 1.0 * @Desc: WEB返回JSON结果 * @history v1.0 */ public class WebResult implements Serializable { private static final long serialVersionUID = -4776437900752507269L; /** * 返回消息 */ private String msg; /** * 返回码 */ private String code; /** * 返回数据 */ private Object data; private Map<?,?> map; private List<Map<String, Object>> list; public WebResult() { } public WebResult(String msg, String code) { super(); this.msg = msg; this.code = code; } public WebResult(String msg, String code, Object data) { super(); this.msg = msg; this.code = code; this.data = data; } public String getMsg() { return msg; } public void setMsg(String msg) { this.msg = msg; } public String getCode() { return code; } public void setCode(String code) { this.code = code; } public Object getData() { return data; } public void setData(Object data) { this.data = data; } public Map<?, ?> getMap() { return map; } public void setMap(Map<?, ?> map) { this.map = map; } public List<Map<String, Object>> getList() { return list; } public void setList(List<Map<String, Object>> list) { this.list = list; } @Override public String toString() { return "WebResult [msg=" + msg + ", code=" + code + ", data=" + data + "]"; } /** * 初始失败方法 * * @author cc HSSD0473 * @see [类、类#方法、类#成员] */ public void invokeFail(){ this.data = null; this.code = FlagContact.BACK_FAIL; this.msg = "操作失败"; } public void invokeFail(String msg){ this.data = null; this.code = FlagContact.BACK_FAIL; if(msg != null && !msg.equals("")) { this.msg = msg; } } public void invokeSuccess() { this.code = FlagContact.BACK_SUCCESS; this.msg = "操作成功"; } public void invokeSuccess(String msg) { if(msg != null && !msg.equals("")) { this.msg = msg; } this.code = FlagContact.BACK_SUCCESS; } }
三、工具类
获取登录用户,客户ip主机ip等方法*** @ClassName: WebUtils
* @version 1.0
* @Desc: WebUtils
* @history v1.0
*/
public class WebUtils
{
/**
* 描述:获取request对象
* @return
*/
public static HttpServletRequest getRequest()
{
return ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
}
/**
* 描述:获取responce对象
* @return
*/
public static HttpServletResponse getResponse()
{
return ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getResponse();
}
/**
* 描述:获取session
* @return
*/
public static HttpSession getSession()
{
return getRequest().getSession();
}
/**
* 描述:设置session值
* @param key
* @param val
*/
public static <T> void setSessionValue(String key, T val)
{
getSession().setAttribute(key, val);
}
/**
* 描述:获取session值
* @param key
* @return
*/
@SuppressWarnings("unchecked")
public static <T> T getSessionValue(String key)
{
return (T) getSession().getAttribute(key);
}
/**
* 描述:移除session
* @param key
* @return
*/
@SuppressWarnings("unchecked")
public static <T> T removeSessionValue(String key)
{
Object obj = getSession().getAttribute(key);
getSession().removeAttribute(key);
return (T) obj;
}
/**
* 描述:获取客户端ip
* @param request
* @return
*/
public static String getRemoteIP(HttpServletRequest request)
{
String ip = request.getHeader("x-forwarded-for");
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip))
{
ip = request.getHeader("Proxy-Client-IP");
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip))
{
ip = request.getHeader("WL-Proxy-Client-IP");
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip))
{
ip = request.getRemoteAddr();
}
return ip.equals("0:0:0:0:0:0:0:1") ? "127.0.0.1" : ip;
}
/**
*
* 获得本机IP
* @return
* @throws Exception
* @see [类、类#方法、类#成员]
*/
public final static String getLocalAddr()
{
String hostAddress = "";
try
{
hostAddress = InetAddress.getLocalHost().getHostAddress();
}
catch (Exception e)
{
}
return hostAddress;
}
/**
* 描述:获取客户端ip
* @return
*/
public static String getRemoteIP()
{
HttpServletRequest request = getRequest();
return getRemoteIP(request);
}
}
四、清理工作
tomcat停止前,异步日志的清理动作
/** * * tomcat停止前,异步日志的清理动作 * @see [相关类/方法] * @since [产品/模块版本] */ @WebListener() public class BeforeDestoryListener implements ServletContextListener { @Override public void contextInitialized(ServletContextEvent sce) { } @Override public void contextDestroyed(ServletContextEvent sce) { while (SystemLogAspect.getQueue().size() == 0) { SystemLogAspect.setRun(false); break; } } }
数据库
用的是mysql,其他数据库请自行更改语句CREATE TABLE `t_log` (`id` bigint(20) NOT NULL AUTO_INCREMENT,
`reqSource` varchar(10) DEFAULT 'pc' COMMENT '请求来源,pc:pc端,wap:wap端 默认来源为pc',
`type` varchar(10) DEFAULT NULL COMMENT '日志类型,‘operate’:操作日志,‘exception’:异常日志',
`ip` varchar(20) NOT NULL COMMENT '操作电脑ip',
`fullName` varchar(50) NOT NULL COMMENT '操作人员名字',
`loginName` varchar(50) NOT NULL COMMENT '操作人员登录账号',
`moduleType` varchar(50) NOT NULL COMMENT '模块代码',
`operateCode` varchar(50) NOT NULL COMMENT '操作代码',
`operateValue` varchar(50) DEFAULT NULL COMMENT '操作类型',
`operateDateTime` datetime NOT NULL COMMENT '操作时间',
`createDateTime` datetime NOT NULL COMMENT '创建时间',
`remark` varchar(100) DEFAULT NULL COMMENT '操作备注(记录参数)',
`operateStatus` varchar(20) DEFAULT NULL COMMENT '操作状态(成功与否Y\\N)',
`localAddr` varchar(20) DEFAULT NULL COMMENT '服务器IP',
`method` varchar(100) DEFAULT NULL COMMENT '调用方法',
`param` varchar(2000) DEFAULT NULL COMMENT '方法的请求参数',
`exceptionDetail` varchar(1000) DEFAULT NULL COMMENT '异常信息',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3430 DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC;
测试及结果
控制层代码
/** * 登录请求 * * @param userName 用户名 * @param password 密码 * @return WebResult msg:系统反馈消息 code:登录标识码 * @see [类、类#方法、类#成员] */ @ResponseBody @RequestMapping("login") @SystemControllerLog(moduleType=LogTypes.moduleType.LOGIN,operateValue=LogTypes.operateValue.login,description = "登录动作") public WebResult userLogin(String accoutnNo, String password) { WebResult wt = new WebResult(); try { // 登录逻辑 } catch(Exception e) { log.error("登录异常:" + e.toString()); wt.invokeFail(); } return wt; }
数据库结果
相关文章推荐
- 基于SSM利用SpringAOP切面及自定义注解 记录每次操作记录(操作日志 同理)
- java ssh spring aop 切面编程 操作日志
- java SpringAOP拦截Controller,Service实现日志管理(自定义注解的方式)
- java SpringAOP拦截Controller,Service实现日志管理(自定义注解的方式)
- 使用spring aop + 注解完成对业务操作的日志记录
- 使用AOP与注解记录Java日志
- spring aop注解配置web日志
- java springMVC SSM 操作日志 4级别联动 文件管理 头像编辑 shiro redis
- 2017/2/23 Java SpringAOP拦截Service实现日志管理(自定义注解)
- java SpringAOP拦截Controller,Service实现日志管理(自定义注解的方式)
- aop和注解将权限和操作日志与业务解耦
- web 工程下 java操作属性文件保存在classes下的读写操作
- java springMVC SSM 操作日志 4级别联动 文件管理 头像编辑 shiro redis
- 160919、使用AOP与注解记录Java日志
- 利用Spring AOP与JAVA注解为系统增加日志功能
- 使用Spring AOP使用注解记录用户操作日志
- 利用Spring的AOP编程和JAVA自定义注解,实现Web项目的HTTP请求头域检测
- spring aop注解配置web日志
- 【JavaWeb-14】代理Proxy、动态代理、AOP编程思想、注解、元注解、类加载器
- 基于Spring aop 和JAVA注解方式添加日志