3

我在使用Spring Boot(Jetty)運行REST Web服務時遇到問題。 我的REST方法之一是文件上傳,我猜測CommonsMultipartResolver在多部分請求期間沒有使用。Spring Boot不使用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環境中工作 - 我可以毫無問題地上傳文件。是什麼改變了multipartResolver GlassFish中的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> 

回答

3

您使用Spring引導,然後使用它,你正在試圖解決它。

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自動配置的一部分,以正確地讓它配置的東西。

+0

非常感謝!使用您的解決方案,我的上傳方法正在運行! :)我使用dispatcher-servlet.xml文件,因爲我在將應用程序部署到Glassfish時正在使用它,但現在我發現這是非常不必要的。 –

+1

我也猜測同樣適用於'applicationContext.xml',你可能想要清理它並使用Spring Boot的自動配置功能。 –

+0

我也將配置從'applicationContext.xml'移到了配置類,一切正常。現在我免於XML配置。謝謝你的建議 ! –

0

我認爲他們已經解決了在彈簧引導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; 
} 

問題還需要排除春節-Boot的MulipartAutoConfiguration。類

@EnableAutoConfiguration(排除= {} MultipartAutoConfiguration.class)

這爲我工作。

相關問題