当前位置: 代码网 > it编程>编程语言>Java > 一文详解SpringBoot中控制器的动态注册与卸载

一文详解SpringBoot中控制器的动态注册与卸载

2025年07月06日 Java 我要评论
在项目开发中,通过动态注册和卸载控制器功能,可以根据业务场景和项目需要实现功能的动态增加、删除,提高系统的灵活性和可扩展性。本文将介绍如何在 springboot 中实现控制器的动态注册和卸载。项目结

在项目开发中,通过动态注册和卸载控制器功能,可以根据业务场景和项目需要实现功能的动态增加、删除,提高系统的灵活性和可扩展性。

本文将介绍如何在 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控制器注册与卸载内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2025  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com