基础版见这个
依赖
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.8.8</version>
</dependency>
自定义监控日志类
package com.java.core.com.annotation;
import com.java.core.com.enums.BusinessType;
import java.lang.annotation.*;
@Target({ ElementType.PARAMETER, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Log
{
/**
* 模块
*/
public String title() default "";
/**
* 功能
*/
public BusinessType businessType() default BusinessType.OTHER;
/**
* 是否保存请求的参数
*/
public boolean isSaveRequestData() default true;
/**
* 是否保存响应的参数
*/
public boolean isSaveResponseData() default true;
}
枚举
package com.java.core.com.enums;
public enum BusinessType
{
/**
* 其它
*/
OTHER,
/**
* 获取
*/
GET,
/**
* 新增
*/
INSERT,
/**
* 修改
*/
UPDATE,
/**
* 删除
*/
DELETE,
/**
* 授权
*/
GRANT,
/**
* 导出
*/
EXPORT,
/**
* 导入
*/
IMPORT,
/**
* 强退
*/
FORCE,
/**
* 生成代码
*/
GENCODE,
/**
* 清空
*/
CLEAN,
}
controller用法
@ApiOperation(value = "刷新登录状态")
@Log(title = "在线用户", businessType = BusinessType.UPDATE)
@PreAuthorize("hasAuthority('sys:userOnline:insert') || hasAuthority('sys:userOnline:edit')")
@PostMapping(value = "/refreshToken")
public HttpResult refreshToken(HttpServletRequest request){
//在线用户
SysUserOnline onlineUser= WebApp.getOnlineUser(request,"","");
//保存到数据库
return HttpResult.ok(sysUserOnlineService.saveOnline(onlineUser));
}
请求后的监控,和报错的监控
package com.java.core.web.config;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.support.spring.PropertyPreFilters;
import com.java.core.com.annotation.Log;
import com.java.core.com.enums.BusinessStatus;
import com.java.core.com.utils.StringUtils;
import com.java.core.com.utils.http.AddressUtils;
import com.java.core.com.utils.http.IpUtils;
import com.java.core.com.utils.spring.SpringUtils;
import com.java.core.com.vo.HttpResult;
import com.java.core.core.security.JwtTokenUtils;
import com.java.core.entity.master.SysOperLog;
import com.java.core.service.system.SysOperLogService;
import com.java.core.service.system.SysUserOnlineService;
import eu.bitwalker.useragentutils.UserAgent;
import io.jsonwebtoken.Claims;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import org.springframework.validation.BindingResult;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Collection;
import java.util.Date;
import java.util.Map;
//处理AOP切面请求日志
@Slf4j
@Component
@Aspect
public class OperLogConfig {
/** 排除敏感属性字段 */
public static final String[] EXCLUDE_PROPERTIES = { "salt","sessionId","password", "oldPassword", "newPassword", "confirmPassword" };
// 配置织入点
@Pointcut("@annotation(com.java.core.com.annotation.Log)")
public void pointcut()
{
}
/**
* 处理完请求后执行
*
* @param joinPoint 切点
*/
@AfterReturning(pointcut = "@annotation(controllerLog)", returning = "result")
public void requestAfter(JoinPoint joinPoint, Log controllerLog, Object result) throws Exception {
handleLog(joinPoint, controllerLog, null, result);
}
/**
* 拦截异常操作
*
* @param joinPoint 切点
* @param e 异常
*/
@AfterThrowing(value = "@annotation(controllerLog)", throwing = "e")
public void doAfterThrowing(JoinPoint joinPoint, Log controllerLog, Exception e) throws Exception {
handleLog(joinPoint, controllerLog, e, null);
}
private void handleLog(final JoinPoint joinPoint, Log controllerLog, final Exception e, Object result) throws Exception {
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletRequest request = attributes.getRequest();
//浏览器信息
UserAgent userAgent = UserAgent.parseUserAgentString(request.getHeader("User-Agent"));
String token = request.getHeader(JwtTokenUtils.AUTHORITIES);
Claims claims =JwtTokenUtils.getClaimsFromToken(token);
String userId=claims.getSubject();
String userName = claims.getAudience();
SysOperLog dbLog=new SysOperLog();
// 设置标题
dbLog.setTitle(controllerLog.title());
// 设置action动作
dbLog.setBusiness_type(controllerLog.businessType().ordinal());
// 设置方法名称
String className = joinPoint.getTarget().getClass().getName();
String methodName = joinPoint.getSignature().getName();
dbLog.setMethod(className + "." + methodName + "()");
dbLog.setRequest_method(request.getMethod());
dbLog.setBrowser(userAgent.getBrowser().getName());
dbLog.setOs(userAgent.getOperatingSystem().getName());
dbLog.setOper_user_id(userId);
dbLog.setOper_user_name(userName);
dbLog.setOper_url(request.getRequestURI());
dbLog.setOper_ip(IpUtils.getIpAddr(request));
dbLog.setOper_location(AddressUtils.getRealAddressByIP(dbLog.getOper_ip()));
dbLog.setJson_result(StringUtils.substring(JSONObject.toJSONString(result),0,2000));
if (e != null)
{
dbLog.setStatus(BusinessStatus.FAIL.ordinal());
dbLog.setError_msg(StringUtils.substring(e.getMessage(), 0, 2000));
}else {
dbLog.setStatus(BusinessStatus.SUCCESS.ordinal());
dbLog.setError_msg("");
}
dbLog.setOper_time(new Date());
if(result!=null){
//设置参数
setRequestValue(joinPoint,request,dbLog);
}
//保存参数
SpringUtils.getBean(SysOperLogService.class).insertOperlog(dbLog);
}
/**
* 获取请求的参数,放到log中
*
* @param operLog 操作日志
* @throws Exception 异常
*/
private void setRequestValue(JoinPoint joinPoint, HttpServletRequest request, SysOperLog operLog) throws Exception
{
Map<String, String[]> map = request.getParameterMap();
if (StringUtils.isNotEmpty(map))
{
String params = JSONObject.toJSONString(map, excludePropertyPreFilter());
operLog.setOper_param(StringUtils.substring(params, 0, 2000));
}
else
{
Object args = joinPoint.getArgs();
if (StringUtils.isNotNull(args))
{
String params = argsArrayToString(joinPoint.getArgs());
operLog.setOper_param(StringUtils.substring(params, 0, 2000));
}
}
}
/**
* 忽略敏感属性
*/
public PropertyPreFilters.MySimplePropertyPreFilter excludePropertyPreFilter()
{
return new PropertyPreFilters().addFilter().addExcludes(EXCLUDE_PROPERTIES);
}
/**
* 参数拼装
*/
private String argsArrayToString(Object[] paramsArray)
{
String params = "";
if (paramsArray != null && paramsArray.length > 0)
{
for (Object o : paramsArray)
{
if (StringUtils.isNotNull(o) && !isFilterObject(o))
{
try
{
Object jsonObj = JSONObject.toJSONString(o, excludePropertyPreFilter());
params += jsonObj.toString() + " ";
}
catch (Exception e)
{
}
}
}
}
return params.trim();
}
/**
* 判断是否需要过滤的对象。
*
* @param o 对象信息。
* @return 如果是需要过滤的对象,则返回true;否则返回false。
*/
@SuppressWarnings("rawtypes")
public boolean isFilterObject(final Object o)
{
Class<?> clazz = o.getClass();
if (clazz.isArray())
{
return clazz.getComponentType().isAssignableFrom(MultipartFile.class);
}
else if (Collection.class.isAssignableFrom(clazz))
{
Collection collection = (Collection) o;
for (Object value : collection)
{
return value instanceof MultipartFile;
}
}
else if (Map.class.isAssignableFrom(clazz))
{
Map map = (Map) o;
for (Object value : map.entrySet())
{
Map.Entry entry = (Map.Entry) value;
return entry.getValue() instanceof MultipartFile;
}
}
return o instanceof MultipartFile || o instanceof HttpServletRequest || o instanceof HttpServletResponse
|| o instanceof BindingResult;
}
}
实现效果