qq_39248517 2022-08-11 15:50 采纳率: 0%
浏览 755

springboot从2.2升级到2.7后,ResourceProperties类缺失,如何使用WebProperties的内部类Resources替换并正常运行

问题遇到的现象和发生背景

我的项目是一个API网关项目,使用的spring-cloud-gateway,之前使用的springboot2.2版本,并在项目中自定义了错误异常处理,其中使用到一个类ResourceProperties,但是当我升级到springboot2.7.1后,该类被移除了,但是有一个类WebProperties的内部静态类Resources好像是ResourceProperties的代替者,但是我使用的过程中总是报错,还没找到如何使用。

问题相关代码,请勿粘贴截图

就是如下两个类使用到了ResourceProperties,在springboot2.7.1缺失

package com.cosmosource.core.exception;

import org.springframework.beans.factory.ObjectProvider;
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
import org.springframework.boot.autoconfigure.condition.SearchStrategy;
import org.springframework.boot.autoconfigure.web.ResourceProperties;
import org.springframework.boot.autoconfigure.web.ServerProperties;
import org.springframework.boot.autoconfigure.web.reactive.WebFluxAutoConfiguration;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.web.reactive.error.DefaultErrorAttributes;
import org.springframework.boot.web.reactive.error.ErrorAttributes;
import org.springframework.boot.web.reactive.error.ErrorWebExceptionHandler;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.http.codec.ServerCodecConfigurer;
import org.springframework.web.reactive.config.WebFluxConfigurer;
import org.springframework.web.reactive.result.view.ViewResolver;

import java.util.List;
import java.util.stream.Collectors;

@Configuration
@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.REACTIVE)
@ConditionalOnClass(WebFluxConfigurer.class)
@AutoConfigureBefore(WebFluxAutoConfiguration.class)
@EnableConfigurationProperties({ServerProperties.class, ResourceProperties.class})
public class CustomErrorWebFluxAutoConfiguration {

    private final ServerProperties serverProperties;

    private final ApplicationContext applicationContext;

    private final ResourceProperties resourceProperties;

    private final List<ViewResolver> viewResolvers;

    private final ServerCodecConfigurer serverCodecConfigurer;

    public CustomErrorWebFluxAutoConfiguration(ServerProperties serverProperties,
                                               ResourceProperties resourceProperties, // 就这个类缺失了
                                               ObjectProvider<ViewResolver> viewResolversProvider,
                                               ServerCodecConfigurer serverCodecConfigurer,
                                               ApplicationContext applicationContext) {
        this.serverProperties = serverProperties;
        this.applicationContext = applicationContext;
        this.resourceProperties = resourceProperties;
        this.viewResolvers = viewResolversProvider.orderedStream()
                .collect(Collectors.toList());
        this.serverCodecConfigurer = serverCodecConfigurer;
    }

    @Bean
    @ConditionalOnMissingBean(value = ErrorWebExceptionHandler.class,
            search = SearchStrategy.CURRENT)
    @Order(-1)
    public ErrorWebExceptionHandler errorWebExceptionHandler(ErrorAttributes errorAttributes) {
        JsonErrorWebExceptionHandler exceptionHandler = new JsonErrorWebExceptionHandler(
                errorAttributes,
                resourceProperties,
                this.serverProperties.getError(),
                applicationContext);
        exceptionHandler.setViewResolvers(this.viewResolvers);
        exceptionHandler.setMessageWriters(this.serverCodecConfigurer.getWriters());
        exceptionHandler.setMessageReaders(this.serverCodecConfigurer.getReaders());
        return exceptionHandler;
    }

    @Bean
    @ConditionalOnMissingBean(value = ErrorAttributes.class, search = SearchStrategy.CURRENT)
    public DefaultErrorAttributes errorAttributes() {
        return new DefaultErrorAttributes(this.serverProperties.getError().isIncludeException());
    }
}

package com.cosmosource.core.exception;

import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.web.ErrorProperties;
import org.springframework.boot.autoconfigure.web.ResourceProperties;
import org.springframework.boot.autoconfigure.web.reactive.error.DefaultErrorWebExceptionHandler;
import org.springframework.boot.web.reactive.error.ErrorAttributes;
import org.springframework.context.ApplicationContext;
import org.springframework.http.HttpStatus;
import org.springframework.web.reactive.function.server.*;

import java.net.UnknownHostException;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.LinkedHashMap;
import java.util.Map;

/**
 * @author liaoyuanyuan@cosmosource.com
 * @date 2022/5/5 19:27
 **/
