要求:
在controller层对update , insert , delete类型的请求对应的方法 进行拦截, 然后获取方法的请求参数,
根据不同的请求类型, 想日志表中计入不同的内容. 这样就可以实现每次改动数据库中表时,就会记录日志.
一般日志表会会记录如下内容:
修改人id
表名称
修改数据行id
修改时间
请求端ip地址
修改内容
实现方式:
我们以update操作计入日志为例
在controller层的update类型的方法上加一个注解(可以是自定义注解, 也可以用springboot的注解)
单独定义一个切面类OperLogAspect , 将加在方法上的注解定义为一个切点.
对这个切点加一个前置通知, 前置通知里 执行计入日志信息的操作.
具体实现如下:
首先看controller层
public class CConsController extends BasicController<CCons,ICConsService>{
@PreAuthorize("hasAuthority('billing:cons:insert')")
@PostMapping(value = "/insert")
public ResponseResult<Object> insert(@RequestBody(required = false) Map<String, Object> paraMap) {...}
}
在insert方法前, 加了一个preAuthorize注解, 注解的value是billing:cons:insert
然后定义一个切面类
@Aspect
@Component
@Slf4j
public class OperLogAspect {
@Pointcut("@annotation(org.springframework.security.access.prepost.PreAuthorize)")
public void operLogPointCut(){
}
@Before(value = "operLogPointCut()")
public void saveOperLog(JoinPoint joinPoint){
// 从切面织入点处通过反射机制获取织入点处的方法
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
// 获取切入点所在的方法
Method method = signature.getMethod();
// 获取操作
PreAuthorize preAuthorize = method.getAnnotation(PreAuthorize.class);
String pre = preAuthorize.value();
//如果pre中包含update的字符串的话, 记日志时将修改前数据和修改后数据都记录日志
//如果pre中包含insert/delete的话, 记日志时只用将被改的数据计入日志即可
Class<IBasicService> basicService = (Class<IBasicService>) ((ParameterizedType) joinPoint.getTarget().getClass().getGenericSuperclass()).getActualTypeArguments()[1];
IBasicService service = (IBasicService) SpringUtil.getBean(basicService);
Class<BasicEntity> entityClass = (Class<BasicEntity>) ((ParameterizedType) joinPoint.getTarget().getClass().getGenericSuperclass()).getActualTypeArguments()[0];
//表名称
String tablename = entityClass.newInstance().getTableName();
//从线程池获取用户信息
//request中获取ip地址
//创建日志模板类, 填入日志的数据
//调用日志service的insert方法插入日志数据
}
}
这里解释一些方法:
getTarget() 获取被调方法的代理类
getClass() 获取类类型
getGenericSuperclass() 获取类的带泛型的父类
joinPoint.getTarget().getClass().getGenericSuperclass(): 获取被调方法的代理类的类类型后获取该类的带泛型的父类
getActualTypeArguments()[0] : 获取第一个泛型
留意controller层, 会发现他的父类传了两个泛型 , 第一个是model , 第二个是service