如非授权,禁止用于商业用途,转载请注明出处
作者:mynewworldyyl
往下看前,建议完成前面1到10小节
JMicro目前仅支持基于Zookeeper做配置管理,全部配置信息可以在ZK做增删改查,建议通过ZKUI做对配置做日常管理,非常方便( 【8】JMicro微服务-JMicro ZKUI)
1. 使用
应用中只需要通过Cfg注解即可使用配置,如
@Cfg("/defaultLimiterName") private String name; @Cfg(value="/TestRpcServiceImpl/MapParams-*") public Map<String,String> params = null;
Cfg注解唯一必填属性为value,表示配置的KEY,Key以“/”开始,组成ZK中配置路径的一部份。
@Target(FIELD) @Retention(RUNTIME) public @interface Cfg { /** * value值以“/”开始,以非“/”结束 * 对于Map,可以以*号结尾,表示匹配的条目全部放Map中,Key即配置的Key值,字符串类型,通过Map的泛型解析Value的类型 * 相对于org.jmicro.Config#CfgDir 或 org.jmicro.Config#ServiceConfigDir 的路径 */ public String value(); /** * 是否是必填属性 * @return */ public boolean required() default false; /** * 配置改变监听器,如果配置的值改变时,系统会调用这个值作为名称的对应的方法,以通知应用配置值改变了 * 方法名可以不带参数,或者带一个参数,参数的值即为修改后的最新值,系统 优先调用带参数同名方法。 * @return */ public String changeListener() default ""; /** * 是否默认使用全局配置(org.jmicro.Config#CfgDir ZK中全局配置路径下的值) * 如果全局配置有值,则不使用服务级配置,否则优先使用服务级配置 * org.jmicro.Config#ServiceConfigDir 路径下的值 * @return */ public boolean defGlobal() default true; }
2. 通过API获取配置的值
代码中可以通过Config实例获取配置,如
Config中还有很多get开头的方法,用以获取不同配置来源的配置值,如getServiceParam获取服务实例级参数,getGlobalParam获取全局配置参数,getCommandParam取命令行参数,getValue按特定优先级获取参数 等等。
3. 配置信息源
Cfg注解按如下优先级取配置,从高到低分别为,如果高优先级获取到值,则不会去低优先级取值
a. 命令行参数:启动JVM时,通过-D设置的参数,具有最高优先级;
b. 服务实例级参数org.jmicro.Config#ServiceConfigDir,值可以实时修改生效;
c. 服务级参数(目前未实现)值可以实时修改生效;
d. 全局服务参数org.jmicro.Config#CfgDir,值可以实时修改生效;
e. /META-INF/jmicro/*.properties目录下配置的参数;
f. 系统环境变量System.getProperty(key)
g. 系统环境变量System.getenv(key)
Cfg注解就是按特定优先级获取参数,所以配置时特别注意优先级并按需要存放配置信息。
4. 默认值
如果代码中按如下方式编写,则在系统启动时,如果ZK中还不存在/TestRpcServiceImpl/defaultLimiterName对应值,系统会将当前值defaultLimit存储到ZK中,下次启动时就会默认使用这个值,并且这个值可以修改并持久生效,这就是为什么前面启动的很多服务都没有做任何配置就能启动的原因。
@Cfg("/TestRpcServiceImpl/defaultLimiterName") private String name="defaultLimit";
5. Map<String,Value>配置
如下代码,系统会将全部以/TestRpcServiceImpl/MapParams-打头(后面必须有*号)的Key对应的值加入到params中,KEY即是路径值,路径值必然是字符串,
所以params的KEY必须是字符串类型。
值可以是任意类型,如果是Java 8种基本数据类型,则直接转换,否则通过JSON反序列化为指定类型,通过泛型获取值的类型,所以这个Map参数必须通过泛型定义。
@Cfg(value="/TestRpcServiceImpl/MapParams-*") public Map<String,String> params = null;
Map的Cfg注解的value必须以*号结尾
5. Collection<Value>配置
Collection包括List和Set,必须通过泛型定义元素类型。如下代码表示以/StaticResourceHttpHandler/staticResourceRoot_开头的配置值全部加到staticResourceRoots 列表中,changeListener指定有新值加入时,调用resourceRootChange方法。
@Cfg(value="/StaticResourceHttpHandler/staticResourceRoot_*", changeListener="resourceRootChange") private List<String> staticResourceRoots = new ArrayList<>();
resourceRootChange方法定义如下:
public void resourceRootChange(String root) { if(!staticResourceRoots.contains(root)) { return; } Set<String> clears = new HashSet<String>(); for(String p : contents.keySet()) { if(p.startsWith(root)) { clears.add(p); } } for(String p : clears) { contents.remove(p); } }
这段代码的意思是如果当前web静态资源存在缓存中,则将其缓存删除,以使下次有资源请求时,重新从系统加载资源。
Collection另外一种配置方式,
@Cfg(value="/StaticResourceHttpHandler/staticResourceRoot", changeListener="resourceRootChange") private List<String> staticResourceRoots = new ArrayList<>();
value不以*号结尾,配置注入时,将值以英文逗号做分隔,然后再将每个分隔后的值转化为集合元素类型值,并加入到集合中。
6. 数组配置
数组配置注入逻辑与集合相同,样例代码如下:
@Cfg("/RouterManager/routerSort") private String[] routerSorts = {"tagRouter","serviceRouter","ipRouter"};
以上代码作用是注入服务路由优先级,因为只有一个属性值,所以省略了value名称。
7. ZK路径与properties,命令行参数配置风格兼容
在java的properties文件中,通常是使用"."号作为Key中单词的分隔符,而ZK的路径必须以"/"做分隔。在JMicro配置管理系统中对两者做兼容。以上5和6小节的value值又可以配置为以下等价形式:
@Cfg(value="StaticResourceHttpHandler.staticResourceRoot", changeListener="resourceRootChange") private List<String> staticResourceRoots = new ArrayList<>();
@Cfg("RouterManager.routerSort") private String[] routerSorts = {"tagRouter","serviceRouter","ipRouter"};
用户可以在jmicro.example.provider及jmicro.example.comsumer相关代码中做测试,也可以自己按相同的方式写java项目做测试
JMicro微服务基础入门系列: