【问题标题】:Value of the servlet attribute if the attribute was replaced如果属性被替换,则 servlet 属性的值
【发布时间】:2015-02-01 17:20:36
【问题描述】:

这是我正在阅读的书:

鉴于此代码来自一个有效的 HttpServlet,该 HttpServlet 也已 注册为 ServletRequestAttributeListener:

public void doGet(HttpServletRequest req, HttpServletResponse res) throws IOException, ServletException {
         req.setAttribute(“a”, “b”);
         req.setAttribute(“a”, “c”);
          req.removeAttribute(“a”);
}
        public void attributeAdded(ServletRequestAttributeEvent ev) {
        System.out.print(“ A:” + ev.getName() + “->” + ev.getValue());
}
       public void attributeRemoved(ServletRequestAttributeEvent ev) {
       System.out.print(“ M:” + ev.getName() + “->” + ev.getValue());
}
       public void attributeReplaced(ServletRequestAttributeEvent ev) {
       System.out.print(“ P:” + ev.getName() + “->” + ev.getValue());
}

生成什么日志输出?

答案是:

C. A:a->b P:a->b M:a->c

书上的解释是:

棘手! getValue 方法返回属性的 OLD 值,如果 属性被替换了。

我的问题是这怎么可能? 特别是这部分序列我不清楚:P:a->b 为什么又是 P:a->b 而不是 P:a->c

【问题讨论】:

    标签: servlets servlet-listeners


    【解决方案1】:

    您混淆了 attribute 的值,以及表示属性值已被替换的 event 的值。

    当你打电话时

    req.setAttribute("a", "c");
    

    请求创建一个新事件并触发它。所以代码基本上是这样的:

    public void setAttribute(String name, Object newValue) {
        // 1. get the old value
        Object oldValue = getAttribute(name);
    
        // 2. construct an event containing the old value
        ServletRequestAttributeEvent event = new ServletRequestAttributeEvent(context, request, name, oldValue);
    
        // 3. store the new value of the attribute
        this.attributeMap.put(name, newValue);
    
        // 4. call all the listeners with the event
        for (ServletRequestAttributeListener listener : listeners) {
            listener.attributeReplaced(event);
        }
    }
    

    【讨论】:

    • 感谢您的及时回答,但恕我直言,我认为我没有混淆属性值和事件值。请参阅我在提供的答案中找到的解释。
    【解决方案2】:

    我找到了解释:

    getName() 方法返回触发事件的属性的字符串名称。 getValue() 方法返回触发事件的属性的对象值。小心!它返回旧值,而不是新值。换句话说,它返回属性在触发事件的更改之前的值!

    所以它正在做我认为它应该做的事情,只是没有按照我期望的顺序(首先更改值然后触发事件)。

    更详细的解释是这个:

    为了澄清这个输出,我们可以称它们为“添加”、“替换”和 “已移除”,所以我们正在查看:

    已添加:a->b 已替换:a->b 已删除:a->c

    现在的问题是,为什么 Replaced 会为值返回“b” “c”?

    简单的答案是因为文档说它应该这样做: http://docs.oracle.com/javaee/7/api/javax/servlet/ServletRequestAttributeListener.html

    void attributeReplaced(ServletRequestAttributeEvent srae) 接收 属性已被替换的通知 Servlet 请求。参数:srae - ServletRequestAttributeEvent 包含 ServletRequest 以及 被替换的属性

    现在也许更有趣的问题是他们为什么要这样做?

    通常像这样的 API 旨在向您传递旧值, 因为您始终可以选择在 打回来。因此,如果他们将旧值传递给您-您将拥有更多 提供给您的信息比他们刚刚通过当前 价值。 (没有办法问“这个属性使用了什么值 有吗?”在它消失之后)。

    因此,通过这种 API 设计,您可以编写一个侦听器而不是花费一些时间 每当“a:b”被删除时的动作 - 通过显式删除 调用或用另一个值替换它。如果他们只是通过 新值,您无法编写该侦听器(不存储 自己添加的值)。

    希望这有助于更清楚地说明为什么会这样。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-09-05
      • 2012-11-15
      • 2014-12-16
      • 1970-01-01
      • 2015-05-13
      • 2018-04-19
      • 2022-11-21
      • 1970-01-01
      相关资源
      最近更新 更多