@Slf4j
public class JsonErrorWebExceptionHandler extends DefaultErrorWebExceptionHandler {

    public JsonErrorWebExceptionHandler(ErrorAttributes errorAttributes,
                                        ResourceProperties resourceProperties,
                                        ErrorProperties errorProperties,
                                        ApplicationContext applicationContext) {
        super(errorAttributes, resourceProperties, errorProperties, applicationContext);
    }

    @Override
    protected Map<String, Object> getErrorAttributes(ServerRequest request, boolean includeStackTrace) {
        //定制化逻辑
        Throwable error = super.getError(request);
        Map<String, Object> errorAttributes = new LinkedHashMap<>(8);
        if (error instanceof UnknownHostException) {
            errorAttributes.put("message", StrUtil.contains(error.getMessage(), "未知的名称或服务")
                    ? error.getMessage() : error.getMessage() + " 未知的名称或服务");
        } else {
            errorAttributes.put("message", error.getMessage());
        }
        errorAttributes.put("timestamp", LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
        errorAttributes.put("status", HttpStatus.INTERNAL_SERVER_ERROR.value());
        errorAttributes.put("method", request.methodName());
        errorAttributes.put("path", request.path());
        errorAttributes.put("requestId", request.exchange().getRequest().getId());

        log.error("全局异常处理:" + JSON.toJSONString(errorAttributes));
        return errorAttributes;
    }

    @Override
    protected RouterFunction<ServerResponse> getRoutingFunction(ErrorAttributes errorAttributes) {
        return RouterFunctions.route(RequestPredicates.all(), this::renderErrorResponse);
    }

    @Override
    protected int getHttpStatus(Map<String, Object> errorAttributes) {
        // 这里其实可以根据errorAttributes里面的属性定制HTTP响应码
        return HttpStatus.INTERNAL_SERVER_ERROR.value();
    }
}

运行结果及报错内容

我将ResourceProperties替换成了WebProperties,但是启动报错:

java.lang.IllegalStateException: No ConfigurationProperties annotation found on  'org.springframework.boot.autoconfigure.web.WebProperties$Resources'.
    at org.springframework.util.Assert.state(Assert.java:97) ~[spring-core-5.3.21.jar:5.3.21]
    at org.springframework.boot.context.properties.ConfigurationPropertiesBeanRegistrar.registerBeanDefinition(ConfigurationPropertiesBeanRegistrar.java:86) ~[spring-boot-2.7.1.jar:2.7.1]
    at org.springframework.boot.context.properties.ConfigurationPropertiesBeanRegistrar.register(ConfigurationPropertiesBeanRegistrar.java:60) ~[spring-boot-2.7.1.jar:2.7.1]
    at org.springframework.boot.context.properties.ConfigurationPropertiesBeanRegistrar.register(ConfigurationPropertiesBeanRegistrar.java:54) ~[spring-boot-2.7.1.jar:2.7.1]
    at java.lang.Iterable.forEach(Iterable.java:75) ~[na:1.8.0_321]
    at org.springframework.boot.context.properties.EnableConfigurationPropertiesRegistrar.registerBeanDefinitions(EnableConfigurationPropertiesRegistrar.java:49) ~[spring-boot-2.7.1.jar:2.7.1]
    at org.springframework.context.annotation.ImportBeanDefinitionRegistrar.registerBeanDefinitions(ImportBeanDefinitionRegistrar.java:86) ~[spring-context-5.3.21.jar:5.3.21]
    at org.springframework.context.annotation.ConfigurationClassBeanDefinitionReader.lambda$loadBeanDefinitionsFromRegistrars$1(ConfigurationClassBeanDefinitionReader.java:396) ~[spring-context-5.3.21.jar:5.3.21]
    at java.util.LinkedHashMap.forEach(LinkedHashMap.java:684) ~[na:1.8.0_321]
    at org.springframework.context.annotation.ConfigurationClassBeanDefinitionReader.loadBeanDefinitionsFromRegistrars(ConfigurationClassBeanDefinitionReader.java:395) ~[spring-context-5.3.21.jar:5.3.21]
    at org.springframework.context.annotation.ConfigurationClassBeanDefinitionReader.loadBeanDefinitionsForConfigurationClass(ConfigurationClassBeanDefinitionReader.java:157) ~[spring-context-5.3.21.jar:5.3.21]
    at org.springframework.context.annotation.ConfigurationClassBeanDefinitionReader.loadBeanDefinitions(ConfigurationClassBeanDefinitionReader.java:129) ~[spring-context-5.3.21.jar:5.3.21]
    at org.springframework.context.annotation.ConfigurationClassPostProcessor.processConfigBeanDefinitions(ConfigurationClassPostProcessor.java:343) ~[spring-context-5.3.21.jar:5.3.21]
    at org.springframework.context.annotation.ConfigurationClassPostProcessor.postProcessBeanDefinitionRegistry(ConfigurationClassPostProcessor.java:247) ~[spring-context-5.3.21.jar:5.3.21]
    at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanDefinitionRegistryPostProcessors(PostProcessorRegistrationDelegate.java:311) ~[spring-context-5.3.21.jar:5.3.21]
    at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:112) ~[spring-context-5.3.21.jar:5.3.21]
    at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:746) ~[spring-context-5.3.21.jar:5.3.21]
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:564) ~[spring-context-5.3.21.jar:5.3.21]
    at org.springframework.boot.web.reactive.context.ReactiveWebServerApplicationContext.refresh(ReactiveWebServerApplicationContext.java:66) ~[spring-boot-2.7.1.jar:2.7.1]
    at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:734) [spring-boot-2.7.1.jar:2.7.1]
    at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:408) [spring-boot-2.7.1.jar:2.7.1]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:308) [spring-boot-2.7.1.jar:2.7.1]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1306) [spring-boot-2.7.1.jar:2.7.1]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1295) [spring-boot-2.7.1.jar:2.7.1]
    at com.cosmosource.PlatformWebApplication.main(PlatformWebApplication.java:20) [classes/:na]

