英文:
Choose Controller Bean instance by RequestMapping
问题
我希望Spring创建2个FooController的实例。对/f00的请求应该由其中一个实例处理,而对/bar的请求应该由另一个实例处理。我想要类似以下的效果,但是`@RequestMapping`当然不会以这种方式工作,而且Spring还会在FooController上给我一个模糊映射错误。
```Java
@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");
}
}
英文:
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");
}
}
</details>
# 答案1
**得分**: 2
我真的很困惑,为什么您需要这个要求?您能解释一下为什么需要这个要求吗?是每个映射都需要不同的名称吗?
首先,您不应该将Beans映射到RequestMapping上。虽然我甚至不确定Spring应用程序是否会启动,但每次访问这些映射之一时,都可能会创建一个具有相同名称的新Bean,这可能会引发错误。
您可能可以通过自己的注解处理来克服重复的名称,但这比看起来值得的工作要多得多。
仅仅看看您的代码,有没有任何理由不满足您的要求呢?
```java
@RestController
public class FooController {
private static final fooName = "fooName";
private static final barName = "barName";
@RequestMapping("/foo")
public String getFoo(){
return fooName;
}
@RequestMapping("/bar")
public String getBar(){
return barName;
}
}
英文:
I'm really confused by why you need this requirement? Can you please explain why this is required? Is it that each mapping requires a different name?
First you do not map Beans to a RequestMapping. While I am not even sure the spring application would start it would potentially create a new Bean with an identical name every time you access one of these mappings which would probably throw an error.
You could potentially overcome the duplicate names with your own annotation processing but that is way more work then this looks like it is worth.
Just looking at what you have there is there any reason why the following will not meet your requirements?
@RestController
public class FooController {
private static final fooName = "fooName";
private static final barName = "barName";
@RequestMapping("/foo")
public String getFoo(){
return fooName;
}
@RequestMapping("/bar")
public String getBar(){
return barName;
}
}
答案2
得分: 1
不要在家里尝试这个。这段代码是由一个无聊的专业训练人员执行的...
您可以拥有同一个控制器类的多个实例,每个实例通过控制器中的相同或不同方法处理不同的URL。唯一的问题是,我不知道如何只使用注释来做到这一点。我刚刚所做的方法是在初始化时动态注册每个请求映射。FooController变为原型bean(使用注释定义),因此您可以让Spring多次实例化它,每个映射实例化一次
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();
}
}
}
结果:
访问 http://localhost:8080/blah1 返回:Yo: blahblah1 1391627345
访问 http://localhost:8080/blah3 返回:Yo: blahblah3 2078995154
英文:
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
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论