选择控制器Bean实例通过RequestMapping

huangapple go评论65阅读模式
英文:

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 = &quot;fooName&quot;;
private static final barName = &quot;barName&quot;;
@RequestMapping(&quot;/foo&quot;)
public String getFoo(){
return fooName;
}
@RequestMapping(&quot;/bar&quot;)
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(&quot;prototype&quot;)
public class FooController {
private String name;
public FooController() {}
public FooController(String name) {
this.name = name;
}
public ResponseEntity&lt;String&gt; handleRequests() throws Exception {
return new ResponseEntity&lt;&gt;(&quot;Yo: &quot; + name + &quot; &quot; + 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(&quot;handleRequests&quot;));
}
@EventListener
public void handleContextRefreshEvent(ContextRefreshedEvent ctxStartEvt) {
try {
addFooController(&quot;/blah1&quot;, &quot;blahblah1&quot;);
addFooController(&quot;/blah2&quot;, &quot;blahblah2&quot;);
addFooController(&quot;/blah3&quot;, &quot;blahblah3&quot;);
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
}
}

Results:

http://localhost:8080/blah1 returns: Yo: blahblah1 1391627345
http://localhost:8080/blah3 returns: Yo: blahblah3 2078995154

huangapple
  • 本文由 发表于 2020年10月17日 09:08:37
  • 转载请务必保留本文链接:https://go.coder-hub.com/64398141.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定