操作日志表
CREATE TABLE `log` (
`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '日志编号',
`user_id` int(11) DEFAULT NULL COMMENT '操作者编号',
`user_name` varchar(10) DEFAULT NULL COMMENT '操作者姓名',
`ip` varchar(255) DEFAULT NULL COMMENT 'IP',
`operate_content` varchar(255) DEFAULT NULL COMMENT '操作说明',
`method` varchar(255) DEFAULT NULL COMMENT '方法名',
`controller` varchar(255) DEFAULT NULL COMMENT '控制器名',
`type` int(255) DEFAULT '1' COMMENT '日志类型(1无异常,2有异常)',
`exmsg` varchar(255) DEFAULT NULL COMMENT '异常信息',
`operate_time` datetime DEFAULT NULL COMMENT '操作时间',
`parameters` longtext COMMENT '方法参数',
`return_value` longtext COMMENT '返回值',
PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=51 DEFAULT CHARSET=utf8mb4;
操作日志的实体类,Mapper由mybatis生成器编写,Service,ServiceImpl自己编写
操作者实体类(与登陆模块的session中保存的登录者信息相关,这里已经省略getter和setter)
public class UserInfo {
private long userId;
private String userName;
private String password;
}
在spring-mvc.xml中开启aop
<aop:aspectj-autoproxy/>
<aop:config proxy-target-class="true"></aop:config>
自定义注解
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@Documented
public @interface ArchivesLog {
/**
* 操作说明
*/
public String operteContent() default "";
}
aop类
@Aspect
@Component
public class ArchivesLogAspect {
@Autowired
private LogService logService;
private static final Logger logger = LoggerFactory.getLogger(ArchivesLog.class);
@Pointcut("@annotation(com.framework.annotation.ArchivesLog)")
public void controllerAspect() {
//System.out.println("切入点...");
}
/**
* 方法调用后触发 , 记录正常操作
*
* @param joinPoint
* @throws ClassNotFoundException
*/
@AfterReturning(value = "controllerAspect()", returning = "returnValue")
public void after(JoinPoint joinPoint, Object returnValue) throws ClassNotFoundException, UnknownHostException {
// 用户id
int userId = (int) getUSerMsg().getUserId();
String userName = getUSerMsg().getUserName();
// 用户IP
String ip = InetAddress.getLocalHost().getHostAddress();
// 控制器名
String targetName = getMethodDesc(joinPoint).getController();
// 方法名
String methodName = getMethodDesc(joinPoint).getMethod();
// 操作说明
String operteContent = getMethodDesc(joinPoint).getOperateContent();
String parameters = Arrays.toString(removeServletObjects(joinPoint.getArgs()));
String returnValueStr = (returnValue == null ? "null" : returnValue.toString());
System.out.println("操作者:" + userName);
System.out.println("操作说明:" + operteContent);
System.out.println("方法参数:" + Arrays.toString(joinPoint.getArgs()));
System.out.println("方法返回值:" + (returnValue == null ? "null" : returnValue.toString()));
Log log = new Log();
log.setParameters(parameters);
log.setReturnValue(returnValueStr);
log.setUserId(userId);
log.setIp(ip);
log.setOperateContent(operteContent);
log.setMethod(methodName);
log.setController(targetName);
log.setOperateTime(new Date());
log.setUserName(userName);
logService.insertSelective(log);
}
/**
* 发生异常,走此方法
*
* @param joinPoint
* @param e
*/
@AfterThrowing(pointcut = "controllerAspect()", throwing = "e")
public void AfterThrowing(JoinPoint joinPoint, Throwable e) {
try {
// 用户id
int userId = (int) getUSerMsg().getUserId();
// 操作者姓名
String userName = getUSerMsg().getUserName();
// 用户IP
String ip = InetAddress.getLocalHost().getHostAddress();
// 控制器名
String targetName = getMethodDesc(joinPoint).getController();
// 方法名
String methodName = getMethodDesc(joinPoint).getMethod();
// 操作说明
String operteContent = getMethodDesc(joinPoint).getOperateContent();
Log log = new Log();
String exMsg = e.getCause().toString();
String parameters = Arrays.toString(removeServletObjects(joinPoint.getArgs()));
System.out.println("操作者:" + userName);
System.out.println("操作说明:" + operteContent);
System.out.println("方法参数:" + Arrays.toString(joinPoint.getArgs()));
System.out.println("操作有异常:" + e.getCause().toString());
if (exMsg != null) {
int type = 2;
log.setUserId(userId);
log.setIp(ip);
log.setOperateContent(operteContent);
log.setParameters(parameters);
log.setMethod(methodName);
log.setController(targetName);
log.setType(type);
log.setExmsg(exMsg);
log.setUserName(userName);
logService.insertSelective(log);
}
} catch (Exception e1) {
logger.error(e1.getMessage());
}
}
/**
* 获取 注解中对方法的描述
*
* @return
* @throws ClassNotFoundException
*/
public static Log getMethodDesc(JoinPoint joinPoint) throws ClassNotFoundException {
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 operteContent = "";
for (Method method : methods) {
if (method.getName().equals(methodName)) {
Class[] clazzs = method.getParameterTypes();
if (clazzs.length == arguments.length) {
//操作说明
operteContent = method.getAnnotation(ArchivesLog.class).operteContent();
break;
}
}
}
Log log = new Log();
log.setController(targetName);
log.setMethod(methodName);
log.setOperateContent(operteContent);
return log;
}
/**
* 得到用户信息
*
* @return
*/
public static UserInfo getUSerMsg() {
HttpServletRequest req = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
// 获取session
HttpSession session = req.getSession();
// 从session中获取网站登录者信息
UserInfo user = (UserInfo) session.getAttribute("userInfo");
return user;
}
/*去掉方法参数的servlet对象*/
public static Object[] removeServletObjects(Object[] objects) {
List list = Arrays.asList(objects);
list = new ArrayList(list);
for (int i = 0; i < list.size(); i++) {
Object object = list.get(i);
if (object instanceof HttpServletResponse || object instanceof HttpServletRequest) {
list.remove(object);
i--;
}
}
System.out.println(list);
objects = list.toArray();
return objects;
}
}
在控制层的方法上加入注解
@ArchivesLog(operteContent = "退费")
@RequestMapping(value = "/addPaymentRefund.html", method = RequestMethod.POST)
public void addPaymentRefund(HttpServletRequest request,
HttpServletResponse response,
PaymentRefund paymentRefund) {