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")来判断,如果能取到值,说明原始请求已经被这个过滤器包装过了。