本文目录导读:

我来提供一个完整的Java审计日志实现案例,包含多个实现方案。
基于Spring AOP的审计日志实现
依赖配置 (pom.xml)
<dependencies>
<!-- Spring Boot Web -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- Spring AOP -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<!-- Spring Data JPA -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<!-- MySQL -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<!-- Lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<!-- Jackson -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
</dependencies>
审计日志注解
package com.example.audit.annotation;
import java.lang.annotation.*;
/**
* 审计日志注解
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface AuditLog {
/** 操作类型 */
String operation() default "";
/** 模块名称 */
String module() default "";
/** 操作描述 */
String description() default "";
/** 是否记录请求参数 */
boolean recordRequest() default true;
/** 是否记录响应结果 */
boolean recordResponse() default false;
}
审计日志实体
package com.example.audit.entity;
import lombok.Data;
import javax.persistence.*;
import java.time.LocalDateTime;
@Data
@Entity
@Table(name = "audit_log")
public class AuditLogEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
/** 操作人ID */
@Column(name = "user_id")
private Long userId;
/** 操作人名称 */
@Column(name = "username")
private String username;
/** 操作IP */
@Column(name = "ip")
private String ip;
/** 模块 */
@Column(name = "module")
private String module;
/** 操作类型 */
@Column(name = "operation")
private String operation;
/** 方法描述 */
@Column(name = "description")
private String description;
/** 请求参数 */
@Column(name = "request_params", columnDefinition = "TEXT")
private String requestParams;
/** 响应结果 */
@Column(name = "response_result", columnDefinition = "TEXT")
private String responseResult;
/** 执行时间(毫秒) */
@Column(name = "execution_time")
private Long executionTime;
/** 是否成功 */
@Column(name = "success")
private Boolean success;
/** 异常信息 */
@Column(name = "error_message", columnDefinition = "TEXT")
private String errorMessage;
/** 创建时间 */
@Column(name = "create_time")
private LocalDateTime createTime;
}
审计日志仓储
package com.example.audit.repository;
import com.example.audit.entity.AuditLogEntity;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.stereotype.Repository;
@Repository
public interface AuditLogRepository extends JpaRepository<AuditLogEntity, Long>,
JpaSpecificationExecutor<AuditLogEntity> {
}
审计日志AOP切面
package com.example.audit.aspect;
import com.example.audit.annotation.AuditLog;
import com.example.audit.entity.AuditLogEntity;
import com.example.audit.repository.AuditLogRepository;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.stream.Collectors;
@Aspect
@Component
public class AuditLogAspect {
@Autowired
private AuditLogRepository auditLogRepository;
@Autowired
private ObjectMapper objectMapper;
@Around("@annotation(auditLog)")
public Object around(ProceedingJoinPoint joinPoint, AuditLog auditLog) throws Throwable {
long startTime = System.currentTimeMillis();
AuditLogEntity logEntity = new AuditLogEntity();
try {
// 设置基本信息
logEntity.setModule(auditLog.module());
logEntity.setOperation(auditLog.operation());
logEntity.setDescription(auditLog.description());
logEntity.setCreateTime(LocalDateTime.now());
// 获取当前用户信息
setUserInfo(logEntity);
// 记录请求参数
if (auditLog.recordRequest()) {
String requestParams = getRequestParams(joinPoint);
logEntity.setRequestParams(requestParams);
}
// 执行目标方法
Object result = joinPoint.proceed();
// 记录执行时间
long executionTime = System.currentTimeMillis() - startTime;
logEntity.setExecutionTime(executionTime);
logEntity.setSuccess(true);
// 记录响应结果
if (auditLog.recordResponse()) {
logEntity.setResponseResult(objectMapper.writeValueAsString(result));
}
return result;
} catch (Throwable throwable) {
// 记录异常信息
long executionTime = System.currentTimeMillis() - startTime;
logEntity.setExecutionTime(executionTime);
logEntity.setSuccess(false);
logEntity.setErrorMessage(throwable.getMessage());
throw throwable;
} finally {
// 异步保存审计日志
saveAuditLogAsync(logEntity);
}
}
private void setUserInfo(AuditLogEntity logEntity) {
try {
HttpServletRequest request = getHttpServletRequest();
if (request != null) {
// 从请求中获取用户信息(根据实际认证方式修改)
logEntity.setUsername(request.getHeader("X-User-Name"));
logEntity.setUserId(Long.valueOf(request.getHeader("X-User-Id")));
logEntity.setIp(getIpAddress(request));
}
} catch (Exception e) {
logEntity.setUsername("anonymous");
logEntity.setIp("unknown");
}
}
private HttpServletRequest getHttpServletRequest() {
ServletRequestAttributes attributes =
(ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
return attributes != null ? attributes.getRequest() : null;
}
private String getIpAddress(HttpServletRequest request) {
String ip = request.getHeader("X-Forwarded-For");
if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("Proxy-Client-IP");
}
if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("WL-Proxy-Client-IP");
}
if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) {
ip = request.getRemoteAddr();
}
return ip;
}
private String getRequestParams(ProceedingJoinPoint joinPoint) {
try {
Object[] args = joinPoint.getArgs();
// 过滤掉HttpServletRequest、HttpServletResponse等对象
Object[] filteredArgs = Arrays.stream(args)
.filter(arg -> !(arg instanceof HttpServletRequest)
&& !(arg instanceof HttpServletResponse)
&& !(arg instanceof MultipartFile))
.collect(Collectors.toList())
.toArray();
return objectMapper.writeValueAsString(filteredArgs);
} catch (Exception e) {
return "Failed to serialize request params: " + e.getMessage();
}
}
private void saveAuditLogAsync(AuditLogEntity logEntity) {
new Thread(() -> {
auditLogRepository.save(logEntity);
}).start();
}
}
使用示例 - Service
package com.example.audit.service;
import com.example.audit.annotation.AuditLog;
import com.example.audit.entity.User;
import com.example.audit.repository.UserRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class UserService {
@Autowired
private UserRepository userRepository;
@AuditLog(
module = "用户管理",
operation = "CREATE",
description = "创建用户",
recordRequest = true,
recordResponse = false
)
public User createUser(User user) {
// 业务逻辑
return userRepository.save(user);
}
@AuditLog(
module = "用户管理",
operation = "UPDATE",
description = "更新用户信息"
)
public User updateUser(User user) {
// 业务逻辑
return userRepository.save(user);
}
@AuditLog(
module = "用户管理",
operation = "DELETE",
description = "删除用户"
)
public void deleteUser(Long id) {
// 业务逻辑
userRepository.deleteById(id);
}
@AuditLog(
module = "用户管理",
operation = "QUERY",
description = "查询用户列表",
recordResponse = true
)
public List<User> findUsers(String keyword) {
// 业务逻辑
return userRepository.findByUsernameContaining(keyword);
}
}
Controller示例
package com.example.audit.controller;
import com.example.audit.entity.User;
import com.example.audit.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/api/users")
public class UserController {
@Autowired
private UserService userService;
@PostMapping
public User createUser(@RequestBody User user) {
return userService.createUser(user);
}
@PutMapping("/{id}")
public User updateUser(@PathVariable Long id, @RequestBody User user) {
user.setId(id);
return userService.updateUser(user);
}
@DeleteMapping("/{id}")
public void deleteUser(@PathVariable Long id) {
userService.deleteUser(id);
}
@GetMapping
public List<User> findUsers(@RequestParam(required = false) String keyword) {
return userService.findUsers(keyword);
}
}
审计日志查询Service
package com.example.audit.service;
import com.example.audit.entity.AuditLogEntity;
import com.example.audit.repository.AuditLogRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import javax.persistence.criteria.Predicate;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
@Service
public class AuditLogQueryService {
@Autowired
private AuditLogRepository auditLogRepository;
public List<AuditLogEntity> queryAuditLogs(AuditLogQueryParam param) {
Specification<AuditLogEntity> specification = (root, query, criteriaBuilder) -> {
List<Predicate> predicates = new ArrayList<>();
// 按用户名查询
if (param.getUsername() != null && !param.getUsername().isEmpty()) {
predicates.add(criteriaBuilder.like(
root.get("username"), "%" + param.getUsername() + "%"));
}
// 按模块查询
if (param.getModule() != null && !param.getModule().isEmpty()) {
predicates.add(criteriaBuilder.equal(
root.get("module"), param.getModule()));
}
// 按操作类型查询
if (param.getOperation() != null && !param.getOperation().isEmpty()) {
predicates.add(criteriaBuilder.equal(
root.get("operation"), param.getOperation()));
}
// 按时间范围查询
if (param.getStartTime() != null) {
predicates.add(criteriaBuilder.greaterThanOrEqualTo(
root.get("createTime"), param.getStartTime()));
}
if (param.getEndTime() != null) {
predicates.add(criteriaBuilder.lessThanOrEqualTo(
root.get("createTime"), param.getEndTime()));
}
// 按成功状态查询
if (param.getSuccess() != null) {
predicates.add(criteriaBuilder.equal(
root.get("success"), param.getSuccess()));
}
return criteriaBuilder.and(predicates.toArray(new Predicate[0]));
};
return auditLogRepository.findAll(specification);
}
}
查询参数类
package com.example.audit.service;
import lombok.Data;
import java.time.LocalDateTime;
@Data
public class AuditLogQueryParam {
private String username;
private String module;
private String operation;
private LocalDateTime startTime;
private LocalDateTime endTime;
private Boolean success;
}
配置类
package com.example.audit.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.transaction.annotation.EnableTransactionManagement;
@Configuration
@EnableAsync
@EnableScheduling
@EnableTransactionManagement
public class AppConfig {
}
使用方法
在Service方法上添加注解
@Service
public class OrderService {
@AuditLog(
module = "订单管理",
operation = "CREATE",
description = "创建订单",
recordRequest = true
)
public Order createOrder(Order order) {
// 业务逻辑
}
}
查询审计日志
@RestController
@RequestMapping("/api/audit")
public class AuditController {
@Autowired
private AuditLogQueryService auditLogService;
@GetMapping("/logs")
public List<AuditLogEntity> queryLogs(@RequestBody AuditLogQueryParam param) {
return auditLogService.queryAuditLogs(param);
}
}
数据库表结构
CREATE TABLE audit_log (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
user_id BIGINT,
username VARCHAR(50),
ip VARCHAR(50),
module VARCHAR(100),
operation VARCHAR(50),
description VARCHAR(500),
request_params TEXT,
response_result TEXT,
execution_time BIGINT,
success TINYINT(1),
error_message TEXT,
create_time DATETIME
);
-- 创建索引
CREATE INDEX idx_audit_time ON audit_log(create_time);
CREATE INDEX idx_audit_user ON audit_log(username);
CREATE INDEX idx_audit_module ON audit_log(module);
高级特性扩展
异步处理配置优化
@Configuration
@EnableAsync
public class AsyncConfig {
@Bean("auditLogExecutor")
public Executor auditLogExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(2);
executor.setMaxPoolSize(5);
executor.setQueueCapacity(1000);
executor.setThreadNamePrefix("audit-log-");
executor.initialize();
return executor;
}
}
敏感信息脱敏
public class DataDesensitizationUtil {
public static String desensitize(String data, String type) {
if (data == null || data.isEmpty()) {
return data;
}
switch (type) {
case "password":
return "******";
case "phone":
return data.replaceAll("(\\d{3})\\d{4}(\\d{4})", "$1****$2");
case "email":
return data.replaceAll("(\\w{3})\\w+(@\\w+\\.[a-z]+)", "$1***$2");
default:
return data;
}
}
}
这个完整的审计日志实现包括:
- 灵活的注解配置:通过自定义注解实现审计功能
- 完整的日志信息:记录用户、IP、操作、参数、响应等
- 异步处理:避免影响主业务流程
- 异常记录:记录失败操作和错误信息
- 查询能力:支持多条件组合查询
- 扩展性好:易于添加新的审计场景
使用时只需在需要审计的方法上添加@AuditLog注解即可。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播