APIJSON(11: AbstractVerifier 소스 코드 읽기(2))

APIJSON(11: AbstractVerifier 소스 코드 읽기(2))

2021SC@SDUSC

요소 정의

물론 수업 초반에는 여전히 많은 요소 정의가 있습니다——

// 共享 STRUCTURE_MAP 则不能 remove 等做任何变更,否则在并发情况下可能会出错,加锁效率又低,所以这里改为忽略对应的 key
public static final Map<String, Entry<String, Object>> ROLE_MAP;

public static final List<String> OPERATION_KEY_LIST;

// <TableName, <METHOD, allowRoles>>
// <User, <GET, [OWNER, ADMIN]>>
@NotNull
public static final Map<String, Map<RequestMethod, String[]>> SYSTEM_ACCESS_MAP;
@NotNull
public static final Map<String, Map<RequestMethod, String[]>> ACCESS_MAP;

// <method tag, <version, Request>>
// <PUT Comment, <1, { "method":"PUT", "tag":"Comment", "structure":{ "MUST":"id"... }... }>>
@NotNull
public static final Map<String, SortedMap<Integer, JSONObject>> REQUEST_MAP;

// 正则匹配的别名快捷方式,例如用 "PHONE" 代替 "^((13[0-9])|(15[^4,\\D])|(18[0-2,5-9])|(17[0-9]))\\d{8}$"
@NotNull
public static final Map<String, Pattern> COMPILE_MAP;

지도

여기서 많은 @NotNull 주석을 사용하여 비워둘 수 없음을 선언하고 지도 인터페이스

Map은 Java의 인터페이스이고 Map.Entry는 Map의 내부 인터페이스입니다.

Map은 keySet(), entrySet() 및 기타 메소드와 같은 몇 가지 일반적인 메소드를 제공합니다.

keySet() 메서드의 반환 값은 Map에 있는 키 값의 모음이고 entrySet()의 반환 값도 Set 모음을 반환하며 이 모음의 유형은 Map.Entry입니다.

Map.Entry는 Map에 의해 선언된 내부 인터페이스로 제네릭이며 Entry<K,V>로 정의됩니다. 맵에서 엔터티(키-값 쌍)를 나타냅니다. 인터페이스에는 getKey() 및 getValue 메서드가 있습니다.

다음은 정적 블록입니다.

static {
   ROLE_MAP = new LinkedHashMap<>();
   ROLE_MAP.put(UNKNOWN, new Entry<String, Object>());
   ROLE_MAP.put(LOGIN, new Entry<String, Object>("userId>", 0));
   ROLE_MAP.put(CONTACT, new Entry<String, Object>("userId{}", "contactIdList"));
   ROLE_MAP.put(CIRCLE, new Entry<String, Object>("userId-()", "verifyCircle()")); // "userId{}", "circleIdList"));  // 还是 {"userId":"currentUserId", "userId{}": "contactIdList", "@combine": "userId,userId{}" } ? 
   ROLE_MAP.put(OWNER, new Entry<String, Object>("userId", "userId"));
   ROLE_MAP.put(ADMIN, new Entry<String, Object>("userId-()", "verifyAdmin()"));
   
   OPERATION_KEY_LIST = new ArrayList<>();
   OPERATION_KEY_LIST.add(TYPE.name());
   OPERATION_KEY_LIST.add(VERIFY.name());
   OPERATION_KEY_LIST.add(INSERT.name());
   OPERATION_KEY_LIST.add(UPDATE.name());
   OPERATION_KEY_LIST.add(REPLACE.name());
   OPERATION_KEY_LIST.add(EXIST.name());
   OPERATION_KEY_LIST.add(UNIQUE.name());
   OPERATION_KEY_LIST.add(REMOVE.name());
   OPERATION_KEY_LIST.add(MUST.name());
   OPERATION_KEY_LIST.add(REFUSE.name());


   SYSTEM_ACCESS_MAP = new HashMap<String, Map<RequestMethod, String[]>>();

   SYSTEM_ACCESS_MAP.put(Access.class.getSimpleName(), getAccessMap(Access.class.getAnnotation(MethodAccess.class)));
   SYSTEM_ACCESS_MAP.put(Function.class.getSimpleName(), getAccessMap(Function.class.getAnnotation(MethodAccess.class)));
   SYSTEM_ACCESS_MAP.put(Request.class.getSimpleName(), getAccessMap(Request.class.getAnnotation(MethodAccess.class)));
   SYSTEM_ACCESS_MAP.put(Response.class.getSimpleName(), getAccessMap(Response.class.getAnnotation(MethodAccess.class)));

   if (Log.DEBUG) {
      SYSTEM_ACCESS_MAP.put(Table.class.getSimpleName(), getAccessMap(Table.class.getAnnotation(MethodAccess.class)));
      SYSTEM_ACCESS_MAP.put(Column.class.getSimpleName(), getAccessMap(Column.class.getAnnotation(MethodAccess.class)));
      SYSTEM_ACCESS_MAP.put(PgAttribute.class.getSimpleName(), getAccessMap(PgAttribute.class.getAnnotation(MethodAccess.class)));
      SYSTEM_ACCESS_MAP.put(PgClass.class.getSimpleName(), getAccessMap(PgClass.class.getAnnotation(MethodAccess.class)));
      SYSTEM_ACCESS_MAP.put(SysTable.class.getSimpleName(), getAccessMap(SysTable.class.getAnnotation(MethodAccess.class)));
      SYSTEM_ACCESS_MAP.put(SysColumn.class.getSimpleName(), getAccessMap(SysColumn.class.getAnnotation(MethodAccess.class)));
      SYSTEM_ACCESS_MAP.put(ExtendedProperty.class.getSimpleName(), getAccessMap(ExtendedProperty.class.getAnnotation(MethodAccess.class)));

      SYSTEM_ACCESS_MAP.put(Document.class.getSimpleName(), getAccessMap(Document.class.getAnnotation(MethodAccess.class)));
      SYSTEM_ACCESS_MAP.put(TestRecord.class.getSimpleName(), getAccessMap(TestRecord.class.getAnnotation(MethodAccess.class)));
   }

   ACCESS_MAP = new HashMap<>(SYSTEM_ACCESS_MAP);

   REQUEST_MAP = new HashMap<>(ACCESS_MAP.size()*6);  // 单个与批量增删改

   COMPILE_MAP = new HashMap<String, Pattern>();
}

