nelson
4 years ago
13 changed files with 382 additions and 14 deletions
@ -0,0 +1,19 @@ |
|||
package com.aiprose.mbp.annotation; |
|||
import java.lang.annotation.Documented; |
|||
import java.lang.annotation.ElementType; |
|||
import java.lang.annotation.Retention; |
|||
import java.lang.annotation.RetentionPolicy; |
|||
import java.lang.annotation.Target; |
|||
|
|||
/** |
|||
* 自定义操作日志注解 |
|||
* @author nelson |
|||
*/ |
|||
@Target(ElementType.METHOD) //注解放置的目标位置,METHOD是可注解在方法级别上
|
|||
@Retention(RetentionPolicy.RUNTIME) //注解在哪个阶段执行
|
|||
@Documented |
|||
public @interface OperLog { |
|||
String operModul() default ""; // 操作模块
|
|||
String operType() default ""; // 操作类型
|
|||
String operDesc() default ""; // 操作说明
|
|||
} |
@ -0,0 +1,186 @@ |
|||
package com.aiprose.mbp.aop; |
|||
|
|||
import com.aiprose.mbp.annotation.OperLog; |
|||
import com.aiprose.mbp.entity.ExceptionLog; |
|||
import com.aiprose.mbp.entity.SysLog; |
|||
import com.aiprose.mbp.service.ExceptionLogService; |
|||
import com.aiprose.mbp.service.SysLogService; |
|||
import com.aiprose.mbp.util.IPUtil; |
|||
import com.alibaba.fastjson.JSON; |
|||
import org.aspectj.lang.JoinPoint; |
|||
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.springframework.beans.factory.annotation.Autowired; |
|||
import org.springframework.beans.factory.annotation.Value; |
|||
import org.springframework.stereotype.Component; |
|||
import org.springframework.web.context.request.RequestAttributes; |
|||
import org.springframework.web.context.request.RequestContextHolder; |
|||
|
|||
import javax.servlet.http.HttpServletRequest; |
|||
import java.lang.reflect.Method; |
|||
import java.util.HashMap; |
|||
import java.util.Map; |
|||
|
|||
@Aspect |
|||
@Component |
|||
public class OperLogAspect { |
|||
|
|||
@Value("${version}") |
|||
private String operVer; |
|||
|
|||
@Autowired |
|||
private SysLogService sysLogService; |
|||
|
|||
@Autowired |
|||
private ExceptionLogService excService; |
|||
|
|||
/** |
|||
* 设置操作日志切入点 记录操作日志 在注解的位置切入代码 |
|||
*/ |
|||
@Pointcut("@annotation(com.aiprose.mbp.annotation.OperLog)") |
|||
public void syslogPoinCut() { |
|||
} |
|||
|
|||
/** |
|||
* 设置操作异常切入点记录异常日志 扫描所有controller包下操作 |
|||
*/ |
|||
@Pointcut("execution(* com.aiprose.mbp.controller..*.*(..))") |
|||
public void operExceptionLogPoinCut() { |
|||
} |
|||
|
|||
|
|||
/** |
|||
* 正常返回通知,拦截用户操作日志,连接点正常执行完成后执行, 如果连接点抛出异常,则不会执行 |
|||
* @param joinPoint 切入点 |
|||
* @param keys 返回结果 |
|||
*/ |
|||
@AfterReturning(value = "syslogPoinCut()", returning = "keys") |
|||
public void savesyslog(JoinPoint joinPoint, Object keys) { |
|||
// 获取RequestAttributes
|
|||
RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes(); |
|||
// 从获取RequestAttributes中获取HttpServletRequest的信息
|
|||
HttpServletRequest request = (HttpServletRequest) requestAttributes |
|||
.resolveReference(RequestAttributes.REFERENCE_REQUEST); |
|||
|
|||
SysLog syslog = new SysLog(); |
|||
try { |
|||
|
|||
// 从切面织入点处通过反射机制获取织入点处的方法
|
|||
MethodSignature signature = (MethodSignature) joinPoint.getSignature(); |
|||
// 获取切入点所在的方法
|
|||
Method method = signature.getMethod(); |
|||
// 获取操作
|
|||
OperLog opLog = method.getAnnotation(OperLog.class); |
|||
if (opLog != null) { |
|||
String operModul = opLog.operModul(); |
|||
String operType = opLog.operType(); |
|||
String operDesc = opLog.operDesc(); |
|||
syslog.setOperModul(operModul); // 操作模块
|
|||
syslog.setOperType(operType); // 操作类型
|
|||
syslog.setOperDesc(operDesc); // 操作描述
|
|||
} |
|||
// 获取请求的类名
|
|||
String className = joinPoint.getTarget().getClass().getName(); |
|||
// 获取请求的方法名
|
|||
String methodName = method.getName(); |
|||
methodName = className + "." + methodName; |
|||
|
|||
syslog.setOperMethod(methodName); // 请求方法
|
|||
|
|||
// 请求的参数
|
|||
Map<String, String> rtnMap = converMap(request.getParameterMap()); |
|||
// 将参数所在的数组转换成json
|
|||
String params = JSON.toJSONString(rtnMap); |
|||
|
|||
syslog.setOperRequParam(params); // 请求参数
|
|||
syslog.setOperRespParam(JSON.toJSONString(keys)); // 返回结果
|
|||
syslog.setOperUserId(1l); // 请求用户ID
|
|||
syslog.setOperUserName("nelson"); // 请求用户名称
|
|||
syslog.setOperIp(IPUtil.getIpAddr(request)); // 请求IP
|
|||
syslog.setOperUri(request.getRequestURI()); // 请求URI
|
|||
syslog.setOperVersion(operVer); // 操作版本
|
|||
sysLogService.save(syslog); |
|||
} catch (Exception e) { |
|||
e.printStackTrace(); |
|||
} |
|||
} |
|||
|
|||
/** |
|||
* 异常返回通知,用于拦截异常日志信息 连接点抛出异常后执行 |
|||
* |
|||
* @param joinPoint 切入点 |
|||
* @param e 异常信息 |
|||
*/ |
|||
@AfterThrowing(pointcut = "operExceptionLogPoinCut()", throwing = "e") |
|||
public void saveExceptionLog(JoinPoint joinPoint, Throwable e) { |
|||
// 获取RequestAttributes
|
|||
RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes(); |
|||
// 从获取RequestAttributes中获取HttpServletRequest的信息
|
|||
HttpServletRequest request = (HttpServletRequest) requestAttributes |
|||
.resolveReference(RequestAttributes.REFERENCE_REQUEST); |
|||
|
|||
ExceptionLog excepLog = new ExceptionLog(); |
|||
try { |
|||
// 从切面织入点处通过反射机制获取织入点处的方法
|
|||
MethodSignature signature = (MethodSignature) joinPoint.getSignature(); |
|||
// 获取切入点所在的方法
|
|||
Method method = signature.getMethod(); |
|||
// 获取请求的类名
|
|||
String className = joinPoint.getTarget().getClass().getName(); |
|||
// 获取请求的方法名
|
|||
String methodName = method.getName(); |
|||
methodName = className + "." + methodName; |
|||
// 请求的参数
|
|||
Map<String, String> rtnMap = converMap(request.getParameterMap()); |
|||
// 将参数所在的数组转换成json
|
|||
String params = JSON.toJSONString(rtnMap); |
|||
excepLog.setExcRequParam(params); // 请求参数
|
|||
excepLog.setOperMethod(methodName); // 请求方法名
|
|||
excepLog.setExcName(e.getClass().getName()); // 异常名称
|
|||
excepLog.setExcMsg(stackTraceToString(e.getClass().getName(), e.getMessage(), e.getStackTrace())); // 异常信息
|
|||
excepLog.setOperUserId(1l); // 请求用户ID
|
|||
excepLog.setOperUserName("nelson"); // 请求用户名称
|
|||
excepLog.setOperUri(request.getRequestURI()); // 操作URI
|
|||
excepLog.setOperIp(IPUtil.getIpAddr(request)); // 操作员IP
|
|||
excepLog.setOperVersion(operVer); // 操作版本号
|
|||
|
|||
excService.save(excepLog); |
|||
|
|||
} catch (Exception e2) { |
|||
e2.printStackTrace(); |
|||
} |
|||
|
|||
} |
|||
|
|||
/** |
|||
* 转换request 请求参数 |
|||
* |
|||
* @param paramMap request获取的参数数组 |
|||
*/ |
|||
public Map<String, String> converMap(Map<String, String[]> paramMap) { |
|||
Map<String, String> rtnMap = new HashMap<String, String>(); |
|||
for (String key : paramMap.keySet()) { |
|||
rtnMap.put(key, paramMap.get(key)[0]); |
|||
} |
|||
return rtnMap; |
|||
} |
|||
|
|||
/** |
|||
* 转换异常信息为字符串 |
|||
* |
|||
* @param exceptionName 异常名称 |
|||
* @param exceptionMessage 异常信息 |
|||
* @param elements 堆栈信息 |
|||
*/ |
|||
public String stackTraceToString(String exceptionName, String exceptionMessage, StackTraceElement[] elements) { |
|||
StringBuffer strbuff = new StringBuffer(); |
|||
for (StackTraceElement stet : elements) { |
|||
strbuff.append(stet + "\n"); |
|||
} |
|||
String message = exceptionName + ":" + exceptionMessage + "\n\t" + strbuff.toString(); |
|||
return message; |
|||
} |
|||
} |
@ -0,0 +1,39 @@ |
|||
package com.aiprose.mbp.entity; |
|||
import com.baomidou.mybatisplus.annotation.TableName; |
|||
import com.gitee.sunchenbin.mybatis.actable.annotation.Column; |
|||
import com.gitee.sunchenbin.mybatis.actable.annotation.Table; |
|||
import com.gitee.sunchenbin.mybatis.actable.constants.MySqlTypeConstant; |
|||
import lombok.Data; |
|||
|
|||
@Data |
|||
@Table(name="mbp_exception_log") |
|||
@TableName("mbp_exception_log") |
|||
public class ExceptionLog extends SuperEntity{ |
|||
|
|||
@Column(name = "oper_user_id",comment = "操作用户id") |
|||
private Long operUserId; |
|||
|
|||
@Column(name = "oper_user_name",comment = "操作用户名") |
|||
private String operUserName; |
|||
|
|||
@Column(name = "exc_requ_param",comment = "请求参数",type = MySqlTypeConstant.TEXT) |
|||
private String excRequParam; |
|||
|
|||
@Column(name = "oper_method",comment = "操作方法") |
|||
private String operMethod; |
|||
|
|||
@Column(name = "oper_uri",comment = "请求uri") |
|||
private String operUri; |
|||
|
|||
@Column(name = "oper_ip",comment = "请求ip") |
|||
private String operIp; |
|||
|
|||
@Column(name = "oper_version",comment = "版本号") |
|||
private String operVersion; |
|||
|
|||
@Column(name = "exc_name",comment = "异常名称") |
|||
private String excName; |
|||
|
|||
@Column(name = "exc_msg",comment = "异常信息",type = MySqlTypeConstant.TEXT) |
|||
private String excMsg; |
|||
} |
@ -0,0 +1,45 @@ |
|||
package com.aiprose.mbp.entity; |
|||
import com.baomidou.mybatisplus.annotation.TableName; |
|||
import com.gitee.sunchenbin.mybatis.actable.annotation.Column; |
|||
import com.gitee.sunchenbin.mybatis.actable.annotation.Table; |
|||
import com.gitee.sunchenbin.mybatis.actable.constants.MySqlTypeConstant; |
|||
import lombok.Data; |
|||
|
|||
@Data |
|||
@Table(name="mbp_syslog") |
|||
@TableName("mbp_syslog") |
|||
public class SysLog extends SuperEntity{ |
|||
|
|||
@Column(name = "oper_user_id",comment = "操作用户id") |
|||
private Long operUserId; |
|||
|
|||
@Column(name = "oper_user_name",comment = "操作用户名") |
|||
private String operUserName; |
|||
|
|||
@Column(name = "oper_modul",comment = "功能模块") |
|||
private String operModul; |
|||
|
|||
@Column(name = "oper_type",comment = "操作类型") |
|||
private String operType; |
|||
|
|||
@Column(name = "oper_desc",comment = "操作描述") |
|||
private String operDesc; |
|||
|
|||
@Column(name = "oper_requ_param",comment = "请求参数",type = MySqlTypeConstant.TEXT) |
|||
private String operRequParam; |
|||
|
|||
@Column(name = "oper_resp_param",comment = "返回参数",type = MySqlTypeConstant.TEXT) |
|||
private String operRespParam; |
|||
|
|||
@Column(name = "oper_method",comment = "操作方法") |
|||
private String operMethod; |
|||
|
|||
@Column(name = "oper_uri",comment = "请求uri") |
|||
private String operUri; |
|||
|
|||
@Column(name = "oper_ip",comment = "请求ip") |
|||
private String operIp; |
|||
|
|||
@Column(name = "oper_version",comment = "版本号") |
|||
private String operVersion; |
|||
} |
@ -0,0 +1,10 @@ |
|||
package com.aiprose.mbp.mapper; |
|||
|
|||
import com.aiprose.mbp.entity.ExceptionLog; |
|||
import com.aiprose.mbp.entity.SysLog; |
|||
import com.baomidou.mybatisplus.core.mapper.BaseMapper; |
|||
import org.apache.ibatis.annotations.Mapper; |
|||
|
|||
@Mapper |
|||
public interface ExceptionLogMapper extends BaseMapper<ExceptionLog> { |
|||
} |
@ -0,0 +1,9 @@ |
|||
package com.aiprose.mbp.mapper; |
|||
|
|||
import com.aiprose.mbp.entity.SysLog; |
|||
import com.baomidou.mybatisplus.core.mapper.BaseMapper; |
|||
import org.apache.ibatis.annotations.Mapper; |
|||
|
|||
@Mapper |
|||
public interface SysLogMapper extends BaseMapper<SysLog> { |
|||
} |
@ -0,0 +1,13 @@ |
|||
package com.aiprose.mbp.service; |
|||
|
|||
import com.aiprose.mbp.entity.ExceptionLog; |
|||
import com.aiprose.mbp.entity.SysLog; |
|||
import com.aiprose.mbp.mapper.ExceptionLogMapper; |
|||
import com.aiprose.mbp.mapper.SysLogMapper; |
|||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; |
|||
import org.springframework.stereotype.Service; |
|||
|
|||
@Service |
|||
public class ExceptionLogService extends ServiceImpl<ExceptionLogMapper, ExceptionLog> { |
|||
|
|||
} |
@ -0,0 +1,18 @@ |
|||
package com.aiprose.mbp.service; |
|||
|
|||
import com.aiprose.mbp.entity.SysLog; |
|||
import com.aiprose.mbp.entity.User; |
|||
import com.aiprose.mbp.mapper.SysLogMapper; |
|||
import com.aiprose.mbp.mapper.UserMapper; |
|||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; |
|||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; |
|||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; |
|||
import org.springframework.beans.factory.annotation.Autowired; |
|||
import org.springframework.stereotype.Service; |
|||
|
|||
import java.util.List; |
|||
|
|||
@Service |
|||
public class SysLogService extends ServiceImpl<SysLogMapper, SysLog> { |
|||
|
|||
} |
@ -0,0 +1,26 @@ |
|||
package com.aiprose.mbp.util; |
|||
|
|||
import javax.servlet.http.HttpServletRequest; |
|||
|
|||
public class IPUtil { |
|||
/** |
|||
* 获取IP地址 |
|||
* |
|||
* 使用Nginx等反向代理软件, 则不能通过request.getRemoteAddr()获取IP地址 |
|||
* 如果使用了多级反向代理的话,X-Forwarded-For的值并不止一个,而是一串IP地址,X-Forwarded-For中第一个非unknown的有效IP字符串,则为真实IP地址 |
|||
*/ |
|||
public static String getIpAddr(HttpServletRequest request) { |
|||
|
|||
String 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 || "unknown".equalsIgnoreCase(ip)) { |
|||
ip = request.getHeader("WL-Proxy-Client-IP"); |
|||
} |
|||
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { |
|||
ip = request.getRemoteAddr(); |
|||
} |
|||
return "0:0:0:0:0:0:0:1".equals(ip) ? "127.0.0.1" : ip; |
|||
} |
|||
} |
Loading…
Reference in new issue