【问题标题】:Spring-MVC controller redirect to "previous" page?Spring-MVC 控制器重定向到“上一个”页面?
【发布时间】:2009-04-29 22:36:58
【问题描述】:

假设我有一个用于编辑 Pony 属性的表单,在我的 Web 应用程序中,您可以选择多个位置来编辑 Pony。例如,在小马列表中,每个小马旁边可能有一个“编辑”链接,当用户查看小马时,该视图中可能还有一个“编辑”链接。

当用户在编辑 Pony 后单击“提交”时,我想将用户返回到他或她在单击“编辑”链接时所在的页面。

如何编写控制器以将用户重定向回他们开始的位置?当然,我可以通过将参数传递给控制器​​来做到这一点,但这似乎有点愚蠢。我是不是在想这一切都错了,或者这就是我必须做的事情?

【问题讨论】:

    标签: java spring-mvc


    【解决方案1】:

    这里是如何做的男孩(注意这是 RESTful Spring 3 MVC 语法,但它可以在旧的 Spring 控制器中工作):

    @RequestMapping(value = "/rate", method = RequestMethod.POST)
    public String rateHandler(HttpServletRequest request) {
        //your controller code
        String referer = request.getHeader("Referer");
        return "redirect:"+ referer;
    }
    

    【讨论】:

    • 如果在编辑小马时出现验证错误并且用户返回到编辑小马页面,这将不起作用。因为现在引用者将指向编辑小马页面。
    • 也可以通过 @RequestHeader 注释将其绑定到方法的参数来获取 more declarative way 中的引用标头:rateHandler(@RequestHeader String referer)
    【解决方案2】:

    当然,一种选择是在新窗口中打开编辑表单,这样用户只需将其关闭,然后他们就会回到原来的位置。

    在我当前的应用程序中有几个地方我需要做一些复杂的事情,然后将用户传递给一个表单,然后让他们返回到起点。在这些情况下,我在传递它们之前将起点存储在会话中。对于你正在做的事情来说,这可能是矫枉过正。

    其他选项:1)您可以存储“Referer”标头并使用它,但这可能不可靠;并非所有浏览器都设置该标题。 2)您可以在调用“history.go(-2)”的表单提交后的确认页面上有javascript。

    【讨论】:

      【解决方案3】:

      我的答案与 Sam Brodkins 的相似(我也推荐它)。但是考虑到“Referer”值可能不可用,我让这个函数在我的控制器中使用它

      /**
      * Returns the viewName to return for coming back to the sender url
      *
      * @param request Instance of {@link HttpServletRequest} or use an injected instance
      * @return Optional with the view name. Recomended to use an alternativa url with
      * {@link Optional#orElse(java.lang.Object)}
      */
      protected Optional<String> getPreviousPageByRequest(HttpServletRequest request)
      {
         return Optional.ofNullable(request.getHeader("Referer")).map(requestUrl -> "redirect:" + requestUrl);
      }
      

      因此,在您的控制器调用函数中,您应该返回如下内容:

      @RequestMapping(value = "/upload", method = RequestMethod.POST)
      public @ResponseBody
      String testRedirection(HttpServletRequest request)
      {
            //Logic....
            //Returns to the sender url
            return getPreviousPageByRequest(request).orElse("/"); //else go to home page
      }
      

      【讨论】:

        【解决方案4】:

        是的,我认为 Jacob 对新窗口中的表单的想法可能是一个不错的选择。 或在隐藏的 div 中。就像一个道场对话。 http://dojocampus.org/explorer/#Dijit_Dialog_Basic

        【讨论】:

          【解决方案5】:

          另一种选择是设计您的网址,以便它们显示您正在做的事情的上下文,并且按照惯例,可以让您“知道”操作的开始位置。

          例如,你可以有这样的网址

          site/section1/pony/edit
          site/section1/pony/delete
          
          site/somewhere/else/entirely/pony/edit
          site/somewhere/else/entirely/pony/delete
          

          这两个网址都允许小马编辑和删除。要回到他们两个的起点,您只需“向上”2 个文件夹。这可以通过一个查看当前 url 的 javascript 函数来完成,并且只上升 2 个文件夹,或者您可以在服务器端 2 上找出它,并进行类似的重定向。

          【讨论】:

          • 这个解决方案不是返回上一页而是非常适合网站流量。
          【解决方案6】:

          您还可以使用拦截器跟踪上次呈现给用户的 ModelAndView(或仅视图)。此示例仅跟踪最后一个模型和视图,但您可以使用列表导航回更多级别。

          package com.sample;
          import org.springframework.web.servlet.ModelAndView;
          import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
          
          import javax.servlet.http.HttpServletRequest;
          import javax.servlet.http.HttpServletResponse;
          
          public class LastModelAndViewInterceptor extends HandlerInterceptorAdapter {
          
              public static final String LAST_MODEL_VIEW_ATTRIBUTE = LastModelAndViewInterceptor.class.getName() + ".lastModelAndView";
          
              @Override
              public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
                  request.getSession(true).setAttribute(LAST_MODEL_VIEW_ATTRIBUTE, modelAndView);
                  super.postHandle(request, response, handler, modelAndView);
              }
          
          }
          

          使用 Spring XML 配置:

          <bean id="handlerMapping" class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping">
              <property name="interceptors">
                  <bean class="com.sample.LastModelAndViewInterceptor"/>
              </property>
          </bean>
          

          然后使用以下代码在控制器中返回该视图:

          ModelAndView mv = (ModelAndView)request.getSession().getAttribute(LastModelAndViewInterceptor.LAST_MODEL_VIEW_ATTRIBUTE);
          return mv;
          

          【讨论】:

            【解决方案7】:
            response.sendRedirect(request.getHeader("Referer"));
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2015-10-08
              • 2015-03-12
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2023-03-22
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多