【SpringBootAOP记录用户操作日志】4.切面和切点
定义一个LogAspect类,使用@Aspect
标注让其成为一个切面,切点为使用@Log
注解标注的方法
加aop依赖
<!-- aop依赖 --><dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
新建LogAspect类
import com.aoplog.springbootaoplog.annotation.Log;import com.aoplog.springbootaoplog.domain.SysOperLog;
import com.aoplog.springbootaoplog.enums.BusinessStatus;
import com.aoplog.springbootaoplog.manager.AsyncManager;
import com.aoplog.springbootaoplog.manager.factory.AsyncFactory;
import com.aoplog.springbootaoplog.util.JSON;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.JoinPoint;
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.stereotype.Component;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import java.lang.reflect.Method;
import java.util.Map;
/**
* 操作日志记录处理
*
* @author hekang
*/
@Aspect
@Component
public class LogAspect
{
private static final Logger log = LoggerFactory.getLogger(LogAspect.class);
/**
* 配置织入点
*/
@Pointcut("@annotation(com.aoplog.springbootaoplog.annotation.Log)")
public void logPointCut()
{
}
/**
* 处理完请求后执行
*
* @param joinPoint 切点
*/
@AfterReturning(pointcut = "logPointCut()", returning = "jsonResult")
public void doAfterReturning(JoinPoint joinPoint, Object jsonResult)
{
handleLog(joinPoint, null, jsonResult);
}
/**
* 拦截异常操作
*
* @param joinPoint 切点
* @param e 异常
*/
@AfterThrowing(value = "logPointCut()", throwing = "e")
public void doAfterThrowing(JoinPoint joinPoint, Exception e)
{
handleLog(joinPoint, e, null);
}
protected void handleLog(final JoinPoint joinPoint, final Exception e, Object jsonResult)
{
try
{
// 获得注解
Log controllerLog = getAnnotationLog(joinPoint);
if (controllerLog == null)
{
return;
}
// 获取当前的用户资料取数据库 或者 Shiro Session
// *========数据库日志=========*//
SysOperLog operLog = new SysOperLog();
operLog.setStatus(BusinessStatus.SUCCESS.ordinal());
// 请求的地址 从Shiro或者security取都行
String ip = "127.0.0.1";
operLog.setOperIp(ip);
// 返回参数
operLog.setJsonResult(JSON.marshal(jsonResult));
/**
* 请求url
*/
RequestAttributes attributes = RequestContextHolder.getRequestAttributes();
ServletRequestAttributes getRequestAttributes = (ServletRequestAttributes) attributes;
operLog.setOperUrl(getRequestAttributes.getRequest().getRequestURI());
//动态 从Shiro或者security取都行
operLog.setOperName("admin");
if (e != null)
{
operLog.setStatus(BusinessStatus.FAIL.ordinal());
operLog.setErrorMsg(StringUtils.substring(e.getMessage(), 0, 2000));
}
// 设置方法名称
String className = joinPoint.getTarget().getClass().getName();
String methodName = joinPoint.getSignature().getName();
operLog.setMethod(className + "." + methodName + "()");
// 设置请求方式
operLog.setRequestMethod(getRequestAttributes.getRequest().getMethod());
// 处理设置注解上的参数
getControllerMethodDescription(controllerLog, operLog);
// 保存数据库
AsyncManager.me().execute(AsyncFactory.recordOper(operLog));
}
catch (Exception exp)
{
// 记录本地异常日志
log.error("==前置通知异常==");
log.error("异常信息:{}", exp.getMessage());
exp.printStackTrace();
}
}
/**
* 获取注解中对方法的描述信息 用于Controller层注解
*
* @param log 日志
* @param operLog 操作日志
* @throws Exception
*/
public void getControllerMethodDescription(Log log, SysOperLog operLog) throws Exception
{
// 设置action动作
operLog.setBusinessType(log.businessType().ordinal());
// 设置标题
operLog.setTitle(log.title());
// 设置操作人类别
operLog.setOperatorType(log.operatorType().ordinal());
// 是否需要保存request,参数和值
if (log.isSaveRequestData())
{
// 获取参数的信息,传入到数据库中。
setRequestValue(operLog);
}
}
/**
* 获取请求的参数,放到log中
*
* @param operLog 操作日志
* @throws Exception 异常
*/
private void setRequestValue(SysOperLog operLog) throws Exception
{
RequestAttributes attributes = RequestContextHolder.getRequestAttributes();
ServletRequestAttributes getRequestAttributes = (ServletRequestAttributes) attributes;
Map<String, String[]> map = getRequestAttributes.getRequest().getParameterMap();
String params = JSON.marshal(map);
operLog.setOperParam(StringUtils.substring(params, 0, 2000));
}
/**
* 是否存在注解,如果存在就获取
*/
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;
}
}
创建JSON解析处理工具包
import com.fasterxml.jackson.core.JsonGenerationException;
import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.ObjectWriter;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
/**
* JSON解析处理
*
* @author hekang
*/
public class JSON
{
public static final String DEFAULT_FAIL = ""Parse failed"";
private static final ObjectMapper objectMapper = new ObjectMapper();
private static final ObjectWriter objectWriter = objectMapper.writerWithDefaultPrettyPrinter();
public static void marshal(File file, Object value) throws Exception
{
try
{
objectWriter.writeValue(file, value);
}
catch (JsonGenerationException e)
{
throw new Exception(e);
}
catch (JsonMappingException e)
{
throw new Exception(e);
}
catch (IOException e)
{
throw new Exception(e);
}
}
public static void marshal(OutputStream os, Object value) throws Exception
{
try
{
objectWriter.writeValue(os, value);
}
catch (JsonGenerationException e)
{
throw new Exception(e);
}
catch (JsonMappingException e)
{
throw new Exception(e);
}
catch (IOException e)
{
throw new Exception(e);
}
}
public static String marshal(Object value) throws Exception
{
try
{
return objectWriter.writeValueAsString(value);
}
catch (JsonGenerationException e)
{
throw new Exception(e);
}
catch (JsonMappingException e)
{
throw new Exception(e);
}
catch (IOException e)
{
throw new Exception(e);
}
}
public static byte[] marshalBytes(Object value) throws Exception
{
try
{
return objectWriter.writeValueAsBytes(value);
}
catch (JsonGenerationException e)
{
throw new Exception(e);
}
catch (JsonMappingException e)
{
throw new Exception(e);
}
catch (IOException e)
{
throw new Exception(e);
}
}
public static <T> T unmarshal(File file, Class<T> valueType) throws Exception
{
try
{
return objectMapper.readValue(file, valueType);
}
catch (JsonParseException e)
{
throw new Exception(e);
}
catch (JsonMappingException e)
{
throw new Exception(e);
}
catch (IOException e)
{
throw new Exception(e);
}
}
public static <T> T unmarshal(InputStream is, Class<T> valueType) throws Exception
{
try
{
return objectMapper.readValue(is, valueType);
}
catch (JsonParseException e)
{
throw new Exception(e);
}
catch (JsonMappingException e)
{
throw new Exception(e);
}
catch (IOException e)
{
throw new Exception(e);
}
}
public static <T> T unmarshal(String str, Class<T> valueType) throws Exception
{
try
{
return objectMapper.readValue(str, valueType);
}
catch (JsonParseException e)
{
throw new Exception(e);
}
catch (JsonMappingException e)
{
throw new Exception(e);
}
catch (IOException e)
{
throw new Exception(e);
}
}
public static <T> T unmarshal(byte[] bytes, Class<T> valueType) throws Exception
{
try
{
if (bytes == null)
{
bytes = new byte[0];
}
return objectMapper.readValue(bytes, 0, bytes.length, valueType);
}
catch (JsonParseException e)
{
throw new Exception(e);
}
catch (JsonMappingException e)
{
throw new Exception(e);
}
catch (IOException e)
{
throw new Exception(e);
}
}
}
创建操作状态BusinessStatus枚举
/** * 操作状态
*
* @author hekang
*/
public enum BusinessStatus
{
/**
* 成功
*/
SUCCESS,
/**
* 失败
*/
FAIL,
}
修改SysOperLogController类加@Log
import com.aoplog.springbootaoplog.annotation.Log;import com.aoplog.springbootaoplog.domain.SysOperLog;
import com.aoplog.springbootaoplog.enums.BusinessType;
import com.aoplog.springbootaoplog.service.ISysOperLogService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
@RestController
public class SysOperLogController {
@Autowired
private ISysOperLogService iSysOperLogService;
/**
* 查询全部日志 加操作日志
*
* @return
*/
@GetMapping("/api/operLog")
@Log(title = "查询全部日志", businessType = BusinessType.SELECT)
public List<SysOperLog> selectOperLogList1() {
return this.iSysOperLogService.selectOperLogList(null);
}
/**
* 修改日志 加操作日志
*
* @return
*/
@GetMapping("/api/operLog/{id}")
@Log(title = "修改日志", businessType = BusinessType.UPDATE)
public List<SysOperLog> updateOperLog(@PathVariable("id") Long id) {
//不做实际操作
return this.iSysOperLogService.selectOperLogList(null);
}
/**
* 查询全部日志
*
* @return
*/
@GetMapping("/operLog")
public List<SysOperLog> selectOperLogList2() {
return this.iSysOperLogService.selectOperLogList(null);
}
}
启动项目测试:
先查询没有数据:http://127.0.0.1:8080/operLog
访问:
查询操作
http://127.0.0.1:8080/api/operLog
修改操作
http://127.0.0.1:8080/api/operLog/1
再访问:http://127.0.0.1:8080/operLog
源码:https://gitee.com/hekang_admin/spring-boot-aop-log.git
以上是 【SpringBootAOP记录用户操作日志】4.切面和切点 的全部内容, 来源链接: utcz.com/z/512231.html