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则不会加入到容器。

发布了225 篇原创文章 · 获赞 30 · 访问量 5万+

猜你喜欢

转载自blog.csdn.net/qq_35634181/article/details/89454052