如何解决 Spring MVC 中的多重映射?

Posted

技术标签:

【中文标题】如何解决 Spring MVC 中的多重映射?【英文标题】:How to resolve multimapping in Spring MVC? 【发布时间】:2014-04-19 20:51:09 【问题描述】:

在我的控制器中,我有两种方法来处理来自用户的请求。

@RequestMapping(method = RequestMethod.GET)
@PreAuthorize("hasRole('ROLE_INTERNAL_USER')")
public String homeInt() 
    return "redirect:/internal";


@RequestMapping(method = RequestMethod.GET)
@PreAuthorize("hasRole('ROLE_EXTERNAL_USER')")
public String homeExt() 
    return "redirect:/external";

例外:

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping#0': Invocation of init method failed; nested exception is java.lang.IllegalStateException: Ambiguous mapping found. Cannot map 'loginController' bean method 
public java.lang.String de.mark.project.web.controller.LoginController.homeInt()
to [/],methods=[GET],params=[],headers=[],consumes=[],produces=[],custom=[]: There is already 'loginController' bean method
public java.lang.String de.mark.project.web.controller.LoginController.homeExt() mapped.

但问题是这两种方法都不能映射到一个请求方法或一个 URI。有什么解决方案可以按照我的逻辑映射请求吗?

【问题讨论】:

方法的主体应该根据你拥有的任何信息做出决定,并重定向到正确的 url,内部或外部。 “方法的主体应该做出决定”是什么意思?我的注释完成了这项工作。不是吗? 大概,您想要一个带有单一方法 (GET) 的单一 URL,那么您将不得不使用其他方法来确定正确的响应是内部响应还是外部响应。您可以编写一个方法来响应请求,并在末尾添加 if 语句,从而导致外部或内部重定向。 真的,要回答这个问题,我需要更多地了解请求本身。内部响应与外部响应有何区别?你怎么知道客户是内部的还是外部的?仅仅是他们的角色吗?您不能按角色路由请求,只能通过请求映射。 【参考方案1】:

您需要为方法分配不同的上下文路径:

@RequestMapping(value="/path1", method = RequestMethod.GET)
public String homeInt() 
    ...


@RequestMapping(value="/path2", method = RequestMethod.GET)
public String homeExt() 
   ...

或者为这两个请求分配不同的 HTTP 动词:

@RequestMapping(method = RequestMethod.GET)
public String homeInt() 
    ...


@RequestMapping(method = RequestMethod.POST)
public String homeExt() 
   ...

否则,从 HTTP 的角度来看,无法知道将选择哪种方法,这就是错误消息的含义:在当前形式中,这两个方法定义是模棱两可的,因为它们具有相同的上下文路径和动词。

另一种方法是只编写一个方法,并在可能的情况下决定方法体:

@RequestMapping(value="/path1", method = RequestMethod.GET)
public String homeIntOrExt() 
    if (... some condition ...) 
        return "redirect:/internal";
    
    else 
        return "redirect:/external";
    

【讨论】:

我对这个答案并不满意,请看这里:***.com/a/12574562/572954【参考方案2】:

虽然有点神奇,但使用 RequestConditions 和自定义 RequestMappingHandlerMapping 实现的 Spring 可以做到这一点。

例如,看看this。

【讨论】:

以上是关于如何解决 Spring MVC 中的多重映射?的主要内容,如果未能解决你的问题,请参考以下文章

源码剖析Spring MVC如何将请求映射到Controller?

如何将 Spring MVC 控制器映射到特定文件夹?

在 Spring MVC 的 servlet 映射中,如何映射 url 模式目录的根目录?

如何在 Spring MVC 中将请求映射到 HTML 文件?

如何将 Spring MVC 控制器映射到带有和不带有斜杠的 uri?

Spring MVC 3.0:如何有效地验证对所有请求映射都是全局的路径变量?