MultipartConfigElement

MultipartConfigElement

application.properties中,我有:

spring.http.multipart.maxFileSize
spring.http.multipart.maxRequestSize


但是我希望有可能在不重新启动应用程序的情况下更改此属性。

可能吗 ?

最佳答案

深入研究源代码后,我找到了一种针对StandardServletMultipartResolver的方法。

StandardServletMultipartResolverHttpServletRequest包装StandardMultipartHttpServletRequest,后者使用request.getParts()的标准servlet api实现来处理多部分请求。在内部,此方法使用在注册调度程序servlet期间由MultipartConfigElement设置的ServletRegistrationBean。我们对MultipartConfigElement感兴趣,因为它包含我们感兴趣的属性。

默认情况下,ServletRegistrationBeanMultipartConfigElement获取MultipartAutoConfigurationMultipartConfigElement的默认实现不允许修改其属性,因此我们需要扩展此类以添加这种功能。进一步的实现取决于您是否要根据每个请求或不时为整个应用程序修改参数。

根据请求

MultipartConfigurationContext存储特定请求的配置。 UpdateMultipartConfigurationFilter设置给定请求的多部分属性。 UpdatableMultipartConfigElement使用此信息(如果提供)。

public class MultipartConfigurationContext {

    private static ThreadLocal<Integer> maxFileSize = new ThreadLocal<>();

    public static void setMaxFileSize(Integer val) {
        maxFileSize.set(val);
    }

    public static Integer getMaxFileSize() {
        return maxFileSize.get();
    }

    public static void clear() {
        maxFileSize.set(null);
    }
}

public class UpdatableMultipartConfigElement extends MultipartConfigElement {

    private final long maxFileSize;

    public UpdatableMultipartConfigElement(String location, long maxFileSize, long maxRequestSize, int fileSizeThreshold) {
        super(location, maxFileSize, maxRequestSize, fileSizeThreshold);
        this.maxFileSize = maxFileSize;
    }

    @Override
    public long getMaxFileSize() {
        return MultipartConfigurationContext.getMaxFileSize() == null
                ? maxFileSize : MultipartConfigurationContext.getMaxFileSize();
    }
}

public class UpdateMultipartConfigurationFilter extends OncePerRequestFilter implements Ordered {

    // this filter must be before OrderedHiddenHttpMethodFilter
    public static final int ORDER = FilterRegistrationBean.REQUEST_WRAPPER_FILTER_MAX_ORDER - 20000;

    @Override
    public int getOrder() {
        return ORDER;
    }

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
            throws ServletException, IOException {
        // gets file size from request if present and sets it to MultipartConfigurationContext
        MultipartConfigurationContext.setMaxFileSize(150_000);

        filterChain.doFilter(request, response);

        MultipartConfigurationContext.clear();
    }
}

@Configuration
@EnableConfigurationProperties(MultipartProperties.class)
public class MultipartConfiguration {

    private final MultipartProperties multipartProperties;

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

    @Bean
    public MultipartConfigElement multipartConfigElement() {
        MultipartConfigElement multipartConfigElement = multipartProperties.createMultipartConfig();
        return new UpdatableMultipartConfigElement(multipartConfigElement.getLocation(), multipartConfigElement.getMaxFileSize(),
                multipartConfigElement.getMaxRequestSize(), multipartConfigElement.getFileSizeThreshold());
    }

    @Bean
    public UpdateMultipartConfigurationFilter updateMultipartConfigurationFilter() {
        return new UpdateMultipartConfigurationFilter();
    }
}


全球范围

UpdatableMultipartConfigElement存储可以在运行时使用rest api调用更新的信息。

public class UpdatableMultipartConfigElement extends MultipartConfigElement {

    private volatile long maxFileSize = -1;

    public UpdatableMultipartConfigElement(String location, long maxFileSize, long maxRequestSize, int fileSizeThreshold) {
        super(location, maxFileSize, maxRequestSize, fileSizeThreshold);
    }

    @Override
    public long getMaxFileSize() {
        return maxFileSize == -1 ? super.getMaxFileSize() : maxFileSize;
    }

    public void setMaxFileSize(long maxFileSize) {
        this.maxFileSize = maxFileSize;
    }
}

@Configuration
@EnableConfigurationProperties(MultipartProperties.class)
public class MultipartConfiguration {

    private final MultipartProperties multipartProperties;

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

    @Bean
    public MultipartConfigElement multipartConfigElement() {
        MultipartConfigElement multipartConfigElement = multipartProperties.createMultipartConfig();
        return new UpdatableMultipartConfigElement(multipartConfigElement.getLocation(), multipartConfigElement.getMaxFileSize(),
                multipartConfigElement.getMaxRequestSize(), multipartConfigElement.getFileSizeThreshold());
    }
}

@RestController
public class ConfigurationController {

    @Autowired
    private UpdatableMultipartConfigElement updatableMultipartConfigElement;

    @RequestMapping("/configuration")
    public void configuration(@RequestParam("maxFileSize") long maxFileSize) {
        updatableMultipartConfigElement.setMaxFileSize(maxFileSize);
    }

}

09-05 05:40