测试RestController拦截,后续改为委托方式进行方法增强

This commit is contained in:
kazusa 2025-07-23 16:46:31 +08:00
parent 27adffa183
commit 4e0ee42053
14 changed files with 364 additions and 249 deletions

15
pom.xml
View File

@ -25,7 +25,6 @@
<junit.version>5.10.0</junit.version>
<logback.version>1.5.13</logback.version>
<slf4j.version>2.0.16</slf4j.version>
<spring.version>5.3.37</spring.version>
<jackson.version>2.17.3</jackson.version>
</properties>
@ -71,20 +70,6 @@
<version>${logback.version}</version>
</dependency>
<!-- Spring Web -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>${spring.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${spring.version}</version>
<scope>provided</scope>
</dependency>
<!-- Jackson for JSON -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>

View File

@ -18,5 +18,16 @@
<name>Spring MVC Plugin</name>
<description>Spring MVC interceptor plugin for Press Monster</description>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
</dependency>
</dependencies>
</project>

View File

@ -1,17 +1,14 @@
package io.github.kazusa.pressmonster.plugins.web;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import net.bytebuddy.description.annotation.AnnotationDescription;
import org.slf4j.Logger;
import io.github.kazusa.pressmonster.common.logging.LoggerFactory;
import io.github.kazusa.pressmonster.common.plugin.PluginInfo;
import io.github.kazusa.pressmonster.common.plugin.TransformerPlugin;
import net.bytebuddy.agent.builder.AgentBuilder;
import net.bytebuddy.asm.Advice;
import net.bytebuddy.matcher.ElementMatchers;
import org.slf4j.Logger;
import java.lang.reflect.Method;
/**
* RestController拦截插件
@ -69,10 +66,11 @@ public class RestControllerPlugin implements TransformerPlugin {
logger.info("配置RestController字节码转换器");
return agentBuilder
// 临时方案先用包名匹配Controller类运行时验证注解
.type(ElementMatchers.nameContains("Controller")
.and(ElementMatchers.not(ElementMatchers.isInterface()))
.and(ElementMatchers.not(ElementMatchers.isAbstract())))
//ElementMatchers.isAnnotatedWith(RestController.class)
//.and(ElementMatchers.not(ElementMatchers.isInterface()))
//.and(ElementMatchers.not(ElementMatchers.isAbstract()))
)
.transform((builder,
typeDescription,
classLoader,
@ -120,7 +118,7 @@ public class RestControllerPlugin implements TransformerPlugin {
.method(ElementMatchers.isPublic()
.and(ElementMatchers.not(ElementMatchers.isStatic()))
.and(ElementMatchers.not(ElementMatchers.isConstructor()))
.and(ElementMatchers.not(ElementMatchers.nameStartsWith("get").and(ElementMatchers.takesArguments(0))))
//.and(ElementMatchers.not(ElementMatchers.nameStartsWith("get").and(ElementMatchers.takesArguments(0))))
.and(ElementMatchers.not(ElementMatchers.nameStartsWith("set").and(ElementMatchers.takesArguments(1))))
.and(ElementMatchers.not(ElementMatchers.nameStartsWith("is").and(ElementMatchers.takesArguments(0)))))
.intercept(Advice.to(RestControllerAdvice.class));
@ -148,7 +146,7 @@ public class RestControllerPlugin implements TransformerPlugin {
private static final RestControllerInterceptor INTERCEPTOR = new RestControllerInterceptor();
@Advice.OnMethodEnter
@Advice.OnMethodEnter(suppress = Throwable.class)
public static long onEnter(@Advice.This Object target,
@Advice.Origin Method method,
@Advice.AllArguments Object[] args) {
@ -163,7 +161,7 @@ public class RestControllerPlugin implements TransformerPlugin {
}
}
@Advice.OnMethodExit(onThrowable = Throwable.class)
@Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class)
public static void onExit(@Advice.This Object target,
@Advice.Origin Method method,
@Advice.AllArguments Object[] args,

View File

@ -22,22 +22,33 @@
<module>mvc-plugin</module>
</modules>
<dependencies>
<!-- Spring Web dependencies for all Spring plugins -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
</dependency>
<properties>
<spring.version>5.3.37</spring.version>
</properties>
<dependencies>
<!-- Jackson for JSON -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<!-- Spring Web -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>${spring.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${spring.version}</version>
<scope>provided</scope>
</dependency>
</dependencies>
</dependencyManagement>
</project>

View File

@ -36,7 +36,7 @@ src/main/java/io/github/kazusa/pressmonster/demo/
### 1. 精确类名匹配
```java
named("io.github.kazusa.pressmonster.demo.SampleController")
named("io.github.kazusa.pressmonster.plugins.web.SampleController")
```
### 2. Spring注解匹配
@ -112,7 +112,7 @@ java -javaagent:target/demo-1.0.0-SNAPSHOT.jar -jar target/demo-1.0.0-SNAPSHOT.j
Simple ByteBuddy Agent 启动中...
Agent参数: 无
========================================
[AGENT] 成功增强类: io.github.kazusa.pressmonster.demo.SampleController (匹配方式: SPRING_CONTROLLER)
[AGENT] 成功增强类: io.github.kazusa.pressmonster.plugins.web.SampleController (匹配方式: SPRING_CONTROLLER)
[AGENT] 成功增强类: io.github.kazusa.pressmonster.demo.service.UserService (匹配方式: SERVICE_PACKAGE)
[AGENT] 成功增强类: io.github.kazusa.pressmonster.demo.service.OrderService (匹配方式: SERVICE_PACKAGE)
[AGENT] ByteBuddy Agent 安装完成!

View File

@ -36,22 +36,12 @@
<dependency>
<groupId>net.bytebuddy</groupId>
<artifactId>byte-buddy</artifactId>
<version>1.14.9</version>
<!-- <version>1.14.9</version>-->
</dependency>
<dependency>
<groupId>net.bytebuddy</groupId>
<artifactId>byte-buddy-agent</artifactId>
<version>1.14.9</version>
</dependency>
<!-- Spring Web for demo controllers -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<!-- <version>1.14.9</version>-->
</dependency>
<!-- Jackson for JSON -->
@ -69,6 +59,18 @@
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
</dependency>
<!-- Spring Web 被加强的应用需要将依赖打入包中, 插件只在编码时依赖不打入包<scope>provided</scope>中
在应用启动后会查询应用的依赖是否含有目标增强类-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>5.3.37</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.3.37</version>
</dependency>
</dependencies>
<build>

View File

@ -1,6 +1,14 @@
package io.github.kazusa.pressmonster.demo;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.util.HashMap;
import java.util.Map;

View File

@ -93,7 +93,7 @@ public class SimpleAgent {
private static net.bytebuddy.matcher.ElementMatcher.Junction<net.bytebuddy.description.type.TypeDescription> buildTypeMatchers() {
return
// 方式1精确类名匹配
named("io.github.kazusa.pressmonster.demo.SampleController")
named("io.github.kazusa.pressmonster.plugins.web.SampleController")
// 方式2Spring @RestController注解匹配使用字符串名称避免类加载问题
.or(isAnnotatedWith(named("org.springframework.web.bind.annotation.RestController")))
@ -132,7 +132,7 @@ public class SimpleAgent {
* 用于在日志中显示是通过什么方式匹配到的目标类
*/
private static String determineMatchType(String className) {
if ("io.github.kazusa.pressmonster.demo.SampleController".equals(className)) {
if ("io.github.kazusa.pressmonster.plugins.web.SampleController".equals(className)) {
return "EXACT_NAME";
} else if (className.contains("Controller")) {
return "SPRING_CONTROLLER";

View File

@ -36,10 +36,12 @@
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>5.3.37</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.3.37</version>
</dependency>
</dependencies>

View File

@ -0,0 +1,14 @@
package io.github.kazusa.pressmonster.mvc;
import io.github.kazusa.pressmonster.mvc.web.SampleController;
/**
* @author Wen
* @date 2025/7/23 15:56
*/
public class Main {
public static void main(String[] args) {
SampleController controller = new SampleController();
controller.getUsers();
}
}

View File

@ -0,0 +1,199 @@
//package io.github.kazusa.pressmonster.mvc.web;
//
//import io.github.kazusa.pressmonster.common.plugin.PluginRegistry;
//import io.github.kazusa.pressmonster.plugins.web.ApiEndpoint;
//import io.github.kazusa.pressmonster.plugins.web.EndpointRegistry;
//import io.github.kazusa.pressmonster.plugins.web.RestControllerInterceptor;
//import io.github.kazusa.pressmonster.plugins.web.RestControllerPlugin;
//import org.junit.jupiter.api.BeforeEach;
//import org.junit.jupiter.api.Test;
//import org.springframework.web.bind.annotation.GetMapping;
//import org.springframework.web.bind.annotation.PostMapping;
//import org.springframework.web.bind.annotation.RestController;
//
//import java.lang.reflect.Method;
//
//import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
//import static org.junit.jupiter.api.Assertions.assertEquals;
//import static org.junit.jupiter.api.Assertions.assertFalse;
//import static org.junit.jupiter.api.Assertions.assertNotNull;
//import static org.junit.jupiter.api.Assertions.assertTrue;
//
///**
// * RestController插件测试
// */
//public class RestControllerPluginTest {
//
// private RestControllerPlugin plugin;
// private RestControllerInterceptor interceptor;
// private EndpointRegistry endpointRegistry;
//
// @BeforeEach
// public void setUp() {
// plugin = new RestControllerPlugin();
// interceptor = new RestControllerInterceptor();
// endpointRegistry = EndpointRegistry.getInstance();
// endpointRegistry.clear(); // 清空之前的数据
// }
//
// @Test
// public void testPluginInfo() {
// assertEquals("RestControllerPlugin", plugin.getName());
// assertEquals("1.0.0", plugin.getVersion());
// assertTrue(plugin.getDescription().contains("RestController"));
// assertTrue(plugin.isEnabled());
// assertEquals(10, plugin.getPriority());
// }
//
// @Test
// public void testPluginLifecycle() {
// // 测试初始化
// assertDoesNotThrow(() -> plugin.initialize());
//
// // 测试销毁
// assertDoesNotThrow(() -> plugin.destroy());
// assertFalse(plugin.isEnabled());
// }
//
// @Test
// public void testSupports() {
// assertTrue(plugin.supports("com.example.UserController"));
// assertTrue(plugin.supports("RestController"));
// assertTrue(plugin.supports("org.springframework.SomeClass"));
// assertFalse(plugin.supports("com.example.Service"));
// }
//
// @Test
// public void testEndpointExtraction() throws Exception {
// // 创建测试Controller实例
// TestController controller = new TestController();
//
// // 获取方法
// Method getUsersMethod = TestController.class.getMethod("getUsers");
// Method createUserMethod = TestController.class.getMethod("createUser");
//
// // 测试方法拦截
// assertTrue(interceptor.beforeMethod(controller, getUsersMethod, new Object[]{}));
// assertEquals("result", interceptor.afterMethod(controller, getUsersMethod, new Object[]{}, "result"));
//
// // 验证端点注册
// assertEquals(1, endpointRegistry.getAllControllerClasses().size());
// assertTrue(endpointRegistry.getAllControllerClasses().contains(TestController.class.getName()));
// }
//
// @Test
// public void testEndpointRegistry() {
// // 创建测试端点
// ApiEndpoint endpoint1 = new ApiEndpoint(
// "com.example.UserController",
// "getUsers",
// "GET",
// "/api/users"
// );
//
// ApiEndpoint endpoint2 = new ApiEndpoint(
// "com.example.UserController",
// "createUser",
// "POST",
// "/api/users"
// );
//
// // 注册端点
// endpointRegistry.registerEndpoint(endpoint1);
// endpointRegistry.registerEndpoint(endpoint2);
//
// // 验证注册结果
// assertEquals(2, endpointRegistry.getAllEndpoints().size());
// assertEquals(1, endpointRegistry.getAllControllerClasses().size());
//
// // 验证统计信息
// EndpointRegistry.EndpointStats stats = endpointRegistry.getStats();
// assertEquals(1, stats.getControllerCount());
// assertEquals(2, stats.getEndpointCount());
// assertEquals(1, stats.getMethodCounts().get("GET").intValue());
// assertEquals(1, stats.getMethodCounts().get("POST").intValue());
// }
//
// @Test
// public void testEndpointSearch() {
// // 创建测试端点
// ApiEndpoint endpoint1 = new ApiEndpoint(
// "com.example.UserController",
// "getUsers",
// "GET",
// "/api/users"
// );
//
// ApiEndpoint endpoint2 = new ApiEndpoint(
// "com.example.OrderController",
// "getOrders",
// "GET",
// "/api/orders"
// );
//
// endpointRegistry.registerEndpoint(endpoint1);
// endpointRegistry.registerEndpoint(endpoint2);
//
// // 测试搜索
// assertEquals(2, endpointRegistry.searchEndpoints("api").size());
// assertEquals(1, endpointRegistry.searchEndpoints("user").size());
// assertEquals(1, endpointRegistry.searchEndpoints("order").size());
// assertEquals(0, endpointRegistry.searchEndpoints("nonexistent").size());
// }
//
// @Test
// public void testJsonExport() {
// // 创建测试端点
// ApiEndpoint endpoint = new ApiEndpoint(
// "com.example.TestController",
// "test",
// "GET",
// "/test"
// );
//
// endpointRegistry.registerEndpoint(endpoint);
//
// // 测试JSON导出
// String json = endpointRegistry.exportToJson();
// assertNotNull(json);
// assertTrue(json.contains("TestController"));
// assertTrue(json.contains("/test"));
// assertTrue(json.contains("GET"));
// }
//
// @Test
// public void testPluginRegistry() {
// PluginRegistry registry = PluginRegistry.getInstance();
//
// // 注册插件
// registry.registerPlugin(plugin);
//
// // 验证注册
// assertTrue(registry.isRegistered("RestControllerPlugin"));
// assertNotNull(registry.getPlugin("RestControllerPlugin"));
//
// // 测试类型过滤
// assertEquals(1, registry.getPluginsByType(RestControllerPlugin.class).size());
//
// // 清理
// registry.unregisterPlugin("RestControllerPlugin");
// assertFalse(registry.isRegistered("RestControllerPlugin"));
// }
//
// /**
// * 测试用的Controller类
// */
// @RestController
// public static class TestController {
//
// @GetMapping("/users")
// public String getUsers() {
// return "users";
// }
//
// @PostMapping("/users")
// public String createUser() {
// return "created";
// }
// }
//}

View File

@ -0,0 +1,80 @@
package io.github.kazusa.pressmonster.mvc.web;
import org.springframework.web.bind.annotation.*;
import java.util.HashMap;
import java.util.Map;
/**
* 示例Controller
* 用于演示RestController插件的拦截功能
*/
@RestController
@RequestMapping("/api")
public class SampleController {
@GetMapping("/users")
public Map<String, Object> getUsers() {
Map<String, Object> result = new HashMap<>();
result.put("users", new String[]{"user1", "user2", "user3"});
result.put("total", 3);
return result;
}
//@GetMapping("/users/{id}")
//public Map<String, Object> getUserById(@PathVariable String id) {
// Map<String, Object> result = new HashMap<>();
// result.put("id", id);
// result.put("name", "User " + id);
// result.put("email", "user" + id + "@example.com");
// return result;
//}
//
//@PostMapping("/users")
//public Map<String, Object> createUser(@RequestBody Map<String, Object> user) {
// Map<String, Object> result = new HashMap<>();
// result.put("id", "new-user-id");
// result.put("name", user.get("name"));
// result.put("email", user.get("email"));
// result.put("created", System.currentTimeMillis());
// return result;
//}
//
//@PutMapping("/users/{id}")
//public Map<String, Object> updateUser(@PathVariable String id, @RequestBody Map<String, Object> user) {
// Map<String, Object> result = new HashMap<>();
// result.put("id", id);
// result.put("name", user.get("name"));
// result.put("email", user.get("email"));
// result.put("updated", System.currentTimeMillis());
// return result;
//}
//
//@DeleteMapping("/users/{id}")
//public Map<String, Object> deleteUser(@PathVariable String id) {
// Map<String, Object> result = new HashMap<>();
// result.put("deleted", true);
// result.put("id", id);
// result.put("timestamp", System.currentTimeMillis());
// return result;
//}
//
//@GetMapping("/orders")
//public Map<String, Object> getOrders(@RequestParam(required = false) String status) {
// Map<String, Object> result = new HashMap<>();
// result.put("orders", new String[]{"order1", "order2"});
// result.put("status", status != null ? status : "all");
// result.put("total", 2);
// return result;
//}
//
//@PostMapping("/orders/{userId}")
//public Map<String, Object> createOrder(@PathVariable String userId, @RequestBody Map<String, Object> order) {
// Map<String, Object> result = new HashMap<>();
// result.put("orderId", "new-order-id");
// result.put("userId", userId);
// result.put("amount", order.get("amount"));
// result.put("created", System.currentTimeMillis());
// return result;
//}
}

View File

@ -1,195 +0,0 @@
package io.github.kazusa.pressmonster.plugins.web;
import io.github.kazusa.pressmonster.common.plugin.PluginRegistry;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;
import java.lang.reflect.Method;
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
/**
* RestController插件测试
*/
public class RestControllerPluginTest {
private RestControllerPlugin plugin;
private RestControllerInterceptor interceptor;
private EndpointRegistry endpointRegistry;
@BeforeEach
public void setUp() {
plugin = new RestControllerPlugin();
interceptor = new RestControllerInterceptor();
endpointRegistry = EndpointRegistry.getInstance();
endpointRegistry.clear(); // 清空之前的数据
}
@Test
public void testPluginInfo() {
assertEquals("RestControllerPlugin", plugin.getName());
assertEquals("1.0.0", plugin.getVersion());
assertTrue(plugin.getDescription().contains("RestController"));
assertTrue(plugin.isEnabled());
assertEquals(10, plugin.getPriority());
}
@Test
public void testPluginLifecycle() {
// 测试初始化
assertDoesNotThrow(() -> plugin.initialize());
// 测试销毁
assertDoesNotThrow(() -> plugin.destroy());
assertFalse(plugin.isEnabled());
}
@Test
public void testSupports() {
assertTrue(plugin.supports("com.example.UserController"));
assertTrue(plugin.supports("RestController"));
assertTrue(plugin.supports("org.springframework.SomeClass"));
assertFalse(plugin.supports("com.example.Service"));
}
@Test
public void testEndpointExtraction() throws Exception {
// 创建测试Controller实例
TestController controller = new TestController();
// 获取方法
Method getUsersMethod = TestController.class.getMethod("getUsers");
Method createUserMethod = TestController.class.getMethod("createUser");
// 测试方法拦截
assertTrue(interceptor.beforeMethod(controller, getUsersMethod, new Object[]{}));
assertEquals("result", interceptor.afterMethod(controller, getUsersMethod, new Object[]{}, "result"));
// 验证端点注册
assertEquals(1, endpointRegistry.getAllControllerClasses().size());
assertTrue(endpointRegistry.getAllControllerClasses().contains(TestController.class.getName()));
}
@Test
public void testEndpointRegistry() {
// 创建测试端点
ApiEndpoint endpoint1 = new ApiEndpoint(
"com.example.UserController",
"getUsers",
"GET",
"/api/users"
);
ApiEndpoint endpoint2 = new ApiEndpoint(
"com.example.UserController",
"createUser",
"POST",
"/api/users"
);
// 注册端点
endpointRegistry.registerEndpoint(endpoint1);
endpointRegistry.registerEndpoint(endpoint2);
// 验证注册结果
assertEquals(2, endpointRegistry.getAllEndpoints().size());
assertEquals(1, endpointRegistry.getAllControllerClasses().size());
// 验证统计信息
EndpointRegistry.EndpointStats stats = endpointRegistry.getStats();
assertEquals(1, stats.getControllerCount());
assertEquals(2, stats.getEndpointCount());
assertEquals(1, stats.getMethodCounts().get("GET").intValue());
assertEquals(1, stats.getMethodCounts().get("POST").intValue());
}
@Test
public void testEndpointSearch() {
// 创建测试端点
ApiEndpoint endpoint1 = new ApiEndpoint(
"com.example.UserController",
"getUsers",
"GET",
"/api/users"
);
ApiEndpoint endpoint2 = new ApiEndpoint(
"com.example.OrderController",
"getOrders",
"GET",
"/api/orders"
);
endpointRegistry.registerEndpoint(endpoint1);
endpointRegistry.registerEndpoint(endpoint2);
// 测试搜索
assertEquals(2, endpointRegistry.searchEndpoints("api").size());
assertEquals(1, endpointRegistry.searchEndpoints("user").size());
assertEquals(1, endpointRegistry.searchEndpoints("order").size());
assertEquals(0, endpointRegistry.searchEndpoints("nonexistent").size());
}
@Test
public void testJsonExport() {
// 创建测试端点
ApiEndpoint endpoint = new ApiEndpoint(
"com.example.TestController",
"test",
"GET",
"/test"
);
endpointRegistry.registerEndpoint(endpoint);
// 测试JSON导出
String json = endpointRegistry.exportToJson();
assertNotNull(json);
assertTrue(json.contains("TestController"));
assertTrue(json.contains("/test"));
assertTrue(json.contains("GET"));
}
@Test
public void testPluginRegistry() {
PluginRegistry registry = PluginRegistry.getInstance();
// 注册插件
registry.registerPlugin(plugin);
// 验证注册
assertTrue(registry.isRegistered("RestControllerPlugin"));
assertNotNull(registry.getPlugin("RestControllerPlugin"));
// 测试类型过滤
assertEquals(1, registry.getPluginsByType(RestControllerPlugin.class).size());
// 清理
registry.unregisterPlugin("RestControllerPlugin");
assertFalse(registry.isRegistered("RestControllerPlugin"));
}
/**
* 测试用的Controller类
*/
@RestController
public static class TestController {
@GetMapping("/users")
public String getUsers() {
return "users";
}
@PostMapping("/users")
public String createUser() {
return "created";
}
}
}