解决启动SpringBoot项目加载 @Value注解报异常问题

Posted 一宿君

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了解决启动SpringBoot项目加载 @Value注解报异常问题相关的知识,希望对你有一定的参考价值。

在开发的过程中很多时候我们需要用到公共配置组件,@Value注解就是开发中常用到的工具,但是该注解使用不当很容易出现错误,查阅资料后总结了以下几种解决方案。


1、使用场景及异常错误

最近在做项目中需要用到文件上传,我采用的是七牛云对象存储管理平台,就是将本地文件上传到云端存储及管理,这个时候就需要一些从远程配置管理中心获取公共配置参数的场景。

在编写文件上传下载服务业务逻辑实现类的时候,启动项目报出了如下异常:

看下业务逻辑实现类:

import com.cloudflashpay.common.domain.BusinessException;
import com.cloudflashpay.common.domain.CommonErrorCode;
import com.cloudflashpay.common.util.QiniuUtils;
import com.cloudflashpay.merchant.service.FileService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

/**
 * @author: 一宿君
 * @date: 2022-03-23 16:47:25
 * @description: 文件上传下载服务
 */
@Service
@Slf4j
public class FileServiceImpl implements FileService 

    @Value("$oss.qiniu.url")
    private String qiniuUrl;

    @Value("$oss.qiniu.accessKey")
    private String accessKey;

    @Value("$oss.qiniu.secretKey")
    private String secretKey;

    @Value("$oss.qiniu.bucket")
    private String bucket;

    /**
     * 上传文件
     * @param bytes 文件字节
     * @param fileName 文件名称
     * @return 文件下载访问路径地址
     * @throws BusinessException
     */
    @Override
    public String upload(byte[] bytes, String fileName) throws BusinessException 

        try 
            //调用上传文件到七牛云工具类方法
            QiniuUtils.uploadFileQiniu(accessKey,secretKey,bucket,bytes,fileName);
        catch (RuntimeException e)
            e.printStackTrace();
            log.error("上传文件到七牛云异常:",e.getMessage());
            throw new BusinessException(CommonErrorCode.E_100106);
        
        //上传成功后,将文件的下载访问地址返回给前端(绝对路径)
        return qiniuUrl+fileName;
    

出现上述异常错误是因为在启动SpringBoot项目的时候会预先检索@Value注解对应的配置参数值,如果该注解对应的配置参数key没有取到值,就会报错无效异常!

2、解决方法

2.1、@Value注解后面加上默认值

	@Value("$oss.qiniu.url: default_value")
    private String qiniuUrl;

    @Value("$oss.qiniu.accessKey: default_value")
    private String accessKey;

    @Value("$oss.qiniu.secretKey: default_value")
    private String secretKey;

    @Value("$oss.qiniu.bucket: default_value")
    private String bucket;

注解后面加上默认值,如果@Value注解在加载的过程中没有取到值,或者说$key不存在,则会默认采用这个default_value,这样就可以避免在启动项目的时候报错中断,便于后续排查。

2.2、在 Application启动类中设置PropertySourcesPlaceholderConfigurer类的默认属性

	// 设置开启忽略@Value注解取不到值时不报错
    @Bean
    public static PropertySourcesPlaceholderConfigurer placeholderConfigurer()
        PropertySourcesPlaceholderConfigurer configurer = new PropertySourcesPlaceholderConfigurer();
        configurer.setIgnoreUnresolvablePlaceholders(true);
        return configurer;
    

这种方法虽然可以解决启动项目时避免报错,但是不推荐使用。

2.3、将配置文件名称由application.yml修改为bootstap.yml

这个也是最容易忽略的,SprintBoot项目在启动的过程中,会采用优先加载的机制加载配置文件。若application.ymlbootStrap.yml在同一目录下,则bootStrap.yml的加载顺序要高于application.yml,如果当前配置文件名称为application.yml,即使配置文件中存在所使用的属性key,使用@Value注解也会报错,因为在启动项目时@Value只能检索到优先及最高的配置文件,也就是bootStrap.yml

原理:

  • bootstrap.yml用于应用程序上下文的引导阶段,由父Spring ApplicationContext加载。bootstrap.yml 可以理解成系统级别的一些参数配置,这些参数一般是不会变动的。
  • application.yml可以用来定义应用级别的,如果搭配 spring-cloud-config 使用 application.yml 里面定义的文件可以实现动态替换。

以上是关于解决启动SpringBoot项目加载 @Value注解报异常问题的主要内容,如果未能解决你的问题,请参考以下文章

SpringBoot多模块项目子模块controller未加载问题

Springboot 排除不想加载的配置

STS启动springboot项目,加载不了resources下的配置文件的问题

SpringBoot-- 启动加载数据

spring boot启动自动关闭

springboot加载外部dll成功,但执行方法失败