服务注册
服务发现
发布配置
获取配置
对于基本方法中的中的一些注解,涉及到权限管理的:@Secured
自定义注解:
了解自定义注解之前需要先了解相关的元注解,
java.lang.annotation提供了四种元注解,专门注解其他的注解(自定义注解的时候需要使用到元注解)
@Documented :注解将包含在javaDoc中
@Retention :什么时候使用该注解
@Target :注解用于什么地方
@Inherited :是否允许子类继承zhu'jie
@Retention :什么时候使用该注解--定义生命周期
RetentionPolicy.SOURCE :在编译阶段丢弃,这些注解在编译结束后就不再有任何的意义,
所以不会写入字节码,@Override,@SuppressWarnings都属于这类注解。
RetentionPolicy.CLASS:在类加载的时候丢弃,在字节码文件中处理有用,注解默认使用这种方式。
RetentionPolicy.RUNTIME:始终不会丢弃,运行期间是有保留这个注解的,因此可以使用反射机制读取该注解的信息,我们自定义的注解通常需要使用这种方式。
2、Target 表示该注解用于什么地方,默认任何元素,表示注解用于什么地方,可以用的ElementType参数包括:
● ElementType.CONSTRUCTOR: 用于描述构造器
● ElementType.FIELD: 成员变量、对象、属性(包括enum实例)
● ElementType.LOCAL_VARIABLE: 用于描述局部变量
● ElementType.METHOD: 用于描述方法
● ElementType.PACKAGE: 用于描述包
● ElementType.PARAMETER: 用于描述参数
● ElementType.TYPE: 用于描述类、接口(包括注解类型) 或enum声明
3.)@Documented – 一个简单的Annotations 标记注解,表示是否将注解信息添加在java 文档中。
4.)@Inherited – 定义该注释和子类的关系
@Inherited 元注解是一个标记注解,@Inherited 阐述了某个被标注的类型是被继承的。如果一个使用了@Inherited 修饰的annotation 类型被用于一个class,则这个annotation 将被用于该class 的子类。
自定义注解类编写的而一些规则:
1、annotation 型定义为@interface,所有的annotation会自动继承java.lang.Annotation这一个接口,并且不能再去继承别的类的接口。
2、参数成员只用使用public或者默认的defalut这两个访问权修饰符号。
3、数成员只能用基本类型byte、short、char、int、long、float、double、boolean八种基本数据类型和String、Enum、Class、annotations等数据类型,以及这一些类型的数组.
4、要获取类方法和字段的注解信息,必须通过Java的反射技术来获取 Annotation 对象,因为你除此之外没有别的获取注解对象的方法。
文章二:自定义注解与使用场景 https://www.jianshu.com/p/a7bedc771204
一般的使用场景为:自定义注解+拦截器或者aop,使用自定义的注解来自己设计框架,使得代码看起来非常的优雅。
Target:描述了注解修饰的对象范围,取值在java.lang.annotation.ElementType定义,常用的包括:
METHOD:用于描述方法
PACKAGE:用于描述包
PARAMETER:用于描述方法变量
TYPE:用于描述类、接口或enum类型
Retention: 表示注解保留时间长短。取值在java.lang.annotation.RetentionPolicy中,取值为:
SOURCE:在源文件中有效,编译过程中会被忽略
CLASS:随源文件一起编译在class文件中,运行时忽略
RUNTIME:在运行时有效
关于nacos中使用的自定义注解 @Secured
主要的作用还是权限管理,具体的自定义的注解的作用需要看拦截器中基于注解进行了哪些逻辑
在nacos中,@Secored的作用流程为
// 如果方法上有@Secored注解需要进行对应的逻辑判断。
if (method.isAnnotationPresent(Secured.class) && authConfigs.isAuthEnabled()) {
if (Loggers.AUTH.isDebugEnabled()) {
Loggers.AUTH.debug("auth start, request: {} {}", req.getMethod(), req.getRequestURI());
}
Secured secured = method.getAnnotation(Secured.class);
String action = secured.action().toString();
String resource = secured.resource();
if (StringUtils.isBlank(resource)) {
ResourceParser parser = getResourceParser(secured.parser());
resource = parser.parseName(req);
}
if (StringUtils.isBlank(resource)) {
// deny if we don't find any resource:
throw new AccessException("resource name invalid!");
}
authManager.auth(new Permission(resource, action), authManager.login(req));
}
chain.doFilter(request, response);
}
1、过滤器逻辑:
如果已经校验过是否还需要校验呢?// 从设计上应该是可以保存校验过的信息,不用每次访问都去校验。
a
authConfigs.isAuthEnabled()
authConfigs.isEnableUserAgentAuthWhite()
根据请求头查询 :userAgent
直接返回对应的值
如果userAgent字段是以Nacos-Server开头的(需要进一步逻辑处理)
一个适配器模式的例子:
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.alibaba.nacos.samples.spring.config;
import java.io.IOException;
import com.alibaba.nacos.api.config.convert.NacosConfigConverter;
import com.alibaba.nacos.samples.spring.domain.Pojo;
import com.fasterxml.jackson.databind.ObjectMapper;
/**
* {@link Pojo} Jackson {@link NacosConfigConverter}
*
* @author <a href="mailto:mercyblitz@gmail.com">Mercy</a>
* @since 0.1.0
*/
public class PojoNacosConfigConverter implements NacosConfigConverter<Pojo> {
private ObjectMapper objectMapper = new ObjectMapper();
@Override
public boolean canConvert(Class<Pojo> targetType) {
return objectMapper.canSerialize(targetType);
}
@Override
public Pojo convert(String config) {
try {
return objectMapper.readValue(config, Pojo.class);
}
catch (IOException e) {
throw new RuntimeException(e);
}
}
}