request的生存期只限于服务器跳转
症状:
刚才想做一个实验,在a.jsp中向request添加属性(页面编码为UTF-8),在b.jsp中删除该属性(页面编码为ISO-8859-1),通过ServletRequestAttributeListener来观察是否删除成功。(目的是看页面编码会不会影响attribute name的比较。)
先在浏览器输入...a.jsp,回车,然后输入...b.jsp,回车
后来发现ServletRequestAttributeListener始终没有检测到request的属性被删除。
分析:
“先在浏览器输入...a.jsp,回车,然后输入...b.jsp,回车”
2个不同的request,访问b.jsp的时候已经是另一个request object了,注意client-side跳转与server-side跳转的区别
解决方案:
使用server-side跳转,例如<jsp:forward>
代码如下:
主要的思路就是,a.jsp提交一个参数arg1,作为attibute的key(或者说name),然后跳转(server-side跳转)到b.jsp,再输入另一个参数arg2,提交后如果arg1.equals(arg2)返回true,那么就能删除request找中由arg1作为key的attribute了
ServletRequestAttributeListener.java
public class ServletRequestAttributeListenerDemo implements ServletRequestAttributeListener { public void attributeAdded(ServletRequestAttributeEvent srae){ System.out.println("** 增加request属性 --> 属性名称:" + srae.getName() + ",属性内容:" + srae.getValue()) ; } public void attributeRemoved(ServletRequestAttributeEvent srae){ System.out.println("** 删除request属性 --> 属性名称:" + srae.getName() + ",属性内容:" + srae.getValue()) ; } public void attributeReplaced(ServletRequestAttributeEvent srae){ System.out.println("** 替换request属性 --> 属性名称:" + srae.getName() + ",属性内容:" + srae.getValue()) ; } } /* <listener> <listener-class> org.foo.listenerdemo.ServletRequestAttributeListenerDemo </listener-class> </listener> */
request_attribute_remove1.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Insert title here</title> </head> <body> <!-- 之所以要加上form来提交这个步骤,是因为页面编码无法影响到java的默认charset,所以如果直接在java代码中写上attrname的话估计起不到检验的作用 --> <% String attr_name1 = request.getParameter("attr_name1"); if (attr_name1!=null && !attr_name1.equals("")) { session.setAttribute(attr_name1, "java") ; // 只能用server-side跳转,否则request就被销毁了 request.getRequestDispatcher("request_attribute_remove2.jsp").forward(request, response); } %> <form action="request_attribute_remove1.jsp" method="post"> 要添加的属性名:<input type="text" name="attr_name1"> <input type="submit" value="添加属性"> </form> </body> </html>
request_attribute_remove2.jsp
<%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"> <title>Insert title here</title> </head> <body> <% String attr_name2 = request.getParameter("attr_name2"); if (attr_name2!=null && !attr_name2.equals("")) { session.removeAttribute(attr_name2) ; } %> <form action="request_attribute_remove2.jsp" method="post"> Attribute name:<input type="text" name="attr_name2"> <input type="submit" value="Delete Attribute"> </form> </body> </html>
运行测试,Oops!又出问题了!
症状:
在a.jsp提交了一个参数"info"之后,console显示了"** 增加request属性 --> 属性名称:info,属性内容:java",然后跳转到b.jsp(server-side跳转),再提交参数"info",console没有显示任何内容!
分析:
form的action是client-side跳转,注意看浏览器的地址栏发生了变化!
解决方案:
目前我是把request换成了session,然后使用了一个HttpSessionAttributeListener
form action可以实现server-side跳转吗?
换成session之后,得出结论:只要提交的参数是ACSII字符,页面的编码即便不相同,也不会影响到内部String的比较,非ASCII字符,例如中文字符可能导致2个编码不一致的页面,即使是相同的字符串,equals的比较结果也是false(可以参考这篇文章:http://www.cnblogs.com/qrlozte/p/3516716.html)
代码如下:
HttpSessionAttributeListener
public class HttpSessionAttributeListenerDemo implements HttpSessionAttributeListener { public void attributeAdded(HttpSessionBindingEvent se){ System.out.println(se.getSession().getId() + ",增加属性 --> 属性名称" + se.getName() + ",属性内容:" + se.getValue()) ; } public void attributeRemoved(HttpSessionBindingEvent se){ System.out.println(se.getSession().getId() + ",删除属性 --> 属性名称" + se.getName() + ",属性内容:" + se.getValue()) ; } public void attributeReplaced(HttpSessionBindingEvent se){ System.out.println(se.getSession().getId() + ",替换属性 --> 属性名称" + se.getName() + ",属性内容:" + se.getValue()) ; } } /* <listener> <listener-class> org.foo.listenerdemo.HttpSessionAttributeListenerDemo </listener-class> </listener> */
session_attribute_remove1.jsp --- 编码UTF-8
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Insert title here</title> </head> <body> <!-- 之所以要加上form来提交这个步骤,是因为页面编码无法影响到java的默认charset,所以如果直接在java代码中写上attrname的话估计起不到检验的作用 --> <% String attr_name1 = request.getParameter("attr_name1"); if (attr_name1!=null && !attr_name1.equals("")) { session.setAttribute(attr_name1, "java") ; request.getRequestDispatcher("request_attribute_remove2.jsp").forward(request, response); } %> <form action="session_attribute_remove1.jsp" method="post"> 要添加的属性名:<input type="text" name="attr_name1"> <input type="submit" value="添加属性"> </form> </body> </html>
session_attribute_remove2.jsp --- 编码ISO-8859-1
<%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"> <title>Insert title here</title> </head> <body> <% String attr_name2 = request.getParameter("attr_name2"); if (attr_name2!=null && !attr_name2.equals("")) { session.removeAttribute(attr_name2) ; } %> <form action="session_attribute_remove2.jsp" method="post"> Attribute name:<input type="text" name="attr_name2"> <input type="submit" value="Delete Attribute"> </form> </body> </html>