Java使用aop实现操作日志
1、设计数据表
-- ---------------------------- -- Table structure for t_log -- ---------------------------- DROP TABLE IF EXISTS `t_log`; CREATE TABLE `t_log` ( `id` int(11) NOT NULL auto_increment COMMENT '操作日志id', `username` varchar(20) default NULL COMMENT '操作人', `module` varchar(30) default NULL COMMENT '执行模块', `methods` varchar(50) default NULL COMMENT '执行方法', `content` varchar(255) default NULL COMMENT '操作内容', `actionurl` varchar(50) default NULL COMMENT '请求路径', `ip` varchar(50) default NULL COMMENT 'IP地址', `date` datetime default NULL COMMENT '操作时间', `commite` tinyint(2) default NULL COMMENT '执行描述(1:执行成功、2:执行失败)', PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
2、实体类
import java.util.Date; public class Log { private Integer id;//操作日志ID private String username;//操作人 private String module;//操作模块 private String methods;//执行方法 private String content;//操作内容 private String actionurl;//请求路径 private String ip;//IP private Date date;//操作时间 private Byte commite;//执行描述(1:执行成功、2:执行失败) }
3、Spring配置文件添加AOP配置
<!--xml头部配置aop--> xmlns:aop="http://www.springframework.org/schema/aop" http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd <!-- 操作日志配置 指定扫描aop执行操作的类 --> <aop:aspectj-autoproxy proxy-target-class="true" />
<bean id="logAopAction" class="com.saffi.action.LogAopAction"/>
4、自定义注解
import java.lang.annotation.*;
/**
* <p>Title: SystemLog</p>
* <p>Description:自定义操作日志标签,模块名和方法名 </p>
* @author Saffichan
* @date 2018-06-01 15:57
*/
@Target({ElementType.PARAMETER, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface OptionalLog {
String module() default "";
String methods() default "";
}
5、Controller层
/** * <p>Title: LogAopAction.java</p> * <p>Description: 操作日志Controller</p> * <p>Company: </p> * @author Saffichan * @date 2018-06-01 15:38 * @version 1.0 */import java.lang.reflect.Method; import java.net.InetAddress; import java.net.UnknownHostException; import java.util.Date; import java.util.HashMap; import java.util.Map; import javax.annotation.Resource; import javax.servlet.http.HttpServletRequest; import org.springframework.web.context.request.RequestContextHolder; import org.springframework.web.context.request.ServletRequestAttributes; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.Signature; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Pointcut; import org.aspectj.lang.reflect.MethodSignature; import com.saffi.web.BaseAction; import com.saffi.common.util.MapperUtil; import com.saffi.system.bo.LogBO; import com.saffi.service.LogService; import com.saffi.user.bo.AdminBO; import com.saffi.web.annotation.PermssionMethodCode; @Aspect public class LogAopAction { // 注入service,用来将日志信息保存在数据库 @Resource(name = "logService") private LogService logService; // 配置接入点,即为所要记录的action操作目录 @Pointcut("execution(* com.saffi.*.action..*.*(..))") private void controllerAspect() { } @Around("controllerAspect()") public Object around(ProceedingJoinPoint pjp) throws Throwable { //日志实体对象 LogBO logBo = new LogBO(); HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()) .getRequest(); // 从session获取用户名 String username = request.getSession().getAttribute("user"); logBo.setUsername(username); // 获取系统当前时间 logBo.setDate(new Date()); // 获取访问真实IP String ipAddress = request.getHeader("x-forwarded-for"); if(ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) { ipAddress = request.getHeader("Proxy-Client-IP"); } if(ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) { ipAddress = request.getHeader("WL-Proxy-Client-IP"); } if(ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) { ipAddress = request.getRemoteAddr(); if(ipAddress.equals("127.0.0.1") || ipAddress.equals("0:0:0:0:0:0:0:1")){ //根据网卡取本机配置的IP InetAddress inet=null; try { inet = InetAddress.getLocalHost(); } catch (UnknownHostException e) { e.printStackTrace(); } ipAddress= inet.getHostAddress(); } } //对于通过多个代理的情况,第一个IP为客户端真实IP,多个IP按照','分割 if(ipAddress!=null && ipAddress.length()>15){ //"***.***.***.***".length() = 15 if(ipAddress.indexOf(",")>0){ ipAddress = ipAddress.substring(0,ipAddress.indexOf(",")); } } logBo.setIp(ipAddress); // 拦截的实体类,就是当前正在执行的controller Object target = pjp.getTarget(); // 拦截的方法名称。当前正在执行的方法 String methodName = pjp.getSignature().getName(); // 拦截的方法参数 Object[] args = pjp.getArgs(); //获取请求路径 String actionUrl = request.getRequestURI(); // 拦截的放参数类型 Signature sig = pjp.getSignature(); MethodSignature msig = null; if (!(sig instanceof MethodSignature)) { throw new IllegalArgumentException("该注解只能用于方法"); } msig = (MethodSignature) sig; Class[] parameterTypes = msig.getMethod().getParameterTypes(); Object object = null; // 获得被拦截的方法 Method method = null; try { method = target.getClass().getMethod(methodName, parameterTypes); } catch (NoSuchMethodException e1) { e1.printStackTrace(); } catch (SecurityException e1) { e1.printStackTrace(); } if (null != method) { // 获取方法(此为自定义注解) OptionalLog op = method.getAnnotation(OptionalLog .class); // 获取注解的modules 设为操作模块 logBo.setModule(op.modules()); // 获取注解的methods 设为执行方法 logBo.setMethods(op.methods()); // 将上面获取到的请求路径 设为请求路径 logBo.setActionurl(actionUrl); try { object = pjp.proceed(); //接受客户端的数据 Map<String,String[]> map = request.getParameterMap();
// 解决获取参数乱码 Map<String,String[]> newmap = new HashMap<String,String[]>(); for(Map.Entry<String, String[]> entry : map.entrySet()){ String name = entry.getKey(); String values[] = entry.getValue(); if(values==null){ newmap.put(name, new String[]{}); continue; } String newvalues[] = new String[values.length]; for(int i=0; i<values.length;i++){ String value = values[i]; value = new String(value.getBytes("iso8859-1"),request.getCharacterEncoding()); newvalues[i] = value; //解决乱码后封装到Map中 } newmap.put(name, newvalues); } logBo.setContent(MapperUtil.toJsonStr(newmap)); //1为执行成功 logBo.setCommite((byte) 1); // 添加到数据库 logService.add(logBo); } catch (Throwable e) {
//接受客户端的数据 Map<String,String[]> map = request.getParameterMap();
// 解决获取参数乱码 Map<String,String[]> newmap = new HashMap<String,String[]>(); for(Map.Entry<String, String[]> entry : map.entrySet()){ String name = entry.getKey(); String values[] = entry.getValue(); if(values==null){ newmap.put(name, new String[]{}); continue; } String newvalues[] = new String[values.length]; for(int i=0; i<values.length;i++){ String value = values[i]; value = new String(value.getBytes("iso8859-1"),request.getCharacterEncoding()); newvalues[i] = value; //解决乱码后封装到Map中 } newmap.put(name, newvalues); }
//MapperUtil.toJsonStr为自定义的转换工具类 logBo.setContent(MapperUtil.toJsonStr(newmap)); //2为执行失败 logBo.setCommite((byte) 2);
//添加到数据库 logService.add(logBo); } } return object; } }
6、具体操作action使用方法
/** * <p>Description:查询所有操作日志 </p> * @author Saffichan * */ @OptionalLog(modules="操作日志", methods="查询操作日志") @RequestMapping("/query") public void listLogInfo(){ }