zoukankan      html  css  js  c++  java
  • 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(){
        }    
  • 相关阅读:
    #一点杂记
    《洛谷P3373 【模板】线段树 2》
    《Codeforces Round #681 (Div. 2, based on VK Cup 2019-2020
    《牛客练习赛72C》
    《hdu2819》
    《hdu2818》
    《Codeforces Round #680 (Div. 2, based on Moscow Team Olympiad)》
    《51nod1237 最大公约数之和 V3》
    对输入的单词进行排序
    快速排序
  • 原文地址:https://www.cnblogs.com/shoose/p/9166184.html
Copyright © 2011-2022 走看看