今天做项目的时候遇到一个很奇怪的问题, 开发环境没有问题, 生产环境却提示java.lang.IllegalStateException: Form too large 和java.lang.IllegalStateException: Form too many keys异常.
追朔了一下堆栈和源码, 发现在 org.eclipse.jetty.server.Request 类中发现这段代码:
public void extractFormParameters(MultiMap<String> params) { try { int maxFormContentSize = -1; int maxFormKeys = -1; if (_context != null) { maxFormContentSize = _context.getContextHandler().getMaxFormContentSize(); maxFormKeys = _context.getContextHandler().getMaxFormKeys(); } if (maxFormContentSize < 0) { Object obj = _channel.getServer().getAttribute("org.eclipse.jetty.server.Request.maxFormContentSize"); if (obj == null) maxFormContentSize = 200000; else if (obj instanceof Number) { Number size = (Number)obj; maxFormContentSize = size.intValue(); } else if (obj instanceof String) { maxFormContentSize = Integer.valueOf((String)obj); } } if (maxFormKeys < 0) { Object obj = _channel.getServer().getAttribute("org.eclipse.jetty.server.Request.maxFormKeys"); if (obj == null) maxFormKeys = 1000; else if (obj instanceof Number) { Number keys = (Number)obj; maxFormKeys = keys.intValue(); } else if (obj instanceof String) { maxFormKeys = Integer.valueOf((String)obj); } } int contentLength = getContentLength(); if (contentLength > maxFormContentSize && maxFormContentSize > 0) { throw new IllegalStateException("Form too large: " + contentLength + " > " + maxFormContentSize); } InputStream in = getInputStream(); if (_input.isAsync()) throw new IllegalStateException("Cannot extract parameters with async IO"); UrlEncoded.decodeTo(in,params,getCharacterEncoding(),contentLength<0?maxFormContentSize:-1,maxFormKeys); } catch (IOException e) { if (LOG.isDebugEnabled()) LOG.warn(e); else LOG.warn(e.toString()); } }
很明显在这段代码中获取了两个配置项:
1.org.eclipse.jetty.server.Request.maxFormContentSize: 请求头中 Content-Length 的最大值, 单位:字节, 默认200000字节
2.org.eclipse.jetty.server.Request.maxFormKeys: 请求参数的最大个数, 默认1000
显然我现在需要重新设置这两个参数, 百度得到的多数结果都是在WEB-INF目录下创建jetty配置文件来解决. 但我们的项目是基于spring-boot 1.3x, 使用的是内嵌Web容器, 没有WEB-INF目录.
最后在我们公司大神推荐的网址 https://stackoverflow.com/questions/36872540/spring-boot-rest-service-form-too-large 中得到答案.
private static void setHandlerMaxHttpPostSize(int maxHttpPostSize, int maxFormKeys, Handler... handlers) { for (Handler handler : handlers) { if (handler instanceof ContextHandler) { ((ContextHandler) handler).setMaxFormContentSize(maxHttpPostSize); ((ContextHandler) handler).setMaxFormKeys(maxFormKeys); } else if (handler instanceof HandlerWrapper) { setHandlerMaxHttpPostSize(maxHttpPostSize, maxFormKeys, ((HandlerWrapper) handler).getHandler()); } else if (handler instanceof HandlerCollection) { setHandlerMaxHttpPostSize(maxHttpPostSize, maxFormKeys, ((HandlerCollection) handler).getHandlers()); } } }
如果是spring-boot 1.4x之后的版本, 则可以通过简单的 server.max-http-post-size=20MB 来解决第 form too large的问题
至于form too many keys的问题, 我还没有发现通过配置解决的.如果可以通过配置解决并且你知道的, 希望能告诉我, 非常感谢