继承HttpServletRequestWrapper实现流重复读、参数过滤等场景

背景

项目基于springboot开发,RestFull接口向外暴露的API需要进行签名验证,即在进入真正controller方法前,需要先验证接口请求的有效性,所以需要对提交的POST流进行JSON读,并将相关参数进行验签。如果在Filter中使用request.getInputStream()来获取流来得到body中的信息,可以达到预期效果,但是流的获取只能获取一次,之后再获取就获取不到了,导致controller无法拿到参数而报错。参考相关资料发现实现一个类继承HttpServletRequestWrapper,重写其中的getInputStream方法,让其可以重复获取我们想要的流。

自定义RequestWrapper类

package com.argrace.platform.interceptor;

import com.argrace.platform.exception.VeecloudBizException;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.charset.Charset;
import javax.servlet.ReadListener;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class RequestWrapper extends HttpServletRequestWrapper {
     
   private static final Logger log = LoggerFactory.getLogger(RequestWrapper.class);
   private String mBody;

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

   public static String convertStreamToString(InputStream is) {
     
      BufferedReader reader = new BufferedReader(new InputStreamReader(is));
      StringBuilder sb = new StringBuilder();

      try {
     
         String line;
         try {
     
            while((line = reader.readLine()) != null) {
     
               sb.append(line + "\n");
            }
         } catch (IOException var13) {
     
            log.error("IOException", var13);
         }
      } finally {
     
         try {
     
            is.close();
         } catch (IOException var12) {
     
            log.error("IOException", var12);
         }

      }

      return sb.toString();
   }

   private String getBody(HttpServletRequest request) {
     
      try {
     
         return convertStreamToString(request.getInputStream());
      } catch (IOException var3) {
     
         log.debug(var3.getMessage());
         throw new VeecloudBizException(var3);
      }
   }

   public String getBody() {
     
      return this.mBody;
   }

   public BufferedReader getReader() throws IOException {
     
      return new BufferedReader(new InputStreamReader(this.getInputStream()));
   }

   public ServletInputStream getInputStream() throws IOException {
     
      final ByteArrayInputStream bais = new ByteArrayInputStream(this.mBody.getBytes(Charset.defaultCharset()));
      return new ServletInputStream() {
     
         public boolean isFinished() {
     
            return false;
         }

         public boolean isReady() {
     
            return false;
         }

         public void setReadListener(ReadListener readListener) {
     
         }

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

实用案例

代码块:

public void test(HttpServletRequest request, HttpServletResponse response) throws Exception {
     
      String param;
      if (this.isJson(request)) {
     
         param = (new RequestWrapper(request)).getBody();
         log.info("[test] 获取到application/json请求参数 : {}", param);
      }  else if (isMultipart(request)) {
     
            // 文件上传
            param = new RequestWrapper(request).getBody();
            log.info("[preHandle] 文件上传,获取到application/json请求参数 : {}", param);
        } else {
     
         SortedMap<String, String> map = this.getAllParams(request);
         param = JSON.toJSONString(map);
         log.info("[test] 获取到application/x-www-form-urlencoded请求参数 : {}", param);
      }
}
private boolean isJson(HttpServletRequest request) {
     
      if (request.getContentType() == null) {
     
         return false;
      } else {
     
         return request.getContentType().equals("application/json") || request.getContentType().equals("application/json;charset=UTF-8");
      }
   }
 /**
     * 判断本次请求的数据类型是否为上传文件
     *
     * @param request request
     * @return boolean
     */
    private boolean isMultipart(HttpServletRequest request) {
     
        if (request.getContentType() != null) {
     
            return request.getContentType().equals(MediaType.MULTIPART_FORM_DATA_VALUE);
        }

        return false;
    }

你可能感兴趣的:(springmvc,J2EE学习,j2ee)