springboot 获取body内数据并赋值给servlet, 同时保留body数据

在此我们通过过滤器来完成本功能

@WebFilter(filterName = "RequestBodyFilter", urlPatterns = "/**")
public class RequestBodyFilter implements Filter {
    public static final String LOGTHREAD_ID="logthreadId";
    private static final Logger LOGGER = LoggerFactory.getLogger(RequestBodyFilter.class);

    public static final String URI_ENCODING = NsConfiguration.getInstance()
            .getConf(NsConfiguration.KEY_URI_ENCODING);

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        //日志打印唯一标识
        MDC.put(LOGTHREAD_ID,java.util.UUID.randomUUID().toString().replace("-",""));

        HttpServletRequest request = (HttpServletRequest) servletRequest;
        HttpServletResponse response = (HttpServletResponse) servletResponse;
        request.setCharacterEncoding("UTF-8");
        //获取body数据
        BufferedReader reader = new BufferedReader(new InputStreamReader(request.getInputStream()));
        String line = null;
        StringBuilder sb = new StringBuilder();
        while((line = reader.readLine())!=null){
            sb.append(line);
        }
        String postContent = sb.toString();

        //如果body中存在数据放入HttpServletRequest
        if (!RequestBodyFilter.isEmpty(postContent) ){
            request = new ParameterRequestWrapper(request);
            LOGGER.debug(postContent);
            String[] params = postContent.split("&");
            for (String param : params) {
                String[] pkv = param.split("=");
                String data = URLDecoder.decode(pkv[1], URI_ENCODING);
                ((ParameterRequestWrapper)request).addParameter(pkv[0],data);
            }
        }
        filterChain.doFilter(request,response);

    }

    @Override
    public void destroy() {

    }

    public static boolean isEmpty(Object str) {
        return str == null || "".equals(str) || "{}".equals(str);
    }
}

@WebFilter 

filterName String 指定过滤器的 name 属性,等价于
value String[] 该属性等价于 urlPatterns 属性。但是两者不应该同时使用。
urlPatterns String[] 指定一组过滤器的 URL 匹配模式。等价于 标签。

ParameterRequestWrapper类  : 重构

public class ParameterRequestWrapper extends HttpServletRequestWrapper {

    private Map params = new HashMap();

    @SuppressWarnings("unchecked")
    public ParameterRequestWrapper(HttpServletRequest request) {
        // 将request交给父类,以便于调用对应方法的时候,将其输出,其实父亲类的实现方式和第一种new的方式类似
        super(request);
        //将参数表,赋予给当前的Map以便于持有request中的参数
        this.params.putAll(request.getParameterMap());
    }

    @Override
    public String getParameter(String name) {//重写getParameter,代表参数从当前类中的map获取
        String[]values = params.get(name);
        if(values == null || values.length == 0) {
            return null;
        }
        return values[0];
    }

    public String[] getParameterValues(String name) {//同上
        return params.get(name);
    }

    public void addAllParameters(MapotherParams) {//增加多个参数
        for(Map.Entryentry : otherParams.entrySet()) {
            addParameter(entry.getKey() , entry.getValue());
        }
    }

    public void addParameter(String name , Object value) {//增加参数
        if(value != null) {
            if(value instanceof String[]) {
                params.put(name , (String[])value);
            }else if(value instanceof String) {
                params.put(name , new String[] {(String)value});
            }else {
                params.put(name , new String[] {String.valueOf(value)});
            }
        }
    }
}

在springboot中配置过滤器:可以直接在启动类中添加以下代码

        @Bean
	public FilterRegistrationBean someFilterRegistration() {
		FilterRegistrationBean registration = new FilterRegistrationBean(new RequestBodyFilter());
		registration.addUrlPatterns("/*");
		//registration.addInitParameter("paramName", "paramValue");
		registration.setName("requestBodyFilter");
		return registration;
	}

也可以创建被@configuration注解的类中


由于body只能被读取一次,也就是说,在本次读取后,下面就不能对body进行操作了,为了解决该问题,对

HttpServletRequestWrapper重写  
import com.bailian.middleware.util.HttpHelper; 

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.Charset;

public class BodyRequestWrapper extends HttpServletRequestWrapper {

    private byte[] body;

    public BodyRequestWrapper(HttpServletRequest request) throws IOException {
        super(request);
        body = HttpHelper.getBodyString(request).getBytes(Charset.forName("UTF-8"));
    }

    @Override
    public BufferedReader getReader() throws IOException {
        return new BufferedReader(new InputStreamReader(getInputStream()));
    }

    @Override
    public ServletInputStream getInputStream() throws IOException {

        final ByteArrayInputStream bais = new ByteArrayInputStream(body);

        return new ServletInputStream() {

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

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

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

            @Override
            public void setReadListener(ReadListener readListener) {

            }

        };
    }

    public void setInputStream(byte[] body) {
        this.body = body;
    }
}
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.servlet.ServletRequest;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.charset.Charset;


public class HttpHelper {

    private static final Logger LOGGER = LoggerFactory.getLogger(HttpHelper.class);
    /**
     * 获取请求Body
     * @param request
     * @return
     */
    public static String getBodyString(ServletRequest request) {
        StringBuilder sb = new StringBuilder();
        InputStream inputStream = null;
        BufferedReader reader = null;
        try {
            inputStream = request.getInputStream();
            reader = new BufferedReader(new InputStreamReader(inputStream, Charset.forName("UTF-8")));
            String line = "";
            while ((line = reader.readLine()) != null) {
                sb.append(line);
            }
        } catch (IOException e) {
            LOGGER.error(e.getMessage(),e);
        } finally {
            if (inputStream != null) {
                try {
                    inputStream.close();
                } catch (IOException e) {
                    LOGGER.error(e.getMessage(),e);
                }
            }
            if (reader != null) {
                try {
                    reader.close();
                } catch (IOException e) {
                    LOGGER.error(e.getMessage(),e);
                }
            }
        }
        return sb.toString();
    }

}

使用方式   new BodyRequestWrapper(request);通过创建对象获取servlet



你可能感兴趣的:(SpringBoot,遇到问题)