由于本项目使用的是spring boot,内部自动集成spring相关配置,这里就不在使用注入xml方式进行讨论,只针对于本项目。
AOP是面向切面编程思想,就本项目来说,目前作用最大的是,对接口出参和入参的数据进行打印并保存,这里就运用到了AOP
先声明AOP切点标识以及说明
然后定义Aspect这里找度娘一大把,核心是定义切面 @Pointcut("@annotation(com.epbox.lite.cloud.annotation.SysLog)")
有些什么抛异常执行 或者执行方法前执行或者 返回前执行,这里就不在说明,这里只说明环绕执行,包含了方法前和后
@Pointcut("@annotation(com.epbox.lite.cloud.annotation.SysLog)")
public void webLog(){}
@AfterReturning(returning = "ret", pointcut = "webLog()")
public void doAfterReturning(JoinPoint joinPoint, Object ret){
}
@AfterThrowing(pointcut = "webLog()")
public void throwss(JoinPoint joinPoint){
}
//环绕通知,环绕增强,相当于MethodInterceptor
@Around("webLog()")
public Object arround(ProceedingJoinPoint pjp) {
Object returnObj = null;
SystemLog systemLog = new SystemLog();
String id = null;
Object oldObj = null;
try{
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletRequest request = attributes.getRequest();
//获取注解信息
SysLog sysLog = ((MethodSignature)pjp.getSignature()).getMethod().getAnnotation(SysLog.class);
Integer accountId = AccountUtils.getAccountIdFromRequest(request);
systemLog.setOperateBy(Long.valueOf(accountId));
if(sysLog.operateModule()!= null){
systemLog.setOperateModule(sysLog.operateModule().getCode());
}
if(sysLog.actionType() != null){
systemLog.setActionType(Byte.valueOf(sysLog.actionType().getCode()));
}
if(sysLog.logType()!= null ){
systemLog.setLogType(Byte.valueOf(sysLog.logType().getCode()));
}
if(sysLog.desc() != null && sysLog.desc() != ""){
systemLog.setRemark(sysLog.desc());
}
String remoteAddr = NetworkUtil.getIpAddress(request);
systemLog.setIp(remoteAddr);
systemLog.setPath(request.getRequestURI());
systemLog.setInputParams(JSON.toJSONString(pjp.getArgs()));
String interfaceName = pjp.getSignature().getDeclaringTypeName();
String sipin = interfaceName.substring(interfaceName.lastIndexOf("."));
systemLog.setInterfaceName(interfaceName + "." + pjp.getSignature().getName());
systemLog.setActionType(Byte.valueOf(sysLog.actionType().getCode()));
if(ActionEnum.ADD.equals(sysLog.actionType()) || ActionEnum.UPDATE.equals(sysLog.actionType())){
//insert or update
Object obj = getParamObject(pjp);
try{
id = PropertyUtils.getProperty(obj,"id").toString();
}catch (Exception e){
//ignore
logger.error("==>获取id失败[exception:{}]",e);
}
if(id == null){
List<ChangeField> changeFields = DiffUtil.getInsertChangeItems(obj);
String jsonStr = JSON.toJSONString(changeFields);
systemLog.setChanges(jsonStr);
systemLog.setObjectClass(obj.getClass().getSimpleName());
}else{
try {
systemLog.setObjectId(String.valueOf(id));
Object oldObjTemp = DiffUtil.getObjectById(pjp.getTarget(),id);
if(sipin.endsWith("Controller")){
ResponseEntity<ResultBody> rs = (ResponseEntity<ResultBody>)oldObjTemp;
oldObj = rs.getBody().getResult();
}else {
oldObj = oldObjTemp;
}
systemLog.setObjectClass(oldObj.getClass().getSimpleName());
} catch (Exception e) {
//ignore
logger.error("==>获取修改前的值失败[exception:{}]",e);
}
}
}else if(ActionEnum.DELETE.equals(sysLog.actionType())){
//设置删除变更内容
try {
if(getParamObject(pjp) != null){
id =getParamObject(pjp).toString();
}
Object oldObjTemp = DiffUtil.getObjectById(pjp.getTarget(),id);
if(sipin.endsWith("Controller")){
ResponseEntity<ResultBody> rs = (ResponseEntity<ResultBody>)oldObjTemp;
oldObj = rs.getBody().getResult();
}else {
oldObj = oldObjTemp;
}
ChangeField changeItem = DiffUtil.getDeleteChangeItem(oldObj);
systemLog.setChanges(JSON.toJSONString(changeItem));
systemLog.setObjectId(pjp.getArgs()[0].toString());
systemLog.setObjectClass(oldObj.getClass().getSimpleName());
} catch (Exception e) {
//ignore
logger.error("==>设置删除变更内容失败[exception:{}]",e);
}
}
//执行返回结果
boolean flag = false;
try {
returnObj = pjp.proceed(pjp.getArgs());
flag = true;
} catch (Throwable throwable) {
logger.error("==>执行方法异常[exception:{}]",throwable);
}
if(flag){
try {
String jsonStr = JSON.toJSONString(returnObj);
JSONObject object = JSON.parseObject(jsonStr);
if(object != null && StringUtils.isNotBlank(object.getString("status"))){
if(Constant.FAIL.equals(object.getString("status"))) {
systemLog.setOperateState(Byte.valueOf("0"));
}else if(Constant.SUCCESS.equals(object.getString("status"))){
systemLog.setOperateState(Byte.valueOf("1"));
}
}else {
systemLog.setOperateState(Byte.valueOf("1"));
}
} catch (Exception e) {
//ignore
logger.error("==>设置操作操作状态失败[exception:{}]",e);
}
if(ActionEnum.ADD.equals(sysLog.actionType())){
//new id
Object newId = null;
try {
if(sipin.endsWith("Controller")){
ResponseEntity<ResultBody> rs = (ResponseEntity<ResultBody>)returnObj;
newId = PropertyUtils.getProperty(rs.getBody().getResult(),"id");
}else {
newId = PropertyUtils.getProperty(returnObj,"id");
}
systemLog.setObjectId(String.valueOf(newId.toString()));
} catch (Exception e) {
//ignore
logger.error("==>设置新增id失败[exception:{}]",e);
}
}else if(ActionEnum.UPDATE.equals(sysLog.actionType())){
Object newObj = null;
try {
Object newObjTemp = DiffUtil.getObjectById(pjp.getTarget(),id);
if(sipin.endsWith("Controller")){
ResponseEntity<ResultBody> rs = (ResponseEntity<ResultBody>)newObjTemp;
newObj = rs.getBody().getResult();
}else {
newObj = newObjTemp;
}
List<ChangeField> changeItems = DiffUtil.getChangeItems(oldObj,newObj);
systemLog.setChanges(JSON.toJSONString(changeItems));
} catch (Exception e) {
//ignore
logger.error("==>设置变更内容失败[exception:{}]",e);
}
}
}else {
systemLog.setOperateState(Byte.valueOf("0"));
}
systemLogService.create(systemLog);
}catch (Exception e){
logger.error("==>系统日志错诶:{}",e);
}
return returnObj;
}
/**
* 获取参数
* @param pjp
* @return
*/
private Object getParamObject(ProceedingJoinPoint pjp) {
int paraLen = pjp.getArgs().length;
Object obj = null;
if(paraLen>0){
for(Object o:pjp.getArgs()){
obj = o;
Class clazz = o.getClass();
if(clazz.equals(HttpServletRequest.class) || clazz.equals(HttpServletResponse.class)){
obj = null;
continue;
}
return obj;
}
}
return obj;
}
在使用方面,只需要在使用的切点加入 下图所示即可