本文主要是介绍一文详解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中控制器的动态注册与卸载的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!