栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Request中getInputStream和getReader无法重复读流/HandlerMethod对象无法获取body数据解决方案

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Request中getInputStream和getReader无法重复读流/HandlerMethod对象无法获取body数据解决方案

前言: 在使用自定义注解获取接口中形参中的参数或者实体类对象数据的时候,需要用到拦截器去拦截每次请求,但在拦截器使用getInputStream()或者getReader()方法后会导致后面的执行无法获取到数据(也就是使用@RequestBody注解),这是因为这两个方法只能读一次数据流之后会失效,本人亲测在HandlerMethod对象中能获取到方法入参参数,但无法获取到实体类数据,整了有点时间查询相关文章解决后分享

新建Demo项目 引入Maven依赖

        org.springframework.boot
        spring-boot-starter-parent
        2.2.5.RELEASE
         
    
    
        UTF-8
        UTF-8
        1.8
        
        true
    

    
        
        
            org.springframework.boot
            spring-boot-starter
        
        
            org.springframework.boot
            spring-boot-starter-web
        
        
            org.springframework.boot
            spring-boot-starter-test
        
        
        
            org.apache.commons
            commons-lang3
            3.5
        
        
            commons-io
            commons-io
            2.5
        
    
引入SpringBoot启动类
@SpringBootApplication
public class RequestStreamApplication {

    public static void main(String[] args) {
        SpringApplication.run(RequestStreamApplication.class);
    }
}
创建实体类和Controller类
public class Student {

    private int id;

    private String name;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "Student{" +
                "id=" + id +
                ", name='" + name + ''' +
                '}';
    }
}
@RestController
public class RequestStreamController {

    private static final Logger log = LoggerFactory.getLogger(RequestStreamController.class);

    @PostMapping(value = "/requestDemo")
    @Permission
    public String requestDemo(@RequestBody Student student){
        log.info(student.toString());
        return student.toString();
    }
}

创建自定义注解类
@Target({ElementType.METHOD,ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface Permission {

    boolean isOpen() default true;
}

配置文件
server:
  port: 8085
  servlet:
    context-path: /requestStream
创建自定义RequestWrapper装饰类
import javax.servlet.ReadListener;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.io.*;

public class RequestWrapper extends HttpServletRequestWrapper {

    
    private byte[] requestBody;

    
    private HttpServletRequest request;

    
    public RequestWrapper(HttpServletRequest request) {
        super(request);
        this.request = request;
    }

    
    @Override
    public ServletInputStream getInputStream() throws IOException {
        if(null == requestBody){
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            IOUtils.copy(request.getInputStream(),baos);
            
            this.requestBody = baos.toByteArray();
        }

        
        final ByteArrayInputStream bais = new ByteArrayInputStream(requestBody);
        return new ServletInputStream() {
            @Override
            public boolean isFinished() {
                return false;
            }

            @Override
            public boolean isReady() {
                return false;
            }

            @Override
            public void setReadListener(ReadListener readListener) {

            }

            @Override
            public int read() throws IOException {
                return bais.read();
            }
        };
    }

    
    @Override
    public BufferedReader getReader() throws IOException {
        return new BufferedReader(new InputStreamReader(this.getInputStream()));
    }
}
创建自定义过滤器
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;


@Component
@WebFilter(filterName = "channelFilter",urlPatterns = {"
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        try {
            ServletRequest requestWrapper = null;
            
            if(request instanceof HttpServletRequest){
                requestWrapper = new RequestWrapper((HttpServletRequest) request);
            }

            
            if (null == requestWrapper) {
                chain.doFilter(request, response);
            } else {
                chain.doFilter(requestWrapper, response);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ServletException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void destroy() {
        
    }
}

创建自定义拦截器

说明:这里是利用@Permission注解判断,如果学生名为alice则被拦截无法进入接口,否则就放行

import com.fasterxml.jackson.databind.ObjectMapper;
import org.example.edward.annotation.Permission;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedReader;
import java.util.HashMap;
import java.util.Map;


@Component
public class MyInterceptor implements HandlerInterceptor {

    private static final Logger log = LoggerFactory.getLogger(MyInterceptor.class);

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        if(handler instanceof HandlerMethod){
            
            HandlerMethod handlerMethod = (HandlerMethod) handler;
            
            boolean isAnnotation = handlerMethod.hasMethodAnnotation(Permission.class);
            if(isAnnotation){
                Permission perm = handlerMethod.getMethodAnnotation(Permission.class);
                boolean open = perm.isOpen();
                if(open){
                    BufferedReader reader = request.getReader();
                    String str = "";
                    StringBuilder stringBuilder = new StringBuilder();
                    
                    while((str = reader.readLine())!= null){
                        stringBuilder.append(str);
                    }

                    
                    ObjectMapper objectMapper = new ObjectMapper();
                    Map map = objectMapper.readValue(stringBuilder.toString(), Map.class);
                    if("alice".equals(map.get("name"))){
                        response.setContentType("application/json;charset=utf-8");
                        HashMap returnMap = new HashMap<>();
                        returnMap.put("message","学生名为alice被拦截");
                        String value = objectMapper.writeValueAsString(returnMap);
                        
                        response.getWriter().print(value);
                        
                        return false;
                    }
                }
            }
        }
        return true;
    }
}
创建WebMvc配置类,用于添加自定义拦截器

说明:这里实现WebMvcConfigurer或继承WebMvcConfigurationSupport,两种只能选择其中一种,同时配置会导致其中一个失效

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 WebAppConfigurer implements WebMvcConfigurer {

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        
        registry.addInterceptor(new MyInterceptor()).addPathPatterns("/**");
    }
}
测试结果

这里字段名为name的alice被拦截了

字段名为name的edward不会拦截

参考文章:https://blog.csdn.net/qq_33548675/article/details/121015317

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/843214.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号