【发布时间】:2019-08-03 22:44:43
【问题描述】:
我正在尝试为我的 Spring Boot Rest 项目实现继承的控制器。正如您在示例代码 sn-ps 中看到的,我在 BaseTableController 中为所有控制器提供了标准端点,但对于一些具体的控制器,我需要覆盖方法。当我像这样实现它时,我在启动时得到Ambiguous mapping. Cannot map 'clientRfmController' method 异常。
public abstract class BaseTableController<T extends BaseTableModel> {
@Override
public BaseTableService<T> getService() {
return (BaseTableService<T>) super.getService();
}
@GetMapping({
PATH_GET,
PATH_VIEW_GET}
)
public T getWithParam(@RequestParam UUID gid) {
T t = null;
if (gid != null) {
t = getService().get(gid);
}
return getWithErrorCheck(t);
}
}
-
@RestController
@RequestMapping(TBL_CLIENTRFM)
public class ClientRfmController extends BaseTableController<ClientRfmCommon> {
@Override
public ClientRfmService getService() {
return (ClientRfmService) super.getService();
}
@GetMapping(value = {PATH_GET, PATH_VIEW_GET})
public List<ClientRfmCommon> getByAccid(Long accid, @RequestParam(required = false) UUID gid) {
List<ClientRfmCommon> byAccid = null;
if (gid != null) {
byAccid = Collections.singletonList(super.getWithParam(gid));
} else {
byAccid = Collections.singletonList(getService().getByAccid(accid));
}
return byAccid;
}
}
我通过实现自定义 RequestMappingHandlerMapping 找到了解决方法。
@Configuration
public class WebMvcRegistrationsConfig implements WebMvcRegistrations {
@Override
public OoRequestMappingHandlerMapping getRequestMappingHandlerMapping() {
OoRequestMappingHandlerMapping ooRequestMappingHandlerMapping = new OoRequestMappingHandlerMapping();
ooRequestMappingHandlerMapping.setOrder(0);
return ooRequestMappingHandlerMapping;
}
}
-
public class OoRequestMappingHandlerMapping extends RequestMappingHandlerMapping {
@Override
protected void registerHandlerMethod(Object handler, Method method, RequestMappingInfo mapping) {
HandlerMethod existingHandlerMethod = getHandlerMethods().get(mapping);
if (existingHandlerMethod != null) {
HandlerMethod handlerMethod = createHandlerMethod(handler, method);
if (handlerMethod.getMethod().getDeclaringClass().isAssignableFrom(existingHandlerMethod.getMethod().getDeclaringClass())) {
logger.warn(handlerMethod.getBeanType().getSimpleName() + " type (" + handlerMethod.getMethod().getDeclaringClass().getSimpleName() + "->" + handlerMethod.getMethod().getName() +
") registration omitted to avoid ambigious mapping (" + existingHandlerMethod.getMethod().getDeclaringClass().getSimpleName() + "->" + existingHandlerMethod.getMethod().getName() + ")");
return;
}
unregisterMapping(mapping);
}
super.registerHandlerMethod(handler, method, mapping);
}
}
- 这是正确的处理方式吗?
- 当我添加@EnableWebMvc 注解时,这变得没用了。有没有更通用的解决方案?
【问题讨论】:
-
你有重复的映射,你不能将同一个 URL 映射到不同的方法,不管你是否覆盖。所以不,这不是处理它的方法。不要扩展基类,只实现这里的逻辑。
-
@M.Deinum 这是控制器的一小部分。我在基本控制器上有很多不同的方法。我只想用相同的 url 覆盖其中一个。
-
你不能因为所有的元数据都将被处理导致相同的 URL/映射。它仅在映射不同时才有效。显然您正在添加一个不同的参数,因此将其包含在映射信息中以获得唯一映射。
标签: java spring spring-boot spring-restcontroller