springboot圖片(文件)上傳時爲null

       這幾天在使用springboot時,controller層接受前端傳入的數據爲null,而在發送請求時也是有數據的,這就讓我很疑惑,於是在查看了一下源碼,發現了問題所在。

      1. 我們都知道,在springboot啓動完成之後,會加載很多的bean進入容器,怎麼加載的請在網上自行搜索,其中就有這麼一個配置類DispatcherServletAutoConfiguration.java,看源碼:

@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE)
@Configuration
@ConditionalOnWebApplication
@ConditionalOnClass(DispatcherServlet.class)
@AutoConfigureAfter(EmbeddedServletContainerAutoConfiguration.class)
public class DispatcherServletAutoConfiguration {
	/*
	 * The bean name for a DispatcherServlet that will be mapped to the root URL "/"
	 */
	public static final String DEFAULT_DISPATCHER_SERVLET_BEAN_NAME = "dispatcherServlet";

	/*
	 * The bean name for a ServletRegistrationBean for the DispatcherServlet "/"
	 */
	public static final String DEFAULT_DISPATCHER_SERVLET_REGISTRATION_BEAN_NAME = "dispatcherServletRegistration";

	@Configuration
	@Conditional(DefaultDispatcherServletCondition.class)
	@ConditionalOnClass(ServletRegistration.class)
	@EnableConfigurationProperties(WebMvcProperties.class)
	protected static class DispatcherServletConfiguration {

		private final WebMvcProperties webMvcProperties;

		public DispatcherServletConfiguration(WebMvcProperties webMvcProperties) {
			this.webMvcProperties = webMvcProperties;
		}

		@Bean  //就是這個bean啦
		@ConditionalOnBean(MultipartResolver.class)
		@ConditionalOnMissingBean(name = DispatcherServlet.MULTIPART_RESOLVER_BEAN_NAME)
		public MultipartResolver multipartResolver(MultipartResolver resolver) {
			// Detect if the user has created a MultipartResolver but named it incorrectly
			return resolver;
		}

	}
}

       我們會發現DispatcherServletAutoConfiguration.java類中DispatcherServletConfiguration內部類中會向容器中導入一個MultipartResolver類型的bean,要想導入這個bean是有前提的,容器中需要有MultipartResolver.class的類,而且需要當容器中沒有這個名字的bean,name = DispatcherServlet.MULTIPART_RESOLVER_BEAN_NAME,而這個name是這樣的:

package org.springframework.web.servlet;

public class DispatcherServlet extends org.springframework.web.servlet.FrameworkServlet {
    public static final java.lang.String MULTIPART_RESOLVER_BEAN_NAME = "multipartResolver";

       這樣我們就知道了,當我們容器中有MultipartResolver.class這個類,卻沒有multipartResolver名字的bean,這時springboot認爲我們的命名不規範,就會容器中註冊一個multipartResolver名字的,類型爲MultipartResolver的bean。

       2. 我們查看另一個配置類MultipartAutoConfiguration.java,

@Configuration
@ConditionalOnClass({ Servlet.class, StandardServletMultipartResolver.class,
		MultipartConfigElement.class })
@ConditionalOnProperty(prefix = "spring.http.multipart", name = "enabled",
		matchIfMissing = true)
@EnableConfigurationProperties(MultipartProperties.class)
public class MultipartAutoConfiguration {

	private final MultipartProperties multipartProperties;

	public MultipartAutoConfiguration(MultipartProperties multipartProperties) {
		this.multipartProperties = multipartProperties;
	}

	@Bean
	@ConditionalOnMissingBean({ MultipartConfigElement.class,
			CommonsMultipartResolver.class })
	public MultipartConfigElement multipartConfigElement() {
		return this.multipartProperties.createMultipartConfig();
	}

	@Bean(name = DispatcherServlet.MULTIPART_RESOLVER_BEAN_NAME)
	@ConditionalOnMissingBean(MultipartResolver.class)
	public StandardServletMultipartResolver multipartResolver() {
		StandardServletMultipartResolver multipartResolver = new StandardServletMultipartResolver();
		multipartResolver.setResolveLazily(this.multipartProperties.isResolveLazily());
		return multipartResolver;
	}

}

         它主要往容器中添加兩個bean,在添加multipartConfigElement時會判斷容器中是否缺少CommonsMultipartResolver和MultipartConfigElement類型的bean,如果缺少,那麼就multipartConfigElement加入容器中。

         第二個bean是當缺少MultipartResolver類型的bean時,加入到容器。

         當我們知道這些就可以解決爲啥controller傳入的爲空,我自己寫的MultipartResolver是這樣定義的:

    //顯示聲明CommonsMultipartResolver爲mutipartResolver
    @Bean(name = "multipartResolver")
    public MultipartResolver multipartResolver() {
        CommonsMultipartResolver resolver = new CommonsMultipartResolver();
        resolver.setDefaultEncoding("UTF-8");
        resolver.setMaxUploadSize(50 * 1024 * 1024);//上傳文件大小 50M 50*1024*1024
        return resolver;
    }

         這樣定義我們來分析一下,首先容器會將在我們自己定義的bean到容器中,然後判斷前面的情況,在DispatcherServletAutoConfiguration類中的bean不會被加入到容器,爲什麼?因爲我們自己定義的bean已經叫multipartResolver了,所以不會加入到容器。

         再看MultipartAutoConfiguration,multipartConfigElement會被加入到容器,因爲沒有CommonsMultipartResolver類型的bean,我自己寫的向上轉型了,StandardServletMultipartResolver 類型bean不會被加入到容器,這時容器有兩個bean,而且我自己定義的bean是MultipartResolver ,這時就會出錯了。

         出錯原因是我們定義的MultipartResolver要明確的指出是哪個類的,不應該是MultipartResolver這個接口類型,改成

 //顯示聲明CommonsMultipartResolver爲mutipartResolver
    @Bean(name = "multipartResolver")
    public CommonsMultipartResolver multipartResolver() {
        CommonsMultipartResolver resolver = new CommonsMultipartResolver();
        resolver.setDefaultEncoding("UTF-8");
        resolver.setMaxUploadSize(50 * 1024 * 1024);//上傳文件大小 50M 50*1024*1024
        return resolver;
    }

        就可以了,這時在思考一下,會發現springboot只會將我們的multipartResolver加入到容器,multipartConfigElement則不會加入到容器。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章