需求:日志插入,比如一个权限平台管理,系统希望记录每一条管理员操作权限或应用的记录,如修改权限,新增权限,删除权限,新增应用,修改应用,删除应用等,将这些审计记录存到数据库,方便追踪。
用面向切面编程,自定义切面实例
1.自定义审计注解,用来指定操作类型和操作目标
/**
* 审计
*/
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
public @interface Audit {
/**
* 类型
* @return
*/
String type();
/**
* 目标
* @return
*/
String target();
}
2.创建切面类AuditAop
@Aspect
@Component
public class AuditAop {
@Autowired
private HttpServletRequest request;
@Autowired
private AuditService auditService;
/**
* 定义拦截规则
*/
@Pointcut("execution(* com..*(..)) && @annotation(com.xxxx.authz.audit.annotation.Audit)")
public void controllerMethodPointcut() {
}
/**
* 审计
*/
@Before("controllerMethodPointcut()")
public void before(JoinPoint joinPoint) {
Signature signature = joinPoint.getSignature();
MethodSignature methodSignature = (MethodSignature) signature;
Method targetMethod = methodSignature.getMethod();
Audit audit = targetMethod.getAnnotation(Audit.class);
String type = audit.type();
String target = audit.target();
Object[] parameters = joinPoint.getArgs();
String[] parameterNames = methodSignature.getParameterNames();
Object value = null;
for (int i = 0; i < parameterNames.length; i++) {
if (target.equals(parameterNames[i])) {
value = parameters[i];
break;
}
}
String ip = NetworkUtil.getIpAddress(request);
auditService.addAudit(type, value, ip);
}
}
3.创建审计服务类
/**
* 审计服务
*/
@Service
public class AuditService {
@Autowired
private JdbcDao jdbcDao;
@Autowired(required = false)
private DbConfig dbConfig;
/**
* 添加审计
*/
public void addAudit(String type, Object target, String ip) {
AuditEntry audit = new AuditEntry();
audit.setIp(ip);
if (StringUtil.isNotEmpty(target)) {
audit.setOperTarget(target.toString());
}
audit.setOperType(type);
audit.setUserId(getUserId());
jdbcDao.insert(audit);
}
private String getUserId() {
if (null == dbConfig) {
return "system";
}
String id = dbConfig.getUserId();
if (StringUtils.isEmpty(id)) {
return "system";
}
return id;
}
}