springboot 은 업무 로그 와 이상 업무 로 그 를 기록 하 는 작업 을 수행 합 니 다.

로그 기록 redis 표현 형식



1.주 해 를 바탕 으로 로그 기록 을 실현 하고 해당 하 는 방법 을 스 캔 하여 로그 기록 을 실현 합 니 다.

@Inherited
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
public @interface BussinessLog {
 
    /**
     *      ,  :"    "
     */
    String value() default "";
 
    /**
     *            ,  :          "id"
     */
    String key() default "id";
 
    /**
     *     
     */
    String type() default "0";
 
    /**
     *   (    key             )
     */
    Class<? extends AbstractDictMap> dict() default SystemDict.class; 
}
2.스 캔 방법,주 해 를 바탕 으로 로 그 를 스 캔 하고 기록 합 니 다.

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
@Component
public 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;
 
/**
 *              
 *
 * @author ...
 * @Date 2017/3/31 10:36
 */
public class Contrast {
 
    //            
    public static final String separator = ";;;";
 
    /**
     *       ,         
     *
     * @author ...
     * @Date 2017/5/9 19:34
     */
    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;
    }
 
    /**
     *       pojo1 pojo2,        
     *
     * @author ...
     * @Date 2017/5/9 19:34
     */
    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;
    }
 
    /**
     *       pojo1 pojo2,        
     *
     * @author ...
     * @Date 2017/5/9 19:34
     */
    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;
    }
 
    /**
     *     key(     )
     *
     * @author ...
     * @Date 2017/5/16 22:19
     */
    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; 
/**
 * Spring ApplicationContext    ,            spring    bean
 */
@Component
public 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;
    }
    /**
     *        ,       1、 null <br>
     * 2、 ""<br>
     */
    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.실행 중 이상 가 져 오기

@ControllerAdvice
public 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;
 
/**
 * @Description:
 * @Auther: wj
 * @Date: 2019/5/28 13:56
 */
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;
        }
    }
}
이상 은 개인 적 인 경험 이 므 로 여러분 에 게 참고 가 되 기 를 바 랍 니 다.여러분 들 도 저 희 를 많이 응원 해 주시 기 바 랍 니 다.

좋은 웹페이지 즐겨찾기