공전{}

개념 설명

1. 클래스 로딩의 특징
JVM의 라이프 사이클에서 각 클래스는 한번만 로딩된다.

클래스 로딩의 원칙: 레이지 로딩, 가상 머신의 공간이 제한되어 있기 때문에 가능한 한 적게 로드합니다.

2. 클래스 로딩 시점
1) 객체를 처음 생성할 때 클래스를 로딩해야 합니다.

2) 정적 메서드를 호출하면 클래스가 로드되고 정적 속성에 액세스하면 클래스가 로드됩니다.

3) 서브 클래스를 불러올 때 부모 클래스를 먼저 불러와야 합니다.

4) 개체 참조를 생성해도 클래스가 로드되지 않습니다.

  1. 자식 클래스가 부모 클래스의 정적 메서드를 호출하는 경우

(1) 서브클래스가 부모 클래스의 정적 메서드를 오버라이드하지 않는 경우 부모 클래스만 로드되고 서브 클래스는 로드되지 않음

(2) 하위 클래스에 상위 클래스를 재정의하는 정적 메서드가 있는 경우 상위 클래스와 하위 클래스가 모두 로드됩니다.

6) 정적 상수에 액세스하기 위해 컴파일러가 상수 값을 계산할 수 있으면 클래스가 로드되지 않습니다(예: public static final int a =123). 그렇지 않으면 클래스가 로드됩니다(예: public static final int). a = 수학.PI.

정적 블록(정적{})
(1) 정적 키워드는 프로그램 성능을 최적화하기 위해 정적 코드 블록(정적{}(즉, 정적 블록))을 형성하는 데 사용되는 보다 중요한 역할을 합니다.

(2) 정적 블록은 클래스의 아무 곳에나 배치할 수 있으며 클래스에 여러 개의 정적 블록이 있을 수 있습니다.

(3) 클래스가 처음 로드될 때 실행되며 한 번만 실행됩니다(이것이 성능을 최적화하는 이유입니다!!!) 각 정적 블록은 정적 블록의 순서대로 실행되며 일반적으로 정적 변수를 초기화하고 정적 메서드를 호출합니다.
그렇지 않으면 메서드가 호출될 때마다 이러한 멤버 개체가 생성되어 공간 낭비가 발생합니다.

LinkedHashMap

ROLE_MAP = new LinkedHashMap<>();

먼저 LinkedHashMap 객체가 생성된 것을 확인할 수 있습니다.

본질적으로 LinkedHashMap = HashMap + 이중 연결 목록, 즉 HashMap과 이중 연결 목록의 조합은 LinkedHashMap입니다. 또한 LinkedHashMap은 HashMap을 변경하지 않고 HashMap의 두 노드 사이에 두 개의 링크(포인터 앞과 포인터 뒤)를 추가하여 이러한 노드가 이중 연결 목록을 형성한다는 것도 이해할 수 있습니다. LinkedHashMapMap에서는 모든 put 항목이 HashMap에 저장되지만 head를 헤드 노드로 하는 빈 이중 연결 목록을 추가로 정의하므로 tail의 각 put 항목에 대해 이중 연결 목록에 삽입됩니다.
여기에 사진 설명 쓰기

