springboot过滤器、拦截器相关知识
request.getParameterNames()不会消耗HTTP请求的输入流。
当处理application/json或multipart/form-data(特别是包含文件上传时)等类型的请求体时,这些内容通常不会通过getParameter或getParameterNames等方法直接访问,因为这些方法主要用于处理URL编码的表单数据。需要通过getInputStream()或getReader()等方法来读取整个请求体,并将其解析为相应的数据结构(如JSON对象或MultipartFile列表)。调用getInputStream()、getReader()等来读取请求体时,读取后会被关闭或消耗,意味着你不能在同一个请求中再次调用这些方法(除非你使用了某种形式的缓存或包装机制)。
getParameterNames()和getParameter()等方法访问的是请求参数,而不是请求体本身,因此它们不会消耗请求体。
HTTP请求体在Servlet容器中通常只能被读取一次,因为ServletInputStream和BufferedReader(后者通常是通过HttpServletRequest.getReader()获得的)在读取数据后不会将读取位置重置回开始。这意味着一旦你读取了请求体,你就无法在同一个请求中再次读取它,除非你在第一次读取时就已经将内容存储起来(比如复制到一个字节数组或字符流中)。
示例:在拦截器中读取Json参数
Java配置文件
java
@Configuration
public class CustomWebMvcConfig implements WebMvcConfigurer {
@Autowired
private CustomInterceptor customInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(customInterceptor)
.addPathPatterns("/**"); // 拦截所有请求,或根据需要调整
}
@Bean
public FilterRegistrationBean<FormDataToJsonFilter> formDataToJsonFilter() {
FilterRegistrationBean<FormDataToJsonFilter> registrationBean = new FilterRegistrationBean<>();
registrationBean.setFilter(new FormDataToJsonFilter());
registrationBean.addUrlPatterns("/*"); // 拦截所有请求
return registrationBean;
}
}
过滤器
java
public class FormDataToJsonFilter implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;
ServletRequest requestWrapper = new JsonParamRequestWrapper(httpServletRequest);
filterChain.doFilter(requestWrapper, servletResponse);//
}
}
自定义的HttpServletRequestWrapper
这个包装类将允许读取请求体,并且不会阻止其他组件(如Controller)再次读取它。
java
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;
public class JsonParamRequestWrapper extends HttpServletRequestWrapper {
private final String body;
public JsonParamRequestWrapper (HttpServletRequest request) throws IOException {
super(request);
StringBuilder stringBuilder = new StringBuilder();
BufferedReader bufferedReader = null;
try {
InputStream inputStream = request.getInputStream();
if (inputStream != null) {
bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
char[] charBuffer = new char[128];
int bytesRead = -1;
while ((bytesRead = bufferedReader.read(charBuffer)) > 0) {
stringBuilder.append(charBuffer, 0, bytesRead);
}
}
} finally {
if (bufferedReader != null) {
bufferedReader.close();
}
}
body = stringBuilder.toString();
}
@Override
public BufferedReader getReader() throws IOException {
return new BufferedReader(new InputStreamReader(new ByteArrayInputStream(body.getBytes())));
}
@Override
public ServletInputStream getInputStream() throws IOException {
final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(body.getBytes());
return new ServletInputStream() {
@Override
public boolean isFinished() {
return byteArrayInputStream.available() == 0;
}
@Override
public boolean isReady() {
return true;
}
@Override
public int read() throws IOException {
return byteArrayInputStream.read();
}
};
}
// Getter for the body (if needed)
public String getBody() {
return this.body;
}
}
拦截器
java
@Component
public class CustomInterceptor implements HandlerInterceptor {
private final RestTemplate restTemplate = new RestTemplate();
private final ObjectMapper objectMapper = new ObjectMapper();
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
if ("POST".equalsIgnoreCase(request.getMethod())) {
JsonParamRequestWrapper requestWrapper = new JsonParamRequestWrapper(request);
String body = requestWrapper.getRequestBody();
logger.info("请求体:" + body);
String sign = "";
String data = "";
// 进行验签逻辑
boolean isValid = verifySignature(sign, data);
if (!isValid) {
response.setStatus(HttpServletResponse.SC_FORBIDDEN);
return false;
}
}
// 继续执行下一个拦截器或目标处理器
return true;
}
// 验签方法
private boolean validateSignature(String body) {
// 验签逻辑
return true;
}
}