MVC 拦截器Spring MVC 拦截器对应HandlerInterctor接口该接口位于org.springframework.web.servlet的包中定义了三个方法若要实现该接口就要实现其三个方法前置处理preHandle()方法该方法在执行控制器方法之前执行。返回值为Boolean类型如果返回false表示拦截请求不再向下执行如果返回true表示放行程序继续向下执行如果后面没有其他Interceptor就会执行controller方法。所以此方法可对请求进行判断决定程序是否继续执行或者进行一些初始化操作及对请求进行预处理。后置处理postHandle()方法该方法在执行控制器方法调用之后且在返回ModelAndView之前执行。由于该方法会在DispatcherServlet进行返回视图渲染之前被调用所以此方法多被用于处理返回的视图可通过此方法对请求域中的模型和视图做进一步的修改。已完成处理afterCompletion()方法该方法在执行完控制器之后执行由于是在Controller方法执行完毕后执行该方法所以该方法适合进行一些资源清理记录日志信息等处理操作。可以通过拦截器进行权限检验参数校验记录日志等操作拦截器 (Interceptor) 实现案例拦截器Interceptor依赖于web框架在SpringMVC中就是依赖于SpringMVC框架。在实现上,基于Java的反射机制属于面向切面编程AOP的一种运用。就是在service或者一个方法前调用一个方法或者在方法后调用一个方法比如动态代理就是拦截器的简单实现在调用方法前打印出字符串或者做其它业务逻辑的操作。也可以在调用方法后打印出字符串甚至在抛出异常的时候做业务逻辑的操作。由于拦截器是基于web框架的调用因此可以使用Spring的依赖注入DI进行一些业务操作同时一个拦截器实例在一个controller生命周期之内可以多次调用。但是缺点是只能对controller请求进行拦截对其他的一些比如直接访问静态资源的请求则没办法进行拦截处理。自定义拦截器实现javaimport org.springframework.stereotype.Component; import org.springframework.web.servlet.HandlerInterceptor; import org.springframework.web.servlet.ModelAndView; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.util.Arrays; import java.util.Map; /** * 自定义拦截器 - 实现HandlerInterceptor接口 * 适用于业务相关的预处理和后处理 */ Component public class CustomInterceptor implements HandlerInterceptor { private static final ThreadLocalLong startTimeThreadLocal new ThreadLocal(); /** * 预处理回调方法 - 在控制器执行之前调用 * 返回true表示继续执行false表示中断执行 */ Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { // 记录请求开始时间 startTimeThreadLocal.set(System.currentTimeMillis()); // 获取请求信息 String requestURI request.getRequestURI(); String method request.getMethod(); String clientIP getClientIP(request); System.out.println(【拦截器-preHandle】请求开始: method requestURI); System.out.println(【拦截器-preHandle】客户端IP: clientIP); // 1. 权限验证示例 if (requiresAuth(requestURI) !isAuthenticated(request)) { response.sendError(HttpServletResponse.SC_UNAUTHORIZED, 未授权访问); return false; // 中断请求 } // 2. 参数预处理示例 MapString, String[] params request.getParameterMap(); if (!params.isEmpty()) { System.out.println(【拦截器-preHandle】请求参数: paramsToString(params)); } // 3. 设置请求属性供控制器使用 request.setAttribute(requestStartTime, System.currentTimeMillis()); return true; // 继续执行后续拦截器和控制器 } /** * 后处理回调方法 - 在控制器执行之后视图渲染之前调用返回ModelAndView之前 */ Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { Long startTime startTimeThreadLocal.get(); if (startTime ! null) { long costTime System.currentTimeMillis() - startTime; System.out.println(【拦截器-postHandle】请求处理耗时: costTime ms); // 可以修改ModelAndView if (modelAndView ! null) { modelAndView.addObject(processTime, costTime); modelAndView.addObject(interceptorMessage, 经过拦截器处理); } } } /** * 完成回调方法 - 在整个请求完成之后调用视图渲染完成后 * 适合进行资源清理 */ Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { Long startTime startTimeThreadLocal.get(); if (startTime ! null) { long totalTime System.currentTimeMillis() - startTime; int status response.getStatus(); System.out.println(【拦截器-afterCompletion】请求完成: request.getRequestURI() 状态: status 总耗时: totalTime ms); if (ex ! null) { System.err.println(【拦截器-afterCompletion】异常信息: ex.getMessage()); } // 清理ThreadLocal防止内存泄漏 startTimeThreadLocal.remove(); } } // 工具方法 private String getClientIP(HttpServletRequest request) { String ip request.getHeader(X-Forwarded-For); if (ip null || ip.length() 0 || unknown.equalsIgnoreCase(ip)) { ip request.getHeader(Proxy-Client-IP); } if (ip null || ip.length() 0 || unknown.equalsIgnoreCase(ip)) { ip request.getHeader(WL-Proxy-Client-IP); } if (ip null || ip.length() 0 || unknown.equalsIgnoreCase(ip)) { ip request.getRemoteAddr(); } return ip; } private boolean requiresAuth(String uri) { // 需要认证的路径规则 return uri.startsWith(/api/admin) || uri.startsWith(/api/user); } private boolean isAuthenticated(HttpServletRequest request) { // 简单的认证检查 String token request.getHeader(Authorization); return token ! null token.startsWith(Bearer ); } private String paramsToString(MapString, String[] params) { StringBuilder sb new StringBuilder(); for (Map.EntryString, String[] entry : params.entrySet()) { sb.append(entry.getKey()).append() .append(Arrays.toString(entry.getValue())).append(; ); } return sb.toString(); } }拦截器配置javaimport org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.InterceptorRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; import java.util.Arrays; import java.util.List; Configuration public class InterceptorConfig implements WebMvcConfigurer { Autowired private CustomInterceptor customInterceptor; // 排除路径 private static final ListString EXCLUDE_PATHS Arrays.asList( /api/public/**, /static/**, /error, /login, /logout ); Override public void addInterceptors(InterceptorRegistry registry) { // 注册自定义拦截器 registry.addInterceptor(customInterceptor) .addPathPatterns(/**) // 拦截所有路径 .excludePathPatterns(EXCLUDE_PATHS); // 排除特定路径 // 可以注册多个拦截器按添加顺序执行 registry.addInterceptor(new LoggingInterceptor()) .addPathPatterns(/api/**) .order(1); // 设置执行顺序数字越小优先级越高 } } /** * 另一个日志拦截器示例 */ class LoggingInterceptor implements HandlerInterceptor { Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) { System.out.println(【日志拦截器】请求路径: request.getRequestURI()); return true; } }过滤器 (Filter) 实现案例过滤器 (Filter) 依赖于servlet容器。在实现上基于函数回调它可以对几乎所有请求进行过滤但是缺点是一个过滤器实例只能在容器初始化时调用一次。使用过滤器的目的是用来做一些过滤操作获取我们想要获取的数据。比如在Javaweb中对传入的request、response提前过滤掉一些信息或者提前设置一些参数然后再传入servlet或者Controller进行业务逻辑操作。通常用的场景是在过滤器中修改字符编码CharacterEncodingFilter、在过滤器中修改HttpServletRequest的一些参数XSSFilter(自定义过滤器)。如过滤低俗文字、危险字符等。自定义过滤器实现javaimport org.springframework.core.annotation.Order; import org.springframework.stereotype.Component; import javax.servlet.*;