Java Spring-MVC 控制器重定向到“上一个”页面?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/804581/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 19:39:56  来源:igfitidea点击:

Spring-MVC controller redirect to "previous" page?

javaspring-mvc

提问by Boden

Let's say I've got a form for editing the properties of a Pony, and in my web application there are multiple places where you can choose to edit a Pony. For instance, in a list of Ponies there might be an "edit" link next to each Pony, and when the user is viewing a Pony, there might also be an "edit" link in that view.

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

When a user clicks "submit" after editing a Pony, I would like to return the user to the page that he or she was when clicking the "edit" link.

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

How do I write my controller to redirect the user back to where they started? Certainly I can do this by passing a parameter to the controller, but that seems a little goofy. Am I thinking about this all wrong or is that pretty much what I'll have to do?

如何编写我的控制器以将用户重定向回他们开始的地方?当然,我可以通过将参数传递给控制器​​来做到这一点,但这似乎有点愚蠢。我在想这一切是错误的还是我必须要做的?

采纳答案by Jacob Mattison

One option, of course, would be to open the edit form in a new window, so all the user has to do is close it and they're back where they were.

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

There are a few places in my current application where I need to do something complicated, then pass the user to a form, and then have them return to the starting point. In those cases I store the starting point in the session before passing them off. That's probably overkill for what you're doing.

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

Other options: 1) you can store the "Referer" header and use that, but that may not be dependable; not all browsers set that header. 2) you could have javascript on the confirmation page after the form submission that calls "history.go(-2)".

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

回答by Derek

Yes I think Jacob's idea for the form in a new window may be a good option. Or in a hidden div. Like a dojo dialog. http://dojocampus.org/explorer/#Dijit_Dialog_Basic

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

回答by Sam Brodkin

Here's how to do it boys (Note this is RESTful Spring 3 MVC syntax but it will work in older Spring controllers):

这是如何做到的男孩(请注意,这是 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;
}

回答by Brad Parks

one other option would be to design your urls so they reveal the context of what you're doing, and by convention, would allow you to "know" where the start of an operation was.

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

For example, you could have urls like so

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

site/section1/pony/edit
site/section1/pony/delete

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

both those urls allow pony editing and deleting. To go back to the start for both of them, you'd simply go "up" 2 folders. This could be done via a javascript function that looks at the current url, and just goes up 2 folders, or you could figure it out on the server side 2, and do a redirect like that as well.

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

回答by Werner Altewischer

You can also keep track of the ModelAndView (or just the view) that have been last presented to the user with an interceptor. This example keeps track of only the last model and view, but you could use a list to navigate back more levels.

您还可以使用拦截器跟踪最后呈现给用户的 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);
    }

}

With Spring XML configuration:

使用 Spring XML 配置:

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

And then use the following code to get back to that view in a controller:

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

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

回答by EliuX

My answer is alike to Sam Brodkins′s (i recomended it also). But having in count that the "Referer" value may not be available i made this function to use it in my controllers

我的回答与 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);
}

So in your controller caller function you should return something like this:

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

@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
}

回答by Rajat

response.sendRedirect(request.getHeader("Referer"));