作用
将日志记录,性能统计,安全控制,事务处理,异常处理等代码从业务逻辑代码中划分出来,通过对这些行为的分离,我们希望可以将它们独立到非指导业务逻辑的方法中,进而改变这些行为的时候不影响业务逻辑的代码。
注解
@Aspect 定义切面类
@Component 定义配置
@Pointcut 定义切入点
@AfterReturning 方法执行后执行的方法
应用
基于SpringBoot实现接口日志记录
定义切面类
@Aspect
@Component
public class UserAspect {
Logger LOGGER = LoggerFactory.getLogger(this.getClass());
@Autowired
ISrmUserLogService srmUserLogService;
@Pointcut("@annotation(com.purchasecloud.srm.annotation.UserOperation)")
public void aspectaMethod() {
}
@AfterReturning(value = "@annotation(userOperation)", returning = "result")
public void doAfterReturning(JoinPoint point, Object result, UserOperation userOperation) throws Exception {
//用户操作日志记录
ResponseResult responseResult = srmUserLogService.addSrmUserLogOfAop(point, result, userOperation);
LOGGER.debug(DateUtils.getCurrentTime()+"--AOP添加日志返回结果:"+responseResult);
}
}
用户注解
/**
* 用户注解
* 功能:作用于controller接口,用于aop记录日志使用
*/
@Retention(RetentionPolicy.RUNTIME) //RetentionPolicy.RUNTIME 表示注解不仅被保存到class文件中,jvm加载class文件之后,仍然存在
@Target({ElementType.METHOD}) //ElementType.METHOD 表示该注解是用来描述方法的
@Documented
public @interface UserOperation {
//模块名
String moduleName() default "";
//操作记录
String operationRecord() default "";
}
日志Service业务处理
/**
* <p>
* 服务实现类
* </p>
*
* @author shenyidong
* @since 2019-07-26
*/
@Service
public class SrmUserLogServiceImpl extends ServiceImpl<SrmUserLogMapper, SrmUserLog> implements ISrmUserLogService {
@Autowired
SrmUserLogMapper srmUserLogMapper;
@Override
public ResponseResult addSrmUserLogOfAop(JoinPoint point, Object result, UserOperation userOperation) {
SrmUserLog srmUserLog = new SrmUserLog();
//ID
srmUserLog.setId(StringUtils.uuid());
//用户名
//模块名
srmUserLog.setModuleName(userOperation.moduleName());
//操作记录
srmUserLog.setOperation(userOperation.operationRecord());
//操作时间
srmUserLog.setOperationTime(DateUtils.getCurrentDate());
//类名
srmUserLog.setClassName(point.getTarget().getClass().getName());
//方法名
srmUserLog.setMethodName(point.getSignature().getName());
//请求url
//请求参数
//请求值
MethodSignature signature = (MethodSignature) point.getSignature(); //获取签名对象
Method method = signature.getMethod(); //获取方法
ParameterNameDiscoverer pnd = new DefaultParameterNameDiscoverer();
Object[] args = point.getArgs();
String[] parameterNames = pnd.getParameterNames(method); //请求字段名
JSONObject object = new JSONObject();
for (int i = 0; i < parameterNames.length; i++) {
object.put(parameterNames[i],args[i]);
}
srmUserLog.setParams(object.toJSONString());
//ip
//地址
int res = srmUserLogMapper.insert(srmUserLog);
return HandleResponseResult.checkAddValue(res);
}
}
用户注解作用在controller层
@Api(value = "采购云SRM系统用户模块接口", description = "采购云SRM系统用户模块接口")
@RestController
@RequestMapping("/srmuser")
@CrossOrigin //解决跨域
public class SrmUserController {
private static final String MODULE_NAME = "用户";
@Autowired
ISrmUserService srmUserService;
@Autowired
OrderService orderService;
@UserOperation(moduleName= MODULE_NAME,operationRecord = "根据账号密码查询" + MODULE_NAME)
@ApiOperation("根据账号密码查询" + MODULE_NAME)
@PostMapping(value = "/login")
public ResponseResult queryUserByNameAndPassword(@RequestBody SrmUser srmUser) {
if (StringUtils.isBlank(String.valueOf(srmUser.getUserNumber())) || StringUtils.isBlank(srmUser.getUserPassword())) {
throw new ParameterIsNullException();
}
return srmUserService.login(srmUser);
}
}
UserOperation
UserOperation注解作用于接口上,aop切面类在切入点时会扫描到,aop业务类可以获取到接口上的UserOperation属性值。