preface

So normally you write Controller, you declare at sign RestController or at sign Controller on your class, and then you put a URL path on the method, but you can register it dynamically, you don’t have to write at sign Controller, you just write the method, you can dynamically register it when the system starts up, Dynamic removal.

SpringBoot will eventually encapsulate the “request map” in a map, so we can store information directly in the map, where the “request” is the URL of the requested address, and the “map” is the response from that URL to some method.

So we need two pieces of information, the URL and the specific response method.

SpringBoot encapsulates it as RequestMappingInfo, so the first thing to do is to build RequestMappingInfo, but its constructor is cumbersome and provides an internal Builder class.

As shown below, test specifies the URL for the request, and the method is GET.

val requestMappingInfo = RequestMappingInfo
    .paths("test")
    .methods(RequestMethod.GET)
    .build()
Copy the code

Below is through the internal RequestMappingHandlerMapping added to the map, the RequestMappingHandlerMapping can automatically by the @ Inject injection, Can also through the ApplicationContext. GetBean access.

As shown below, when the registerMapping method is called, the second parameter is the bean name of the class in which the method specifically responds to the data.

That is, the method class must be managed by the SpringBoot container, which makes sense because when a method is called through reflection, there is always an instance of it.

fun main(args: Array<String>) {
    var application = runApplication<CoolDeployApplication>(*args)
    var bean = application.getBean(RequestMappingHandlerMapping::class.java)

    val requestMappingInfo = RequestMappingInfo
        .paths("test")
        .methods(RequestMethod.GET)
        .build()

    bean.registerMapping(requestMappingInfo, "testRequest", TestRequest::class.java.getDeclaredMethod("test",Int::class.java))
}
Copy the code

Start by simply using @Component, and the final bean name is testRequest.

@Component
class TestRequest {
    @ResponseBody
    fun test(@RequestParam("id")id:Int): Any {
        return "${id}"}}Copy the code

But it can also be managed via @beans, so that no annotations are required on the final TestRequest class.

@SpringBootApplication
class CoolDeployApplication : SpringApplicationRunListener {
    @Bean
    fun testRequest(a): TestRequest {
        returnTestRequest(); }}Copy the code

So you can test it.

Remove all controllers with the following code

bean.handlerMethods.forEach { t, u ->
    bean.unregisterMapping(t)
}
Copy the code