pre过滤器——FormBodyWrapperFilter

FormBodyWrapperFilter

本过滤器的作用同Servlet30RequestWrapper一样,也是对请求的一个包装。

该过滤器属于条件过滤器,即只有在特定条件下才会执行

判断条件是content-type中必须带有“application/x-www-form-urlencoded”或“multipart/form-data”

application/x-www-form-urlencoded:表示数据发送到服务器之前,所有字符都会进行编码。属于比较常用的编码方式。

multipart/form-data:指表单数据有多部分构成,既有文本数据,又有文件等二进制数据的意思。

具体的使用范围参考http协议的规定。

public boolean shouldFilter() {
        RequestContext ctx = RequestContext.getCurrentContext();
        HttpServletRequest request = ctx.getRequest();
        //content-type:内容类型;客户端告诉服务器实际发送的数据类型;也可以叫MediaType
        String contentType = request.getContentType();
        if (contentType == null) {
            return false;
        } else {
            try {
                /**APPLICATION_FORM_URLENCODED:application/x-www-form-urlencoded
                    *this.isDispatcherServletRequest(request) :判断是否是dispatcherServlet请求    
                    *MULTIPART_FORM_DATA:multipart/form-data
                    */
                MediaType mediaType = MediaType.valueOf(contentType);
                return MediaType.APPLICATION_FORM_URLENCODED.includes(mediaType) || this.isDispatcherServletRequest(request) && MediaType.MULTIPART_FORM_DATA.includes(mediaType);
            } catch (InvalidMediaTypeException var5) {
                return false;
            }
        }
    }            

 

主要执行逻辑:可以看出与Servlet30RequestWrapper的执行逻辑差不多,将http请求进行了包装。

 public Object run() {
        RequestContext ctx = RequestContext.getCurrentContext();
        HttpServletRequest request = ctx.getRequest();
        FormBodyWrapperFilter.FormBodyRequestWrapper wrapper = null;
        if (request instanceof HttpServletRequestWrapper) {
            HttpServletRequest wrapped = (HttpServletRequest)ReflectionUtils.getField(this.requestField, request);
            wrapper = new FormBodyWrapperFilter.FormBodyRequestWrapper(wrapped);
            ReflectionUtils.setField(this.requestField, request, wrapper);
            if (request instanceof ServletRequestWrapper) {
                ReflectionUtils.setField(this.servletRequestField, request, wrapper);
            }
        } else {
            wrapper = new FormBodyWrapperFilter.FormBodyRequestWrapper(request);
            ctx.setRequest(wrapper);
        }
        /**将编码类型从request中提取出来放到RequestContext中
      *getContentType()操作向wrapper中的contentData属性进行了赋值操作。
      */
if (wrapper != null) { ctx.getZuulRequestHeaders().put("content-type", wrapper.getContentType()); } return null; }

可以看到FormBodyWrapperFilter是通过new FormBodyWrapperFilter.FormBodyRequestWrapper(request);进行的

而FormBodyRequestWrapper是FormBodyWrapperFilter的一个内部类,继承了Servlet30RequestWrapper类。

private class FormBodyRequestWrapper extends Servlet30RequestWrapper {
        private HttpServletRequest request;
        private volatile byte[] contentData;
        private MediaType contentType;
        private int contentLength;

        public FormBodyRequestWrapper(HttpServletRequest request) {
            super(request);
            this.request = request;
        }
  
  
/**在获取contentType的时候,给contentData进行了赋值操作。*/  
    
public String getContentType() {
if (this.contentData == null) {
this.buildContentData();
}

return this.contentType.toString();
}

//....省略 }

所以当此过滤器执行时。会覆盖并扩展Servlet30RequestWrapper的包装效果。同时对包装的请求进行了相应的赋值操作。

比如请求的contentData、contentLength、contentType都从原始请求中提取出来了。

而Servlet30RequestWrapperFilter只是做了一个包装,并没有进行任何赋值操作。

 

判断一个请求是否经过FormBodyWrapperFilter处理的依据是ctx.getZuulRequestHeaders().put("content-type", wrapper.getContentType());

可以通过代码ctx.getZuulRequestHeaders().get("content-type")来判断,如果能取到值,说明原始请求已经被这个过滤器包装过了。

posted @ 2019-03-31 16:45  龟速前进  阅读(1001)  评论(0编辑  收藏  举报