我的解答思路和尝试过的方法

我找到了WebProperties的内部类Resource可以作为替代者,但是不知道如何使用,简单的使用总是报错

我想要达到的结果

我想知道该如何使用WebProperties来代替我之前的ResourceProperties

  • 写回答

2条回答 默认 最新

  • kse_music 2022-08-11 22:27
    关注
    
    package com.cosmosource.core.exception;
     
    import org.springframework.beans.factory.ObjectProvider;
    import org.springframework.boot.autoconfigure.AutoConfigureBefore;
    import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
    import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
    import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
    import org.springframework.boot.autoconfigure.condition.SearchStrategy;
    import org.springframework.boot.autoconfigure.web.WebProperties;
    import org.springframework.boot.autoconfigure.web.ServerProperties;
    import org.springframework.boot.autoconfigure.web.reactive.WebFluxAutoConfiguration;
    import org.springframework.boot.context.properties.EnableConfigurationProperties;
    import org.springframework.boot.web.reactive.error.DefaultErrorAttributes;
    import org.springframework.boot.web.reactive.error.ErrorAttributes;
    import org.springframework.boot.web.reactive.error.ErrorWebExceptionHandler;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.core.annotation.Order;
    import org.springframework.http.codec.ServerCodecConfigurer;
    import org.springframework.web.reactive.config.WebFluxConfigurer;
    import org.springframework.web.reactive.result.view.ViewResolver;
     
    import java.util.List;
    import java.util.stream.Collectors;
     
    @Configuration
    @ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.REACTIVE)
    @ConditionalOnClass(WebFluxConfigurer.class)
    @AutoConfigureBefore(WebFluxAutoConfiguration.class)
    @EnableConfigurationProperties({ServerProperties.class, WebProperties.class})
    public class CustomErrorWebFluxAutoConfiguration {
     
        private final ServerProperties serverProperties;
     
        private final ApplicationContext applicationContext;
     
        private final  WebProperties webProperties;
     
        private final List<ViewResolver> viewResolvers;
     
        private final ServerCodecConfigurer serverCodecConfigurer;
     
        public CustomErrorWebFluxAutoConfiguration(ServerProperties serverProperties,
                                                   WebProperties webProperties,
                                                   ObjectProvider<ViewResolver> viewResolversProvider,
                                                   ServerCodecConfigurer serverCodecConfigurer,
                                                   ApplicationContext applicationContext) {
            this.serverProperties = serverProperties;
            this.applicationContext = applicationContext;
            this.webProperties= webProperties;
            this.viewResolvers = viewResolversProvider.orderedStream()
                    .collect(Collectors.toList());
            this.serverCodecConfigurer = serverCodecConfigurer;
        }
     
        @Bean
        @ConditionalOnMissingBean(value = ErrorWebExceptionHandler.class,
                search = SearchStrategy.CURRENT)
        @Order(-1)
        public ErrorWebExceptionHandler errorWebExceptionHandler(ErrorAttributes errorAttributes) {
            JsonErrorWebExceptionHandler exceptionHandler = new JsonErrorWebExceptionHandler(
                    errorAttributes,
                    webProperties,
                    this.serverProperties.getError(),
                    applicationContext);
            exceptionHandler.setViewResolvers(this.viewResolvers);
            exceptionHandler.setMessageWriters(this.serverCodecConfigurer.getWriters());
            exceptionHandler.setMessageReaders(this.serverCodecConfigurer.getReaders());
            return exceptionHandler;
        }
     
        @Bean
        @ConditionalOnMissingBean(value = ErrorAttributes.class, search = SearchStrategy.CURRENT)
        public DefaultErrorAttributes errorAttributes() {
            return new DefaultErrorAttributes(this.serverProperties.getError().isIncludeException());
        }
    }
     
    package com.cosmosource.core.exception;
     
    import cn.hutool.core.util.StrUtil;
    import com.alibaba.fastjson.JSON;
    import lombok.extern.slf4j.Slf4j;
    import org.springframework.boot.autoconfigure.web.ErrorProperties;
    import org.springframework.boot.autoconfigure.web.WebProperties;
    import org.springframework.boot.autoconfigure.web.reactive.error.DefaultErrorWebExceptionHandler;
    import org.springframework.boot.web.reactive.error.ErrorAttributes;
    import org.springframework.context.ApplicationContext;
    import org.springframework.http.HttpStatus;
    import org.springframework.web.reactive.function.server.*;
     
    import java.net.UnknownHostException;
    import java.time.LocalDateTime;
    import java.time.format.DateTimeFormatter;
    import java.util.LinkedHashMap;
    import java.util.Map;
     
    /**
     * @author liaoyuanyuan@cosmosource.com
     * @date 2022/5/5 19:27
     **/
    @Slf4j
    public class JsonErrorWebExceptionHandler extends DefaultErrorWebExceptionHandler {
     
        public JsonErrorWebExceptionHandler(ErrorAttributes errorAttributes,
                                             WebProperties webProperties,
                                            ErrorProperties errorProperties,
                                            ApplicationContext applicationContext) {
            super(errorAttributes, webProperties.getResources(), errorProperties, applicationContext);
        }
     
        @Override
        protected Map<String, Object> getErrorAttributes(ServerRequest request, boolean includeStackTrace) {
            //定制化逻辑
            Throwable error = super.getError(request);
            Map<String, Object> errorAttributes = new LinkedHashMap<>(8);
            if (error instanceof UnknownHostException) {
                errorAttributes.put("message", StrUtil.contains(error.getMessage(), "未知的名称或服务")
                        ? error.getMessage() : error.getMessage() + " 未知的名称或服务");
            } else {
                errorAttributes.put("message", error.getMessage());
            }
            errorAttributes.put("timestamp", LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
            errorAttributes.put("status", HttpStatus.INTERNAL_SERVER_ERROR.value());
            errorAttributes.put("method", request.methodName());
            errorAttributes.put("path", request.path());
            errorAttributes.put("requestId", request.exchange().getRequest().getId());
     
            log.error("全局异常处理:" + JSON.toJSONString(errorAttributes));
            return errorAttributes;
        }
     
        @Override
        protected RouterFunction<ServerResponse> getRoutingFunction(ErrorAttributes errorAttributes) {
            return RouterFunctions.route(RequestPredicates.all(), this::renderErrorResponse);
        }
     
        @Override
        protected int getHttpStatus(Map<String, Object> errorAttributes) {
            // 这里其实可以根据errorAttributes里面的属性定制HTTP响应码
            return HttpStatus.INTERNAL_SERVER_ERROR.value();
        }
    }
     
    
    评论 编辑记录

报告相同问题?

问题事件

  • 创建了问题 8月11日

悬赏问题

  • ¥20 请问这种量表怎么用spss量化分析(作为中介模型的因变量
  • ¥55 AD844 howland电流源如何驱动大额负载
  • ¥15 C++ /QT 内存权限的判断函数列举
  • ¥15 深度学习GFnet理解问题
  • ¥15 单细胞小提琴堆叠图代码
  • ¥50 升级strust2版本到2.3.15.1后使用ognl3.0.6.jar windows环境中没有问题,但部署到linux环境报错
  • ¥15 vue页面,node封装接口
  • ¥15 求TMS320F280039C工程模板!
  • ¥15 delphi+fastreport实现分组补空打印问题
  • ¥15 使用python把两台mysql数据库服务器数据导出和导入