Spring Boot不使用CommonsMultipartResolver?

标签 spring spring-mvc file-upload spring-boot multipartform-data

我在使用 Spring Boot (Jetty) 运行 REST Web 服务时遇到问题。 我的 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

我还有一个根应用程序类,如下所示:

@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$2.run(AbstractConnection.java:540)
at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:635)
at org.eclipse.jetty.util.thread.QueuedThreadPool$3.run(QueuedThreadPool.java:555)
at java.lang.Thread.run(Thread.java:745)

这个堆栈跟踪有什么奇怪的,我看不到任何 CommonsMultipartResolver 调用。 另一件事是,完全相同的代码在 GlassFish 环境中运行 - 我可以毫无问题地上传文件。改变的是 GlassFish 中的 multipartResolver bean 是在dispatcher-servlet.xml 中定义的,而在 Spring Boot 中,我在 BootApplication 类中初始化它。我还尝试将 multipartResolver 保留在 dispatcher-servlet.xml 中,我也在加载它以进行配置,但这个解决方案都不起作用。

当我在 Spring Boot 中查看 /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 Boot,然后使用它,您正在尝试解决它。​​

Spring Boot 默认情况下已配置文件上传,因此您可以删除定义。如果您想控制某些值,可以通过向 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 Boot 自动配置的一部分以使其正确配置。

关于Spring Boot不使用CommonsMultipartResolver?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31178160/

相关文章:

java - Spring转换器、 validator 和DataBinder : how to handle multivalued bean fields individually?

java - 使用 Spring MVC 在 JSP 页面上显示列表的未解析 EL 表达式

Tomcat 上的 Java Web 应用程序 - 显示用户上传的文件

javascript - jquery.fileupload.js :87 Uncaught TypeError: $. 小部件不是 jQuery-file-upload 上的函数

spring - 刷新 Spring Boot 自动配置的属性

java - 通过 mvn tomcat7 :deploy 部署时 Maven webapp 不工作

java - Spring MVC 3.1.0 错误?升级 Controller 后不再自动检测

java - Apache commons 文件上传替代方案

javascript - 没有任何插件Jquery的Ajax文件上传进度

java - 为什么Spring中的RequestMapping得到空值