ビジネスシナリオについて考え、技術的な実装のみを共有します。次のデモは便宜上会社のプロジェクトで直接書かれているので、いくつかの機密情報の適切な名詞についてコメントしたいと思います。ご理解いただければ幸いです。
まず第一に、SpringのIOCメカニズム、すべてのインターフェイスとサービスには、BeanFactoryとApplicationContextを介して取得できるマップコンテナがあることは誰もが知っています。そうすれば、これから操作できます。
オプション1
(1)ApplicationContextを取得できるメソッドまたはインターフェイスについて考えてください。答えはもちろん、Awareインターフェイスです。ApplicationContextAwareを見つけた場合、理論的にはApplicationContextコンテナ自体を取得できます。
Awareインターフェイスの詳細な説明:SpringBootのAwareインターフェイス
(2)ApplicationContextが取得され、残りは実際にはそこからインターフェイスを取得することです。ここでは、便宜上、起動後にrunメソッドを直接書き直します。
CommandLineRunner:このインターフェイスを実装し、runメソッドをオーバーライドすることで、スタートアップクラスの完了後に実行したいことを実行できます。複数のメソッドがCommandLineRunnerインターフェイスを継承する場合は、複数のrunメソッドを実行する必要があり、シーケンスと@が必要です。 Order(value =)に重みを割り当てることができます。
@Component
@Order(value = 2)
public class A implements CommandLineRunner{
@Override
public void run(String... strings) throws Exception {
}
}
@Component
@Order(value = 1)
public class B implements CommandLineRunner {
@Override
public void run(String... strings) throws Exception {
}
}
このように、正常に起動した後、BはAの前に実行する必要があります。
遠くまで行き、それについて言えば、便宜上書くだけです:
@Override
public void run(String... args) throws Exception {
//获取使用RestController注解标注的的所有controller类
Map<String, Object> controllers = applicationContext.getBeansWithAnnotation(RestController.class);
//遍历每个controller层
for (Map.Entry<String, Object> entry : controllers.entrySet()) {
Object value = entry.getValue();
System.out.println("拿到controller:"+entry.getKey()+",拿到value:"+value);
Class<?> aClass = AopUtils.getTargetClass(value);
System.out.println("拿到Class:"+aClass);
}
}
まず、出力を直接見てください。
GoodControllerとAnalysisControllerが見つかったことがわかりますが、具体的に例を挙げたGood2Controllerは見つかりませんでした。
その理由は、Good2ではRestControllerアノテーションを使用せず、代わりに@Controller + @ResponseBodyを使用したためです。これは小さな穴です。もちろん、RestControllerコンポジットアノテーションに含まれる@Controllerが見つかるとは思わないでください。結果はそうではありません。これはインターフェイスタイプに基づいているため、RestController.classでない限り、インターフェイスの内容は関係ありません。均一に検出されません。
(3)すべてのコントローラーの取得に成功しましたが、インターフェースがコントローラーの下のパブリックメソッドを参照していることは誰もが知っているので、引き続き見下ろします。上記のコードにこの行を追加し続けます。
実行結果:
正常に印刷されました〜
(4)すべてのメソッドを検出するのではなく、Get、Post、Putなどのメソッドを選択的に検出する場合も、非常に簡単です。
// 首先拿到所有的方法
List<Method> declaredMethods = Arrays.asList(aClass.getDeclaredMethods());
for (int i = 0; i < declaredMethods.size() ; i++) {
// 下面开始根据注解类型进行输出统计
GetMapping getMapping = declaredMethods.get(i).getAnnotation(GetMapping.class);
PostMapping postMapping = declaredMethods.get(i).getDeclaredAnnotation(PostMapping.class);
System.out.println("Get相关的:"+JSON.toJSONString(getMapping));
System.out.println("Post相关的:"+JSON.toJSONString(postMapping));
}
成功〜!
(5)全体的なコードを提供します。統計またはその他のインターフェイスを実行する場合は、MapおよびSETを使用して自分で実装します。
public class EarlyWarningApplication implements ApplicationContextAware ,CommandLineRunner {
// 定义一个私有的方便本class中调用
private ApplicationContext applicationContext;
// 通过重写ApplicationContextAware感知接口,将ApplicationContext赋值给当前的私有context容器
@Override
public void setApplicationContext(ApplicationContext arg0) {
this.applicationContext = arg0;
}
public static void main(String[] args) {
SpringApplication application = new SpringApplication(EarlyWarningApplication.class);
application.run(args);
}
@Override
public void run(String... args) throws Exception {
Map<String, Object> controllers = applicationContext.getBeansWithAnnotation(RestController.class);
for (Map.Entry<String, Object> entry : controllers.entrySet()) {
Object value = entry.getValue();
System.out.println("拿到controller:"+entry.getKey()+",拿到value:"+value);
Class<?> aClass = AopUtils.getTargetClass(value);
System.out.println("拿到Class:"+aClass);
RequestMapping annotation = aClass.getAnnotation(RequestMapping.class);
RequestMapping declaredAnnotation = aClass.getDeclaredAnnotation(RequestMapping.class);
List<Method> methods = Arrays.asList(aClass.getMethods());
System.out.println("Public Methods:" + methods);
List<Method> declaredMethods = Arrays.asList(aClass.getDeclaredMethods());
for (int i = 0; i < declaredMethods.size() ; i++) {
GetMapping getMapping = declaredMethods.get(i).getAnnotation(GetMapping.class);
PostMapping postMapping = declaredMethods.get(i).getDeclaredAnnotation(PostMapping.class);
System.out.println("Get相关的:"+JSON.toJSONString(getMapping));
System.out.println("Post相关的:"+JSON.toJSONString(postMapping));
}
}
}
}
オプションII
(1)ApplicationContextの息子に属するWebApplicationContextグローバルインターフェイスの壮大な紹介。多くの機能がありますが、今日です!ここにあります!これは、各コントローラーのすべてのパブリックインターフェイスを取得するためにのみ使用されます〜
(2)コードを直接書き込むか、サービスまたはコントローラーに直接書き込むか、またはどこにでも記述します。
@Autowired
WebApplicationContext applicationContext;
@GetMapping("/getParam")
public String getParam(){
RequestMappingHandlerMapping mapping = applicationContext.getBean(RequestMappingHandlerMapping.class);
// 拿到Handler适配器中的全部方法
Map<RequestMappingInfo, HandlerMethod> methodMap = mapping.getHandlerMethods();
List<String> urlList = new ArrayList<>();
for (RequestMappingInfo info : methodMap.keySet()){
Set<String> urlSet = info.getPatternsCondition().getPatterns();
// 获取全部请求方式
Set<RequestMethod> Methods = info.getMethodsCondition().getMethods();
System.out.println(Methods.toString());
for (String url : urlSet){
// 加上自己的域名和端口号,就可以直接调用
urlList.add("http://localhost:XXXX"+url);
}
}
return urlList.toString();
}