需求:
针对不同的action 方法中有修改删除的敏感操作的接口,需要记录对应的参数,ip地址,员工的id名称等信息,方便追责定位问题
分析:
1.使用注解将对应方法打上标记
2.每次调用完该方法的时候才开始记录日志
3.需要记录用户请求的ip地址,参数,用户名称等等
①定义注解
import java.lang.annotation.*;
@Target({ ElementType.METHOD, ElementType.TYPE })
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface MethodLog {
//对标记接口的补充说明
String content() default "";
String operType() default "0";
int operLevel() default 0; //操作等级
}
②定义切面
/**
* 操作日志切面配置
*/
@Aspect
@Component("operateLogAspect")
public class OperateLogAspect {
private Logger logger = LoggerFactory.getLogger(getClass());
//注入持久化该日志信息的service
@Autowired
private OperateService operateService;
//注入根据request获取登录用户信息的service
@Autowired
private SysUserService sysUserService;
@After(value = "execution (* com.web.controller..*.*(..))") //指定切点,使用after 让该切面在方法执行完成后切入
public void after(JoinPoint point) throws Throwable {
try {
// 拦截的action方法上面的标记是否包含 MethodLog 的注解
Map map = getMthodRemark(point);
if (map.isEmpty()) {
// 没有MethodLog 注解标记 ,无此配置,直接返回
return;
}
//获取requestBody 参数信息,过滤掉 ServletRequest 和 ServletResponse 类型的参数
Object object = Arrays.stream(point.getArgs()).filter(t ->!( t instanceof ServletRequest) && !( t instanceof ServletResponse) ).collect(Collectors.toList());
//请求参数转成jsonString
String requestBody = JSONObject.toJSONString(object);
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
if (null == request) {
logger.info("获取request失败.直接返回");
return;
}
//根据request获取用户ID
Long userId = this.getSysUserId(request);
if (userId == null) {
logger.error("未从request中获取到员工信息,直接返回");
return;
}
//获取用户数使用客户端信息
String userAgent = request.getHeader("user-agent");
//根据用户ID调用service获取用户信息
SystemUser myUser = sysUserService.queryOne(userId);
//获取该方法的名称
String requestMethod = request.getMethod();
StringBuffer params = new StringBuffer();
// action方法名称
String actionName = point.getSignature().getName();
String pms = requestBody;
// 构建操作日志对象
OperateLog log = new OperateLog();
log.setUserId(Integer.parseInt("" + myUser.getUserId()));
log.setUserName(myUser.getUserName());
log.setOperContent(null == map.get("content") ? "" : map.get("content").toString());
log.setOperLevel(null == map.get("operLevel") ? 0 : Integer.parseInt(map.get("operLevel").toString()));
log.setOpParams(pms);
log.setOperUserAgent(userAgent);
log.setOpIp(getIpAdrress(request));
log.setOpSysType(null == map.get("operType") ? 0 : Integer.parseInt(map.get("operType").toString()));
log.setOperMethod(actionName);
log.setOpDisplayMode("");
operateLogService.insertOperateLog(log);
}catch (JSONException je){
logger.error("记录操作日志参数异常,json转型异常:{}", je.getMessage());
} catch (Exception e) {
logger.error("记录操作日志出错:{}", StackTraceLogUtil.getStackTraceAsString(e));
}
return;
}
/**
* 计算两天是否同一天
*
* @param day1
* @param day2
* @return
*/
public boolean isSameDay(Date day1, Date day2) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
String ds1 = sdf.format(day1);
String ds2 = sdf.format(day2);
return ds1.equals(ds2) ? true : false;
}
/**
* @param request
* @return 当前登陆员工Id
* @desc 获取当前登陆用户Id
*/
protected Long getSysUserId(HttpServletRequest request) {
Object object = request.getAttribute(CommonConstant.UID);
if (object == null)
object = request.getHeader(CommonConstant.UID);
return Optional.ofNullable(object).isPresent() ? Long.valueOf(String.valueOf(object)) : null;
}
/**
* 是否相差time
*
* @param d1
* @param d2
* @param time
* @return
*/
public boolean isDifferTime(Date d1, Date d2, int time) {
if ((d2.getTime() - d1.getTime()) / 1000 / 60 > time)
return true;
else
return false;
}
/**
* 获取Ip地址
* @param request
* @return
*/
private static String getIpAdrress(HttpServletRequest request) {
String Xip = request.getHeader("X-Real-IP");
String XFor = request.getHeader("X-Forwarded-For");
if(StringUtils.isNotEmpty(XFor) && !"unKnown".equalsIgnoreCase(XFor)){
//多次反向代理后会有多个ip值,第一个ip才是真实ip
int index = XFor.indexOf(",");
if(index != -1){
return XFor.substring(0,index);
}else{
return XFor;
}
}
XFor = Xip;
if(StringUtils.isNotEmpty(XFor) && !"unKnown".equalsIgnoreCase(XFor)){
return XFor;
}
if (StringUtils.isBlank(XFor) || "unknown".equalsIgnoreCase(XFor)) {
XFor = request.getHeader("Proxy-Client-IP");
}
if (StringUtils.isBlank(XFor) || "unknown".equalsIgnoreCase(XFor)) {
XFor = request.getHeader("WL-Proxy-Client-IP");
}
if (StringUtils.isBlank(XFor) || "unknown".equalsIgnoreCase(XFor)) {
XFor = request.getHeader("HTTP_CLIENT_IP");
}
if (StringUtils.isBlank(XFor) || "unknown".equalsIgnoreCase(XFor)) {
XFor = request.getHeader("HTTP_X_FORWARDED_FOR");
}
if (StringUtils.isBlank(XFor) || "unknown".equalsIgnoreCase(XFor)) {
XFor = request.getRemoteAddr();
}
return XFor;
}
// 获取方法的中文备注____用于记录用户的操作日志描述
@SuppressWarnings("rawtypes")
public static Map getMthodRemark(JoinPoint joinPoint)
throws Exception {
String targetName = joinPoint.getTarget().getClass().getName();
String methodName = joinPoint.getSignature().getName();
Object[] arguments = joinPoint.getArgs();
Map map = Maps.newHashMap();
Class targetClass = Class.forName(targetName);
Method[] method = targetClass.getMethods();
String methode = "";
for (Method m : method) {
if (m.getName().equals(methodName)) {
Class[] tmpCs = m.getParameterTypes();
if (tmpCs.length == arguments.length) {
MethodLog methodCache = m.getAnnotation(MethodLog.class);
if (methodCache != null) {
methode = methodCache.content();
String operType = methodCache.operType();
int level = methodCache.operLevel();
map.put("content", methode);
map.put("operLevel", level);
map.put("operType", operType);
}
break;
}
}
}
return map;
}
}
具体是持久化方法之类的我就不贴了,这里只是提供一个思路,如果有问题的欢迎指正,谢谢