• springboot 实现注解获取操作日志


    1.第一步加入pom依赖

    <dependency>

      <groupId>org.springframework.boot</groupId>

      <artifactId>spring-boot-starter-aop</artifactId>

    </dependency>

    2.第二步加入自定义一个注解

    @Target(ElementType.METHOD)
    @Retention(RetentionPolicy.RUNTIME)
    public @interface Log {
    String value() default "";
    }


    3.第三步提供四个工具类

    3.1 第一个json转化工具类

    import com.fasterxml.jackson.core.JsonFactory;
    import com.fasterxml.jackson.core.JsonGenerator;
    import com.fasterxml.jackson.databind.ObjectMapper;

    import java.io.StringWriter;
    public class JsonUtil {
    private static ObjectMapper mapper;

    static {
    mapper=SpringContextHolder.getBean(ObjectMapper.class);
    }
    public static String bean2Json(Object obj) {
    try {
    StringWriter sw = new StringWriter();
    JsonGenerator gen = new JsonFactory().createJsonGenerator(sw);


    mapper.writeValue(gen, obj);
    gen.close();

    return sw.toString();
    }catch (Exception e){
    return null;
    }

    }

    public static <T> T json2Bean(String jsonStr, Class<T> objClass) {
    try {
    return mapper.readValue(jsonStr, objClass);
    }
    catch (Exception e){
    return null;
    }
    }
    }

    3.2 第二个获取浏览器信息工具类

    import com.google.common.collect.Maps;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.web.context.request.RequestAttributes;
    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 javax.servlet.http.HttpSession;
    import java.util.HashMap;


    public class ToolUtil {
    public static final Logger LOGGER = LoggerFactory.getLogger(ToolUtil.class);



    /**
    * 获取客户端的ip信息
    *
    * @param request
    * @return
    */
    public static String getClientIp(HttpServletRequest request) {
    String ip = request.getHeader("X-Real-IP");
    LOGGER.info("ipadd : " + ip);
    if (StringUtils.isBlank(ip) || "unknown".equalsIgnoreCase(ip)) {
    ip = request.getHeader("X-Forwarded-For");
    }
    if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
    ip = request.getHeader("Proxy-Client-IP");
    }
    if (ip == null || ip.length() == 0 || "unknow".equalsIgnoreCase(ip)) {
    ip = request.getHeader("WL-Proxy-Client-IP");
    }
    if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
    ip = request.getRemoteAddr();
    }
    LOGGER.info(" ip --> " + ip);
    return ip;
    }

    public static ServletRequestAttributes getRequestAttributes() {
    RequestAttributes attributes = RequestContextHolder.getRequestAttributes();
    return (ServletRequestAttributes) attributes;
    }

    /**
    * 获取request
    */
    public static HttpServletRequest getRequest() {
    return getRequestAttributes().getRequest();
    }

    /**
    * 获取response
    */
    public static HttpServletResponse getResponse() {
    return getRequestAttributes().getResponse();
    }

    /**
    * 获取session
    */
    public static HttpSession getSession() {
    return getRequest().getSession();
    }

    /**
    * 是否是Ajax异步请求
    */
    public static boolean isAjaxRequest(HttpServletRequest request) {
    String accept = request.getHeader("accept");
    if (accept != null && accept.indexOf("application/json") != -1) {
    return true;
    }
    String xRequestedWith = request.getHeader("X-Requested-With");
    if (xRequestedWith != null && xRequestedWith.indexOf("XMLHttpRequest") != -1) {
    return true;
    }
    String uri = request.getRequestURI();
    if (StringUtils.inStringIgnoreCase(uri, ".json", ".xml")) {
    return true;
    }
    String ajax = request.getParameter("__ajax");
    if (StringUtils.inStringIgnoreCase(ajax, "json", "xml")) {
    return true;
    }
    return false;
    }

    /**
    * 获取操作系统,浏览器及浏览器版本信息
    *
    * @param request
    * @return
    */
    public static HashMap<String, String> getOsAndBrowserInfo(HttpServletRequest request) {
    HashMap<String, String> map = Maps.newHashMap();
    String browserDetails = request.getHeader("User-Agent");
    String userAgent = browserDetails;
    String user = userAgent.toLowerCase();

    String os = "";
    String browser = "";

    //=================OS Info=======================
    if (userAgent.toLowerCase().contains("windows")) {
    os = "Windows";
    } else if (userAgent.toLowerCase().contains("mac")) {
    os = "Mac";
    } else if (userAgent.toLowerCase().contains("x11")) {
    os = "Unix";
    } else if (userAgent.toLowerCase().contains("android")) {
    os = "Android";
    } else if (userAgent.toLowerCase().contains("iphone")) {
    os = "IPhone";
    } else {
    os = "UnKnown, More-Info: " + userAgent;
    }
    //===============Browser===========================
    if (user.contains("edge")) {
    browser = (userAgent.substring(userAgent.indexOf("Edge")).split(" ")[0]).replace("/", "-");
    } else if (user.contains("msie")) {
    String substring = userAgent.substring(userAgent.indexOf("MSIE")).split(";")[0];
    browser = substring.split(" ")[0].replace("MSIE", "IE") + "-" + substring.split(" ")[1];
    } else if (user.contains("safari") && user.contains("version")) {
    browser = (userAgent.substring(userAgent.indexOf("Safari")).split(" ")[0]).split("/")[0]
    + "-" + (userAgent.substring(userAgent.indexOf("Version")).split(" ")[0]).split("/")[1];
    } else if (user.contains("opr") || user.contains("opera")) {
    if (user.contains("opera")) {
    browser = (userAgent.substring(userAgent.indexOf("Opera")).split(" ")[0]).split("/")[0]
    + "-" + (userAgent.substring(userAgent.indexOf("Version")).split(" ")[0]).split("/")[1];
    } else if (user.contains("opr")) {
    browser = ((userAgent.substring(userAgent.indexOf("OPR")).split(" ")[0]).replace("/", "-"))
    .replace("OPR", "Opera");
    }

    } else if (user.contains("chrome")) {
    browser = (userAgent.substring(userAgent.indexOf("Chrome")).split(" ")[0]).replace("/", "-");
    } else if ((user.contains("mozilla/7.0")) || (user.contains("netscape6")) ||
    (user.contains("mozilla/4.7")) || (user.contains("mozilla/4.78")) ||
    (user.contains("mozilla/4.08")) || (user.contains("mozilla/3"))) {
    browser = "Netscape-?";

    } else if (user.contains("firefox")) {
    browser = (userAgent.substring(userAgent.indexOf("Firefox")).split(" ")[0]).replace("/", "-");
    } else if (user.contains("rv")) {
    String IEVersion = (userAgent.substring(userAgent.indexOf("rv")).split(" ")[0]).replace("rv:", "-");
    browser = "IE" + IEVersion.substring(0, IEVersion.length() - 1);
    } else {
    browser = "UnKnown, More-Info: " + userAgent;
    }
    map.put("os", os);
    map.put("browser", browser);
    return map;
    }
    }

    3.3 第三个字符串处理工具类

    public class StringUtils {
    public static boolean isNullOrEmpty(String s) {
    return s == null || "".equals(s);
    }

    public static boolean isBlank(CharSequence cs) {
    int strLen;
    if (cs != null && (strLen = cs.length()) != 0) {
    for(int i = 0; i < strLen; ++i) {
    if (!Character.isWhitespace(cs.charAt(i))) {
    return false;
    }
    }

    return true;
    } else {
    return true;
    }
    }

    public static boolean isNotBlank(CharSequence cs) {
    return !isBlank(cs);
    }

    /**
    * 是否包含字符串
    *
    * @param str 验证字符串
    * @param strs 字符串组
    * @return 包含返回true
    */
    public static boolean inStringIgnoreCase(String str, String... strs) {
    if (str != null && strs != null) {
    for (String s : strs) {
    if (str.equalsIgnoreCase(trim(s))) {
    return true;
    }
    }
    }
    return false;
    }

    /**
    * 去空格
    */
    public static String trim(String str) {
    return (str == null ? "" : str.trim());
    }
    }

    3.4 第四个获取实体bean处理工具

    @Service
    @Lazy(false)
    public class SpringContextHolder implements ApplicationContextAware, DisposableBean {

    private static ApplicationContext applicationContext = null;

    private static Logger logger = LoggerFactory.getLogger(SpringContextHolder.class);

    /**
    * 取得存储在静态变量中的ApplicationContext.
    */
    public static ApplicationContext getApplicationContext() {
    assertContextInjected();
    return applicationContext;
    }

    /**
    * 从静态变量applicationContext中取得Bean, 自动转型为所赋值对象的类型.
    */
    @SuppressWarnings("unchecked")
    public static <T> T getBean(String name) {
    assertContextInjected();
    return (T) applicationContext.getBean(name);
    }

    /**
    * 从静态变量applicationContext中取得Bean, 自动转型为所赋值对象的类型.
    */
    public static <T> T getBean(Class<T> requiredType) {
    assertContextInjected();
    return applicationContext.getBean(requiredType);
    }

    /**
    * 清除SpringContextHolder中的ApplicationContext为Null.
    */
    public static void clearHolder() {
    if (logger.isDebugEnabled()){
    logger.debug("清除SpringContextHolder中的ApplicationContext:" + applicationContext);
    }
    applicationContext = null;
    }

    /**
    * 实现ApplicationContextAware接口, 注入Context到静态变量中.
    */
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) {
    SpringContextHolder.applicationContext = applicationContext;
    }

    /**
    * 实现DisposableBean接口, 在Context关闭时清理静态变量.
    */
    @Override
    public void destroy() throws Exception {
    SpringContextHolder.clearHolder();
    }

    /**
    * 检查ApplicationContext不为空.
    */
    private static void assertContextInjected() {
    Validate.validState(applicationContext != null, "applicaitonContext属性未注入, 请在applicationContext.xml中定义SpringContextHolder.");
    }


    4.第四步创建一个实体类

    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    public class ErpLog implements Serializable {

    private String id;


    /**
    * 错误信息
    */

    private String errorMessage;
    /**
    * 返回信息
    */

    private String responseValue;
    /**
    * 操作结束时间
    */

    private Date endTime;
    /**
    * 请求类型
    */

    private String type;
    /**
    * 日志标题
    */

    private String title;
    /**
    * 请求参数
    */

    private String params;
    /**
    * 请求地址
    */

    private String uri;
    /**
    * 操作浏览器
    */

    private String brower;
    /**
    * 操作开始时间
    */

    private Date startTime;
    /**
    * HTTP方法
    */

    private String httpMethod;
    /**
    * 软删除
    */

    private Integer isDeleted;
    /**
    * 请求方法
    */

    private String classMethod;
    /**
    * 执行时间
    */

    private Long executeTime;
    /**
    * 请求主机
    */

    private String host;
    /**
    * 请求头
    */

    private String header;
    /**
    * 操作系统
    */

    private String operatingSystem;
    /**
    * 错误码
    */

    private Integer errorCode;
    /**
    * 操作用户
    */

    private String username;
    }


    5.第五步编写service层,dao层

    service

    public interface ErpLogService {
    List<ErpLog> selectByExample(Object var1);

    Integer softDeleteByID(String id);

    void insertSelective(ErpLog erpLog);
    }

    service实现

    @Service
    public class ErpLogServiceImpl implements ErpLogService {
    @Autowired
    private ErpLogMapper erplogMapper;



    @Override
    public List<ErpLog> selectByExample(Object var1) {
    // return erplogMapper.selectByExample(var1);
    return null;
    }

    @Override
    public Integer softDeleteByID(String id) {
    // ErpLog erpLog = erplogMapper.selectByPrimaryKey(id);
    // erpLog.setIsDeleted(1);
    // return erplogMapper.updateByPrimaryKey(erpLog);
    return null;
    }

    @Override
    public void insertSelective(ErpLog erpLog) {
    System.out.println(erpLog.toString());
    }}

    dao层

    @Mapper
    public interface ErpLogMapper extends BaseMapper<ErpLog> {
    }


    6.第六步编写核心日志处理业务

    @Aspect
    @Order(5)
    @Component
    public class LogAspect {

    private Logger logger = LoggerFactory.getLogger(LogAspect.class);

    @Autowired
    private ErpLogService logService;

    @Autowired
    ObjectMapper objectMapper;

    private ThreadLocal<Date> startTime = new ThreadLocal<Date>();

    @Pointcut("@annotation(net.dgg.qds.share.annotation.Log)")
    public void pointcut() {

    }

    /**
    * 前置通知,在Controller层操作前拦截
    *
    * @param joinPoint 切入点
    */
    @Before("pointcut()")
    public void doBefore(JoinPoint joinPoint) {
    // 获取当前调用时间
    startTime.set(new Date());
    }

    /**
    * 正常情况返回
    *
    * @param joinPoint 切入点
    * @param rvt 正常结果
    */
    @AfterReturning(pointcut = "pointcut()", returning = "rvt")
    public void doAfter(JoinPoint joinPoint, Object rvt) throws Exception {
    handleLog(joinPoint, null, rvt);
    }

    /**
    * 异常信息拦截
    *
    * @param joinPoint
    * @param e
    */
    @AfterThrowing(pointcut = "pointcut()", throwing = "e")
    public void doAfter(JoinPoint joinPoint, Exception e) throws Exception {
    handleLog(joinPoint, e, null);
    }

    @Async
    public void handleLog(final JoinPoint joinPoint, final Exception e, Object rvt) throws Exception{
    // 获得注解
    Method method = getMethod(joinPoint);
    Log log = getAnnotationLog(method);
    if (log == null) {
    return;
    }
    Date now = new Date();
    // 操作数据库日志表
    ErpLog erpLog = new ErpLog();
    erpLog.setErrorCode(0);
    erpLog.setIsDeleted(0);
    // 请求信息
    HttpServletRequest request = ToolUtil.getRequest();
    erpLog.setType(ToolUtil.isAjaxRequest(request) ? "Ajax请求" : "普通请求");
    erpLog.setTitle(log.value());
    erpLog.setHost(request.getRemoteHost());
    erpLog.setUri(request.getRequestURI().toString());
    // erpLog.setHeader(request.getHeader(HttpHeaders.USER_AGENT));
    erpLog.setHttpMethod(request.getMethod());
    erpLog.setClassMethod(joinPoint.getSignature().getDeclaringTypeName() + "." + joinPoint.getSignature().getName());
    // 请求的方法参数值
    Object[] args = joinPoint.getArgs();
    // 请求的方法参数名称
    LocalVariableTableParameterNameDiscoverer u
    = new LocalVariableTableParameterNameDiscoverer();
    String[] paramNames = u.getParameterNames(method);
    if (args != null && paramNames != null) {
    StringBuilder params = new StringBuilder();
    params = handleParams(params, args, Arrays.asList(paramNames));
    erpLog.setParams(params.toString());
    }
    String retString = JsonUtil.bean2Json(rvt);
    erpLog.setResponseValue(retString.length() > 5000 ? JsonUtil.bean2Json("请求参数数据过长不与显示") : retString);
    if (e != null) {
    erpLog.setErrorCode(1);
    erpLog.setErrorMessage(e.getMessage());
    }
    Date stime = startTime.get();
    erpLog.setStartTime(stime);
    erpLog.setEndTime(now);
    erpLog.setExecuteTime(now.getTime() - stime.getTime());
    erpLog.setUsername("");
    HashMap<String, String> browserMap = ToolUtil.getOsAndBrowserInfo(request);
    erpLog.setOperatingSystem(browserMap.get("os"));
    erpLog.setBrower(browserMap.get("browser"));
    erpLog.setId("");
    logService.insertSelective(erpLog);
    }

    /**
    * 是否存在注解,如果存在就获取
    */
    private Log getAnnotationLog(Method method) {
    if (method != null) {
    return method.getAnnotation(Log.class);
    }
    return null;
    }

    private Method getMethod(JoinPoint joinPoint) {
    Signature signature = joinPoint.getSignature();
    MethodSignature methodSignature = (MethodSignature) signature;
    Method method = methodSignature.getMethod();
    if (method != null) {
    return method;
    }
    return null;
    }

    private StringBuilder handleParams(StringBuilder params, Object[] args, List paramNames) throws JsonProcessingException {
    for (int i = 0; i < args.length; i++) {
    if (args[i] instanceof Map) {
    Set set = ((Map) args[i]).keySet();
    List list = new ArrayList();
    List paramList = new ArrayList<>();
    for (Object key : set) {
    list.add(((Map) args[i]).get(key));
    paramList.add(key);
    }
    return handleParams(params, list.toArray(), paramList);
    } else {
    if (args[i] instanceof Serializable) {
    Class<?> aClass = args[i].getClass();
    try {
    aClass.getDeclaredMethod("toString", new Class[]{null});
    // 如果不抛出NoSuchMethodException 异常则存在 toString 方法 ,安全的writeValueAsString ,否则 走 Object的 toString方法
    params.append(" ").append(paramNames.get(i)).append(": ").append(objectMapper.writeValueAsString(args[i]));
    } catch (NoSuchMethodException e) {
    params.append(" ").append(paramNames.get(i)).append(": ").append(objectMapper.writeValueAsString(args[i].toString()));
    }
    } else if (args[i] instanceof MultipartFile) {
    MultipartFile file = (MultipartFile) args[i];
    params.append(" ").append(paramNames.get(i)).append(": ").append(file.getName());
    } else {
    params.append(" ").append(paramNames.get(i)).append(": ").append(args[i]);
    }
    }
    }
    return params;
    }
    }


    7.最后在业务controller层加上@Log()注解就好

    
    

    8.完成业务,打印结果,根据自己的业务存表,这里展示输出结果

    ErpLog(id=, errorMessage=null, responseValue={"code":200,"message":"操作成功","data":{"id":"1234","accumulatedIncome":"5200","unsettledProfit":"2600","shareTimes":"2","orderNum":"2","shareProfit":"3000","recommendCustomers":"2","effectiveResources":"1","signatureNum":"1","recommendedRevenue":"600","userRole":"企帮客","userLevelName":"v1","roleCode":"qds_leader","applyState":"2","settledProfit":"2600","userRoleDescribe":null,"userCode":null,"userPhone":null,"recommendUsername":null,"recommendName":null,"levelCode":null},"errorData":{}}, endTime=Thu May 07 14:25:31 CST 2020, type=普通请求, title=查询用户推广中心信息接口, params= id: "1234", uri=/shareapi/get/promotion_center/information.do, brower=UnKnown, More-Info: Apache-HttpClient/4.5.10 (Java/11.0.6), startTime=Thu May 07 14:25:30 CST 2020, httpMethod=GET, isDeleted=0, classMethod=AllRevenueStatisticsController.getPromotionCenterInformation, executeTime=495, host=127.0.0.1, header=null, operatingSystem=UnKnown, More-Info: Apache-HttpClient/4.5.10 (Java/11.0.6), errorCode=0, username=)

     
  • 相关阅读:
    项目模版(C#),已配置好 Log4net 、AjaxPro 和 AjaxToolKit
    ActionScript 3.0 学习笔记二
    vs 2003项目的打开
    HttpFileCollection 多文件上传的实现以及需要注意的事项
    ActionScript 3.0 学习笔记一
    使用 iframe 实现 web 的推送技术
    媒体集有2个媒体簇,但是只提供了1个
    AjaxPro 的配置和使用
    xp 下安装 spl server express 没有sql server服务
    类中的 static 字段
  • 原文地址:https://www.cnblogs.com/bt2882/p/12843173.html
Copyright © 2020-2023  润新知