简体   繁体   English

春季:依赖于订单注释的注册处理程序方法

[英]Spring: Register Handler Method dependening on Order annotation

I have two Controllers: 我有两个控制器:

@Controller
@Order(Ordered.LOWEST_PRECEDENCE)
public class BaseController {
    @RequestMapping("/hello.html")
    public String hello(ModelMap model) {
        model.addAttribute("hello", "world");
        return "hello";
    }
}

@Controller
public class ProjectSpecificController {
    @Autowired
    private BaseController baseController;

    @Override
    @RequestMapping("/hello.html")
    public String hello(ModelMap model) {
        model.addAttribute("project", "name");
        return baseController.hello(model);
    }
}

As Spring would trigger this Exception: java.lang.IllegalStateException: Ambiguous mapping found. Cannot map 'baseController' bean method public java.lang.String com.example.BaseController.hello(org.springframework.ui.ModelMap) to {[/hello.html],methods=[],params=[],headers=[],consumes=[],produces=[],custom=[]}: There is already 'projectSpecificController' bean method public java.lang.String com.example.ProjectSpecificController.hello(org.springframework.ui.ModelMap) mapped. 由于Spring会触发此异常: java.lang.IllegalStateException: Ambiguous mapping found. Cannot map 'baseController' bean method public java.lang.String com.example.BaseController.hello(org.springframework.ui.ModelMap) to {[/hello.html],methods=[],params=[],headers=[],consumes=[],produces=[],custom=[]}: There is already 'projectSpecificController' bean method public java.lang.String com.example.ProjectSpecificController.hello(org.springframework.ui.ModelMap) mapped. java.lang.IllegalStateException: Ambiguous mapping found. Cannot map 'baseController' bean method public java.lang.String com.example.BaseController.hello(org.springframework.ui.ModelMap) to {[/hello.html],methods=[],params=[],headers=[],consumes=[],produces=[],custom=[]}: There is already 'projectSpecificController' bean method public java.lang.String com.example.ProjectSpecificController.hello(org.springframework.ui.ModelMap) mapped.

I would like to use the @Order annotation to map ProjectSpecificController.hello first and if there's already a mapping found for /hello.html ignore the other mappings and do not register their methods: 我想先使用@Order批注来映射ProjectSpecificController.hello ,如果已经找到了/hello.html的映射,请忽略其他映射,不要注册它们的方法:

public class OrderedRequestMappingHandlerMapping extends RequestMappingHandlerMapping {
    @Override
    protected void registerHandlerMethod(Object handler, Method method, RequestMappingInfo mapping) {
        try {
            super.registerHandlerMethod(handler, method, mapping);
        } catch (IllegalStateException e) {
            // mapping already happened for a controller of higher precedence, so ignore
        }
    }
}

Is it enough to catch the exception or do I have to look for the @Order annotation myself? 是否足以捕获异常,还是我必须自己寻找@Order注释? If I have to take care of the @Order annotation myself: What's the best practice to realize my plan? 如果我必须自己照顾@Order批注:实现我的计划的最佳实践是什么?

If I were you, I would not try to go that way. 如果我是你,我不会尝试那样走。

If I correctly understand, you have one BaseController and you want to override the processing of an URL. 如果我正确理解,则您有一个BaseController并且您想要覆盖 URL的处理。 I already did something not too far from that by : 我已经通过以下方式做了一些事情:

  • delegate processing to a normal method (not @RequestMapping annotated) in base controller 将处理委托给基本控制器中的常规方法(未注释@RequestMapping
  • override that method in a class extending the controller 在扩展控制器的类中重写该方法
  • use the subclass as a bean (and not the parent class) 使用子类作为bean(而不是父类)

The hard part is that you have to explicitely declare the proper controller bean. 困难的部分是您必须显式声明正确的控制器bean。 I did it with XML so it was easy (just a line to change i the xml file). 我使用XML做到了这一点,因此很容易(只需一行即可更改xml文件)。 In Java config, I would explicitely declare the controller bean in a @Configuration annotated class. 在Java配置中,我将在@Configuration注释的类中显式声明控制器bean。

Globally it would look like : 在全球范围内看起来像:

public class BaseController {
    @RequestMapping("/hello.html")
    public String hello(ModelMap model) {
        return doHello(model);
    }
    protected String doHello(ModelMap model) {
        model.addAttribute("hello", "world");
        return "hello";
    }
}

public class ProjectSpecificController extends BaseController{
    @Override
    protected String doHello(ModelMap model) {
        model.addAttribute("project", "name");
        return super.doHello(model);
    }
}

@Configuration
class HelloConfig {
    // other configuration elements ...
    @Bean
    public BaseController helloController() {
        // implement the logic to choose the right implementation
        return (specific ? new ProjectSpecificController() : new BaseController());
    }
    // other configuration elements ...
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM