在java中拦截网络请求数据的核心方法是使用spring框架的handlerinterceptor,它允许在请求处理的不同阶段插入自定义逻辑。1. prehandle方法用于在请求处理前进行权限校验或过滤;2. posthandle方法用于处理完成后、视图渲染前的数据修改;3. aftercompletion方法用于资源清理和异常记录。此外,还可通过servlet filter实现更底层的拦截,或使用aop对方法调用进行细粒度控制。这些机制共同解决了权限控制、日志记录、性能监控、数据清洗、安全防护等横切关注点的问题,使业务代码更简洁清晰。

在Java里拦截网络请求数据,说白了,就是要在请求抵达目标处理逻辑(比如一个控制器方法)之前或者之后,插入我们自己的代码逻辑。这通常是通过一种“中间件”或者“切面”的机制来实现的,它允许你在请求处理的生命周期中设置一些“卡点”,做一些额外的处理,比如权限校验、日志记录、性能监控或者数据转换。这并非什么高深莫测的技术,更多的是一种架构设计上的考量。

要在Java中实现网络请求数据的拦截,尤其是在Web应用背景下,Spring框架的HandlerInterceptor是一个非常优雅且实用的选择。它提供了一套钩子,让你能在请求处理的不同阶段介入。
我们可以定义一个自定义的拦截器,实现HandlerInterceptor接口,并重写其中的方法:
立即学习“Java免费学习笔记(深入)”;

