Nacos集中式配置中的踩坑日记

/ Java / 0 条评论 / 986浏览

Nacos集中式配置中的踩坑日记

我们都知道nacos中的集中式配置是支持自动刷新机制的,可以使用@refreshscope这个注解实现,但是,这种是需要满足一定的条件的

一号坑:

说实话集中式配置真的特别的方便,之前项目中使用的是springcloudconfig来实现集中式配置的,说实话用起来超麻烦就不说了,需要配置的东西还贼多,这让我很难受呀,想了解一下springcloudconfig集中式配置的可以查看我的另一篇博客

如果大家想将代码的变量作为集中式配置,然后可以实现热更新,那么一定要注意了,比如你写一个CentralConfigValue这样一个类,然后将值存在这个类中

import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.stereotype.Component;

import java.util.HashMap;

/**
 * @author zuohui
 * @date 2020/8/11 - 15:37
 */
@Component
public class CentralConfigValue {

    public static String env;

    public static String version;

    public static String token;

    /**
     * 接口的权限认证
     */
    public static HashMap<String,String> apiauth;

    /**
     * 已关闭的接口
     **/
    public static String[] closedList;

    /**
     * 无需认证
     */
    public static String[] noAuthList = {};

    /**
     * 版本说明
     */
    public static String versionnote;

    /**
     * 内部接口认证
     */
    public static String innerauth;

    @Value("${config.innerauth}")
    public  void setIinnerauth(String innerauth) {
        CentralConfigValue.innerauth = innerauth;
    }

    @Value("${config.versionnote}")
    public  void setVersionnote(String versionnote) {
        CentralConfigValue.versionnote = versionnote;
    }

    @Value("${config.noauthlist:1,2,3}")
    public  void setNoAuthList(String[] noAuthList) {
        CentralConfigValue.noAuthList = noAuthList;
    }

    @Value("${config.closedlist:1,2,3}")
    public  void setClosedList(String[] closedList) {
        CentralConfigValue.closedList = closedList;
    }

    @Value("${config.environ}")
    public void setEnv(String env) {
        CentralConfigValue.env = env;
    }

    @Value("${config.version}")
    public void setVersion(String version) {
        CentralConfigValue.version = version;
    }

    @Value("${config.token}")
    public void setToken(String token) {
        CentralConfigValue.token = token;
    }

    @Value("#{${config.auth}}")
    public void setApiauth(HashMap<String,String> apiauth) {
        CentralConfigValue.apiauth = apiauth;
    }
}

这里需要说明的是,因为我想使用的是静态变量,这样就可以保证不需要创建对象直接访问,这样需要注意,@value注解需要写在非static的setter方法上,并且这样写其实是不支持自动刷新的,你可能想在上面这个类上加入@refreshscope注解,注意千万不要这样做,因为@refreshscope会让spring无法识别这个bean,因为和@Compenent冲突,这样做会报错的.那么要怎样才能让这个文件实现自动热更新呢?答案是这样实现不了,总之我是试过很多种方法了,如果屏幕前的大佬有办法还请下方留言哦.我试过使用单例模式存放这些值,但是同样只能获取一次值,更新后需要重启生效.
其实原因很简单,nacos的集中式配置,是需要请求来生效的,就是说,一个请求过来,controller中的变量如果在集中式配置中,那么可以自动刷新,但是很奇怪,就算在controller中这样调用:

    @GetMapping("/xxxxx")
    public R<String> xxxxx()
    {
        commonService.selectProjLabel(CentralConfigValue.token);
        return R.ok().data(xx);
    }

在刷新集中式配置后还是无法自动生效.当然我这个Controller上已经加入了@refreshScope.

最后试了很多方法后,发现如果使用继承父类,然后将集中式配置统一写在父类中就可以实现自动热更新;

@Api("xxx")
@Slf4j
@RefreshScope
@RestController
@RequestMapping("/xxxx")
public class xxxxx extends BaseController {

@GetMapping("/xxxxx")
    public R<String> xxxxx()
    {
        commonService.selectProjLabel(getXxx2());
        return R.ok().data(xx);
    }
}



@RestController
public class BaseController{

    @Value("${config.xxx1}")
    public String xxx1;

    @Value("${api.queue.xxx2}")
    String xxx2;

    @Value("#{${config.xxx3}}")
    HashMap<String,String> xxx3;

    getter().......

}

像上面这样写就可以实现集中式配置更新后,代码可以不用重启自动生效。当然其实我们只需要将这些集中式配置值直接写在对应的Controller中即可,但是强迫症的我还是希望这些零碎的值可以存放在一起,利于我的管理,所以最终我采用了上面那种方式

二号坑

集中式配置中利用了spring中的@value注解,这个注解功能十分强大,可以实现很多类型的注入,包括字符串,list和map,需要注意的是配置list和map时的写法

配置字符串: 使用String接收
注解写法:  @Value("${config.innerauth}")
		  String dahui;
配置写法:  config.innerauth=xxxxxxx

配置list:表示按照逗号分割 其实还可以有很多种写法,比如按照#号  需要使用list接收 
注解写法:  @Value("${config.noauthlist:1,2,3}")
		  List dahui;
配置写法:  config.noauthlist=/xx/**,/xx.html,/xxxx.html/**,/xxxxx/**

配置map:需要使用hashmap接收
注解写法:  @Value("#{${config.xx}}")
		  HashMap<String,String> dahui;
配置写法:  config.xx={'1212':'2'}

注意,需要严格按照这样的格式来编写,否则不能正常注入值,比如config.xx={'1212':'2',}这样在后面结尾加上了一个逗号就会报错了,一定要谨慎哦