I want Spring to create 2 instances of FooController. Requests to /foo should be handled by one of the instances and requests to /bar should be handled by the other instance. I want something like the below, but of course @RequestMapping
doesn’t work that way and also Spring gives me the ambiguous mapping error on FooController as well.
@RestController public class FooController { String name; public FooController(String name) { this.name = name; } } @Configuration public class FooControllerConfig { @Bean @RequestMapping("/foo") public FooController getFooFooController(){ return new FooController("foo"); } @Bean @RequestMapping("/bar") public FooController getBarFooController(){ return new FooController("bar"); } }
Advertisement
Answer
Don’t try this at home. This code was performed by a bored, trained professional…
You can have multiple instances of the same controller class, each of which handles a different URL through the same or a different method in the controller. The only thing is, I don’t know how to do it with just annotations. The way I just did it was to dynamically register each request mapping at initialization time. The FooController becomes a prototype bean (defined with annotations) so you can have Spring instantiate it multiple times, once for each mapping
FooController.java
@Controller @Scope("prototype") public class FooController { private String name; public FooController() {} public FooController(String name) { this.name = name; } public ResponseEntity<String> handleRequests() throws Exception { return new ResponseEntity<>("Yo: " + name + " " + this.hashCode(), HttpStatus.OK); }
EndpointService.java
@Service public class EndpointService { @Autowired private BeanFactory beanFactory; @Autowired private RequestMappingHandlerMapping requestMappingHandlerMapping; public void addFooController(String urlPath, String name) throws NoSuchMethodException { RequestMappingInfo requestMappingInfo = RequestMappingInfo .paths(urlPath) .methods(RequestMethod.GET) .produces(MediaType.APPLICATION_JSON_VALUE) .build(); requestMappingHandlerMapping.registerMapping(requestMappingInfo, beanFactory.getBean(FooController.class, name), FooController.class.getDeclaredMethod("handleRequests")); } @EventListener public void handleContextRefreshEvent(ContextRefreshedEvent ctxStartEvt) { try { addFooController("/blah1", "blahblah1"); addFooController("/blah2", "blahblah2"); addFooController("/blah3", "blahblah3"); } catch (NoSuchMethodException e) { e.printStackTrace(); } } }
Results:
http://localhost:8080/blah1 returns: Yo: blahblah1 1391627345 http://localhost:8080/blah3 returns: Yo: blahblah3 2078995154