【问题标题】:Spring forward with added parameters?带有附加参数的弹簧前进?
【发布时间】:2011-12-21 04:52:51
【问题描述】:

有没有办法在向另一个控制器添加一些参数数据的同时将请求转发给另一个控制器?我尝试添加到 ModelMap,但它似乎并没有出现。我正在做类似的事情:

return "forward:/my-other-controller";

我能想到的唯一其他方法是将参数放在会话上,然后在目标控制器中弹出它们。

【问题讨论】:

    标签: java spring controller forward


    【解决方案1】:

    最简单的方法是将数据添加到请求中。由于这是转发,相同的请求被传递给服务器内的不同处理程序。

    例如,让我们从两个控制器的简单设置开始,一个转发到另一个:

    @Controller
    public class TestController {
        @RequestMapping(value="/test")
        public String showTestPage() {
            return "forward:/test2";
        }
    }
    
    @Controller
    public class TestController2 {
        @RequestMapping(value="/test2")
        public String showTestPage() {
            return "testPageView";
        }
    }
    

    添加数据的第一种方法是将其设置为请求的属性。新控制器将如下所示 (A):

    @Controller
    public class TestController {
        @RequestMapping(value="/test")
        public String showTestPage(HttpServletRequest request) {
            request.setAttribute("param1", "foo");
            request.setAttribute("param2", "bar");
            return "forward:/test2";
        }
    }
    
    @Controller
    public class TestController2 {
        @RequestMapping(value="/test2")
        public String showTestPage(HttpServletRequest request) {
            String param1 = (String) request.getAttribute("param1");
            String param2 = (String) request.getAttribute("param2");
            return "testPageView";
        }
    }
    

    由于forward prefix is basically an URL中的视图名称,还可以有以下版本(属性改为参数)(B):

    @Controller
    public class TestController {
        @RequestMapping(value="/test")
        public String showTestPage() {
            return "forward:/test2?param1=foo&param2=bar";
        }
    }
    
    @Controller
    public class TestController2 {
        @RequestMapping(value="/test2")
        public String showTestPage(HttpServletRequest request) {
            String param1 = request.getParameter("param1");
            String param2 = request.getParameter("param2");
            return "testPageView";
        }
    }
    

    您还可以通过使用注释来进一步简化第二个控制器:

    @Controller
    public class TestController2 {
        @RequestMapping(value="/test2")
        public String showTestPage(@RequestParam String param1, @RequestParam String param2) {
            return "testPageView";
        }
    }
    

    为了好玩,并展示 Spring 的绑定行为,您甚至可以这样做 (C):

    @Controller
    public class TestController {
        @RequestMapping(value="/test")
        public String showTestPage() {
            return "forward:/test2?param1=foo&param2=bar";
        }
    }
    
    @Controller
    public class TestController2 {
        @RequestMapping(value="/test2")
        public String showTestPage(@ModelAttribute DummyBinder params) {
            String param1 = params.getParam1();
            String param2 = params.getParam2();
            return "testPageView";
        }
    }
    
    class DummyBinder {
        private String param1;
        private String param2;
    
        public String getParam1() {
            return param1;
        }
    
        public void setParam1(String param1) {
            this.param1 = param1;
        }
    
        public String getParam2() {
            return param2;
        }
    
        public void setParam2(String param2) {
            this.param2 = param2;
        }
    }
    

    我个人会为许多参数选择解决方案 A,而为少数参数选择解决方案 B。 解决方案 C 有一种“嗯...?!”效果,所以我会避免它(它也适用于添加到 URL 的参数,所以其中一些参数或者你得到一个混乱的 URL)。

    在会话中添加数据也可以正常工作,但会不必要地延长数据的生命周期,因此最好的地方是在过渡到第二个控制器期间将其添加到请求中。

    【讨论】:

    • 感谢您的精彩回答!这触及了我困惑的核心。到处都是“属性”和“参数”,我似乎永远不明白哪个是哪个。我的 POST 请求在正文中有二进制数据,所以我不能将它用于 url 编码的“参数”。那么 request.setAttribute() 实际上做了什么?这些只是 HttpServletRequest 对象上的任意键/值对,还是它们存储为实际的 HTTP 参数,例如查询字符串等?而request.setAttribute和request.setParameter有什么区别?
    • @Tony R:参数是用户在 GET/POST 上提交时发送的内容。它主要是只读数据(没有request.setParameter;服务器构建带有参数的请求对象供您获取)。属性是放置在服务器特定范围内的数据。您使用 request.setAttribute 将数据放置在“请求范围”中(例如,您还可以具有会话范围或应用程序范围)。您可以添加、获取或删除属性。这里简单解释一下:xyzws.com/Servletfaq/…
    • 非常感谢您的解释。我没有意识到参数是只读的,这实际上很有意义。现在答案似乎微不足道......事实上,我想知道为什么要花这么长时间才能得到这个答案,因为其他答案现在似乎是错误
    • 我也在为这个话题而苦苦挣扎,尽管我很清楚什么是属性和参数。我有一个像 (C) 那样的完整模型类,我希望将它添加到模型然后转发也会将它绑定到第二个控制器中的新模型。但事实并非如此。它在第二个控制器中的请求范围内,但未绑定到同名的模型属性(第二个控制器中的参数)。因此,显然绑定只考虑参数,而不是属性。
    • 当我们给请求添加属性的时候,在forward的情况下,整个URI都是持久化的吗?那么,我不需要随时再次添加该属性?在重定向的情况下呢? @Bogdan
    【解决方案2】:

    考虑转发,就像重定向一样,但在这个意义上不需要上下文和主机(转发由服务器内部处理,而重定向指示用户的浏览器请求不同的 url)。

    所以,是的,使用会话、cookie 或发布或获取参数。

    【讨论】:

    • 请求已经有自己的参数......我也希望这些参数也能使用。但我也想要模型,也许还有其他方法可以发送数据?
    • 您是否尝试过将 ModelMap 添加到您的控制器并将您的新值添加到该控制器以供转发的控制器使用?
    • 我认为您应该采用会话方法。这是最简单的解决方法。除非您可以通过 GET 或 POST 参数推送新属性。
    • 哇,如果使用会话是执行此操作的最佳方式,我会感到惊讶。你会认为 Spring 会提供更好的转发框架。
    • 我认为这更多的是Java servlet api和请求范围的限制。
    【解决方案3】:

    您考虑过过滤器吗?您可以使用委托过滤器代理创建过滤器,这将使您可以访问请求参数以及 spring beans。

    【讨论】:

    • 你能详细说明或给我举个例子吗?我不明白它是如何组合在一起的。
    • @Tony 。我可以选择重定向请求并尝试使用过滤器更改参数。如果要使用 forward ,则需要使用会话属性。
    • 我看不出它是如何工作的。从托尼到目前为止所说的话,我怀疑他需要的请求属性中有什么。
    【解决方案4】:

    我找到了this post,它使用HttpRequestWrapper

    第一:
    定义HttpRequestWrapper 并重写方法getParametergetParameterMapgetParameterNamesgetParameterValues 就像在帖子中一样。

    第二:
    通过 RequestDispatcher 转发到您的 url,使用方法参数中的 wrapped 请求:

    request.getRequestDispatcher("myForwardUrl").forward(new MyRequestWrapper(request), response);
    

    我已经尝试过删除参数(这更加困难!)并且它有效!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-03-24
      • 2012-01-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-08-10
      • 1970-01-01
      相关资源
      最近更新 更多