spring mvc拦截器用于拦截http请求,常见场景包括日志记录、权限检查、性能监控和通用行为处理;它通过实现handlerinterceptor接口并重写prehandle、posthandle和aftercompletion方法来完成请求前、后及完成时的处理。

你提到的“通过 dispatchEvent 发出的业务日志”,这里存在关键概念混淆:Spring MVC 的拦截器(Interceptor)作用于 HTTP 请求生命周期(即 DispatcherServlet 接收并分发请求的过程),而 dispatchEvent 是浏览器端 JavaScript 的 DOM 事件分发方法,属于前端运行时行为,**与 Spring 后端拦截器完全无关**。
因此,Spring 拦截器无法、也不应去监听或记录 JS 中调用 dispatchEvent 触发的事件。真正需要记录的,是这些前端事件最终触发的 **HTTP 请求(如 AJAX/Fetch 调用)** —— 这才是后端可拦截、可审计的业务入口。
确认你要记录的是哪类“业务日志”
请先区分清楚:
-
前端 DOM 事件本身(如点击按钮、触发自定义 event)→ 需在浏览器中用 JS 监听,例如:
document.addEventListener('your-event', handler),然后手动上报; -
由 DOM 事件发起的真实 HTTP 请求(如点击后调用
fetch('/api/order/submit'))→ 这才是 Spring 拦截器能捕获并记录的对象。
配置全局拦截器记录所有业务请求日志
这是标准且推荐的做法。只需三步:
- 编写一个实现
HandlerInterceptor的日志拦截器,重点重写preHandle(记录请求开始)和afterCompletion(记录响应结果、耗时、状态码); - 在 WebMvcConfigurer 中注册该拦截器,并设置拦截路径为
/**,实现全局生效; - 建议补充关键字段:请求 URI、HTTP 方法、IP 地址、请求参数(注意脱敏)、响应状态码、处理耗时(毫秒)、异常信息(如有)。
示例:轻量级全局请求日志拦截器
以下是一个生产可用的简化版:
public class GlobalLoggingInterceptor implements HandlerInterceptor {
private static final Logger log = LoggerFactory.getLogger(GlobalLoggingInterceptor.class);
<pre class="brush:php;toolbar:false;">@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
long startTime = System.currentTimeMillis();
request.setAttribute("startTime", startTime);
String uri = request.getRequestURI();
String method = request.getMethod();
String ip = getClientIp(request);
log.info("[REQ] {} {} | IP: {} | Params: {}", method, uri, ip, getParamsString(request));
return true;
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response,
Object handler, Exception ex) {
long startTime = (Long) request.getAttribute("startTime");
long cost = System.currentTimeMillis() - startTime;
int status = response.getStatus();
String uri = request.getRequestURI();
if (ex != null) {
log.error("[ERR] {} {} | Status: {} | Cost: {}ms | Exception: {}",
request.getMethod(), uri, status, cost, ex.getMessage(), ex);
} else {
log.info("[RES] {} {} | Status: {} | Cost: {}ms",
request.getMethod(), uri, status, cost);
}
}
private String getClientIp(HttpServletRequest request) {
String xff = request.getHeader("X-Forwarded-For");
return StringUtils.hasText(xff) ? xff.split(",")[0].trim() : request.getRemoteAddr();
}
private String getParamsString(HttpServletRequest request) {
// 建议对敏感参数(如 password、token)做屏蔽处理
return request.getParameterMap().entrySet().stream()
.map(e -> e.getKey() + "=" + Arrays.toString(e.getValue()))
.collect(Collectors.joining("&"));
}}
注册为全局拦截器(Spring Boot)
在配置类中添加:
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new GlobalLoggingInterceptor())
.excludePathPatterns("/actuator/**", "/webjars/**", "/swagger-ui/**", "/error");
}
}
排除健康检查、静态资源等非业务路径,避免日志噪音。
不复杂但容易忽略:日志格式统一、敏感字段脱敏、异步写入(避免阻塞请求)、结合 traceId 实现链路追踪,才是真正落地好用的业务日志方案。










