本文主要是介绍一文详解SpringBoot中控制器的动态注册与卸载,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
《一文详解SpringBoot中控制器的动态注册与卸载》在项目开发中,通过动态注册和卸载控制器功能,可以根据业务场景和项目需要实现功能的动态增加、删除,提高系统的灵活性和可扩展性,下面我们就来看看Sp...
在项目开发中,通过动态注册和卸载控制器功能,可以根据业务场景和项目需要实现功能的动态增加、删除,提高系统的灵活性和可扩展性。
本文将介绍如何在 SpringBoot 中实现控制器的动态注册和卸载。
项目结构
src
└── main
├── Java
│ └── com
│ └── example
│ ├── DynamicControllerApplication.java
│ ├── controller
│ │ ├── DemoController.java
│ │ └── DynamicControllerRegistry.java
│ │ └── DynamicController.java
│ │ └── ControllerManagement.java
│ └── config
│ └── WebConfig.java
└── resources
└── application.properties
1. 创建 Spring Boot 启动类
首先,创建一个启动类 DynamicControllerApplication.java
。
package com.example; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class DynamicControllerApplication { public static void main(String[] args) { SpringApplication.run(DynamicControllerApplication.class, args); } }
2. 创建一个测试控制器
接下来,我们创建一个控制器 DemoController.java
,该控制器将返回简单的字符串响应。
// 动态控制器注解 @Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) public @interface DynamicController { // 启动时注册 boolean startupRegister() default true; } // 测试控制器 package com.example.controller; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annoChina编程tation.RestController; @RestController @RequestMapping("/demo") @DynamicController(startupRegister = false) public class DemoController { @GetMapping("/hello") public String hello() { return "Hello from Dynamic Controller!"; } }
3. 创建动态控制器注册类
然后,我们创建一个 DynamicControllerRegistry.java
类,用于动态注册和卸载控制器。
package com.example.controller; import cn.hutool.core.util.ReflectUtil; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationContext; import org.springframework.core.annotation.AnnotatedElementUtils; import org.springframework.stereotype.Component; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.servlet.mvc.method.RequestMappingInfo; import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping; import java.lang.reflect.Method; import java.util.HashMap; import java.util.Map; @Component @Slf4j public class DynamicControllerRegistry { @Autowired php private ApplicationContext applicationContext; @Autowired private RequestMappingHandlerMapping reChina编程questMappingHandlerMapping; private final Map<String, String> registeredControllers = new HashMap<>(); public String registerController(Object controller,String methodName) { Class<?> controllerClass = controller.getClass(); String key = key(controllerClass,methodName); String url = ""; if (!registeredControllers.containsKey(key)) { Method m编程China编程ethod = ReflectUtil.getMethod(controllerClass,methodName); RequestMapping methodMapping = AnnotatedElementUtilswww.chinasem.cn.findMergedAnnotation(method, RequestMapping.class); RequestMapping requestMapping = controllerClass.getAnnotation(RequestMapping.class); url = getMethodUrl(requestMapping,methodMapping); // 注册控制器 requestMappingHandlerMapping.registerMapping( RequestMappingInfo.paths(url).methods(methodMapping.method()).build(), controller,method ); registeredControllers.put(key,url); }else{ url = registeredControllers.get(key); log.warn("controller already registered:{}",url); } return url; } public String unregisterController(Class<?> controllerClass,Method method) { RequestMapping methodMapping = AnnotatedElementUtils.findMergedAnnotation(method, RequestMapping.class); RequestMapping requestMapping = controllerClass.getAnnotation(RequestMapping.class); String url = getMethodUrl(requestMapping,methodMapping); RequestMappingInfo mappingInfo = RequestMappingInfo.paths(url).methods(methodMapping.method()).build(); requestMappingHandlerMapping.unregisterMapping(mappingInfo); registeredControllers.remove(key(controllerClass,method.getName())); log.info("unregister controller:{}", url); return url; } public String unregisterController(Class<?> controllerClass,String methodName) { Method method = ReflectUtil.getMethod(controllerClass,methodName); return unregisterController(controllerClass,method); } private String key(Class<?> controllerClass, String method){ return controllerClass.getName() + "." + method; } private String getMethodUrl(RequestMapping requestMapping,RequestMapping methodMapping){ String baseUrl = ""; String url = ""; if(requestMapping != null){ baseUrl = requestMapping.value()[0]; } if(methodMapping != null) { String[] values = methodMapping.value(); if (values.length > 0) { url = baseUrl + values[0]; } } return url; } }
4. 创建 Web 配置类
创建配置类 WebConfig.java
,实现项目启动时将不需要注册的控制器进行卸载。
package com.example.config; import cn.hutool.core.util.ClassUtil; import com.example.controller.DynamicController; import com.example.controller.DynamicControllerRegistry; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.annotation.AnnotatedElementUtils; import org.springframework.core.annotation.AnnotationUtils; import org.springframework.web.bind.annotation.RequestMapping; import java.lang.reflect.Method; import java.util.Map; import java.util.Set; @Configuration @Slf4j public class WebConfig { @Autowired private DynamicControllerRegistry dynamicControllerRegistry; @Bean public Void unregisterDynamicController() { Set<Class<?>> classes = ClassUtil.scanPackageByAnnotation("com.example", DynamicController.class); for(Class<?> clazz : classes) { DynamicController dynamicController = clazz.getAnnotation(DynamicController.class); boolean needRegister = dynamicController.startupRegister(); if(needRegister) { continue; } // 默认不需要注册的controller,需要在启动时注销掉 RequestMapping requestMapping = clazz.getAnnotation(RequestMapping.class); Method[] methods = clazz.getDeclaredMethods(); for(Method method : methods) { dynamicControllerRegistry.unregisterController(clazz,method); } } return null; } }
5. 创建动态控制器注册和卸载控制器
创建一个新的控制器 ControllerManagement.java
,用于处理控制器的注册和卸载请求。
package com.example.controller; import cn.hutool.extra.spring.SpringUtil; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; @RestController @RequestMapping("/controller") public class ControllerManagement { @Autowired private DynamicControllerRegistry dynamicControllerRegistry; @PostMapping("/register") public String registerController(@RequestParam String controllerBeanName, @RequestParam String methodName) { Object controller = SpringUtil.getBean(controllerBeanName); String url = dynamicControllerRegistry.registerController(controller, methodName); return "Controller registered at: " + url; } @DeleteMapping("/unregister") public String unregisterController(@RequestParam String controllerBeanName, @RequestParam String methodName) { Object controller = SpringUtil.getBean(controllerBeanName); String url = dynamicControllerRegistry.unregisterController(controller.getClass(),methodName); return "Controller unregistered from: " + url; } }
6. 测试注册控制器
1. 启动服务
2. 访问 http://localhost:8080/demo/hello ,此时应该是404,因为没有注册控制器
3. POST http://localhost:8080/controller/register?methodName=hello&controllerBeanName=demoController 注册控制器
4. 再次访问 http://localhost:8080/demo/hello
7. 卸载控制器
1. POST http://localhost:8080/controller/unregister?methodName=hello&controllerBeanName=demoController 卸载控制器
2. 再次访问 <http://localhost:8080/demo/hello>,此时应该是404,因为控制器已被卸载
结论
通过以上步骤,我们实现了在 Spring Boot 中动态注册和卸载控制器的功能。
这样的实现能够根据实际需求动态增减功能。
到此这篇关于一文详解SpringBoot中控制器的动态注册与卸载的文章就介绍到这了,更多相关SpringBoot控制器注册与卸载内容请搜索China编程(www.chinasem.cn)以前的文章或继续浏览下面的相关文章希望大家以后多多支持China编程(www.chinasem.cn)!
这篇关于一文详解SpringBoot中控制器的动态注册与卸载的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!