2014-12-04 65 views
0

我有两个控制器:春:注册处理程序方法取决于依赖订单注释

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

由于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.

我想用@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注释:实现我的计划的最佳实践是什么?

回答

0

如果我是你,我不会试图走这条路。

如果我正确理解,你有一个BaseController,你想覆盖一个URL的处理。我已经做了一些来自不太远的:

  • 代理处理一个正常方法(不@RequestMapping注释)在基本控制器,在一个类的方法扩展控制器
  • 使用
  • 覆盖子类作为bean(而不是父类)

最难的部分是你必须明确地声明适当的控制器bean。我用XML做了它,所以很简单(只需要一行来更改我的XML文件)。在Java配置中,我会明确声明控制器bean在@Configuration带注释的类中。

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

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

这不是一个解决方案给我。我不想明确声明所有控制器。顺便说一句:我想你错过了'HelloConfig.helloController'的'@ Bean'注释。 – dtrunk 2014-12-04 13:56:20

+0

@dtrunk:修正了@Bean注释......我明白你的观点,我担心你会在较低的层次上重写Spring MVC,而且我经常读到Spring是可扩展的,但不是(容易)修改的。 – 2014-12-04 14:03:01

+0

它是可扩展的(这就是我上面做的),我做它的方式工作得很好。我的问题就在于Spring是否正在关注我的'BaseController'的'@ Order'注释。我尝试将'BaseController'重命名为'ZBaseController',然后再重新命名'ProjectSpecificController'为'ZProjectSpecificController'并且再次返回,并且它在所有情况下都能正常工作。所以我猜Spring正在照顾'@ Order'注释。 – dtrunk 2014-12-04 14:37:41