springboot过滤器、拦截器相关知识

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; 
    }  
  
}
相关推荐
风象南2 小时前
SpringBoot中6种自定义starter开发方法
java·spring boot·后端
cg501719 小时前
Spring Boot 的配置文件
java·linux·spring boot
橘猫云计算机设计1 天前
基于springboot的考研成绩查询系统(源码+lw+部署文档+讲解),源码可白嫖!
java·spring boot·后端·python·考研·django·毕业设计
有一只柴犬1 天前
深入Spring AI:6大核心概念带你入门AI开发
spring boot·后端
向阳2561 天前
SpringBoot+vue前后端分离整合sa-token(无cookie登录态 & 详细的登录流程)
java·vue.js·spring boot·后端·sa-token·springboot·登录流程
XiaoLeisj1 天前
【MyBatis】深入解析 MyBatis XML 开发:增删改查操作和方法命名规范、@Param 重命名参数、XML 返回自增主键方法
xml·java·数据库·spring boot·sql·intellij-idea·mybatis
风象南1 天前
SpringBoot实现数据库读写分离的3种方案
java·spring boot·后端
CryptoPP1 天前
springboot 对接马来西亚数据源API等多个国家的数据源
spring boot·后端·python·金融·区块链
清风絮柳1 天前
52.个人健康管理系统小程序(基于springboot&vue)
vue.js·spring boot·毕业设计·前后端分离·健康管理系统·个人健康管理系统·个人健康管理小程序
forestsea1 天前
使用 Spring Boot 和 GraalVM 的原生镜像
java·spring boot·spring native·原生映像