springboot @RequestBody注解 application/json类型请求参数复用

@RequestBody注解参数的接口以 application/json 作为请求头Content-Type的类型,以输入流的方式读取json类型参数,因为是输入流,所以只能读取一次,在一些项目中,我们可能需要在controller之前使用到请求参数,比如拦截器、过滤器、Aspect,为了满足这些多次获取输入流中参数需求,利用拦截器对request进行改造;

创建一个类ContentCachingRequestWrapper 继承 HttpServletRequestWrapper
包括一个内部类RequestCachingInputStream 继承 ServletInputStream

构造参数为HttpServletRequest 的构造方法
将输入流中数据缓存到ByteArrayInputStream中,可以重复读取

import org.apache.commons.io.IOUtils;

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;

public class ContentCachingRequestWrapper extends HttpServletRequestWrapper{

    private byte[] body;

    private BufferedReader reader;

    private ServletInputStream inputStream;

    public ContentCachingRequestWrapper(HttpServletRequest request) throws IOException{
        super(request);
        loadBody(request);
    }

    private void loadBody(HttpServletRequest request) throws IOException{
        body = IOUtils.toByteArray(request.getInputStream());
        inputStream = new RequestCachingInputStream(body);
    }


    public byte[] getBody() {
        return body;
    }

    public void setBody(byte[] body){
        this.body=body;
        inputStream = new RequestCachingInputStream(body);
    }

    @Override
    public ServletInputStream getInputStream() throws IOException {
        if (inputStream != null) {
ServletInputStream tmp = this.inputStream;
            this.inputStream = new RequestCachingInputStream(body);
            return tmp;
            return inputStream;
        }
        return super.getInputStream();
    }

    @Override
    public BufferedReader getReader() throws IOException {
        if (reader == null) {
            reader = new BufferedReader(new InputStreamReader(inputStream, getCharacterEncoding()));
        }
        return reader;
    }

    private static class RequestCachingInputStream extends ServletInputStream {

        private final ByteArrayInputStream inputStream;

        public RequestCachingInputStream(byte[] bytes) {
            inputStream = new ByteArrayInputStream(bytes);
        }
        @Override
        public int read() throws IOException {
            return inputStream.read();
        }

        @Override
        public boolean isFinished() {
            return inputStream.available() == 0;
        }

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

        @Override
        public void setReadListener(ReadListener readlistener) {
        }

    }

}

创建过滤器配置类

import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.filter.CharacterEncodingFilter;
import sjy.notion.notion.app.filter.ValidateFilter;

import javax.servlet.DispatcherType;

/**
 * @author zhang
 * @date 2019/3/29 上午12:01
 */
@Configuration
public class FilterConfig {

    @Bean
    public FilterRegistrationBean validateFilterRegistration() {
        FilterRegistrationBean registration = new FilterRegistrationBean();
        registration.setDispatcherTypes(DispatcherType.REQUEST);
        registration.setFilter(new ValidateFilter());
        registration.addUrlPatterns("/*");
        registration.setName("validateFilter");
        registration.setOrder(Integer.MAX_VALUE);
        return registration;
    }
}

创建过滤器过滤request

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;

public class ValidateFilter implements Filter {

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

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        ContentCachingRequestWrapper requestWrapper = new ContentCachingRequestWrapper((HttpServletRequest) request);
        chain.doFilter(requestWrapper, response);
    }
     
}

request.getInputStream() 就可以重复获取数据

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容