自定义Api接口访问系统日志记录

Log:

package com.rz.common.aspect;



import com.rz.common.enums.BusinessType;
import com.rz.common.enums.OperatorType;

import java.lang.annotation.*;

/**
 * @Description : 自定义操作日志记录注解
 */
@Target({ ElementType.PARAMETER, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Log {

    /**
     * 模块
     */
    String title() default "";

    /**
     * 功能
     */
    BusinessType businessType() default BusinessType.OTHER;

    /**
     * 操作人类别
     */
    OperatorType operatorType() default OperatorType.MANAGE;

    /**
     * 是否保存请求的参数
     */
    boolean isSaveRequestData() default true;

}

BusinessType:

package com.rz.common.enums;

/**
 * @Description : 业务操作类型
 */
public enum BusinessType {

    /**
     * 其它
     */
    OTHER,

    /**
     * 新增
     */
    INSERT,

    /**
     * 修改
     */
    UPDATE,

    /**
     * 删除
     */
    DELETE,

    /**
     * 授权
     */
    GRANT,

    /**
     * 导出
     */
    EXPORT,

    /**
     * 导入
     */
    IMPORT,

    /**
     * 强退
     */
    FORCE,

    /**
     * 生成代码
     */
    GENCODE,

    /**
     * 清空
     */
    CLEAN,

    /**
     * 查询
     */
    QUERY
}

OperatorType:

package com.rz.common.enums;

/**
 * @Description : 操作类型

 */
public enum OperatorType {

    /**
     * 其它
     */
    OTHER,

    /**
     * 后台用户
     */
    MANAGE,

    /**
     * 手机端用户
     */
    MOBILE

}

IBaseAspect:

package com.rz.common.aspect;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;

public interface IBaseAspect {

	void before(JoinPoint joinPoint) throws Throwable;

	void after(JoinPoint joinPoint) throws Throwable;

	void afterReturning(JoinPoint joinPoint, Object returnObj) throws Throwable;

	void afterThrowing(JoinPoint joinPoint, Throwable e) throws Throwable;

	Object around(ProceedingJoinPoint pJoinPoint) throws Throwable;

}

LogBaseAspect:

package com.rz.common.aspect.impl;


import com.rz.common.aspect.IBaseAspect;
import com.rz.common.aspect.Log;
import com.rz.common.manager.AsyncFactory;
import com.rz.common.manager.AsyncManager;
import com.alibaba.fastjson.JSON;
import com.rz.common.util.ServletUtils;
import com.rz.common.util.StringUtils;
import com.rz.common.util.local.NetworkUtil;
import com.rz.domian.base.SysOperateLog;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
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.core.annotation.Order;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.util.Date;
import java.util.Map;



@Aspect
@Component
@Order(3)
public class LogBaseAspect implements IBaseAspect {

    private static final Logger log = LoggerFactory.getLogger(LogBaseAspect.class);

    /**
     * 配置织入点
     */
    @Pointcut("@annotation(com.rz.common.aspect.Log)")
    public void logPointCut() {
    }


    @Override
    public void before(JoinPoint joinPoint) throws Throwable {
    }

    @Override
    public void after(JoinPoint joinPoint) throws Throwable {

    }

    /**
     * 后置通知,拦截
     * @param joinPoint
     * @param returnObj
     * @throws Throwable
     */
    @Override
    @AfterReturning(pointcut = "logPointCut()", argNames = "joinPoint,returnObj", returning = "returnObj")
    public void afterReturning(JoinPoint joinPoint, Object returnObj) throws Throwable {
        handleLog(joinPoint, null);
    }

    /**
     * 异常拦截操作
     *
     * @param joinPoint
     * @param e
     * @throws Throwable
     */
    @Override
    @AfterThrowing(value = "logPointCut()", throwing = "e")
    public void afterThrowing(JoinPoint joinPoint, Throwable e) throws Throwable {
        handleLog(joinPoint, e);
    }

    /**
     * @Around 可以更改系统返回值
     * @param pJoinPoint
     * @return
     * @throws Throwable
     */
    @Override
    public Object around(ProceedingJoinPoint pJoinPoint) throws Throwable {
        return null;
    }


    protected void handleLog(final JoinPoint joinPoint, final Throwable e) {
        try {

            // 获取注解
            Log controllerLog = getAnnotationLog(joinPoint);
            if (controllerLog == null) {
                return;
            }
            String userName = "";
            /*boolean result = SpringUtils.containsBean("openUserServiceImpl");
            if (!result) {
                log.error(" noSuchBeanDefinitionException plase setting bean name ‘openUserServiceImpl’");
                log.error("操作日志记录停止,无法获取操作人,请实现IOpenUserService接口,初始化用户名");
                return;
            }
            IOpenUserService userService = SpringUtils.getBean(IOpenUserService.class);
            userName = userService.getUserNameApi();*/
//          userName = (String) SessionUtil.getPrincipal();


            // *========数据库日志=========*//
            SysOperateLog operLog = new SysOperateLog();
            operLog.setStatus(Boolean.TRUE);

            operLog.setOperIp(NetworkUtil.getRemoteAddr(ServletUtils.getRequest()));
            operLog.setOperUrl(ServletUtils.getRequest().getRequestURI());
            operLog.setOperName(userName);
            operLog.setDeptName("");
            operLog.setOperTime(new Date());
            operLog.setToLocalIp(NetworkUtil.getLocalAddr());


            if (e != null) {
                operLog.setStatus(Boolean.FALSE);
                operLog.setErrorMsg(StringUtils.substring(e.getMessage(), 0, 2000));
            }
            // 设置方法名称
            String className = joinPoint.getTarget().getClass().getName();
            String methodName = joinPoint.getSignature().getName();
            operLog.setMethod(className + "." + methodName + "()");
            // 处理设置注解上的参数
            getControllerMethodDescription(controllerLog, operLog);
            // 保存数据库
            AsyncManager.getInstance().execute(AsyncFactory.recordOper(operLog));

        } catch (Exception exp) {
            log.error(" --log-- 操作日志异常信息:{}", exp.getMessage());
            exp.printStackTrace();
        }
    }

    /**
     * 获取注解中对方法的描述信息 用于Controller层注解
     *
     * @param log     日志
     * @param operLog 操作日志
     * @throws Exception
     */
    public void getControllerMethodDescription(Log log, SysOperateLog operLog) throws Exception {
        // 设置action动作
        int businessType = log.businessType().ordinal();
        operLog.setBusinessType((byte) businessType);
        // 设置标题
        operLog.setTitle(log.title());
        // 设置操作人类别
        int operatorType = log.operatorType().ordinal();
        operLog.setOperatorType((byte) operatorType);
        // 是否需要保存request,参数和值
        if (log.isSaveRequestData()) {
            // 获取参数的信息,传入到数据库中。
            setRequestValue(operLog);
        }
    }

    /**
     * 获取请求的参数,放到log中
     *
     * @param operLog 操作日志
     * @throws Exception 异常
     */
    private void setRequestValue(SysOperateLog operLog) throws Exception {
        Map<String, String[]> map = ServletUtils.getRequest().getParameterMap();
        String params = JSON.toJSONString(map);
        operLog.setOperParam(params);
    }

    /**
     * 是否存在注解,如果存在就获取
     */
    private Log getAnnotationLog(JoinPoint joinPoint) throws Exception {
        Signature signature = joinPoint.getSignature();
        MethodSignature methodSignature = (MethodSignature) signature;
        Method method = methodSignature.getMethod();

        if (method != null) {
            return method.getAnnotation(Log.class);
        }
        return null;
    }
}

ServletUtils:

package com.rz.common.util;

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;

/**
 * @Description : Servlet客户端工具类
 */
public class ServletUtils {

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

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

}

SysOperateLog:

package com.rz.domian.base;

import java.io.Serializable;
import java.util.Date;

public class SysOperateLog implements Serializable {
    private Long operId;

    private String title;

    private Byte businessType;

    private String method;

    private Byte operatorType;

    private String operName;

    private String deptName;

    private String operUrl;

    private String operIp;

    private String operLocation;

    private String toLocalIp;

    private Boolean status;

    private String errorMsg;

    private Date operTime;

    private String operParam;

    private static final long serialVersionUID = 1L;

    public Long getOperId() {
        return operId;
    }

    public void setOperId(Long operId) {
        this.operId = operId;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title == null ? null : title.trim();
    }

    public Byte getBusinessType() {
        return businessType;
    }

    public void setBusinessType(Byte businessType) {
        this.businessType = businessType;
    }

    public String getMethod() {
        return method;
    }

    public void setMethod(String method) {
        this.method = method == null ? null : method.trim();
    }

    public Byte getOperatorType() {
        return operatorType;
    }

    public void setOperatorType(Byte operatorType) {
        this.operatorType = operatorType;
    }

    public String getOperName() {
        return operName;
    }

    public void setOperName(String operName) {
        this.operName = operName == null ? null : operName.trim();
    }

    public String getDeptName() {
        return deptName;
    }

    public void setDeptName(String deptName) {
        this.deptName = deptName == null ? null : deptName.trim();
    }

    public String getOperUrl() {
        return operUrl;
    }

    public void setOperUrl(String operUrl) {
        this.operUrl = operUrl == null ? null : operUrl.trim();
    }

    public String getOperIp() {
        return operIp;
    }

    public void setOperIp(String operIp) {
        this.operIp = operIp == null ? null : operIp.trim();
    }

    public String getOperLocation() {
        return operLocation;
    }

    public void setOperLocation(String operLocation) {
        this.operLocation = operLocation == null ? null : operLocation.trim();
    }

    public String getToLocalIp() {
        return toLocalIp;
    }

    public void setToLocalIp(String toLocalIp) {
        this.toLocalIp = toLocalIp == null ? null : toLocalIp.trim();
    }

    public Boolean getStatus() {
        return status;
    }

    public void setStatus(Boolean status) {
        this.status = status;
    }

    public String getErrorMsg() {
        return errorMsg;
    }

    public void setErrorMsg(String errorMsg) {
        this.errorMsg = errorMsg == null ? null : errorMsg.trim();
    }

    public Date getOperTime() {
        return operTime;
    }

    public void setOperTime(Date operTime) {
        this.operTime = operTime;
    }

    public String getOperParam() {
        return operParam;
    }

    public void setOperParam(String operParam) {
        this.operParam = operParam == null ? null : operParam.trim();
    }
}

AsyncManager:

package com.rz.common.manager;


import com.rz.common.util.ThreadUtils;

import java.util.TimerTask;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * @Description : 异步任务管理器
 */
public class AsyncManager {

    /**
     * 操作延迟10毫秒
     */
    private final int OPERATE_DELAY_TIME = 10;

    /**
     * 异步操作任务调度线程池
     */
    private ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(5);


    /**
     * 单例模式
     */
    private volatile static AsyncManager asyncManager;


    private AsyncManager(){

    }

    public static AsyncManager getInstance() {
        if (null == asyncManager) {
            synchronized (AsyncManager.class) {
                if (null == asyncManager) {
                    asyncManager = new AsyncManager();
                }
            }
        }
        return asyncManager;
    }

    /**
     * 执行任务
     *
     * @param task 任务
     */
    public void execute(TimerTask task) {
        executor.schedule(task, OPERATE_DELAY_TIME, TimeUnit.MILLISECONDS);
    }

    /**
     * 停止任务线程池
     */
    public void shutdown() {
        ThreadUtils.shutdownAndAwaitTermination(executor);
    }

}

AsyncFactory:

package com.rz.common.manager;


import com.rz.common.util.SpringUtils;
import com.rz.domian.base.SysOperateLog;
import com.rz.domian.base.RateLimiterRecord;
import com.rz.service.ISysOperateLogService;
import com.rz.service.RateLimiterRecordService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.TimerTask;

/**
 * @Description :
 *      异步工厂(产生任务用),注意分布式环境下,同时跑两个一样的任务
 */
public class AsyncFactory {

    private static final Logger sys_user_logger = LoggerFactory.getLogger(AsyncFactory.class);



    /**
     * 操作日志记录
     *
     * @param operLog 操作日志信息
     * @return 任务task
     */
    public static TimerTask recordOper(final SysOperateLog operLog) {
        return new TimerTask() {
            @Override
            public void run() {

                try {					
                    SpringUtils.getBean(ISysOperateLogService.class).insertOperlog(operLog);
                } catch (Exception e) {
                    sys_user_logger.error("操作日志记录异常  -> errorMsg : {}", e.getMessage());
                }
            }
        };
    }


}

SpringUtils:

package com.rz.common.util;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.stereotype.Component;

/**
 * spring工具类 方便在非spring管理环境中获取bean
 */
@Component
public final class SpringUtils implements BeanFactoryPostProcessor
{
    /** Spring应用上下文环境 */
    private static ConfigurableListableBeanFactory beanFactory;

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException
    {
        SpringUtils.beanFactory = beanFactory;
    }

    /**
     * 获取对象
     *
     * @param name
     * @return Object 一个以所给名字注册的bean的实例
     * @throws org.springframework.beans.BeansException
     *
     */
    @SuppressWarnings("unchecked")
    public static <T> T getBean(String name) throws BeansException
    {
        return (T) beanFactory.getBean(name);
    }

    /**
     * 获取类型为requiredType的对象
     *
     * @param clz
     * @return
     * @throws org.springframework.beans.BeansException
     *
     */
    public static <T> T getBean(Class<T> clz) throws BeansException
    {
        T result = (T) beanFactory.getBean(clz);
        return result;
    }

    /**
     * 如果BeanFactory包含一个与所给名称匹配的bean定义,则返回true
     *
     * @param name
     * @return boolean
     */
    public static boolean containsBean(String name)
    {
        return beanFactory.containsBean(name);
    }

    /**
     * 判断以给定名字注册的bean定义是一个singleton还是一个prototype。 如果与给定名字相应的bean定义没有被找到,将会抛出一个异常(NoSuchBeanDefinitionException)
     *
     * @param name
     * @return boolean
     * @throws org.springframework.beans.factory.NoSuchBeanDefinitionException
     *
     */
    public static boolean isSingleton(String name) throws NoSuchBeanDefinitionException
    {
        return beanFactory.isSingleton(name);
    }

    /**
     * @param name
     * @return Class 注册对象的类型
     * @throws org.springframework.beans.factory.NoSuchBeanDefinitionException
     *
     */
    public static Class<?> getType(String name) throws NoSuchBeanDefinitionException
    {
        return beanFactory.getType(name);
    }

    /**
     * 如果给定的bean名字在bean定义中有别名,则返回这些别名
     *
     * @param name
     * @return
     * @throws org.springframework.beans.factory.NoSuchBeanDefinitionException
     *
     */
    public static String[] getAliases(String name) throws NoSuchBeanDefinitionException
    {
        return beanFactory.getAliases(name);
    }
}

NetworkUtil:

package com.rz.common.util.local;


import com.rz.common.util.StringUtils;

import javax.servlet.http.HttpServletRequest;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.*;
import java.util.Enumeration;
import java.util.Random;

public class NetworkUtil {

    /**
     * 获取本机ip地址
     * @return
     */
    public static String getLocalAddr() {
        String localip = null;// 本地IP,如果没有配置外网IP则返回它
        String netip = null;// 外网IP
        try {
            Enumeration netInterfaces = NetworkInterface.getNetworkInterfaces();
            InetAddress ip = null;
            boolean finded = false;// 是否找到外网IP
            while (netInterfaces.hasMoreElements() && !finded) {
                NetworkInterface ni = (NetworkInterface) netInterfaces.nextElement();
                Enumeration address = ni.getInetAddresses();
                while (address.hasMoreElements()) {
                    ip = (InetAddress) address.nextElement();
                    if (!ip.isSiteLocalAddress() && !ip.isLoopbackAddress() && ip.getHostAddress().indexOf(":") == -1) {// 外网IP
                        netip = ip.getHostAddress();
                        finded = true;
                        break;
                    } else if (ip.isSiteLocalAddress() && !ip.isLoopbackAddress() && ip.getHostAddress().indexOf(":") == -1) {// 内网IP
                        localip = ip.getHostAddress();
                    }
                }
            }
        } catch (SocketException e) {
            e.printStackTrace();
        }

        if (netip != null && !"".equals(netip)) {
            return netip;
        } else {
            return localip;
        }
    }

    /**
     * 获取远程访问地址
     * @param request
     * @return
     */
	public static String getRemoteAddr(HttpServletRequest request) {
		String ip = request.getHeader("x-forwarded-for");

		if (StringUtils.isBlank(ip) || "unknown".equalsIgnoreCase(ip)) {
			ip = request.getHeader("ali-cdn-real-ip");
		}
		if (StringUtils.isBlank(ip) || "unknown".equalsIgnoreCase(ip)) {
			ip = request.getHeader("Proxy-Client-IP");
		}
		if (StringUtils.isBlank(ip) || "unknown".equalsIgnoreCase(ip)) {
			ip = request.getHeader("WL-Proxy-Client-IP");
		}
		if (StringUtils.isBlank(ip) || "unknown".equalsIgnoreCase(ip)) {
			ip = request.getRemoteAddr();
		}

		String[] ipArray = ip.split(",");
		if (ipArray != null && ipArray.length > 0) {
			ip = ipArray[0].trim();
		}

		return ip;
	}
    
	public static String sendPost(String url, String param) {
		PrintWriter out = null;
		BufferedReader in = null;
		String result = "";
		try {
			URL realUrl = new URL(url);
			URLConnection conn = realUrl.openConnection();

			// 随机生成ip
			String ip = randIP();
			conn.setRequestProperty("X-Forwarded-For", ip);
			conn.setRequestProperty("HTTP_X_FORWARDED_FOR", ip);
			conn.setRequestProperty("HTTP_CLIENT_IP", ip);
			conn.setRequestProperty("REMOTE_ADDR", ip);
			conn.setRequestProperty("Host", "operation.cardniu.com");
			conn.setRequestProperty("Connection", "keep-alive");
			conn.setRequestProperty("Content-Length", "17");
			conn.setRequestProperty("Accept", "application/json");
			conn.setRequestProperty("Origin", "ORIGIN");
			conn.setRequestProperty(
					"User-Agent",
					"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.101 Safari/537.36");
			conn.setRequestProperty("Content-Type",
					"application/x-www-form-urlencoded");
			conn.setRequestProperty(
					"Referer",
					"REFERER");
			conn.setRequestProperty("Accept-Encoding", "gzip, deflate");
			conn.setRequestProperty("Accept-Language",
					"zh-CN,zh;q=0.8,en;q=0.6,ja;q=0.4,pt;q=0.2");

			conn.setDoOutput(true);
			conn.setDoInput(true);
			out = new PrintWriter(conn.getOutputStream());
			out.print(param);
			out.flush();
			in = new BufferedReader(
					new InputStreamReader(conn.getInputStream()));
			String line;
			while ((line = in.readLine()) != null) {
				result += line;
			}
		} catch (Exception e) {
			System.out.println("发送 POST 请求出现异常!" + e);
			e.printStackTrace();
		} finally {
			try {
				if (out != null) {
					out.close();
				}
				if (in != null) {
					in.close();
				}
			} catch (IOException ex) {
				ex.printStackTrace();
			}
		}
		return result;
	}

	private static String randIP() {
		Random random = new Random(System.currentTimeMillis());
		return (random.nextInt(255) + 1) + "." + (random.nextInt(255) + 1)
				+ "." + (random.nextInt(255) + 1) + "."
				+ (random.nextInt(255) + 1);
	}

}

ThreadUtils:

package com.rz.common.util;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.TimeUnit;

/**
 * @Description : 线程相关工具类.
 */
public class ThreadUtils {

    private static final Logger logger = LoggerFactory.getLogger("sys-user");

    /**
     * sleep等待,单位为毫秒
     */
    public static void sleep(long milliseconds) {
        try {
            Thread.sleep(milliseconds);
        } catch (InterruptedException e) {
            return;
        }
    }

    /**
     * 停止线程池
     * 先使用shutdown, 停止接收新任务并尝试完成所有已存在任务.
     * 如果超时, 则调用shutdownNow, 取消在workQueue中Pending的任务,并中断所有阻塞函数.
     * 如果仍人超時,則強制退出.
     * 另对在shutdown时线程本身被调用中断做了处理.
     */
    public static void shutdownAndAwaitTermination(ExecutorService pool) {
        if (pool != null && !pool.isShutdown()) {
            pool.shutdown();
            try {
                if (!pool.awaitTermination(120, TimeUnit.SECONDS)) {
                    pool.shutdownNow();
                    if (!pool.awaitTermination(120, TimeUnit.SECONDS)) {
                        logger.info("Pool did not terminate");
                    }
                }
            } catch (InterruptedException ie) {
                pool.shutdownNow();
                Thread.currentThread().interrupt();
            }
        }
    }

}

TestController:

package com.rz.controller;
import com.rz.common.aspect.Log;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


import java.util.List;

/**
 * @Description : 日志测试
 */
@RestController
public class TestController {

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

    @GetMapping("/test")
    @Log(title = "测试", businessType = BusinessType.QUERY)
    public Result test() {
        Result result = new Result();
        result.setMessage("test msg");
        return result;
    }


}

 

  finish!

 


版权声明:本文为m0_37125796原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。