spring boot mvc 使用filter修改入参数据
用户问的是在 Spring Boot MVC 中使用 Filter 来修改入参数据。首先,我需要回忆一下 Spring Boot 中 Filter 的基本用法。Filter 是 Java Servlet 规范中的组件,可以在请求到达 Servlet 之前或之后处理请求和响应。用户想修改入参数据,也就是请求中的参数,比如请求体或者查询参数。
首先,需要考虑的是,HttpServletRequest 中的参数是不可变的,直接修改原生的 request 对象可能不行。这时候可能需要创建一个自定义的 HttpServletRequestWrapper,继承 HttpServletRequestWrapper,重写 getParameter、getParameterMap、getParameterValues 等方法,来包装原始的 request,提供修改后的参数。
接下来,创建 Filter 类,实现 Filter 接口,重写 doFilter 方法。在 doFilter 中,获取原始的 request,包装成自定义的 wrapper,然后将 wrapper 传递给 chain.doFilter 方法,这样后续的处理器就能拿到修改后的参数。
然后,需要注册这个 Filter。在 Spring Boot 中,可以通过 @WebFilter 注解或者编写 FilterRegistrationBean 来注册 Filter,指定过滤的 URL 模式。
另外,用户可能需要修改的是请求体中的数据,比如 JSON 参数,这时候需要注意,HttpServletRequest 的输入流只能读取一次,包装类需要缓存输入流的数据,以便后续的处理器还能读取。这时候可能需要重写 getInputStream 和 getReader 方法,使用缓冲区来保存数据,修改后再提供给后续处理。
还要考虑线程安全的问题,不过 Filter 通常是单例的,所以在 wrapper 中避免使用成员变量来保存请求数据,除非是线程安全的方式。
然后,举个例子,比如修改某个参数的值,或者添加新的参数。在 wrapper 中重写 getParameter 方法,当参数是需要修改的 key 时,返回新的值,其他情况返回原始值。对于参数 Map,可能需要复制一份原始的 map,修改后返回,避免修改原始不可变的 map。
另外,需要注意,Spring MVC 在处理参数时,可能会在 Filter 之后,比如在 Controller 处理之前,所以确保 Filter 在正确的顺序执行,比如在 DispatcherServlet 之前执行。
总结步骤:创建自定义的 RequestWrapper,重写参数相关的方法;创建 Filter,使用 wrapper 包装 request;注册 Filter;测试效果。同时,处理请求体时需要处理输入流的读取问题,可能需要使用 IOUtils 来读取并缓存输入流数据,修改后再提供。
在 Spring Boot MVC 中使用 Filter 修改入参数据,需要通过自定义
HttpServletRequestWrapper 来包装原始请求,并在 Filter 中替换请求对象。以下是详细步骤:一、创建自定义 RequestWrapper(修改参数)
由于原生
HttpServletRequest 的参数不可直接修改,需通过包装类重写参数相关方法。1. 普通参数(Query Param 或 Form Data)
java
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
public class ParameterModifyRequestWrapper extends HttpServletRequestWrapper {
private final Map<String, String[]> parameterMap = new HashMap<>();
public ParameterModifyRequestWrapper(HttpServletRequest request) {
super(request);
// 复制原始参数
request.getParameterMap().forEach((key, values) -> {
parameterMap.put(key, values.clone());
});
}
// 修改单个参数
public void modifyParameter(String paramName, String newParamValue) {
parameterMap.put(paramName, new String[]{newParamValue});
}
// 添加新参数(若参数不存在)
public void addParameter(String paramName, String paramValue) {
if (!parameterMap.containsKey(paramName)) {
parameterMap.put(paramName, new String[]{paramValue});
}
}
@Override
public String getParameter(String name) {
String[] values = parameterMap.get(name);
return values != null && values.length > 0 ? values[0] : null;
}
@Override
public Map<String, String[]> getParameterMap() {
return new HashMap<>(parameterMap); // 返回不可变副本(按需处理)
}
@Override
public String[] getParameterValues(String name) {
return parameterMap.getOrDefault(name, new String[0]);
}
}
二、处理请求体(JSON/XML 等)
若需修改请求体(如 JSON 数据),需额外重写
getInputStream() 和 getReader(),因为请求体流只能读取一次:java
import javax.servlet.ReadListener;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
public class BodyModifyRequestWrapper extends HttpServletRequestWrapper {
private final byte[] body;
public BodyModifyRequestWrapper(HttpServletRequest request, String modifiedBody) {
super(request);
body = modifiedBody.getBytes(StandardCharsets.UTF_8);
}
@Override
public ServletInputStream getInputStream() throws IOException {
final ByteArrayInputStream bis = new ByteArrayInputStream(body);
return new ServletInputStream() {
@Override
public int read() throws IOException {
return bis.read();
}
@Override
public boolean isFinished() {
return false;
}
@Override
public boolean isReady() {
return false;
}
@Override
public void setReadListener(ReadListener readListener) {
}
};
}
@Override
public BufferedReader getReader() throws IOException {
return new BufferedReader(new InputStreamReader(getInputStream()));
}
@Override
public int getContentLength() {
return body.length;
}
@Override
public long getContentLengthLong() {
return body.length;
}
@Override
public String getContentType() {
return "application/json"; // 根据实际情况设置
}
}
三、创建 Filter 并修改参数
java
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
@WebFilter(urlPatterns = "/*", filterName = "parameterModifyFilter")
public class ParameterModifyFilter implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
// 处理普通参数(Query Param/Form Data)
if (request instanceof HttpServletRequest) {
HttpServletRequest httpRequest = (HttpServletRequest) request;
ParameterModifyRequestWrapper wrapper = new ParameterModifyRequestWrapper(httpRequest);
// 修改参数示例:将参数 "name" 的值改为 "newName"
if (wrapper.getParameter("name") != null) {
wrapper.modifyParameter("name", "newName");
}
// 添加新参数示例
wrapper.addParameter("filterAddedParam", "value");
// 传递包装后的请求
chain.doFilter(wrapper, response);
} else {
chain.doFilter(request, response);
}
}
// 可选:处理请求体(需先读取原始 body)
private String modifyRequestBody(HttpServletRequest request) throws IOException {
// 读取原始 body
StringBuilder body = new StringBuilder();
BufferedReader reader = request.getReader();
String line;
while ((line = reader.readLine()) != null) {
body.append(line);
}
// 修改 body(例如 JSON 数据)
String modifiedBody = body.toString().replace("oldValue", "newValue");
return modifiedBody;
}
}
四、注册 Filter(非 @WebFilter 方式)
若不使用
@WebFilter 注解,可通过 FilterRegistrationBean 注册:java
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class FilterConfig {
@Bean
public FilterRegistrationBean<ParameterModifyFilter> parameterModifyFilterRegistration() {
FilterRegistrationBean<ParameterModifyFilter> registration = new FilterRegistrationBean<>();
registration.setFilter(new ParameterModifyFilter());
registration.addUrlPatterns("/*"); // 过滤所有请求
registration.setName("parameterModifyFilter");
registration.setOrder(FilterRegistrationBean.HIGHEST_PRECEDENCE); // 确保 Filter 优先执行
return registration;
}
}
五、注意事项
-
参数修改范围:
- 普通参数(
getParameter):通过ParameterModifyRequestWrapper直接修改。 - 请求体(JSON/XML):需先读取原始内容,修改后通过
BodyModifyRequestWrapper包装输入流。
- 普通参数(
-
线程安全:
Filter是单例,避免在 Filter 中使用成员变量保存请求数据,数据应封装在RequestWrapper中。
-
执行顺序:
- Filter 需在 Spring MVC 处理器(如
DispatcherServlet)之前执行,确保修改后的参数被后续流程处理。
- Filter 需在 Spring MVC 处理器(如
-
与 @RequestBody 配合:
- 若修改 JSON 等请求体,需在 Filter 中提前读取并修改内容,再通过
BodyModifyRequestWrapper提供新的输入流。
- 若修改 JSON 等请求体,需在 Filter 中提前读取并修改内容,再通过
六、测试
在 Controller 中验证参数是否被修改:
java
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class TestController {
@GetMapping("/test")
public String testGet(String name, String filterAddedParam) {
return "name: " + name + ", filterAddedParam: " + filterAddedParam;
}
@PostMapping("/test")
public String testPost(@RequestBody String body) {
return "body: " + body;
}
}
通过以上步骤,Filter 可以在请求到达 Controller 前修改入参数据,包括普通参数和请求体内容。根据实际需求选择合适的
RequestWrapper 实现即可。
摘抄自网络,便于检索查找。

浙公网安备 33010602011771号