问题
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.
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:
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? If I have to take care of the @Order annotation myself: What's the best practice to realize my plan?
回答1:
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. I already did something not too far from that by :
- delegate processing to a normal method (not
@RequestMappingannotated) in base controller - override that method in a class extending the controller
- use the subclass as a bean (and not the parent class)
The hard part is that you have to explicitely declare the proper controller bean. I did it with XML so it was easy (just a line to change i the xml file). In Java config, I would explicitely declare the controller bean in a @Configuration annotated class.
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 ...
}
来源:https://stackoverflow.com/questions/27293043/spring-register-handler-method-dependening-on-order-annotation