preHandle(HttpServletRequest request, HttpServletResponse response, Object handler): 在请求被处理前调用。如果你返回false,请求链就会中断,后续的拦截器和处理器方法都不会执行。这非常适合做权限校验、黑名单过滤等。postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView): 在请求被处理后,视图渲染之前调用。你可以在这里修改ModelAndView,或者对响应进行一些通用处理。afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex): 在整个请求处理完成后,视图也渲染完毕之后调用。通常用于资源清理,比如关闭数据库连接、记录异常日志等,即使处理器抛出异常也会执行。下面是一个简单的HandlerInterceptor实现示例:
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class MyRequestInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
long startTime = System.currentTimeMillis();
request.setAttribute("startTime", startTime); // 记录请求开始时间
System.out.println("请求进入拦截器: " + request.getRequestURI());
// 假设这里做个简单的权限判断
String userToken = request.getHeader("X-Auth-Token");
if (userToken == null || !userToken.equals("valid-token")) {
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); // 401 未授权
response.getWriter().write("Unauthorized access!");
return false; // 阻止请求继续
}
return true; // 继续执行后续拦截器和处理器
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("请求处理完成,视图渲染前: " + request.getRequestURI());
// 可以在这里对返回的ModelAndView做一些修改
if (modelAndView != null) {
modelAndView.addObject("appName", "MyWebApp");
}
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
long startTime = (Long) request.getAttribute("startTime");
long endTime = System.currentTimeMillis();
long executeTime = endTime - startTime;
System.out.println("请求处理结束,总耗时: " + executeTime + "ms for " + request.getRequestURI());
if (ex != null) {
System.err.println("请求处理中发生异常: " + ex.getMessage());
}
}
}接着,你需要将这个拦截器注册到Spring MVC的配置中。通常是在实现WebMvcConfigurer接口的配置类里:

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new MyRequestInterceptor())
.addPathPatterns("/**") // 拦截所有路径
.excludePathPatterns("/public/**"); // 排除某些路径
}
}这样,每次有请求进来,MyRequestInterceptor就会按照定义的规则介入处理。
在我看来,拦截网络请求这事儿,核心目的就是为了实现“非侵入性”的通用逻辑处理。你想啊,如果每个控制器方法、每个业务逻辑里都要写一遍权限校验、日志记录、性能统计的代码,那简直是灾难。代码会变得臃肿不堪,维护起来更是噩梦。
它能解决的痛点简直不要太多:
preHandle里一判断,没权限直接返回401,根本不用走到后面的业务逻辑,效率高,也安全。preHandle记录请求信息,在afterCompletion记录响应和耗时,完美。preHandle和afterCompletion之间计算时间差就能搞定。@ControllerAdvice,但拦截器也能捕获到请求处理过程中的异常,进行统一的记录或响应。说白了,拦截器就是把那些与核心业务逻辑无关但又必不可少的“横切关注点”剥离出来,集中管理,让我们的业务代码更聚焦,更干净。
当然,Spring的HandlerInterceptor虽然好用,但它毕竟是Spring体系下的产物。如果你的项目没有使用Spring,或者你需要更底层、更通用的拦截机制,Java本身也提供了几种方式:
1. Servlet Filter (过滤器)
这是Java Web应用中最基础、最原生的拦截机制。Servlet Filter在请求进入Servlet容器(比如Tomcat)后,但在请求到达任何Servlet(包括Spring MVC的DispatcherServlet)之前就会被执行。它工作在Web应用的更高层面,可以对所有的HTTP请求和响应进行操作。
实现Filter接口,并重写doFilter方法:
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebFilter(urlPatterns = "/*") // 拦截所有路径
public class MyBasicFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("MyBasicFilter 初始化...");
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletRequest httpRequest = (HttpServletRequest) request;
HttpServletResponse httpResponse = (HttpServletResponse) response;
System.out.println("Filter 拦截到请求: " + httpRequest.getRequestURI());
// 在这里可以对请求进行预处理,比如修改请求头、参数等
// 如果不调用chain.doFilter,请求就会在这里被中断
// 比如,一个简单的IP黑名单
String clientIp = httpRequest.getRemoteAddr();
if ("127.0.0.1".equals(clientIp)) { // 假设127.0.0.1是黑名单
httpResponse.setStatus(HttpServletResponse.SC_FORBIDDEN); // 403 禁止
httpResponse.getWriter().write("Access Forbidden for your IP!");
return; // 阻止请求继续
}
chain.doFilter(request, response); // 将请求传递给下一个过滤器或目标资源
// 请求处理完成后,可以在这里对响应进行后处理
System.out.println("Filter 处理完成响应: " + httpRequest.getRequestURI());
// 比如,添加一个自定义响应头
httpResponse.setHeader("X-Processed-By", "MyBasicFilter");
}
@Override
public void destroy() {
System.out.println("MyBasicFilter 销毁...");
}
}Filter的优势在于其通用性,不依赖于任何框架,可以在任何Servlet容器中运行。但它的缺点也很明显,它对Spring等框架内部的组件(如Controller、Service)一无所知,无法直接操作Spring的上下文,也无法像HandlerInterceptor那样细粒度地控制到方法级别。
2. Aspect-Oriented Programming (AOP)
AOP是一种编程范式,它允许开发者定义“横切关注点”,并将其模块化。在Java中,Spring AOP和AspectJ是两种主要的AOP实现。虽然它们通常用于拦截方法调用,但也可以间接用于“拦截”请求。例如,你可以在一个Controller方法执行前后插入逻辑。
AOP的优点是它更关注于“在何时何地执行某个逻辑”,而不是“请求的生命周期”。它能够精确地在方法执行前、执行后、抛出异常后等时机插入代码,粒度更细。缺点是它通常作用于应用程序内部的方法调用,而不是直接作用于HTTP请求本身。
例如,一个简单的Spring AOP切面:
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
@Aspect
@Component
public class MyControllerAspect {
// 定义一个切入点,匹配所有在com.example.controller包下的方法
@Pointcut("execution(* com.example.controller.*.*(..))")
public void controllerMethods() {}
@Around("controllerMethods()")
public Object logAndMonitor(ProceedingJoinPoint joinPoint) throws Throwable {
long startTime = System.currentTimeMillis();
String methodName = joinPoint.getSignature().getName();
System.out.println("AOP: 方法 " + methodName + " 开始执行...");
Object result = null;
try {
result = joinPoint.proceed(); // 执行目标方法
System.out.println("AOP: 方法 " + methodName + " 执行成功。");
} catch (Throwable e) {
System.err.println("AOP: 方法 " + methodName + " 执行异常: " + e.getMessage());
throw e; // 重新抛出异常
} finally {
long endTime = System.currentTimeMillis();
System.out.println("AOP: 方法 " + methodName + " 执行耗时: " + (endTime - startTime) + "ms");
}
return result;
}
}AOP和HandlerInterceptor在某些功能上有所重叠(比如日志和性能监控),但它们作用的层面不同。HandlerInterceptor作用于HTTP请求的生命周期,而AOP作用于方法调用的生命周期。在实际项目中,它们经常被结合使用,互为补充。
选择哪种拦截机制,很大程度上取决于你的项目架构、所使用的框架以及具体的需求。Spring项目通常首选HandlerInterceptor,而对于更底层或非Spring的Web应用,Servlet Filter则是不二之选。AOP则在需要对方法级别进行精细控制时显得尤为强大。
以上就是如何在Java中拦截网络请求数据 Java实现中间件拦截机制的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号