AOP通知类型
- @Before(前置通知):在连接点执行前执行该通知。
- @After(后置通知):又名最终通知,在连接点执行完成后(不管成功、失败、异常)都会执行该通知。
- @AfterReturning(返回通知):在连接点执行完成后执行,若目标方法执行异常则不会执行该通知。
- @AfterThrowing(异常通知):在连接点执行抛出异常时执行该通知。
- @Around(环绕通知):结合了上面四种通知,加强版的通知,围绕在连接点前后。
自定义权限控制注解
前置通知方式:
@Target({ElementType.METHOD})
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Order(Ordered.HIGHEST_PRECEDENCE)
public @interface CheckOperation {
String operationCode();
}
@Aspect
@Component
public class CheckOperationAop {
@Autowired
HttpServletRequest request;
@Pointcut(value = "@annotation(XXX.XXX.CheckOperation)")
public void logAnnotation() {
}
// 前置通知,方法执行前判断用户是否有权限
@Before("logAnnotation()")
public void before(JoinPoint point) {
MethodSignature methodSignature = (MethodSignature) point.getSignature();
CheckOperation annotation = methodSignature.getMethod().getAnnotation(CheckOperation.class);
if (getRequestAttributes() == null) {
throw new XXXException("获取请求体失败");
}
LoginInfo loginInfo = OauthUtils.getCurrentUser();
String userId;
if (loginInfo != null) {
userId = loginInfo.getUserId();
} else {
String token = request.getParameter("token").replace("bearer ", "");
userId = JWT.decode(token).getClaim("userId").asInt().toString();
}
// 获取注解参数
String code = annotation.operationCode();
if (...) {
throw new XXXException("用户没有该操作权限");
}
}
}
@CheckOperation(operationCode = "0cd7647c-696c-9254-b886-5e3405b1aed2")
@PostMapping("/XXX")
public Object XXX(@Valid @RequestBody XXX xxx) {
}
环绕通知方式:
@Target({ElementType.METHOD})
@Documented
@Retention(RetentionPolicy.RUNTIME)
public @interface SysOperationLogRecord {
String operationName();
}
@Aspect
@Component
public class SysOperationLogRecordAop {
@Autowired
SysOperationlogMapper sysOperationlogMapper;
@Autowired
HttpServletRequest request;
@Pointcut(value = "@annotation(com.dsh.annotation.SysOperationLogRecord)")
public void sysOperationLogAnnotation() {
}
// 环绕通知,可在方法执行前后做出各种操作
@Around("sysOperationLogAnnotation()")
public Object before(ProceedingJoinPoint point) throws Throwable {
MethodSignature methodSignature = (MethodSignature) point.getSignature();
SysOperationLogRecord annotation = methodSignature.getMethod().getAnnotation(SysOperationLogRecord.class);
String userId = OauthUtils.getCurrentUser().getUserId();
String ip = RequestHeaderUtil.getRemoteHost(request);
String userAgent = request.getHeader("user-agent");
String browser = RequestHeaderUtil.getBrowser(userAgent);
String os = RequestHeaderUtil.getOS(userAgent);
// 获取注解参数
String operationDesc = annotation.operationName();
int operationResult = 1;
String url = request.getRequestURL().toString();
// 获取执行方法参数
Object[] paramValues = point.getArgs();
// 锁车指令有三种,判断一下是哪种指令
if(operationDesc.equals("下发锁车指令")){
RequestOrder requestOrder = (RequestOrder) paramValues[0];
switch (requestOrder.getLockModel()){
case 0:
operationDesc = "下发查询指令";
break;
case 1:
operationDesc = "下发解锁指令";
break;
default:
}
}
BaseApiResult proceed = null;
JSONObject proceed2 = null;
try {
// 执行方法,获取执行结果
Object methodResult = point.proceed();
if(methodResult instanceof BaseApiResult){
proceed = (BaseApiResult) methodResult;
if(proceed.getCode() != 1){
operationResult = -1;
}
}else if(methodResult instanceof JSONObject){
proceed2 = (JSONObject) methodResult;
if(!(boolean)proceed2.get("success")){
operationResult = -1;
}
}
} catch (Throwable e) {
operationResult = -1;
// 每次操作记录日志
sysOperationlogMapper.insert(SysOperationlog.builder().userId(Integer.valueOf(userId))
.operationTime(System.currentTimeMillis()).operationDesc(operationDesc)
.operationResult(operationResult).ip(ip).browser(browser).os(os).url(url)
.parameter(Arrays.toString(paramValues)).build());
throw e;
}
// 每次操作记录日志
sysOperationlogMapper.insert(SysOperationlog.builder().userId(Integer.valueOf(userId))
.operationTime(System.currentTimeMillis()).operationDesc(operationDesc)
.operationResult(operationResult).ip(ip).browser(browser).os(os).url(url)
.parameter(Arrays.toString(paramValues)).build());
return proceed == null ? proceed2 : proceed;
}
}
@SysOperationLogRecord(operationName = "下发锁车指令")
@PostMapping("/XXX")
public BaseApiResult<?> XXX(@Valid @RequestBody XXX xxx) {
}