【问题标题】:Spring 3: How to handle session based objects between controllersSpring 3:如何处理控制器之间基于会话的对象
【发布时间】:2013-07-17 20:04:58
【问题描述】:

我通常使用 Struts2,但出于各种原因,我正在探索 Spring 的使用,最值得注意的是在 rest 样式 url 功能中的灵活性。我想我也会尝试利用作用域 bean 在控制器之间存放一些数据。这是一个相对较大的项目,我有几个不同的控制器来处理站点的不​​同方面。

我遇到的是我在我的控制器中声明了一个 @Component 和 @Autowiring 它,但是数据没有在会话 bean 中的控制器之间持久化。

豆示例:

@Component
@Scope(value = "session", proxyMode = ScopedProxyMode.TARGET_CLASS)
public class EventBean implements Serializable {
    private Event event;
    ...
}

控制器示例:

@Controller
public class EventController {

    @Autowired
    private EventBean event;

    @ModelAttribute("event")
    public EventBean getEvent() {
        return event;
    }

    @RequestMapping(value = "/{url}", method = RequestMethod.GET)
    public String getEvent(@PathVariable String url, ModelMap model) {
        model.addAttribute("url", url);
        try {
            //  EventEntity in the bean is set by the url from DB
            event.setEvent(url);
        } catch (SQLException ex) {
            Logger.getLogger(EventController.class.getName()).log(Level.SEVERE, null, ex);
        }
        return "public/index";
    }
}

现在我的目标是,如果我在此控制器中设置事件,如果在第二个控制器中我访问事件 bean 并且实体不为空,则无需再次访问数据库。

public void setEvent(String url) throws SQLException {
    if (this.event == null) {
        this.event = EventDAO.retrieveByURL(url);
    }
}

但这不会发生。当我导航到第二个控制器时,bean 中的事件实体始终为空。

我只是在玩 Spring 几天,所以我确定我错过了一些东西,只是不确定我错过了什么。任何想法将不胜感激。

编辑:

JSP 被调用:

<%@page contentType="text/html" pageEncoding="UTF-8"%>
<!DOCTYPE html>

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <title>Home</title>
    </head>
    <body>
         <h1>Event Name: ${event.name}</h1>
         <h2>Event URL: ${url}</h2>
    </body>
</html>

【问题讨论】:

  • 只是为了确认,在您的第二个控制器中,事件字段也自动连接,EventBean 是否正确连接到第一个控制器(字段不为空?)
  • 第二个控制器是此处列出的 EventController 的副本,但 /register 被添加到 @RequestMapping,@RequestMapping(value = "/{url}/register", method = RequestMethod.得到)。在 EventController 中调用 event.setEvent(url) 方法并从数据库中加载事件实体。我可以看到在单步执行调试器时填充了值,并且可以在 JSP 上使用 JSTL 提取值。如果我立即导航到 localhost/myUrl/register,EventBean 中的 event 值不会持久化,就好像它从未在第一个控制器中设置一样。
  • 好的,你确定第一个和第二个控制器在单个会话的范围内,如果你的jsp有&lt;%@ page session="false" %&gt;,那么可能还没有会话本身?
  • 这是一个非常普通的设置。我在 JSP 页面上的唯一声明是针对标记库的,除了它本质上是原始的。两个动作、2 个 JSP、JSTL taglib、原始 HTML 和 EL 检查模型变量。它通过作为 Maven 项目构建的 Netbeans 在 Tomcat 7 中运行。我也将 JSP 代码添加到原始帖子中以供参考。
  • 我最好的猜测是您的第一个和第二个控制器不在同一个会话的范围内 - 可以使用为两个请求发送的会话 cookie 进行验证。

标签: java spring session spring-mvc


【解决方案1】:

有 2 个选项可以解决此问题。希望这会有所帮助。

  1. @SessionAttributes("event") 的使用。这将确保模型存储在会话中,并且可以跨容器使用。您的课程将如下所示。请注意,在跨控制器使用会话属性时应谨慎使用,但是我自己没有遇到任何问题,并且使用它们没有问题。

    @Controller
    @SessionAttributes("event")
    public class EventController {
    
        @Autowired
        private EventBean event;
    
        @ModelAttribute("event")
        public EventBean getEvent() {
            return event;
        }
    
        @RequestMapping(value = "/{url}", method = RequestMethod.GET)
        public String getEvent(@PathVariable String url, ModelMap model) {
            model.addAttribute("url", url);
            try {
                //  EventEntity in the bean is set by the url from DB
                event.setEvent(url);
            } catch (SQLException ex) {
                Logger.getLogger(EventController.class.getName()).log(Level.SEVERE, null, ex);
            }
            return "public/index";
        }
    }
    
  2. 其他选项将是使用 spring 提供的表单标签,以便在调用第二个控制器时根据请求构造“事件”对象。 http://www.dzone.com/tutorials/java/spring/spring-form-tags-1.html

【讨论】:

  • 感谢ArunM的输入,我今天到办公室试试,告诉你进展如何。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-08-02
  • 1970-01-01
  • 2013-03-28
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多