Spring 引导不使用 CommonsMultipartResolver?
Spring Boot doesn't use CommonsMultipartResolver?
我在使用 REST Web 服务时遇到问题 运行 Spring Boot (Jetty)。
我的 REST 方法之一是文件上传,我猜 CommonsMultipartResolver 在多部分请求期间没有使用。
此上传方式的签名为:
@ResponseBody
@RequestMapping(value = "/upload", method = RequestMethod.POST, produces = "application/json")
public BaseResponse upload(@RequestParam("login") String login, @RequestParam("passwd") String passwd,
@RequestParam("partner") String partner, @RequestParam("fileName") String fName,
@RequestParam("length") int fLen, @RequestParam("file") MultipartFile file) throws IOException
我还有一个根应用程序 class,如下所示:
@SpringBootApplication
public class BootApplication {
private static final Logger _logger = Logger.getLogger(BootApplication.class.getName());
public static void main(String[] args) {
SpringApplication app = new SpringApplication(BootApplication.class,
new ClassPathResource("WEB-INF/applicationContext.xml"),
new ClassPathResource("WEB-INF/dispatcher-servlet.xml"));
app.run(args);
}
@Bean(name = "multipartResolver")
public CommonsMultipartResolver multipartResolver(ServletContext servletContext) {
_logger.log(Level.INFO, "[BootApplication] Fetching CommonsMultipartResolver");
return new CommonsMultipartResolver(servletContext);
}
}
当我调用此方法时出现错误:
org.springframework.web.bind.MissingServletRequestParameterException: Required MultipartFile parameter 'file' is not present
at org.springframework.web.method.annotation.RequestParamMethodArgumentResolver.handleMissingValue(RequestParamMethodArgumentResolver.java:253)
at org.springframework.web.method.annotation.AbstractNamedValueMethodArgumentResolver.resolveArgument(AbstractNamedValueMethodArgumentResolver.java:94)
at org.springframework.web.method.support.HandlerMethodArgumentResolverComposite.resolveArgument(HandlerMethodArgumentResolverComposite.java:77)
at org.springframework.web.method.support.InvocableHandlerMethod.getMethodArgumentValues(InvocableHandlerMethod.java:162)
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:129)
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:110)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandleMethod(RequestMappingHandlerAdapter.java:776)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:705)
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:959)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:893)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:966)
at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:868)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:707)
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:842)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:790)
at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:808)
at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1669)
at org.eclipse.jetty.websocket.server.WebSocketUpgradeFilter.doFilter(WebSocketUpgradeFilter.java:224)
at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1652)
at org.springframework.boot.actuate.autoconfigure.EndpointWebMvcAutoConfiguration$ApplicationContextHeaderFilter.doFilterInternal(EndpointWebMvcAutoConfiguration.java:295)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1652)
at org.springframework.boot.actuate.trace.WebRequestTraceFilter.doFilterInternal(WebRequestTraceFilter.java:102)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1652)
at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:77)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1652)
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:85)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1652)
at org.springframework.boot.actuate.autoconfigure.MetricsFilter.doFilterInternal(MetricsFilter.java:68)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1652)
at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:585)
at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:143)
at org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:577)
at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:223)
at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1127)
at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:515)
at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:185)
at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1061)
at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:141)
at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:97)
at org.eclipse.jetty.server.Server.handle(Server.java:497)
at org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:310)
at org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:257)
at org.eclipse.jetty.io.AbstractConnection.run(AbstractConnection.java:540)
at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:635)
at org.eclipse.jetty.util.thread.QueuedThreadPool.run(QueuedThreadPool.java:555)
at java.lang.Thread.run(Thread.java:745)
此堆栈跟踪中有什么奇怪的地方我看不到任何 CommonsMultipartResolver
调用。
另一件事是完全相同的代码在 GlassFish 环境中运行——我可以毫无问题地上传文件。改变的是 GlassFish 中的 multipartResolver
bean 在 dispatcher-servlet.xml
中定义,在 Spring Boot 中我在 BootApplication
class 中初始化它。我还尝试将 multipartResolver
留在 dispatcher-servlet.xml
中,我也在为配置加载它,但此解决方案的 none 有效。
当我在 Spring 引导中查看 /beans
端点时,我可以看到 multipartResolver
bean。没有其他 bean 依赖于这个 multipartResolver
bean - 也许这是错误的,但我不知道如何正确配置它。
下面是我的 dispatcher-servlet.xml
如果有帮助的话:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://www.springframework.org/schema/beans" xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd">
<context:annotation-config />
<context:component-scan base-package="com.my.package" />
<mvc:annotation-driven />
</beans>
您正在使用 Spring 引导然后使用它,您正在尝试解决它。
Spring 默认情况下启动已经配置文件上传,因此您可以删除您的定义。如果您想控制某些值,您可以通过向 application.properties
添加属性来配置这些值。请参阅参考指南的 this section。
我建议删除您的 dispatcher-servlet.xml
,因为 Spring Boot 已经启用了 MVC 配置,而您启用它会干扰自动配置。假设您的 BootApplication
在 com.my.package
中,您已经可以删除该文件,因为它不添加任何内容,如果 BootApplication
在不同的包中,请将 @ComponentScan("com.my.package")
添加到配置中。
要导入 applicationContext.xml
添加 @ImportResource
到您的 BootApplication
而不是您现在正在做的。但是,根据其中的内容(可能是某些数据源、JPA 等配置),您甚至可以删除它并用一些简单的属性替换它。
@SpringBootApplication
@ComponentScan("com.my.package")
@ImportResource("WEB-INF/applicationContext.xml")
public class BootApplication {
public static void main(String[] args) throws Exception {
SpringApplication.run(BootApplication.class, args);
}
}
主要问题是您禁用了部分 Spring 启动自动配置,以使其正确配置。
我认为他们已经解决了 Spring-Boot 1.4 中的问题。2.RELEASE
@Bean
public CommonsMultipartResolver multipartResolver() {
CommonsMultipartResolver multipart = new CommonsMultipartResolver();
multipart.setMaxUploadSize(3 * 1024 * 1024);
return multipart;
}
@Bean
@Order(0)
public MultipartFilter multipartFilter() {
MultipartFilter multipartFilter = new MultipartFilter();
multipartFilter.setMultipartResolverBeanName("multipartResolver");
return multipartFilter;
}
你还需要排除Spring-Boot的MulipartAutoConfiguration.class
@EnableAutoConfiguration(排除={MultipartAutoConfiguration.class})
这对我有用。
我在使用 REST Web 服务时遇到问题 运行 Spring Boot (Jetty)。 我的 REST 方法之一是文件上传,我猜 CommonsMultipartResolver 在多部分请求期间没有使用。
此上传方式的签名为:
@ResponseBody
@RequestMapping(value = "/upload", method = RequestMethod.POST, produces = "application/json")
public BaseResponse upload(@RequestParam("login") String login, @RequestParam("passwd") String passwd,
@RequestParam("partner") String partner, @RequestParam("fileName") String fName,
@RequestParam("length") int fLen, @RequestParam("file") MultipartFile file) throws IOException
我还有一个根应用程序 class,如下所示:
@SpringBootApplication
public class BootApplication {
private static final Logger _logger = Logger.getLogger(BootApplication.class.getName());
public static void main(String[] args) {
SpringApplication app = new SpringApplication(BootApplication.class,
new ClassPathResource("WEB-INF/applicationContext.xml"),
new ClassPathResource("WEB-INF/dispatcher-servlet.xml"));
app.run(args);
}
@Bean(name = "multipartResolver")
public CommonsMultipartResolver multipartResolver(ServletContext servletContext) {
_logger.log(Level.INFO, "[BootApplication] Fetching CommonsMultipartResolver");
return new CommonsMultipartResolver(servletContext);
}
}
当我调用此方法时出现错误:
org.springframework.web.bind.MissingServletRequestParameterException: Required MultipartFile parameter 'file' is not present
at org.springframework.web.method.annotation.RequestParamMethodArgumentResolver.handleMissingValue(RequestParamMethodArgumentResolver.java:253)
at org.springframework.web.method.annotation.AbstractNamedValueMethodArgumentResolver.resolveArgument(AbstractNamedValueMethodArgumentResolver.java:94)
at org.springframework.web.method.support.HandlerMethodArgumentResolverComposite.resolveArgument(HandlerMethodArgumentResolverComposite.java:77)
at org.springframework.web.method.support.InvocableHandlerMethod.getMethodArgumentValues(InvocableHandlerMethod.java:162)
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:129)
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:110)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandleMethod(RequestMappingHandlerAdapter.java:776)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:705)
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:959)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:893)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:966)
at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:868)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:707)
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:842)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:790)
at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:808)
at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1669)
at org.eclipse.jetty.websocket.server.WebSocketUpgradeFilter.doFilter(WebSocketUpgradeFilter.java:224)
at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1652)
at org.springframework.boot.actuate.autoconfigure.EndpointWebMvcAutoConfiguration$ApplicationContextHeaderFilter.doFilterInternal(EndpointWebMvcAutoConfiguration.java:295)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1652)
at org.springframework.boot.actuate.trace.WebRequestTraceFilter.doFilterInternal(WebRequestTraceFilter.java:102)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1652)
at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:77)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1652)
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:85)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1652)
at org.springframework.boot.actuate.autoconfigure.MetricsFilter.doFilterInternal(MetricsFilter.java:68)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1652)
at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:585)
at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:143)
at org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:577)
at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:223)
at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1127)
at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:515)
at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:185)
at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1061)
at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:141)
at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:97)
at org.eclipse.jetty.server.Server.handle(Server.java:497)
at org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:310)
at org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:257)
at org.eclipse.jetty.io.AbstractConnection.run(AbstractConnection.java:540)
at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:635)
at org.eclipse.jetty.util.thread.QueuedThreadPool.run(QueuedThreadPool.java:555)
at java.lang.Thread.run(Thread.java:745)
此堆栈跟踪中有什么奇怪的地方我看不到任何 CommonsMultipartResolver
调用。
另一件事是完全相同的代码在 GlassFish 环境中运行——我可以毫无问题地上传文件。改变的是 GlassFish 中的 multipartResolver
bean 在 dispatcher-servlet.xml
中定义,在 Spring Boot 中我在 BootApplication
class 中初始化它。我还尝试将 multipartResolver
留在 dispatcher-servlet.xml
中,我也在为配置加载它,但此解决方案的 none 有效。
当我在 Spring 引导中查看 /beans
端点时,我可以看到 multipartResolver
bean。没有其他 bean 依赖于这个 multipartResolver
bean - 也许这是错误的,但我不知道如何正确配置它。
下面是我的 dispatcher-servlet.xml
如果有帮助的话:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://www.springframework.org/schema/beans" xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd">
<context:annotation-config />
<context:component-scan base-package="com.my.package" />
<mvc:annotation-driven />
</beans>
您正在使用 Spring 引导然后使用它,您正在尝试解决它。
Spring 默认情况下启动已经配置文件上传,因此您可以删除您的定义。如果您想控制某些值,您可以通过向 application.properties
添加属性来配置这些值。请参阅参考指南的 this section。
我建议删除您的 dispatcher-servlet.xml
,因为 Spring Boot 已经启用了 MVC 配置,而您启用它会干扰自动配置。假设您的 BootApplication
在 com.my.package
中,您已经可以删除该文件,因为它不添加任何内容,如果 BootApplication
在不同的包中,请将 @ComponentScan("com.my.package")
添加到配置中。
要导入 applicationContext.xml
添加 @ImportResource
到您的 BootApplication
而不是您现在正在做的。但是,根据其中的内容(可能是某些数据源、JPA 等配置),您甚至可以删除它并用一些简单的属性替换它。
@SpringBootApplication
@ComponentScan("com.my.package")
@ImportResource("WEB-INF/applicationContext.xml")
public class BootApplication {
public static void main(String[] args) throws Exception {
SpringApplication.run(BootApplication.class, args);
}
}
主要问题是您禁用了部分 Spring 启动自动配置,以使其正确配置。
我认为他们已经解决了 Spring-Boot 1.4 中的问题。2.RELEASE
@Bean
public CommonsMultipartResolver multipartResolver() {
CommonsMultipartResolver multipart = new CommonsMultipartResolver();
multipart.setMaxUploadSize(3 * 1024 * 1024);
return multipart;
}
@Bean
@Order(0)
public MultipartFilter multipartFilter() {
MultipartFilter multipartFilter = new MultipartFilter();
multipartFilter.setMultipartResolverBeanName("multipartResolver");
return multipartFilter;
}
你还需要排除Spring-Boot的MulipartAutoConfiguration.class
@EnableAutoConfiguration(排除={MultipartAutoConfiguration.class})
这对我有用。