inleft
2022-02-09 9bcb19959eeb9da9bde2561e7278f6d0a55eb151
commit | author | age
9bcb19 1 /*
I 2 Copyright [2020] [https://www.xiaonuo.vip]
3
4 Licensed under the Apache License, Version 2.0 (the "License");
5 you may not use this file except in compliance with the License.
6 You may obtain a copy of the License at
7
8   http://www.apache.org/licenses/LICENSE-2.0
9
10 Unless required by applicable law or agreed to in writing, software
11 distributed under the License is distributed on an "AS IS" BASIS,
12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 See the License for the specific language governing permissions and
14 limitations under the License.
15
16 Snowy采用APACHE LICENSE 2.0开源协议,您在使用过程中,需要注意以下几点:
17
18 1.请不要删除和修改根目录下的LICENSE文件。
19 2.请不要删除和修改Snowy源码头部的版权声明。
20 3.请保留源码和相关描述文件的项目出处,作者声明等。
21 4.分发源码时候,请注明软件出处 https://gitee.com/xiaonuobase/snowy
22 5.在修改包名,模块名称,项目代码等时,请注明软件出处 https://gitee.com/xiaonuobase/snowy
23 6.若您的项目无法满足以上几点,可申请商业授权,获取Snowy商业授权许可,请在官网购买授权,地址为 https://www.xiaonuo.vip
24  */
25 package vip.xiaonuo.sys.core.scanner;
26
27 import cn.hutool.core.collection.CollectionUtil;
28 import cn.hutool.core.util.StrUtil;
29 import org.springframework.beans.BeansException;
30 import org.springframework.beans.factory.config.BeanPostProcessor;
31 import org.springframework.stereotype.Controller;
32 import org.springframework.web.bind.annotation.GetMapping;
33 import org.springframework.web.bind.annotation.PostMapping;
34 import org.springframework.web.bind.annotation.RequestMapping;
35 import org.springframework.web.bind.annotation.RestController;
36 import vip.xiaonuo.core.consts.SymbolConstant;
37 import vip.xiaonuo.core.context.resources.ApiResourceContext;
38 import vip.xiaonuo.core.util.AopTargetUtil;
39
40 import java.lang.annotation.Annotation;
41 import java.lang.reflect.AnnotatedElement;
42 import java.lang.reflect.Method;
43 import java.util.Set;
44
45 /**
46  * 资源扫描器
47  *
48  * @author yubaoshan
49  * @date 2018/1/3 14:58
50  */
51 public class ApiResourceScanner implements BeanPostProcessor {
52
53     @Override
54     public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
55         return bean;
56     }
57
58     @Override
59     public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
60
61         //如果controller是代理对象,则需要获取原始类的信息
62         Object aopTarget = AopTargetUtil.getTarget(bean);
63
64         if (aopTarget == null) {
65             aopTarget = bean;
66         }
67         Class<?> clazz = aopTarget.getClass();
68
69         //判断是不是控制器,不是控制器就略过
70         boolean controllerFlag = getControllerFlag(clazz);
71         if (!controllerFlag) {
72             return bean;
73         }
74
75         //扫描控制器的所有带ApiResource注解的方法
76         Set<String> apiUrls = doScan(clazz);
77
78         //将扫描到的注解存储到缓存
79         persistApiResources(apiUrls);
80
81         return bean;
82     }
83
84
85     /**
86      * 判断一个类是否是控制器
87      *
88      * @author yubaoshan
89      * @date 2020/6/21 18:23
90      */
91     private boolean getControllerFlag(Class<?> clazz) {
92         Annotation[] annotations = clazz.getAnnotations();
93
94         for (Annotation annotation : annotations) {
95             if (RestController.class.equals(annotation.annotationType()) || Controller.class.equals(annotation.annotationType())) {
96                 return true;
97             }
98         }
99         return false;
100     }
101
102     /**
103      * 扫描整个类中包含的所有控制器
104      *
105      * @author yubaoshan
106      * @date 2020/6/21 18:23
107      */
108     private Set<String> doScan(Class<?> clazz) {
109
110         // 获取类头的@RequestMapping内容
111         String primaryMappingUrl = getRequestMappingUrl(clazz);
112
113         // 获取所有方法的RequestMapping的url
114         Set<String> apiResources = CollectionUtil.newHashSet();
115         Method[] declaredMethods = clazz.getDeclaredMethods();
116         if (declaredMethods.length > 0) {
117             for (Method declaredMethod : declaredMethods) {
118                 String requestMappingUrl = getRequestMappingUrl(declaredMethod);
119                 apiResources.add(primaryMappingUrl + requestMappingUrl);
120             }
121         }
122         return apiResources;
123     }
124
125     /**
126      * 存储扫描到的api资源
127      *
128      * @author yubaoshan
129      * @date 2020/6/21 17:43
130      */
131     private void persistApiResources(Set<String> apiResources) {
132         ApiResourceContext.addBatchUrls(apiResources);
133     }
134
135     /**
136      * 获取@RequestMapping注解的url信息
137      *
138      * @author yubaoshan
139      * @date 2020/6/21 17:43
140      */
141     private String getRequestMappingUrl(AnnotatedElement annotatedElement) {
142
143         RequestMapping requestMapping = annotatedElement.getAnnotation(RequestMapping.class);
144         GetMapping getMapping = annotatedElement.getAnnotation(GetMapping.class);
145         PostMapping postMapping = annotatedElement.getAnnotation(PostMapping.class);
146
147         // 分别判断三个注解中有没有value和path的值,优先级是 RequestMapping > GetMapping > PostMapping
148         if (requestMapping != null) {
149             String[] value = requestMapping.value();
150             String[] path = requestMapping.path();
151             if (value.length > 0) {
152                 return getRequestMappingPath(value);
153             } else if (path.length > 0) {
154                 return getRequestMappingPath(path);
155             }
156         } else if (getMapping != null) {
157             String[] value = getMapping.value();
158             String[] path = getMapping.path();
159             if (value.length > 0) {
160                 return getRequestMappingPath(value);
161             } else if (path.length > 0) {
162                 return getRequestMappingPath(path);
163             }
164         } else if (postMapping != null) {
165             String[] value = postMapping.value();
166             String[] path = postMapping.path();
167             if (value.length > 0) {
168                 return getRequestMappingPath(value);
169             } else if (path.length > 0) {
170                 return getRequestMappingPath(path);
171             }
172         }
173
174         return "";
175     }
176
177     /**
178      * 获取数组第一个字符串
179      *
180      * @author yubaoshan
181      * @date 2020/6/21 18:10
182      */
183     private String getRequestMappingPath(String[] strings) {
184         if (strings.length == 0) {
185             return "";
186         }
187         String result = strings[0];
188
189         // 如果RequestMapping的值是“/”直接返回
190         if (SymbolConstant.LEFT_DIVIDE.equals(result)) {
191             return result;
192         }
193
194         // 添加路径首部的"/"
195         if (!result.startsWith(SymbolConstant.LEFT_DIVIDE)) {
196             result = SymbolConstant.LEFT_DIVIDE + result;
197         }
198
199         // 则去掉尾部的"/"
200         if (result.endsWith(SymbolConstant.LEFT_DIVIDE)) {
201             result = StrUtil.removeSuffix(result, SymbolConstant.LEFT_DIVIDE);
202         }
203
204         return result;
205     }
206
207 }