精华内容
下载资源
问答
  • 一、比较对象类 import org.springframework.beans.BeanUtils; import java.beans.PropertyDescriptor; import java.lang.reflect.Field; import java.lang.reflect.Method; /** * 对比两个对象的差值 * ...

    一、比较对象类

    import org.springframework.beans.BeanUtils;
     
    import java.beans.PropertyDescriptor;
    import java.lang.reflect.Field;
    import java.lang.reflect.Method;
     
    /**
     * 对比两个对象的差值
     * Created by Administrator on 2018/7/9.
     */
    public class CompareObejct<T> {
     
        private T original;   
     
        private T current;
     
        /**
         *
         * @param cls
         * @return
         */
        public String contrastObj(Class<T> cls){
            StringBuilder sb = new StringBuilder();
            try{
                Field[] fields = cls.getDeclaredFields();
                for(Field field: fields){
                   if("logger".equals(field.getName())){
                        continue;
                    }
                    PropertyDescriptor pd = new PropertyDescriptor(field.getName(),cls);
                    Method getMethod = pd.getReadMethod();
                    String type = field.getType().getName();
                    if(!"java.util.Set".equals(type)){
                        Object o1 = getMethod.invoke(this.original);
                        Object o2 = getMethod.invoke(this.current);
                        if(null != o2){
                            String s1 = o1 == null ? "" :o1.toString();
                            String s2 = o2 == null ? "" :o2.toString();
                            if(!s1.equals(s2)){
                                //System.out.println("不一样的属性:" + field.getName() + " 属性值:[" + s1 + "," + s2 + "]");
                                sb.append(field.getName() + ":" + "[" + s1 + "," + s2 + "];");
                            }
                        }
                    }
                }
            }catch (Exception e){
                e.printStackTrace();
            }
            return sb.toString();
        }
     
     
        public T getOriginal() {
            return original;
        }
     
        public void setOriginal(T original) {
            this.original = original;
        }
     
        public T getCurrent() {
            return current;
        }
     
        public void setCurrent(T current) {
            this.current = current;
        }
    }

    二、将要修改的值组合成一个新的实体类的JavaBean,得到差异内容后进行复制得到更新后的对象:

    /**
         * 复制对象属性(对象类型必须相同)
         *
         * @param orig 资源对象
         * @param dest 目标对象
         * @param clazz 源对象类
         * @param ignoreNull 是否忽略空(true:忽略,false:不忽略)
         * @param ignoreExist  是否只复制dest值为空的数据  true 是,false 否
         * @return
         */
        public static <T> T copyProperties(T orig, T dest, Class<?> clazz, boolean ignoreNull,boolean ignoreExist) {
            if (orig == null || dest == null)
                return null;
            if(!clazz.isAssignableFrom(orig.getClass()))
                return null;
            Field[] fields = clazz.getDeclaredFields();
            for (Field field : fields) {
                try {
                    field.setAccessible(true);
                    Object value = field.get(orig);
                    Object value2 = field.get(dest);
                    System.out.println(field + "----" + value2);
                    if(!java.lang.reflect.Modifier.isFinal(field.getModifiers())){
                        if(!(ignoreNull && value == null)){
                            if(ignoreExist && value2 != null){
     
                            }else{
                                field.set(dest, value);
                            }
     
                        }
     
                    }
                    field.setAccessible(false);
                } catch (Exception e) {
                }
            }
     
            if(clazz.getSuperclass() == Object.class){
                return dest;
            }
     
            return copyProperties(orig, dest, clazz.getSuperclass(), ignoreNull,ignoreExist);
        }

    三、调用示例:

    /**
        * * 记录修改数据的日志
        * * @Param
        * * Class<T> c 修改对应的实体类
        * * T old 修改前的数据
        * * T update 修改的值(通过JSON转换为bean)
        * * @rerturn 返回经过更新后的数据
        */
       @Override
       public <T> T saveUpdateLog(Class<T> c, T old, T update) {
           try {
               TUpdateLog updateLog = new TUpdateLog();
               CompareObejct<T> compareObejct = new CompareObejct<T>();
               compareObejct.setOriginal(old);
               compareObejct.setCurrent(update);
               String updateContrast = compareObejct.contrastObj(c);
               if (!JiuyiUtil.isEmpty(updateContrast)) {
                   updateLog.setUpdateContrast(updateContrast);
                   //通过注解获取tableName
                   Table annotation = c.getAnnotation(Table.class);
                   String tableName = annotation.name();
                   updateLog.setTableName(tableName);
                   updateLog.setBeforeUpdateEntity(JSON.toJSONString(old));
                   JiuyiUtil.copyProperties(old, update, false, true);
                   updateLog.setAfterUpdateEntity(JSON.toJSONString(update));
                   updateLogDao.save(updateLog);
               }
           } catch (Exception e) {
               e.printStackTrace();
           }
           return update;
       }

     

     

    展开全文
  • java 记录修改日志

    千次阅读 2019-02-14 14:27:00
    需求:记录哪些记录进行了修改,要...1、要记录日志对象,添加注解 public class LegalUnit implements Serializable{   private static final long serialVersionUID = 1L; private Long iD;   @XmlElement(n...

    需求:记录哪些记录进行了修改,要记录修改前后的数据。

    原理:利用java反射

    实现:

    1、要记录日志的对象,添加注解

    public class LegalUnit implements Serializable{
        
    private static final long serialVersionUID = 1L;


    private Long iD;
        
    @XmlElement(name = "名称")
    public String name;
        
    @XmlElement(name = "责任单位")
    public String departmentID;
        
    @XmlElement(name = "所在城市")
    public Integer province;
        
    private String provinceName;
        
    @XmlElement(name = "所在区县")
    public Integer city;
        
    private String cityName;
        
    @XmlElement(name = "注册地址")
    public String regAddress;
        
    @XmlElement(name = "经营范围")
    public String manageRange;
        
    @XmlElement(name = "注册资本(万元)")
    public BigDecimal regFund;
        
    @XmlElement(name = "设立日期")
        @JSONField(format="yyyy-MM-dd")
    public Date setUpDate;
        
    @XmlElement(name = "经营期限开始")
        @JSONField(format="yyyy-MM-dd")
    public Date manageBeginDate;
        
           @XmlElement(name = "经营期限结束")
            @JSONField(format="yyyy-MM-dd")
    public Date manageEndDate;
     }

    2、工具类 UpdateLogUtil.Class

    package com.newsee.util;


    import java.lang.annotation.Annotation;
    import java.lang.reflect.Field;
    import java.math.BigDecimal;
    import java.text.DecimalFormat;
    import javax.xml.bind.annotation.XmlElement;


    public class UpdateLogUtil {
    public static String UpdateLog(Object obj_old,Object obj_new) throws Exception {
            Class clas_old = obj_old.getClass();
            Class clas_new = obj_new.getClass();
            if(!(clas_old.isInstance(obj_new))){
            System.out.println("UpdateLogUtil.UpdateLog:传入的两个java对象类型不一致!");
            return "UpdateLogUtil.UpdateLog:传入的两个java对象类型不一致!";
            }
            Field[] fields = clas_old.getFields();  
            String remark = "";
            for (Field field : fields) {
            String name = field.getName();
            String type = field.getType().getName();
            field.setAccessible(true); //设置些属性是可以访问的 
            Object val_old = field.get(obj_old);//得到此属性的修改前值  

            Object val_new = field.get(obj_new);//得到此属性的修改后值

                     //bigdecimal 类型的数据要去掉小数点后尾部的0不一致造成数据比对差异
            if(type.equals("java.math.BigDecimal") && val_old!=null && val_new!=null ){
                BigDecimal val_old_big = new BigDecimal(String.valueOf(val_old)); 
                BigDecimal  val_new_big = new BigDecimal(String.valueOf(val_new)); 
                if(String.valueOf(val_old_big).indexOf(".")!= -1 || String.valueOf(val_new_big).indexOf(".")!= -1 ){//由于无法获取精度值,只能对所有带小数点的数据进行处理
                    DecimalFormat formatter1=new DecimalFormat("0.000000");  
                    val_old = formatter1.format(val_old_big);
                    val_new = formatter1.format(val_new_big);
                }
            }
            if(!String.valueOf(val_old).equals(String.valueOf(val_new))){
            //保存处理数据 
            System.out.println("UpdateLogUtil.UpdateLog:"+name+"--"+val_old+"----"+val_new);
            //1、获取属性上的指定类型的注解    
            Annotation annotation = field.getAnnotation(XmlElement.class);
            //有该类型的注解存在    
            if (annotation!=null) {    
            //强制转化为相应的注解        
            XmlElement xmlElement = (XmlElement)annotation;    
            //3、获取属性上的指定类型的注解的指定方法    
            if (xmlElement.name().equals("##default")) {    
            System.out.println("UpdateLogUtil.UpdateLog:属性【"+name+"】注解使用的name是默认值: "+xmlElement.name()); 
            remark += xmlElement.name()+"修改前:" + String.valueOf(val_old)+"、修改后:"+String.valueOf(val_new)+";";
            }else {    
            System.out.println("UpdateLogUtil.UpdateLog:属性【"+name+"】注解使用的name是自定义的值: "+xmlElement.name());    
            remark += xmlElement.name()+"修改前:" + String.valueOf(val_old)+"、修改后:"+String.valueOf(val_new)+";";
            }    
            }    
            }
            }
    return remark;
    }

    }

     

    JAVA反射中的getFields()方法和getDeclaredFields ()方法的区别

     

    展开全文
  • import java.beans.PropertyDescriptor; import java.lang.reflect.Field; import java.lang.reflect.Method; public class BeanChangeUtil&lt;T&gt; { public static &lt;T&gt; void main...
    import java.beans.PropertyDescriptor;
    import java.lang.reflect.Field;
    import java.lang.reflect.Method;
    
    public class BeanChangeUtil<T> {
    
        public static <T> void main(String[] args) {
            User u1 = new User("1", true, "a");
            User u2 = new User("2", false, "b");
            BeanChangeUtil<T> t = new BeanChangeUtil<>();
            String str = t.contrastObj(u1, u2);
            if (str.equals("")) {
                System.out.println("未有改变");
            } else {
                System.out.println(str);
            }
        }
    
        @SuppressWarnings({ "unchecked", "rawtypes" })
        public String contrastObj(Object oldBean, Object newBean) {
            StringBuilder str = new StringBuilder();
            T pojo1 = (T) oldBean;
            T pojo2 = (T) newBean;
            try {
                // 通过反射获取类的类类型及字段属性
                Class clazz = pojo1.getClass();
                Field[] fields = clazz.getDeclaredFields();
                int i = 1;
                for (Field field : fields) {
                // 排除序列化属性
                    if ("serialVersionUID".equals(field.getName())) {
                        continue;
                    }
                    PropertyDescriptor pd = new PropertyDescriptor(field.getName(), clazz);
                    // 获取对应属性值
                    Method getMethod = pd.getReadMethod();
                    Object o1 = getMethod.invoke(pojo1);
                    Object o2 = getMethod.invoke(pojo2);
                    if (o1 == null || o2 == null) {
                        continue;
                    }
                    if (!o1.toString().equals(o2.toString())) {
                        str.append(i + "、字段名称:" + field.getName() + ",旧值:" + o1 + ",新值:" + o2 + ";");
                        i++;
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
            return str.toString();
        }
    
        static class User {
            private String about;
    
            private boolean lock;
    
            private String name;
    
            public User() {
            }
    
            public User(String about, boolean lock, String name) {
                super();
                this.about = about;
                this.lock = lock;
                this.name = name;
            }
            /*省略get、set方法*/
        }
    
    }

     

    展开全文
  • JAVA记录操作日志步骤

    万次阅读 2019-08-06 14:01:55
    系统日志不论是在日常的管理还是维护中都会起到很大的作用,但是在日志记录中通常会存在很多的问题 日志记录的不规范性 日志记录的重复性 日志记录的难分类 目前日志主要记录的有三方面 请求的入参,出参 关于...

    项目地址:https://gitee.com/Selegant/logs-demo.git

    说明

    系统日志不论是在日常的管理还是维护中都会起到很大的作用,但是在日志的记录中通常会存在很多的问题

    1. 日志记录的不规范性
    2. 日志记录的重复性
    3. 日志记录的难分类

    目前日志主要记录的有三方面

    1. 请求的入参,出参
    2. 关于业务上的操作
    3. 异常日常日志的打印

    解决方案

    1.记录请求的出参入参

    记录出参入参这是日志记录最好操作的一部分,而这里会存在一定的重复性,因为每个请求都需要记录,这是重复操作,完全可以使用Spring AOP进行入参和出参的记录

    import org.apache.log4j.Logger;
    import org.aspectj.lang.JoinPoint;
    import org.aspectj.lang.annotation.AfterReturning;
    import org.aspectj.lang.annotation.Aspect;
    import org.aspectj.lang.annotation.Before;
    import org.aspectj.lang.annotation.Pointcut;
    import org.springframework.core.annotation.Order;
    import org.springframework.stereotype.Component;
    import org.springframework.web.context.request.RequestContextHolder;
    import org.springframework.web.context.request.ServletRequestAttributes;
    
    import javax.servlet.http.HttpServletRequest;
    import java.util.Arrays;
    
    /**
     * Web层日志切面
     */
    @Aspect    //这里使用@Aspect注解方式设置AOP
    @Order(5)  //值越小,越先加载
    @Component
    public class WebLogAspect {
    
        private Logger logger = Logger.getLogger(getClass());
    
        ThreadLocal<Long> startTime = new ThreadLocal<>();
    	
    	//这里@Pointcut设置切点可以设置为Controller层的地址
        @Pointcut("execution(public * com.training..*.*Controller(..))")
        public void webLog(){}
    
    	//@Before指在切点方法之前执行,也就是在Controller层方法执行之前执行,这里可以通过JoinPoint获取一些有关方法的信息,在这里也可以修改参数的值
        
    	//@Before()括号里设置的是切点方法的名称
    	@Before("webLog()")
        public void doBefore(JoinPoint joinPoint) throws Throwable {
            startTime.set(System.currentTimeMillis());
    
            // 接收到请求,记录请求内容
            ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
            HttpServletRequest request = attributes.getRequest();
    
            // 记录下请求内容
            logger.info("URL : " + request.getRequestURL().toString());
            logger.info("HTTP_METHOD : " + request.getMethod());
            logger.info("IP : " + request.getRemoteAddr());
            logger.info("CLASS_METHOD : " + joinPoint.getSignature().getDeclaringTypeName() + "." + joinPoint.getSignature().getName());
            logger.info("ARGS : " + Arrays.toString(joinPoint.getArgs()));
    
        }
    
        @AfterReturning(returning = "ret", pointcut = "webLog()")
        public void doAfterReturning(Object ret) throws Throwable {
            // 处理完请求,返回内容
            logger.info("RESPONSE : " + ret);
            logger.info("SPEND TIME : " + (System.currentTimeMillis() - startTime.get()));
        }
    
    }
    

    2.记录操作日志

    在系统中可能会有很多的增删改查或是会涉及到一些业务操作,这时候我们需要记录一下操作的入口,在此还可以记录下操作的类型,或是业务的名称.不过在就操作日志前需要构建日志的基础部件

    日志对象

    import java.util.Date;
    
    /**
     * 操作日志
     */
    public class OperationLog extends Base {
    
        private static final long serialVersionUID = 1L;
    
        /**
         * 日志类型
         */
        private String  logtype;
        /**
         * 日志名称
         */
        private String  logname;
        /**
         * 用户id
         */
        private Integer userid;
        /**
         * 类名称
         */
        private String  classname;
        /**
         * 方法名称
         */
        private String  method;
        /**
         * 创建时间
         */
        private Date    createtime;
        /**
         * 是否成功
         */
        private String  succeed;
        /**
         * 备注
         */
        private String  message;
    
    
        public Integer getId() {
            return id;
        }
    
        public void setId(Integer id) {
            this.id = id;
        }
    
        public String getLogtype() {
            return logtype;
        }
    
        public void setLogtype(String logtype) {
            this.logtype = logtype;
        }
    
        public String getLogname() {
            return logname;
        }
    
        public void setLogname(String logname) {
            this.logname = logname;
        }
    
        public Integer getUserid() {
            return userid;
        }
    
        public void setUserid(Integer userid) {
            this.userid = userid;
        }
    
        public String getClassname() {
            return classname;
        }
    
        public void setClassname(String classname) {
            this.classname = classname;
        }
    
        public String getMethod() {
            return method;
        }
    
        public void setMethod(String method) {
            this.method = method;
        }
    
        public Date getCreatetime() {
            return createtime;
        }
    
        public void setCreatetime(Date createtime) {
            this.createtime = createtime;
        }
    
        public String getSucceed() {
            return succeed;
        }
    
        public void setSucceed(String succeed) {
            this.succeed = succeed;
        }
    
        public String getMessage() {
            return message;
        }
    
        public void setMessage(String message) {
            this.message = message;
        }
    }
    

    日志对象创建工厂

    import com.stylefeng.guns.common.constant.state.LogSucceed;
    import com.stylefeng.guns.common.constant.state.LogType;
    import com.stylefeng.guns.common.persistence.model.LoginLog;
    import com.stylefeng.guns.common.persistence.model.OperationLog;
    
    import java.util.Date;
    
    /**
     * 日志对象创建工厂
     */
    public class LogFactory {
    
        /**
         * 创建操作日志
         */
        public static OperationLog createOperationLog(LogType logType, Integer userId, String bussinessName, String clazzName, String methodName, String msg, LogSucceed succeed) {
            OperationLog operationLog = new OperationLog();
            operationLog.setLogtype(logType.getMessage());
            operationLog.setLogname(bussinessName);
            operationLog.setUserid(userId);
            operationLog.setClassname(clazzName);
            operationLog.setMethod(methodName);
            operationLog.setCreatetime(new Date());
            operationLog.setSucceed(succeed.getMessage());
            operationLog.setMessage(msg);
            return operationLog;
        }
    
        /**
         * 创建登录日志
         */
        public static LoginLog createLoginLog(LogType logType, Integer userId, String msg,String ip) {
            LoginLog loginLog = new LoginLog();
            loginLog.setLogname(logType.getMessage());
            loginLog.setUserid(userId);
            loginLog.setCreatetime(new Date());
            loginLog.setSucceed(LogSucceed.SUCCESS.getMessage());
            loginLog.setIp(ip);
            loginLog.setMessage(msg);
            return loginLog;
        }
    }
    

    日志任务创建工厂

    日志任务创建工厂的作用是将日志记录存储到数据库中

    import com.stylefeng.guns.common.constant.state.LogSucceed;
    import com.stylefeng.guns.common.constant.state.LogType;
    import com.stylefeng.guns.common.persistence.dao.LoginLogMapper;
    import com.stylefeng.guns.common.persistence.dao.OperationLogMapper;
    import com.stylefeng.guns.common.persistence.model.LoginLog;
    import com.stylefeng.guns.common.persistence.model.OperationLog;
    import com.stylefeng.guns.core.log.LogManager;
    import com.stylefeng.guns.core.util.SpringContextHolder;
    import com.stylefeng.guns.core.util.ToolUtil;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    
    import java.util.TimerTask;
    
    /**
     * 日志操作任务创建工厂
     */
    public class LogTaskFactory {
    
        private static Logger logger  = LoggerFactory.getLogger(LogManager.class);
    	//LoginLogMapper记录登录登出日志
        private static LoginLogMapper loginLogMapper = SpringContextHolder.getBean(LoginLogMapper.class);
    	//OperationLogMapper记录操作日志	    
    	private static OperationLogMapper operationLogMapper = SpringContextHolder.getBean(OperationLogMapper.class);
    
        public static TimerTask loginLog(final Integer userId, final String ip) {
            return new TimerTask() {
                @Override
                public void run() {
                    try {
                        LoginLog loginLog = LogFactory.createLoginLog(LogType.LOGIN, userId, null, ip);
                        loginLogMapper.insert(loginLog);
                    } catch (Exception e) {
                        logger.error("创建登录日志异常!", e);
                    }
                }
            };
        }
    
        public static TimerTask loginLog(final String username, final String msg, final String ip) {
            return new TimerTask() {
                @Override
                public void run() {
                    LoginLog loginLog = LogFactory.createLoginLog(
                            LogType.LOGIN_FAIL, null, "账号:" + username + "," + msg, ip);
                    try {
                        loginLogMapper.insert(loginLog);
                    } catch (Exception e) {
                        logger.error("创建登录失败异常!", e);
                    }
                }
            };
        }
    
        public static TimerTask exitLog(final Integer userId, final String ip) {
            return new TimerTask() {
                @Override
                public void run() {
                    LoginLog loginLog = LogFactory.createLoginLog(LogType.EXIT, userId, null,ip);
                    try {
                        loginLogMapper.insert(loginLog);
                    } catch (Exception e) {
                        logger.error("创建退出日志异常!", e);
                    }
                }
            };
        }
    
        public static TimerTask bussinessLog(final Integer userId, final String bussinessName, final String clazzName, final String methodName, final String msg) {
            return new TimerTask() {
                @Override
                public void run() {
                    OperationLog operationLog = LogFactory.createOperationLog(
                            LogType.BUSSINESS, userId, bussinessName, clazzName, methodName, msg, LogSucceed.SUCCESS);
                    try {
                        operationLogMapper.insert(operationLog);
                    } catch (Exception e) {
                        logger.error("创建业务日志异常!", e);
                    }
                }
            };
        }
    
        public static TimerTask exceptionLog(final Integer userId, final Exception exception) {
            return new TimerTask() {
                @Override
                public void run() {
                    String msg = ToolUtil.getExceptionMsg(exception);
                    OperationLog operationLog = LogFactory.createOperationLog(
                            LogType.EXCEPTION, userId, "", null, null, msg, LogSucceed.FAIL);
                    try {
                        operationLogMapper.insert(operationLog);
                    } catch (Exception e) {
                        logger.error("创建异常日志异常!", e);
                    }
                }
            };
        }
    }
    

    记录操作日志

    这一步是最关键的一环

    原理:通过自定义的注解@BussinessLog(可以任意命名),里面定义了业务的名称,被修改的实体的唯一标识,字典(用于查找key的中文名称和字段的中文名称),然后通过AOP,拦截所有添加了@BussinessLog注解的方法,解析其注解里面的属性,然后记录到对应的操作日志表中,完成操作日志的记录

    @BussinessLog

    import java.lang.annotation.*;
    
    /**
     * 标记需要做业务日志的方法
     */
    @Inherited
    @Retention(RetentionPolicy.RUNTIME)
    @Target({ElementType.METHOD})
    public @interface BussinessLog {
    
        /**
         * 业务的名称,例如:"修改菜单"
         */
        String value() default "";
    
        /**
         * 被修改的实体的唯一标识,例如:菜单实体的唯一标识为"id"
         */
        String key() default "id";
    
        /**
         * 字典(用于查找key的中文名称和字段的中文名称)
         */
        String dict() default "SystemDict";
    }
    

    @BussinessLog注解拦截AOP

    import com.stylefeng.guns.common.annotion.log.BussinessLog;
    import com.stylefeng.guns.common.constant.dictmap.base.AbstractDictMap;
    import com.stylefeng.guns.common.constant.dictmap.factory.DictMapFactory;
    import com.stylefeng.guns.core.log.LogManager;
    import com.stylefeng.guns.core.log.LogObjectHolder;
    import com.stylefeng.guns.core.log.factory.LogTaskFactory;
    import com.stylefeng.guns.core.shiro.ShiroKit;
    import com.stylefeng.guns.core.shiro.ShiroUser;
    import com.stylefeng.guns.core.support.HttpKit;
    import com.stylefeng.guns.core.util.Contrast;
    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 org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.stereotype.Component;
    
    import java.lang.reflect.Method;
    import java.util.Map;
    
    /**
     * 日志记录
     */
    @Aspect
    @Component
    public class LogAop {
    
        private Logger log = LoggerFactory.getLogger(this.getClass());
    
        @Pointcut(value = "@annotation(com.stylefeng.guns.common.annotion.log.BussinessLog)")
        public void cutService() {
        }
    
        @Around("cutService()")
        public Object recordSysLog(ProceedingJoinPoint point) throws Throwable {
    
            //先执行业务
            Object result = point.proceed();
    
            try {
                handle(point);
            } catch (Exception e) {
                log.error("日志记录出错!", e);
            }
    
            return result;
        }
    
        private void handle(ProceedingJoinPoint point) throws Exception {
    
            //获取拦截的方法名
            Signature sig = point.getSignature();
            MethodSignature msig = null;
            if (!(sig instanceof MethodSignature)) {
                throw new IllegalArgumentException("该注解只能用于方法");
            }
            msig = (MethodSignature) sig;
            Object target = point.getTarget();
            Method currentMethod = target.getClass().getMethod(msig.getName(), msig.getParameterTypes());
            String methodName = currentMethod.getName();
    
            //如果当前用户未登录,不做日志
            ShiroUser user = ShiroKit.getUser();
            if (null == user) {
                return;
            }
    
            //获取拦截方法的参数
            String className = point.getTarget().getClass().getName();
            Object[] params = point.getArgs();
    
            //获取操作名称
            BussinessLog annotation = currentMethod.getAnnotation(BussinessLog.class);
            String bussinessName = annotation.value();
            String key = annotation.key();
            String dictClass = annotation.dict();
    
            StringBuilder sb = new StringBuilder();
            for (Object param : params) {
                sb.append(param);
                sb.append(" & ");
            }
    
            //如果涉及到修改,比对变化
            String msg;
            if (bussinessName.indexOf("修改") != -1 || bussinessName.indexOf("编辑") != -1) {
                Object obj1 = LogObjectHolder.me().get();
                Map<String, String> obj2 = HttpKit.getRequestParameters();
                msg = Contrast.contrastObj(dictClass, key, obj1, obj2);
            } else {
                Map<String, String> parameters = HttpKit.getRequestParameters();
                AbstractDictMap dictMap = DictMapFactory.createDictMap(dictClass);
                msg = Contrast.parseMutiKey(dictMap,key,parameters);
            }
    
            LogManager.me().executeLog(LogTaskFactory.bussinessLog(user.getId(), bussinessName, className, methodName, msg));
        }
    }
    

    @BussinessLog使用实例

    /**
     * 新增字典
     @param dictValues 格式例如   "1:启用;2:禁用;3:冻结"
     */
    @BussinessLog(value = "添加字典记录", key = "dictName,dictValues", dict = com.stylefeng.guns.common.constant.Dict.DictMap)
    @RequestMapping(value = "/add")
    @Permission(Const.ADMIN_NAME)
    @ResponseBody
    public Object add(String dictName, String dictValues) {
        if (ToolUtil.isOneEmpty(dictName, dictValues)) {
            throw new BussinessException(BizExceptionEnum.REQUEST_NULL);
        }
        dictService.addDict(dictName, dictValues);
        return SUCCESS_TIP;
    }
    

    3.记录异常日志

    记录异常日志其实也是一个重复式的过程,这也可以通过统一的处理来记录异常抛出的日志

    import com.stylefeng.guns.common.constant.tips.ErrorTip;
    import com.stylefeng.guns.common.exception.BizExceptionEnum;
    import com.stylefeng.guns.common.exception.BussinessException;
    import com.stylefeng.guns.common.exception.InvalidKaptchaException;
    import com.stylefeng.guns.core.log.LogManager;
    import com.stylefeng.guns.core.log.factory.LogTaskFactory;
    import com.stylefeng.guns.core.shiro.ShiroKit;
    import org.apache.shiro.authc.AuthenticationException;
    import org.apache.shiro.authc.CredentialsException;
    import org.apache.shiro.authc.DisabledAccountException;
    import org.apache.shiro.session.InvalidSessionException;
    import org.apache.shiro.session.UnknownSessionException;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.http.HttpStatus;
    import org.springframework.ui.Model;
    import org.springframework.web.bind.annotation.ControllerAdvice;
    import org.springframework.web.bind.annotation.ExceptionHandler;
    import org.springframework.web.bind.annotation.ResponseBody;
    import org.springframework.web.bind.annotation.ResponseStatus;
    
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.lang.reflect.UndeclaredThrowableException;
    
    import static com.stylefeng.guns.core.support.HttpKit.getIp;
    import static com.stylefeng.guns.core.support.HttpKit.getRequest;
    
    /**
     * 全局的的异常拦截器(拦截所有的控制器)(带有@RequestMapping注解的方法上都会拦截)
     */
    @ControllerAdvice
    public class GlobalExceptionHandler {
    
        private Logger log = LoggerFactory.getLogger(this.getClass());
    
        /**
         * 拦截业务异常
         */
        @ExceptionHandler(BussinessException.class)
        @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
        @ResponseBody
        public ErrorTip notFount(BussinessException e) {
            LogManager.me().executeLog(LogTaskFactory.exceptionLog(ShiroKit.getUser().getId(), e));
            getRequest().setAttribute("tip", e.getMessage());
            log.error("业务异常:", e);
            return new ErrorTip(e.getCode(), e.getMessage());
        }
    
        /**
         * 用户未登录
         */
        @ExceptionHandler(AuthenticationException.class)
        @ResponseStatus(HttpStatus.UNAUTHORIZED)
        public String unAuth(AuthenticationException e) {
            log.error("用户未登陆:", e);
            return "/login.html";
        }
    
        /**
         * 账号被冻结
         */
        @ExceptionHandler(DisabledAccountException.class)
        @ResponseStatus(HttpStatus.UNAUTHORIZED)
        public String accountLocked(DisabledAccountException e, Model model) {
            String username = getRequest().getParameter("username");
            LogManager.me().executeLog(LogTaskFactory.loginLog(username, "账号被冻结", getIp()));
            model.addAttribute("tips", "账号被冻结");
            return "/login.html";
        }
    
        /**
         * 账号密码错误
         */
        @ExceptionHandler(CredentialsException.class)
        @ResponseStatus(HttpStatus.UNAUTHORIZED)
        public String credentials(CredentialsException e, Model model) {
            String username = getRequest().getParameter("username");
            LogManager.me().executeLog(LogTaskFactory.loginLog(username, "账号密码错误", getIp()));
            model.addAttribute("tips", "账号密码错误");
            return "/login.html";
        }
    
        /**
         * 验证码错误
         */
        @ExceptionHandler(InvalidKaptchaException.class)
        @ResponseStatus(HttpStatus.BAD_REQUEST)
        public String credentials(InvalidKaptchaException e, Model model) {
            String username = getRequest().getParameter("username");
            LogManager.me().executeLog(LogTaskFactory.loginLog(username, "验证码错误", getIp()));
            model.addAttribute("tips", "验证码错误");
            return "/login.html";
        }
    
        /**
         * 无权访问该资源
         */
        @ExceptionHandler(UndeclaredThrowableException.class)
        @ResponseStatus(HttpStatus.UNAUTHORIZED)
        @ResponseBody
        public ErrorTip credentials(UndeclaredThrowableException e) {
            getRequest().setAttribute("tip", "权限异常");
            log.error("权限异常!", e);
            return new ErrorTip(BizExceptionEnum.NO_PERMITION);
        }
    
        /**
         * 拦截未知的运行时异常
         */
        @ExceptionHandler(RuntimeException.class)
        @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
        @ResponseBody
        public ErrorTip notFount(RuntimeException e) {
            LogManager.me().executeLog(LogTaskFactory.exceptionLog(ShiroKit.getUser().getId(), e));
            getRequest().setAttribute("tip", "服务器未知运行时异常");
            log.error("运行时异常:", e);
            return new ErrorTip(BizExceptionEnum.SERVER_ERROR);
        }
    
        /**
         * session失效的异常拦截
         */
        @ExceptionHandler(InvalidSessionException.class)
        @ResponseStatus(HttpStatus.BAD_REQUEST)
        public String sessionTimeout(InvalidSessionException e, Model model, HttpServletRequest request, HttpServletResponse response) {
            model.addAttribute("tips", "session超时");
            assertAjax(request, response);
            return "/login.html";
        }
    
        /**
         * session异常
         */
        @ExceptionHandler(UnknownSessionException.class)
        @ResponseStatus(HttpStatus.BAD_REQUEST)
        public String sessionTimeout(UnknownSessionException e, Model model, HttpServletRequest request, HttpServletResponse response) {
            model.addAttribute("tips", "session超时");
            assertAjax(request, response);
            return "/login.html";
        }
    
        private void assertAjax(HttpServletRequest request, HttpServletResponse response) {
            if (request.getHeader("x-requested-with") != null
                    && request.getHeader("x-requested-with").equalsIgnoreCase("XMLHttpRequest")) {
                //如果是ajax请求响应头会有,x-requested-with
                response.setHeader("sessionstatus", "timeout");//在响应头设置session状态
            }
        }
    
    }
    

    项目地址:https://gitee.com/Selegant/logs-demo.git

    展开全文
  • 记录Java Bean修改明细 需求描述 今天接到一个需求,修改数据时需要记录修改详情。详情包括,被修改的字段,修改前的值和修改后的值。 解决思路 分别比较修改前后两个Bean实例的所有成员变量,当值不一致时,记录...
  • import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; /** * @Auther: zs * @Date: 2019/9/24 17:13 * @Description: 字段名称注解 */ @Retention(Retention...
  • 每个Java开发人员都知道日志记录Java应用的重要性,尤其是对服务端应用,而且其中许多人都已经熟悉了各种记录日志的库,比如java.util.logging,Apache的log4j,logback,然而如果你不知道SLF4J,java的简单记录日志...
  • Java 一些记录日志系统

    千次阅读 2016-11-05 14:56:56
    在项目开发中,为了跟踪代码的运行情况,常常要使用日志记录信息。  在Java世界中,有很多的日志工具库来实现日志功能,避免我们重复造轮子,下面我们就来逐一了解日志工具。 1. 最常用的 在本地测试用的 ...
  • /** 使用该注解得对象纳入对比范围 例如A对象中有B对象,如果B对象含有该注解,则纳入比对 * Created by skindow on 2019/9/20. */ @Target({ElementType.FIELD}) @Retention(RetentionPolicy.RUNTIME) public @...
  • * @Description: 日志操作注解 * @Author yjw * @Date 2020/4/3 **/ @Documented @Target(value = ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) public @interface Log { // 执行模块 String module...
  • java获取日志记录通用工具类

    千次阅读 2018-10-07 23:34:02
    日志注解类: /** * 日志注解类 * * @author: Rodge * @time: 2018年10月07日 下午11:29:10 * @version: V1.0.0 */ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.FIELD) public @...
  • 一文搞懂Java日志级别,重复记录、丢日志问题

    万次阅读 多人点赞 2020-12-06 21:33:46
    13 | 日志日志记录真没你想象的那么简单 2020-04-07 朱晔 你好,我是朱晔。今天,我和你分享的是,...日志配置文件通常很复杂,因此有些开发同学会从其他项目或者网络上复制一份配置文件,但却不知道如何修改,甚至是
  • package ... import java.beans.PropertyDescriptor; import java.lang.reflect.Field; import java.lang.reflect.Method; public class Test&lt;T&gt; { public String contrastOb...
  • java日志

    千次阅读 2017-03-28 16:07:29
    Java日志基础 Java使用了一种自定义的、可扩展的方法来输出日志。虽然Java通过java.util.logging包提供了一套基本的日志处理API,但你可以很轻松的使用一种或者多种其它日志解决方案。这些解决方案尽管使用不同的...
  • java 记录对象前后修改的内容(工具类) 有时候业务需要,需记录一条记录修改历史,但是不能为完成任务而硬编码,不靠谱 这种情况可以使用java反射来完成 对对象属性的描述可以通过自定义注解来...
  • * 对象比较器 * 比较结果eg:1、字段名称loginName,旧值:liu,新值:gu;2、字段名称address,旧值:hunan,新值:neimenggu * @param oldBean * @param newBean * @return */ public String compareObject(Object ...
  • 需求是客户想跟踪数据修改前和后数据发生了那些变化,并将其输出到日志里面 思路 JavaBean 增加注解,监控那些字段发生变化才会记录日志中。 利用内省机制动态获取JavaBean对象监控的属性值(注意这里不能...
  • Java 日志系统

    千次阅读 2018-07-24 16:26:44
    最开始出现的是log4j,也是应用最广泛的日志系统,成为了目前java日志系统事实上的标准,一切都是美好的 但java的开发主体sun公司认为自己才是正统,为了干掉log4j在jdk1.4中增加了jul(因为在java.util.logging包下...
  • Java 日志规范

    千次阅读 2017-11-09 18:23:59
    本文想讨论的是如何在Java程序里写好日志。一般来说日志分为两种:业务日志和异常日志,使用日志我们希望能达到以下目标: 1. 对程序运行情况的记录和监控; 2. 在必要时可详细了解程序内部的运行状态; 3. 对系统...
  • Java日志系统

    千次阅读 2016-10-24 20:30:27
    本篇文章的部分代码0....1. 最原始的日志记录方式最早期的Java程序中,使用System.out.println()把需要显示的内容打印到屏幕,这种方式使用起来非常简单,但是缺点却是非常多的: - 输出内容不可控 - 可读
  • 日志记录简化,只需要在action或者controller的方法上加logging注解就可以实现记录日志功能方便快捷。注解:@Logging(description = "{username}登录")
  • java 日志处理

    千次阅读 2018-08-13 21:00:00
    java日志组件介绍 common-logging(同时也称JCL)   common-logging是 apache提供的一个通用的日志接口。用户可以自由选择第三方的日志组件作为具体实现,像log4j,或者jdk自带的logging, common-logging会通过...
  • java 日志管理

    万次阅读 2008-12-03 11:18:00
    1.1 java 日志java拥有一个设计良好的类集--java.util.logging,通过日志系统来控制、格式化以及发布消息。日志系统功能非常强大,可以设置日志消息的优先级,可以通过过滤器来选择感兴趣的信息。并且消息可以输出...
  • java日志级别动态调整

    千次阅读 2018-03-10 12:13:25
    java日志级别动态调整 近期在web项目维护过程中,发现一个令人脑袋大的事,线上的项目出了bug,必须日志开启debug才能看到错误。总不能没事重启一下吧?em……,老大听了想打人。后来查了下,其实可以通过动态的...
  • java面向对象

    万次阅读 多人点赞 2018-08-21 16:51:59
    包括面向对象概念、类与对象的关系、封装、构造函数、this关键字、static关键字、单例设计模式、继承、多态、内部类、异常、包等java基础知识。 1、面向对象 面向对象是相对面向过程而言 面向对象和面向过程都是...
  • java spring 记录用户增删改操作日志

    千次阅读 2017-01-06 18:09:19
    在数据库中建立操作记录(方式一)  建立操作记录(方法二)  使用LOG4J,通过配置LOG4J来获取业务日志(Apache ...Spring结合注解和反射利用拦截器实现对日志记录  Hibernate3拦截器  在数据库中建立操作记录
  • Java日志规范

    千次阅读 2016-10-13 10:23:55
    Overview ...一个在生产环境里运行的程序如果没有日志是很让维护者提心吊胆的,有太多杂乱又无意义的日志也是令人伤神。...本文想讨论的是如何在Java程序里写好日志。 一般来说日志分为两种:业务日志和异
  • JAVA 日志埋点

    千次阅读 2017-02-15 10:46:56
     JAVA 日志埋点使用总结: 环境:jdk1.7、tomcat7、win10、maven 3.2.5   一、 删除应用中所有的log jar包 二、 导入unslog jar包   &lt;dependency&gt; &lt;groupId&gt;com.uns.inf&...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 186,134
精华内容 74,453
关键字:

java日志如何记录修改的对象

java 订阅