How to configure @Controller mapping path?

I am creating an internal library that should automatically add multiple controllers to a Spring MVC application. These controllers are all @RestController with several handler methods annotated using @RequestMapping . Since this is a library, I want users to be able to specify the root path where the library should expose all of these controllers. Illustration:

 // given that I have a controller like this: @RestController @RequestMapping("/admin") class AdminController { @RequestMapping("/users") UsersDto allUsers() { ... } } // it will be exposed at `http://localhost/admin/users` 

What I want to achieve is to make the /admin construct customizable. For example, if the user says in application.properties :

 super.admin.path=/top/secret/location/here 

I want the AdminController handlers AdminController be available at http://localhost/top/secret/location/here , so the allUsers() handler should have the full path:

 http://localhost/top/secret/location/here/users 

How do I achieve this? It feels like a pretty common task, but I was not able to find a direct solution that works.

My discovery # 1

There is a SimpleUrlHandlerMapping mechanism, which seems to be exactly what I want:

 @Bean public SimpleUrlHandlerMapping simpleUrlHandlerMapping() { SimpleUrlHandlerMapping simpleUrlHandlerMapping = new SimpleUrlHandlerMapping(); simpleUrlHandlerMapping.setOrder(Integer.MAX_VALUE - 2); simpleUrlHandlerMapping.setUrlMap(Collections.singletonMap("/ANY_CUSTOM_VALUE_HERE/*", "adminController")); return simpleUrlHandlerMapping; } 

But he keeps talking

HandlerAdapter that supports this handler must be enabled in the DispatcherServlet configuration

My discovery # 2

There Spring Boot Admin Project that has this exact function - you can configure where they should expose all their endpoints. It seems that this functionality is implemented from scratch in PrefixHandlerMapping . How do they use it:

 ... @Bean public PrefixHandlerMapping prefixHandlerMappingNotificationFilterController() { PrefixHandlerMapping prefixHandlerMapping = new PrefixHandlerMapping(notificationFilterController()); prefixHandlerMapping.setPrefix(adminServerProperties.getContextPath()); return prefixHandlerMapping; } ... 
+5
source share
1 answer

In addition to @M. Deinum, you can use Path Patterns with Placeholders. As the Spring documentation says:

Templates in @RequestMapping support for annotations ${…​} placeholders versus local properties and / or system properties and environment variables. This can be useful in cases where the controller path for mapping may need to be configured through the configuration.

So, in your case, your controller will look like this:

 @RestController @RequestMapping("/${super.admin.path:admin}") class AdminController { // Same as before } 

The previous controller would use the super.admin.path local / system property or environment variable value as its prefix or admin if they are not provided. If you are using Spring Boot, adding the following to your application.properties :

 super.admin.path=whatever 

You can configure this prefix.

+7
source

All Articles