널리 사용되는 put 방식은 LinkedHashMap에 키-값 쌍을 추가하는 방식이다. 자세한 내용은 다음 문서를 참조하십시오.

맵 개요 (1): HashMap에 대한 철저한 이해

맵 개요(2): LinkedHashMap에 대한 철저한 이해

목록

public static final List<String> OPERATION_KEY_LIST;

List는 Collection의 인터페이스를 상속받은 인터페이스입니다. 순서가 지정된 대기열을 나타냅니다.

List의 요소는 반복될 수 있으며 순서가 있습니다(여기서 순서는 배치된 순서대로 저장소를 나타냅니다. 1, 2, 3이 순서대로 List에 저장되면 목록도 1, 2, 3)입니다.

무효 추가(int 인덱스, E 요소)

지정된 위치에 요소를 삽입하면 모든 후속 요소가 한 요소 뒤로 이동합니다.

이미지

실현 방법

getAccessMap

public static HashMap<RequestMethod, String[]> getAccessMap(MethodAccess access)

getAccessMap에 의해 전달된 값은 MethodAccess 클래스입니다.

public @interface MethodAccess

이것은 MethodAccess 클래스의 정의이며 @interface가 이상하게 보입니다.

Java에서 @interface와 interface의 차이점

Java Annotation이란
Java는 1.5부터 Annotation(annotation, annotation)을 제공하고 있으며 이는 응용 프로그램 요소(클래스, 메서드, 속성, 매개 변수, 로컬 변수, 패키지, 메타 데이터)를 장식하는 데 사용되며 컴파일러는 이를 메타 데이터와 비교하여 저장합니다. 클래스 파일에 함께 포함되며 수정된 요소에 대한 액세스는 런타임 동안 Java 리플렉션을 통해 처리됩니다. 주석은 요소를 장식하는 데만 사용되며 코드 실행에는 영향을 줄 수 없습니다. 해당 정보는 지원 프레임워크 또는 도구를 통해서만 액세스하고 처리할 수 있습니다.

차이점

① 인터페이스: 자바 인터페이스임을 선언

②, @interface: Annotation을 수정하기 위해 사용되며, 인터페이스가 아님을 유의하시기 바랍니다. 이 키워드 선언은 메시지를 의미합니다. 인터페이스를 선언하는 대신 java.lang.annotation.Annotation 인터페이스를 상속합니다.

그 중 요청 방식의 권한을 주로 정의하고 해당 방식을 통해 특정 역할만 데이터베이스에 접근할 수 있도록 한다.

예를 들어 get 메서드에서 기본적으로 허용되는 역할은 UNKNOWN, LOGIN, CONTACT, CIRCLE, OWNER, ADMIN입니다.

String[] GET() default {UNKNOWN, LOGIN, CONTACT, CIRCLE, OWNER, ADMIN};

이러한 메소드의 권한은 낮음에서 높음으로, POST, PUT, DELETE 메소드는 기본적으로 OWNER 또는 ADMIN만 사용할 수 있음을 알 수 있습니다.

String[] GET() default {UNKNOWN, LOGIN, CONTACT, CIRCLE, OWNER, ADMIN};

String[] HEAD() default {UNKNOWN, LOGIN, CONTACT, CIRCLE, OWNER, ADMIN};

String[] GETS() default {LOGIN, CONTACT, CIRCLE, OWNER, ADMIN};

String[] HEADS() default {LOGIN, CONTACT, CIRCLE, OWNER, ADMIN};

String[] POST() default {OWNER, ADMIN};

String[] PUT() default {OWNER, ADMIN};

String[] DELETE() default {OWNER, ADMIN};

이러한 권한 맵을 얻는 데 사용되는 getAcessMap 메서드로 돌아갑니다.

if (access == null) {
   return null;
}

HashMap<RequestMethod, String[]> map = new HashMap<>();
map.put(GET, access.GET());
map.put(HEAD, access.HEAD());
map.put(GETS, access.GETS());
map.put(HEADS, access.HEADS());
map.put(POST, access.POST());
map.put(PUT, access.PUT());
map.put(DELETE, access.DELETE());
return map;

넣다(GET, 액세스.GET());
map.put(HEAD, access.HEAD());
map.put(GETS, access.GETS());
map.put(HEADS, access.HEADS());
map.put(POST, access.POST());
map.put(PUT, access.PUT());
map.put(DELETE, access.DELETE());
반환 지도;


它首先进行判断access是否为空,不是的话,就会创建一个HashMap对这些权限进行依次存储,并返回这个HashMap。

추천

출처blog.csdn.net/qq_50861917/article/details/121878897