在项目开发中,通过动态注册和卸载控制器功能,可以根据业务场景和项目需要实现功能的动态增加、删除,提高系统的灵活性和可扩展性。
本文将介绍如何在 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.annotation.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
private applicationcontext applicationcontext;
@autowired
private requestmappinghandlermapping requestmappinghandlermapping;
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 method = reflectutil.getmethod(controllerclass,methodname);
requestmapping methodmapping = annotatedelementutils.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控制器注册与卸载内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!
发表评论