这来自我正在阅读的书:
给出来自其他有效的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());
}
生成什么日志输出?
答案是:
℃。 A:a-> b:a:> b M:a-> c
书中的解释是:
棘手! getValue方法返回属性if的OLD值 该属性已被替换。
我的问题是这是怎么回事? 特别是这部分序列对我来说并不清楚: P:a-> b 为什么再一次 P:a-> b 而不是 P:a-> c ?
答案 0 :(得分:0)
您会混淆属性的值,以及事件的值,它表示已替换属性值。
致电时
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);
}
}
答案 1 :(得分:0)
我找到了解释:
getName()方法返回触发事件的属性的String名称。 getValue()方法返回触发事件的属性的对象值。小心!它返回旧值,而不是新值。换句话说,它返回属性在触发事件的更改之前的值!
所以它正在做我认为应该做的事情而不是按照我期望的顺序(首先改变值然后触发事件)。
更详细的解释是这个:
为了澄清这个输出,我们可以称之为"添加","替换"和 "删除"所以我们正在考虑这个:
已添加:a-> b已替换:a-> b删除:a-> c
现在问题是为什么替换回来" b"换取价值 " c"?
简单的答案是因为那是文档所说的应该做的事情: http://docs.oracle.com/javaee/7/api/javax/servlet/ServletRequestAttributeListener.html
void attributeReplaced(ServletRequestAttributeEvent srae)接收 通知已更换属性 ServletRequest中。参数:srae - ServletRequestAttributeEvent 包含ServletRequest以及的名称和(旧)值 被替换的属性
现在也许更有趣的问题是他们为什么要这样做?
通常这样的API旨在传递旧的价值, 因为你总是可以选择询问当前的值 打回来。因此,如果他们通过你的旧价值 - 你有更多 您可以获得的信息,而不是他们刚刚通过的信息 值。 (没有办法询问"这个属性使用了什么价值 有&#34?;它消失后。)
因此,使用此API设计,您可以编写一个监听器而不是一些监听器 每当" a:b"被删除 - 通过显式删除 打电话或用另一个值替换它。如果他们只是传入 新的价值,你不能写那个听众(没有存储 自己添加的值。)
希望通过这种方式帮助更清楚。