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!