spring boot 全局异常处理可以通过配置 @controlleradvice 捕获 druid 监控页面抛出的 com.alibaba.druid.support.http.statviewservlet 相关异常,但 druid 的内置监控页面通常直接返回 http 状态码(如 401、403)而非抛出 java 异常,因此常规的全局异常处理器无法拦截这些错误。要捕获或处理 druid 监控异常,最直接的方法是自定义 druid 的 statviewservlet 并覆盖其 doget/dopost 方法,或者在 spring boot 中通过 webmvcconfigurer 注册一个自定义的 filter 来拦截对 druid 监控路径的请求。

如何自定义 StatViewServlet 以捕获认证失败异常?
通过继承 StatViewServlet 并重写 isAllowed 方法,可以在请求进入监控页面之前进行自定义逻辑判断。如果验证失败,可以记录日志或抛出特定异常,从而被全局异常处理器捕获。这种方法适用于需要自定义认证逻辑的场景。

import com.alibaba.druid.support.http.StatViewServlet;
import javax.servlet.http.HttpServletRequest;
import java.util.Enumeration;
public class CustomDruidStatViewServlet extends StatViewServlet {
@Override
protected boolean isAllowed(HttpServletRequest request) {
// 自定义认证逻辑
String username = request.getParameter("username");
String password = request.getParameter("password");
if ("admin".equals(username) && "secret".equals(password)) {
return true;
}
// 认证失败时记录日志或抛出异常
System.err.println("Druid monitor authentication failed for user: " + username);
return false; // 返回 false 会触发 Druid 内部的 401/403 响应
}
}
上述代码展示了如何创建一个自定义的 StatViewServlet。在 isAllowed 方法中,我们检查用户名和密码。如果验证失败,返回 false,Druid 将自动返回 HTTP 401 或 403 状态码。虽然这不会抛出 Java 异常,但可以通过日志记录来追踪这些事件。如果需要更细粒度的控制,可以在 isAllowed 中抛出运行时异常,但这需要确保全局异常处理器能够捕获到它。
如何通过 Filter 拦截 Druid 监控请求并统一处理?
使用 Spring Boot 的 FilterRegistrationBean 注册一个自定义 Filter,可以在请求到达 Druid 监控页面之前进行拦截。这种方式更适合于需要在请求前后执行通用逻辑(如日志记录、权限检查)的场景。

import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import javax.servlet.*;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@Configuration
public class DruidFilterConfig {
@Bean
public FilterRegistrationBean druidStatViewServletFilter() {
FilterRegistrationBean registrationBean = new FilterRegistrationBean();
registrationBean.setFilter(new ServletFilter() {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
HttpServletResponse httpResponse = (HttpServletResponse) response;
try {
chain.doFilter(request, response);
} catch (Exception e) {
// 捕获异常并统一处理
httpResponse.setStatus(500);
httpResponse.getWriter().write("Internal Server Error: " + e.getMessage());
}
}
});
registrationBean.addUrlPatterns("/druid/*");
registrationBean.setOrder(1);
return registrationBean;
}
}
这段代码定义了一个 FilterRegistrationBean,它将拦截所有以 /druid/ 开头的请求。在 doFilter 方法中,我们尝试执行后续的过滤器链。如果发生任何异常,我们将 HTTP 状态码设置为 500,并向客户端返回错误信息。这种方式允许我们在不修改 Druid 源码的情况下,对监控页面的请求进行统一的异常处理和日志记录。
当 Druid 监控页面返回 401 时,全局异常处理器能捕获吗?
不能。Druid 的 StatViewServlet 在认证失败时直接返回 HTTP 401 或 403 状态码,而不是抛出 Java 异常。因此,Spring Boot 的全局异常处理器(如 @ControllerAdvice)无法捕获这些由 Servlet 容器直接生成的错误响应。要处理这种情况,必须依赖上述的自定义 StatViewServlet 或 Filter 方案,在请求层面进行拦截和处理。











