弹簧:寄存器处理程序方法依赖于订单注释



我有两个控制器:

@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);
    }
}

因为春天会触发这个异常: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.

我想先使用 @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
        }
    }
}

捕获异常就足够了,还是我必须自己查找@Order注释?如果我必须自己处理@Order注释:实现我的计划的最佳实践是什么?

如果我是你,我不会尝试那样做。

如果我正确理解,您有一个BaseController并且想要覆盖 URL 的处理。我已经做了一些离那不远的事情:

  • 将处理委托给基本控制器中的常规方法(未@RequestMapping注释)
  • 在扩展控制器的类中重写该方法
  • 将子类用作 Bean(而不是父类)

困难的部分是您必须显式声明正确的控制器 bean。我用XML做了,所以很容易(只是一行更改xml文件)。在 Java 配置中,我会在@Configuration注释类中显式声明控制器 bean。

在全球范围内,它看起来像:

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 ...
}

最新更新