最近项目组因为token检验拿不到content-type=multipart/form-data表单数据产生疑惑,后翻查了网上的资料总结。

 

前端content-type=application/x-www-form-urlencoded传入后端时,我们可以通过getParameter的方法获取到参数。

HttpServletRequest request = (HttpServletRequest)servletRequest;

String value = request.getParameter("key");

备注:content-type=application/x-www-form-urlencoded通过加密参数拼接在url上,后端会解析出来并放入一个map中,供重复使用。

 

除了content-type=application/x-www-form-urlencoded这种情况,项目还会涉及上传文件,这里就会用到另外一种content-type=multipart/form-data,这时我们通过request.getParameter("key")来获取参数会返回一个null,因为参数不再是通过加密传url进来,而是通过流的形式传入。

 

此时我们就需要用到MultipartResolver接口来帮助我们获取得到content-type=multipart/form-data提交上来的参数。

MultipartResolver有两个实现类一个是CommonsMultipartResolver类,另外一个是StandardServletMultipartResolver类,这里示范一下CommonsMultipartResolver的解析方法:

CommonsMultipartResolver resolver = new CommonsMultipartResolver();

MultipartHttpServletRequest multReq = resolver.resolveMultiparrt(request);

String value = multReq.getParametter("key");

问题:通过上面的方法我们成功获取得到前端传给我们的参数,但是另外一个问题出现了,就是我们的流只能够读取一次,读取完之后的request就等于一个空掉的杯子,导致后续的方法都拿不到参数。这是因为我们漏了一个步骤:

request = multReq;

filterChain.doFilter(request, servletResponse);

备注:我们需要把解析完之后的request重新赋值,这样我们就不会丢失掉数据。

 

最后分享一下我这边项目的一个情况就是重新解析后的request虽然能获取params,但是因为流被解析了导致这边底层解析流获取file的方法失效,这边是通过学习码友们把inputstream流复制出来重复使用,达成我想要的效果~

MyHttpServletRequestWrappet类:

public class MyHttpServletRequestWrappet extends HttpServletRequestWrapper{

 

private final byte[] body;

 

public MyHttpServletRequestWrappet(HttpServletRequest request) throws IOException{

super(request);

body = StreamUtils.copyToByteArray(request.getInputStream());

}

 

@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 boolean isFinished(){return false;}

@Override

public boolean isReady(){return false;}

@Override

public void setReadListener(ReadListener readListener){}

@Override

public int read() throws IOException {

return bais.read();

}

};

}

}

 

Filter类:

@WebFilter(filterName = "tokenFilter", urlPatterns = "/*")

public class TokebFilter implements Filter{

 

private static final String FORM_DATA = "multipart/form-data";

 

@Override

public void init(FilterConfig filterConfig) throws ServletException {}

 

@Override

public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {

HttpServletRequest request = (HttpServletRequest) servletRequest;

//跳过白名单检验方法

String requestUri = getRequestUri(request);

if("/signin".equalsIgnoreCase(requestUri)

|| "/signoff".equalsIgnoreCase(requestUri)){

filterChain.doFilter(servletRequest, servletResponse);

return;

} else {

//token设置在头部则不需要去取参数

String token = request.getHeader("token");

if(StringUtils.isEmpty(token)){

token = request.getParameter("token");

}

 

if(request.getContentType() != null && request.getContentType().contains(FORM_DATA)){

MyHttpServletRequestWrapper requestWrapper = new MyHttpServletRequestWrapper(request);

CommonsMultipartResolver resolver = new CommonsMultipartResolver();

MultipartHttpServletRequest multReq = resolver.resolverMultipart(requestWrapper);

token = multReq.getParameter("token");

request = requeatWrapper;

}

 

HttpSession session = request.getSession(false);

Object sessionToken = session.getAttribute("token");

if(!sessionToken.equals(token)

|| StringUtils.isBlank(token)){

servletResponse.setCharacterEncoding("UTF-8");

servletResponse.setContentType("application/json; charset=utf-8");

try(PrintWriter out = servletResponse.getWriter()){

JSONObject json = new JSONObject();

Map<String, Object> ret = new HashMap<>();

ret.put("retCode", "0");

ret.put("retMsg", "请求token错误!");

json.put("returnValue", ret);

out.writer(json.toJSONString());

out.flush();

return;

} catch (Exception e) {

return;

}

}

}

filterChain.doFilter(request, servletResponse);

}

 

public String getRequestUri(HttpServletRequest request){

String requestUri = request.getRequestURI();

String contextPath = request.getContextPath();

requestUri = requestUri.substring(requestUri.indexOf(contextPath) + contextPath.length());

return requestUri;

}

 

@Override

public void destroy(){}

}

 

文章全手打,有错误的地方麻烦指正,会及时修正!

谢谢大家!

 

 

 

 

 

 

 

 

 

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