【问题标题】:Spring MVC Multiple Controllers with same @RequestMapping具有相同 @RequestMapping 的 Spring MVC 多个控制器
【发布时间】:2012-07-23 06:25:25
【问题描述】:

我正在尝试制作一个允许用户从登录页面index.htm 登录的网络应用程序。此操作与 LoginController 映射,成功登录后将用户带回相同的index.htm,但作为登录用户并用欢迎消息问候用户。

index.htm 还有另一个名为 itemform 的表单,允许用户将项目名称添加为文本。此操作由 itemController 控制。

我的问题是我的 LoginController 和 itemController 都具有相同的 @RequestMapping,因此我收到此错误:

在 ServletContext 资源 [/WEB-INF/tinga-servlet.xml] 中定义名称为 'org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping#0' 的 bean 创建错误:bean 初始化失败;嵌套异常是 java.lang.IllegalStateException:无法将处理程序 [loginController] 映射到 URL 路径 [/index.htm]:已经映射了处理程序 [com.tinga.LoginController@bf5555]。

无法将处理程序 [loginController] 映射到 URL 路径 [/index.htm]:已映射处理程序 [com.tinga.LoginController@bf5555]。

我应该如何解决这个问题?

【问题讨论】:

  • 你的两个控制器方法都映射了路径 "/index.htm" ?

标签: java spring spring-mvc


【解决方案1】:
@RequestMapping(value="/login.htm")
public ModelAndView login(HttpServletRequest request, HttpServletResponse response) {
   // show login page if no parameters given
   // process login if parameters are given
}

@RequestMapping(value="/index.htm")
public ModelAndView index(HttpServletRequest request, HttpServletResponse response) {
   // show the index page
}

最后,您需要一个 servlet 过滤器来拦截请求,如果您不请求 login.htm 页面,则必须检查以确保用户已登录。如果您允许过滤链继续。如果没有,您将转发到 /login.htm

public class LoginFilter implements Filter {
  public void doFilter(ServletRequest request,  ServletResponse response, FilterChain chain)
            throws IOException, ServletException {

    HttpServletRequest httpServletRequest = (HttpServletRequest)request;

    boolean loggedIn = ...; // determine if the user is logged in.
    boolean isLoginPage = ...; // use path to see if it's the login page

    if (loggedIn || isLoginPage) {
        chain.doFilter(request, response);
    }
    else {
        request.getRequestDispatcher("/login.htm").forward(request, response);
    }
  }
}

在 web.xml 中

我的部署描述符中的示例:

<filter>
    <filter-name>LoginFilter</filter-name>
    <filter-class>LoginFilter</filter-class>
</filter>

<filter-mapping>
    <filter-name>LoginFilter</filter-name>
    <url-pattern>/*</url-pattern>
    <dispatcher>REQUEST</dispatcher>  
    <dispatcher>FORWARD</dispatcher> 
</filter-mapping>

这全凭记忆,但它应该让您大致了解如何进行此操作。

【讨论】:

    【解决方案2】:

    所有控制器的请求映射在 Spring MVC 中应该是唯一的。

    【讨论】:

    • 是的,因为 LoginController 和 itemController 都将控制权返回给 index.htm
    • 这是您登录方式的一个缺陷。您真正想要的是将登录控制器映射到不同的路径,并使用 servlet 过滤器检查用户是否已登录。如果没有,则转发到登录控制器的相应路径。
    【解决方案3】:

    也许在具有相同@RequestMapping 的控制器中,您应该像这样定义方法(GET、POST...):

    @RequestMapping(value="/index.htm", method = RequestMethod.GET)
    @RequestMapping(value="/index.htm", method = RequestMethod.POST)
    

    带有 GET 方法的控制器用于呈现表单并将数据(某些对象)绑定到它。您通常用来处理表单的提交和验证的带有 POST 方法的控制器。

    【讨论】:

    • 我可能没有正确解释它,也可能没有尝试正确实施。问题出在我的 jsp 页面(index.jsp)中,我有 2 个带有 LoginController 的表单(登录表单)和带有 itemController 的项目表单。它们独立工作正常(也就是说,如果我删除一个表单并留下另一个)唯一的问题是当我将它们都放在同一页面上时(index.jsp),因此对于它们两个我都将@RequestMapping 设置为 /index .htm。我试过你建议的方法,但还是不行。
    • 太好了...也许您应该更改代码中的一些内容。例如,将 LoginController 和 ItemController 的映射名称放在不同的位置,因为这样您会看到它们的工作方式不同。如果我理解,您想在与表单相同的页面中显示“成功”消息...也许在这种情况下您应该使用一些 Ajax,将 jsp 页面返回到“成功 div”(假设您有一个 表示成功)。抱歉,如果它不起作用,但尝试以这种方式解决问题非常困难...... hauhauahuaha
    【解决方案4】:

    在表单中添加一个隐藏参数以区分它们,然后通过在 post 方法的注释中添加 params 属性来区分它们。

    <form:hidden name="hiddenAction" value="login" />
    <form:hidden name="hiddenAction" value="item" />
    
    @RequestMapping(method = RequestMethod.POST, params = {"hiddenAction=login"})
    @RequestMapping(method = RequestMethod.POST, params = {"hiddenAction=item"})
    

    【讨论】:

      猜你喜欢
      • 2014-01-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-10-17
      • 2016-06-21
      • 2012-01-10
      相关资源
      最近更新 更多