spring boot对json 输入流数据拦截分析处理

来源:互联网 发布:足球比赛 编排软件 编辑:程序博客网 时间:2024/06/07 19:31

 之前突发奇想通过过滤器和拦截器把前端的请求数据拦截下来然后做些验证和过滤再到contrlller层做业务逻辑,就尝试着把请求中的json(到了httprequest类里是 输入流数据),拦截下来验证,but有个问题,就是spring boot  httprequest 的getInputStream调用一次获取输入流后就再次调用就会获取为空。so搞了几天,现在分享下解决方案。

一: 配置

spring boot  简化了原本spring mvc 的xml配置,配置上简易了很多。下面简略的阐述下步骤

配置拦截器    @Configuration  表示这个是一个配置类  继承WebMvcConfigurerAdapter 并重写addInterceptors 方法就可以实现拦截器配置


@Configurationpublic class InterceptorConfigurer extends WebMvcConfigurerAdapter {@Overridepublic void addInterceptors(InterceptorRegistry registry) {// 多个拦截器组成一个拦截器链// addPathPatterns 用于添加拦截规则// excludePathPatterns 用户排除拦截// 验证字符registry.addInterceptor(new SpecialCharacterInterceptor()).addPathPatterns("/api/**").excludePathPatterns("/api/sendToOneNormal")// Im发送.excludePathPatterns("/api/sendToGroupNormal");// Im发送// 验证sql注入registry.addInterceptor(new SQLInjectionInterceptor()).addPathPatterns("/api/**").excludePathPatterns("/api/saveFormAttr")// 表单设计保存.excludePathPatterns("/api/sendToOneNormal")// Im发送.excludePathPatterns("/api/sendToGroupNormal");// Im发送// registry.addInterceptor(new MyInterceptor2()).addPathPatterns("/**");super.addInterceptors(registry);}}

过滤器配置

@Configurationpublic class FilterConfiguration {/** * 配置过滤器 * @return */@Beanpublic FilterRegistrationBean someFilterRegistration() {FilterRegistrationBean registration = new FilterRegistrationBean();registration.setFilter(SealFilter());registration.addUrlPatterns("/*");registration.addInitParameter("paramName", "paramValue");registration.setName("SealFilter");return registration;}/** * 创建一个bean * @return */@Bean(name = "SealFilter")public Filter SealFilter() {return new SealFilter();}}

二  过滤器实现重新封装 输入流

@Overridepublic void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)throws IOException, ServletException {// TODO Auto-generated method stubServletRequest requestWrapper = null;    if(request instanceof HttpServletRequest) { //判断是否是http请求 requestWrapper = new MAPIHttpServletRequestWrapper((HttpServletRequest) request); //再封装request}    if(requestWrapper == null) {    chain.doFilter(request, response);    } else {    chain.doFilter(requestWrapper, response);    }}

public class MAPIHttpServletRequestWrapper extends HttpServletRequestWrapper {private final byte[] body; // 报文final static int BUFFER_SIZE = 4096;public MAPIHttpServletRequestWrapper(HttpServletRequest request) throws IOException {super(request);body = InputStreamTOByte(request.getInputStream()); //读取输入流} @Overridepublic BufferedReader getReader() throws IOException {return new BufferedReader(new InputStreamReader(getInputStream()));}@Overridepublic ServletInputStream getInputStream() throws IOException {final ByteArrayInputStream bais = new ByteArrayInputStream(body); //再封装数据return new ServletInputStream() {@Overridepublic int read() throws IOException {return bais.read();}@Overridepublic boolean isFinished() {// TODO Auto-generated method stubreturn false;}@Overridepublic boolean isReady() {// TODO Auto-generated method stubreturn false;}@Overridepublic void setReadListener(ReadListener readListener) { //在这里配置读取监听  可以使用这个方法限制读取次数// TODO Auto-generated method stub}};} public static byte[] InputStreamTOByte(InputStream in) throws IOException {ByteArrayOutputStream outStream = new ByteArrayOutputStream();byte[] data = new byte[BUFFER_SIZE];int count = -1;while ((count = in.read(data, 0, BUFFER_SIZE)) != -1)outStream.write(data, 0, count);data = null;return outStream.toByteArray();}}

通过重写HttpServletRequestWrapper以及过滤器,再封装数据便于拦截器读取数据进行处理,从而规避了HttpServletRequestWrapper的输入流只能读取一次的问题。

原创粉丝点击