文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

springboot中怎么实现记录业务日志和异常业务日志操作

2023-06-20 17:54

关注

今天就跟大家聊聊有关springboot中怎么实现记录业务日志和异常业务日志操作,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。

日志记录到redis展现形式

springboot中怎么实现记录业务日志和异常业务日志操作

springboot中怎么实现记录业务日志和异常业务日志操作

springboot中怎么实现记录业务日志和异常业务日志操作

1.基于注解的方式实现日志记录,扫描对应的方法实现日志记录

@Inherited@Retention(RetentionPolicy.RUNTIME)@Target({ElementType.METHOD})public @interface BussinessLog {         String value() default "";         String key() default "id";         String type() default "0";         Class<? extends AbstractDictMap> dict() default SystemDict.class; }

2.扫描的方法,基于注解实现方法扫描并且记录日志

springboot中怎么实现记录业务日志和异常业务日志操作

3.基于@Aspect注解,实现日志扫描,并且记录日志

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@Componentpublic class LogAop {     private Logger log = LoggerFactory.getLogger(this.getClass());     @Pointcut(value = "@annotation(com.stylefeng.guns.core.common.annotion.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();        Class dictClass = annotation.dict();         StringBuilder sb = new StringBuilder();        for (Object param : params) {            sb.append(param);            sb.append(" & ");        }         //如果涉及到修改,比对变化        String msg;        if (bussinessName.contains("修改") || bussinessName.contains("编辑")) {            Object obj1 = LogObjectHolder.me().get();            Map<String, String> obj2 = HttpContext.getRequestParameters();            msg = Contrast.contrastObj(dictClass, key, obj1, obj2);        } else {            Map<String, String> parameters = HttpContext.getRequestParameters();            AbstractDictMap dictMap = (AbstractDictMap) dictClass.newInstance();            msg = Contrast.parseMutiKey(dictMap, key, parameters);        }        log.info("[记录日志][RESULT:{}]",user.getId()+bussinessName+className+methodName+msg.toString());        LogManager.me().executeLog(LogTaskFactory.bussinessLog(user.getId(), bussinessName, className, methodName, msg));    }}

4.比较两个对象的工具类

import java.beans.PropertyDescriptor;import java.lang.reflect.Field;import java.lang.reflect.Method;import java.util.Date;import java.util.Map; public class Contrast {     //记录每个修改字段的分隔符    public static final String separator = ";;;";         public static String contrastObj(Object pojo1, Object pojo2) {        String str = "";        try {            Class clazz = pojo1.getClass();            Field[] fields = pojo1.getClass().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 instanceof Date) {                    o1 = DateUtil.getDay((Date) o1);                }                if (!o1.toString().equals(o2.toString())) {                    if (i != 1) {                        str += separator;                    }                    str += "字段名称" + field.getName() + ",旧值:" + o1 + ",新值:" + o2;                    i++;                }            }        } catch (Exception e) {            e.printStackTrace();        }        return str;    }         public static String contrastObj(Class dictClass, String key, Object pojo1, Map<String, String> pojo2) throws IllegalAccessException, InstantiationException {        AbstractDictMap dictMap = (AbstractDictMap) dictClass.newInstance();        String str = parseMutiKey(dictMap, key, pojo2) + separator;        try {            Class clazz = pojo1.getClass();            Field[] fields = pojo1.getClass().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 = pojo2.get(StrKit.firstCharToLowerCase(getMethod.getName().substring(3)));                if (o1 == null || o2 == null) {                    continue;                }                if (o1 instanceof Date) {                    o1 = DateUtil.getDay((Date) o1);                } else if (o1 instanceof Integer) {                    o2 = Integer.parseInt(o2.toString());                }                if (!o1.toString().equals(o2.toString())) {                    if (i != 1) {                        str += separator;                    }                    String fieldName = dictMap.get(field.getName());                    String fieldWarpperMethodName = dictMap.getFieldWarpperMethodName(field.getName());                    if (fieldWarpperMethodName != null) {                        Object o1Warpper = DictFieldWarpperFactory.createFieldWarpper(o1, fieldWarpperMethodName);                        Object o2Warpper = DictFieldWarpperFactory.createFieldWarpper(o2, fieldWarpperMethodName);                        str += "字段名称:" + fieldName + ",旧值:" + o1Warpper + ",新值:" + o2Warpper;                    } else {                        str += "字段名称:" + fieldName + ",旧值:" + o1 + ",新值:" + o2;                    }                    i++;                }            }        } catch (Exception e) {            e.printStackTrace();        }        return str;    }         public static String contrastObjByName(Class dictClass, String key, Object pojo1, Map<String, String> pojo2) throws IllegalAccessException, InstantiationException {        AbstractDictMap dictMap = (AbstractDictMap) dictClass.newInstance();        String str = parseMutiKey(dictMap, key, pojo2) + separator;        try {            Class clazz = pojo1.getClass();            Field[] fields = pojo1.getClass().getDeclaredFields();            int i = 1;            for (Field field : fields) {                if ("serialVersionUID".equals(field.getName())) {                    continue;                }                String prefix = "get";                int prefixLength = 3;                if (field.getType().getName().equals("java.lang.Boolean")) {                    prefix = "is";                    prefixLength = 2;                }                Method getMethod = null;                try {                    getMethod = clazz.getDeclaredMethod(prefix + StrKit.firstCharToUpperCase(field.getName()));                } catch (NoSuchMethodException e) {                    System.err.println("this className:" + clazz.getName() + " is not methodName: " + e.getMessage());                    continue;                }                Object o1 = getMethod.invoke(pojo1);                Object o2 = pojo2.get(StrKit.firstCharToLowerCase(getMethod.getName().substring(prefixLength)));                if (o1 == null || o2 == null) {                    continue;                }                if (o1 instanceof Date) {                    o1 = DateUtil.getDay((Date) o1);                } else if (o1 instanceof Integer) {                    o2 = Integer.parseInt(o2.toString());                }                if (!o1.toString().equals(o2.toString())) {                    if (i != 1) {                        str += separator;                    }                    String fieldName = dictMap.get(field.getName());                    String fieldWarpperMethodName = dictMap.getFieldWarpperMethodName(field.getName());                    if (fieldWarpperMethodName != null) {                        Object o1Warpper = DictFieldWarpperFactory.createFieldWarpper(o1, fieldWarpperMethodName);                        Object o2Warpper = DictFieldWarpperFactory.createFieldWarpper(o2, fieldWarpperMethodName);                        str += "字段名称:" + fieldName + ",旧值:" + o1Warpper + ",新值:" + o2Warpper;                    } else {                        str += "字段名称:" + fieldName + ",旧值:" + o1 + ",新值:" + o2;                    }                    i++;                }            }        } catch (Exception e) {            e.printStackTrace();        }        return str;    }         public static String parseMutiKey(AbstractDictMap dictMap, String key, Map<String, String> requests) {        StringBuilder sb = new StringBuilder();        if (key.indexOf(",") != -1) {            String[] keys = key.split(",");            for (String item : keys) {                String fieldWarpperMethodName = dictMap.getFieldWarpperMethodName(item);                String value = requests.get(item);                if (fieldWarpperMethodName != null) {                    Object valueWarpper = DictFieldWarpperFactory.createFieldWarpper(value, fieldWarpperMethodName);                    sb.append(dictMap.get(item) + "=" + valueWarpper + ",");                } else {                    sb.append(dictMap.get(item) + "=" + value + ",");                }            }            return StrKit.removeSuffix(sb.toString(), ",");        } else {            String fieldWarpperMethodName = dictMap.getFieldWarpperMethodName(key);            String value = requests.get(key);            if (fieldWarpperMethodName != null) {                Object valueWarpper = DictFieldWarpperFactory.createFieldWarpper(value, fieldWarpperMethodName);                sb.append(dictMap.get(key) + "=" + valueWarpper);            } else {                sb.append(dictMap.get(key) + "=" + value);            }            return sb.toString();        }    } }

5.根据输入方法获取数据字典的数据

import java.lang.reflect.Method;  public class DictFieldWarpperFactory {      public static Object createFieldWarpper(Object parameter, String methodName) {        IConstantFactory constantFactory = ConstantFactory.me();        try {            Method method = IConstantFactory.class.getMethod(methodName, parameter.getClass());            return method.invoke(constantFactory, parameter);        } catch (Exception e) {            try {                Method method = IConstantFactory.class.getMethod(methodName, Integer.class);                return method.invoke(constantFactory, Integer.parseInt(parameter.toString()));            } catch (Exception e1) {                throw new RuntimeException("BizExceptionEnum.ERROR_WRAPPER_FIELD");            }        }    } }

6.对应获取数据字典的方法

public interface IConstantFactory {         String getWordStatus(Integer DATA_STATUS); }
import com.qihoinfo.dev.log.util.SpringContextHolder;import org.anyline.service.AnylineService;import org.springframework.context.annotation.DependsOn;import org.springframework.stereotype.Component;  @Component@DependsOn("springContextHolder")public class ConstantFactory implements IConstantFactory {     private AnylineService anylineService = SpringContextHolder.getBean(AnylineService.class);     public static IConstantFactory me() {        return SpringContextHolder.getBean("constantFactory");    }     @Override    public String getWordStatus(Integer DATA_STATUS) {        if ("1".equals(DATA_STATUS.toString())) {            return "启用";        } else {            return "停用";        }    } }

7.spring根据方法名获取对应容器中的对象

import org.springframework.beans.BeansException;import org.springframework.context.ApplicationContext;import org.springframework.context.ApplicationContextAware;import org.springframework.stereotype.Component; @Componentpublic class SpringContextHolder implements ApplicationContextAware {      private static ApplicationContext applicationContext;     @Override    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {        SpringContextHolder.applicationContext = applicationContext;    }     public static ApplicationContext getApplicationContext() {        assertApplicationContext();        return applicationContext;    }     @SuppressWarnings("unchecked")    public static <T> T getBean(String beanName) {        assertApplicationContext();        return (T) applicationContext.getBean(beanName);    }     public static <T> T getBean(Class<T> requiredType) {        assertApplicationContext();        return applicationContext.getBean(requiredType);    }     private static void assertApplicationContext() {        if (SpringContextHolder.applicationContext == null) {            throw new RuntimeException("applicaitonContext属性为null,请检查是否注入了SpringContextHolder!");        }    } }

8.字符串工具类

public class StrKit {           public static String firstCharToLowerCase(String str) {        char firstChar = str.charAt(0);        if (firstChar >= 'A' && firstChar <= 'Z') {            char[] arr = str.toCharArray();            arr[0] += ('a' - 'A');            return new String(arr);        }        return str;    }        public static String firstCharToUpperCase(String str) {        char firstChar = str.charAt(0);        if (firstChar >= 'a' && firstChar <= 'z') {            char[] arr = str.toCharArray();            arr[0] -= ('a' - 'A');            return new String(arr);        }        return str;    }        public static String removeSuffix(String str, String suffix) {        if (isEmpty(str) || isEmpty(suffix)) {            return str;        }        if (str.endsWith(suffix)) {            return str.substring(0, str.length() - suffix.length());        }        return str;    }        public static boolean isEmpty(String str) {        return str == null || str.length() == 0;    }}
import java.io.IOException;import java.io.PrintWriter;import java.io.StringWriter;  public class ToolUtil {    public static final int SALT_LENGTH = 6;     public ToolUtil() {    }     public static String getExceptionMsg(Throwable e) {        StringWriter sw = new StringWriter();         try {            e.printStackTrace(new PrintWriter(sw));        } finally {            try {                sw.close();            } catch (IOException var8) {                var8.printStackTrace();            }         }         return sw.getBuffer().toString().replaceAll("\\$", "T");    }}

9.获取数据字典的类

import java.util.HashMap;  public abstract class AbstractDictMap {     protected HashMap<String, String> dictory = new HashMap<>();    protected HashMap<String, String> fieldWarpperDictory = new HashMap<>();     public AbstractDictMap() {        put("ID", "主键ID");        init();        initBeWrapped();    }     public abstract void init();     protected abstract void initBeWrapped();     public String get(String key) {        return this.dictory.get(key);    }     public void put(String key, String value) {        this.dictory.put(key, value);    }     public String getFieldWarpperMethodName(String key) {        return this.fieldWarpperDictory.get(key);    }     public void putFieldWrapperMethodName(String key, String methodName) {        this.fieldWarpperDictory.put(key, methodName);    }}
public class SystemDict extends AbstractDictMap {     @Override    public void init() {    }     @Override    protected void initBeWrapped() {     }}
public class WordMap extends AbstractDictMap {     @Override    public void init() {        put("EN", "英文");        put("CN", "中文");        put("SHORT", "简称");        put("REMARK", "备注");        put("DATA_STATUS", "状态");    }     @Override    protected void initBeWrapped() {        putFieldWrapperMethodName("DATA_STATUS","getWordStatus");    } }

10.获取缓存对象的bean

import org.springframework.context.annotation.Scope;import org.springframework.stereotype.Component;import org.springframework.web.context.WebApplicationContext; import java.io.Serializable;  @Component@Scope(scopeName = WebApplicationContext.SCOPE_SESSION)public class LogObjectHolder implements Serializable{     private Object object = null;     public void set(Object obj) {        this.object = obj;    }     public Object get() {        return object;    }     public static LogObjectHolder me(){        LogObjectHolder bean = SpringContextHolder.getBean(LogObjectHolder.class);        return bean;    } }

11.运行时异常的获取

@ControllerAdvicepublic class GlobalExceptionHandler extends BasicMemberJSONController {     private Logger log = LoggerFactory.getLogger(this.getClass());     @ExceptionHandler(RuntimeException.class)    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)    @ResponseBody    public String notFount(RuntimeException e) {        String userName = curManage().get("USERNAME").toString();        LogManager.me().executeLog(LogTaskFactory.exceptionLog(userName, e));        log.error("运行时异常:", e);        return fail();    }}

12.使用线程池创建操作日志

import java.util.Date;  public class LogFactory {          public static DataRow createOperationLog(LogType logType, String userName, String bussinessName, String clazzName, String methodName, String msg, LogSucceed succeed) {        DataRow operationLog = new DataRow();        operationLog.put("log_type", logType.getMessage());        operationLog.put("USER_NAME", userName);        operationLog.put("log_name", bussinessName);        operationLog.put("CLASS_NAME", clazzName);        operationLog.put("METHOD", methodName);        operationLog.put("CREATE_TIME", new Date());        operationLog.put("SUCCEED", succeed.getMessage());        if (msg.length() > 800) {            msg = msg.substring(0, 800);            operationLog.put("MESSAGE", msg);        } else {            operationLog.put("MESSAGE", msg);        }        return operationLog;    }}
import java.util.TimerTask;import java.util.concurrent.ScheduledThreadPoolExecutor;import java.util.concurrent.TimeUnit;  public class LogManager {     //日志记录操作延时    private final int OPERATE_DELAY_TIME = 10;     //异步操作记录日志的线程池    private ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(10);     private LogManager() {    }     public static LogManager logManager = new LogManager();     public static LogManager me() {        return logManager;    }     public void executeLog(TimerTask task) {        executor.schedule(task, OPERATE_DELAY_TIME, TimeUnit.MILLISECONDS);    } }
public enum LogSucceed {     SUCCESS("成功"),    FAIL("失败");     String message;     LogSucceed(String message) {        this.message = message;    }     public String getMessage() {        return message;    }     public void setMessage(String message) {        this.message = message;    } }
import com.qihoinfo.dev.log.annotation.RedisDb;import com.qihoinfo.dev.log.util.ToolUtil;import org.anyline.entity.DataRow;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.context.annotation.DependsOn;import org.springframework.data.redis.core.StringRedisTemplate;import org.springframework.stereotype.Component; import java.util.TimerTask;  @Component@DependsOn("springContextHolder")public class LogTaskFactory {     private static Logger logger = LoggerFactory.getLogger(LogManager.class);     private static StringRedisTemplate redisTemplate = RedisDb.getMapper(StringRedisTemplate.class);     public static TimerTask bussinessLog(final String userName, final String bussinessName, final String clazzName, final String methodName, final String msg) {        return new TimerTask() {            @Override            public void run() {                DataRow operationLog = LogFactory.createOperationLog(                        LogType.BUSSINESS, userName, bussinessName, clazzName, methodName, msg, LogSucceed.SUCCESS);                try {                     redisTemplate.opsForList().rightPush("sys_operation_log", operationLog.getJson());                } catch (Exception e) {                    logger.error("创建业务日志异常!", e);                }            }        };    }     public static TimerTask exceptionLog(final String userName, final Exception exception) {        return new TimerTask() {            @Override            public void run() {                String msg = ToolUtil.getExceptionMsg(exception);                DataRow operationLog = LogFactory.createOperationLog(                        LogType.EXCEPTION, userName, "", null, null, msg, LogSucceed.FAIL);                try {                    redisTemplate.opsForList().rightPush("sys_operation_log", operationLog.getJson());                } catch (Exception e) {                    logger.error("创建异常日志异常!", e);                }            }        };    } }
public enum LogType {     EXCEPTION("异常日志"),    BUSSINESS("业务日志");     String message;     LogType(String message) {        this.message = message;    }     public String getMessage() {        return message;    }     public void setMessage(String message) {        this.message = message;    } }

13.将日志记录到redis数据库

package com.qihoinfo.dev.log.annotation;  import com.qihoinfo.dev.log.util.SpringContextHolder;import org.springframework.data.redis.core.StringRedisTemplate; public class RedisDb<T> {      private Class<T> clazz;     private StringRedisTemplate baseMapper;      private RedisDb(Class clazz) {        this.clazz = clazz;        this.baseMapper = (StringRedisTemplate) SpringContextHolder.getBean(clazz);    }      public static <T> RedisDb<T> create(Class<T> clazz) {        return new RedisDb<T>(clazz);    }      public StringRedisTemplate getMapper() {        return this.baseMapper;    }      public static <T> T getMapper(Class<T> clazz) {        return SpringContextHolder.getBean(clazz);    }  }
import org.springframework.web.context.request.RequestContextHolder;import org.springframework.web.context.request.ServletRequestAttributes; import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import java.util.Enumeration;import java.util.HashMap;import java.util.Map; public class HttpContext {    public HttpContext() {    }     public static String getIp() {        HttpServletRequest request = getRequest();        return request == null ? "127.0.0.1" : request.getRemoteHost();    }     public static HttpServletRequest getRequest() {        ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();        return requestAttributes == null ? null : requestAttributes.getRequest();    }     public static HttpServletResponse getResponse() {        ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();        return requestAttributes == null ? null : requestAttributes.getResponse();    }     public static Map<String, String> getRequestParameters() {        HashMap<String, String> values = new HashMap();        HttpServletRequest request = getRequest();        if (request == null) {            return values;        } else {            Enumeration enums = request.getParameterNames();             while (enums.hasMoreElements()) {                String paramName = (String) enums.nextElement();                String paramValue = request.getParameter(paramName);                values.put(paramName, paramValue);            }             return values;        }    }}

看完上述内容,你们对springboot中怎么实现记录业务日志和异常业务日志操作有进一步的了解吗?如果还想了解更多知识或者相关内容,请关注编程网行业资讯频道,感谢大家的支持。

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