浏览 8274 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
|
|
---|---|
作者 | 正文 |
发表时间:2010-06-09
最后修改:2010-06-11
由于目前有的手机不支持cookie,导致手机上session支持不了,于是乎就有了几种针对这些特殊情况而提出的解决方案。而最常见的就是url重写,而url重写又分几种,有jstl实现,struts实现,普通传参实现,而我用的也就是最普通最常见的一种实现方式。 其实我也是根据kaixin001中的方式来做的,kaixin001中的wap形式就是在链接后面直接传sessionId的方式(其中包括了用户的id,后面有串字符串,我猜想应该就是sessionId),比如:http://localhost:8080/project/MobileLogin.do?sessionId=xxxxxxxx;这个sessionId就是session的id,通过链接传参的方式传到后台,在后台,由于不支持session,故需要自己开发一套基于session的操作。 首先,先了解下Map的含义,在java中,我们都知道Map是一个用于存储键值对的一个集合,也就是我们常说的key、value对应值,并且每个键映射一个值,这个键是不能重复的。 上面了解了Map的含义,为什么要了解Map,是因为在接下来我需要在程序中用到Map。好了,言归正传,怎么才能实现sessionId取session的步骤呢,相信看了上面的Map,应该有人脑子里面有思路了,那就是利用Map的存储方式来操作sessionId,根据sessionId生成一个session,由于Map是key不能重复,所以就可以把sessionId设置成key,session设置为map的value,并且要保证这个sessionId永远都只需要创建一次,这就又用到了一个经典的设计模式:单例模式。第一次登录访问sessionId是新的,就往map中put一个, public synchronized void sessionCreated(HttpSession session) { if(session != null) { map.put(session.getId(), session); } } 除非你登录失败,否则这个sessionId一直跟随你的程序在运行,直到你手动注销session(把session destroryed)或者重新登录一次(替换原有的sessionId)。 public synchronized void sessionDestroyed(HttpSession session) { if(session != null) { map.remove(session.getId()); } } 单例模式的session容器已经构建,最后就是在类中提供一个getSession的方法; public synchronized HttpSession getSession(String sessionId) { if(sessionId == null) return null; return (HttpSession) map.get(sessionId); } session容器的构建类已经写完,现在就是监听事件了,新建一个Listener监听器,实现HttpSessionListener,HttpSessionListener提供2个方式,一个是sesionCreated(session的创建方法),一个是sessionDistoryed(session的销毁方法),在created方法中,调用单例类中的sessionCreate方法,在destroyed方法中调用单例类中的sessionDistoryed方法,监听器需要在web.xml中进行配置. <listener> <listener-class>xxx包下的xxx类</listener-class> </listener> 至此,就完成了一个session的构建,并且这个session是根据sessionId的变化而变化。下面看具体的代码: //session容器单例类 import java.util.HashMap; import java.util.Map; import javax.servlet.http.HttpSession; public class SessionContext { private static SessionContext instance; private Map<String, HttpSession> map; private SessionContext() { map = new HashMap<String, HttpSession>(); } public static SessionContext getInstance() { if(instance == null) { instance = new SessionContext(); } return instance; } public synchronized void sessionCreated(HttpSession session) { if(session != null) { map.put(session.getId(), session); } } public synchronized void sessionDestroyed(HttpSession session) { if(session != null) { map.remove(session.getId()); } } public synchronized HttpSession getSession(String sessionId) { if(sessionId == null) return null; return (HttpSession) map.get(sessionId); } } //session监听器 import javax.servlet.http.HttpSessionEvent; import javax.servlet.http.HttpSessionListener; public class SessionListener implements HttpSessionListener { private SessionContext sessionContext = SessionContext.getInstance(); public void sessionCreated(HttpSessionEvent httpSessionEvent) { sessionContext.sessionCreated(httpSessionEvent.getSession()); } public void sessionDestroyed(HttpSessionEvent httpSessionEvent) { sessionContext.sessionDestroyed(httpSessionEvent.getSession()); } } session容器构建好了,现在就是action的操作了,action中相对比较简单。 public String sessionId; public HttpSession getWapSession() throws Exception { HttpSession session = SessionContext.getInstance().getSession(sessionId); return session; } public void delSession() throws Exception { SessionContext.getInstance().sessionDestroyed(getWapSession()); } public void setWapAttribute(String key, Object value) throws Exception { this.getWapSession().setAttribute(key, value); } public String getSessionId() { return sessionId; } public void setSessionId(String sessionId) { this.sessionId = sessionId; } 通过session传值,setWapAttribute(key,value),在页面上同样还是用SessionContext.getInstance().getSession(sessionId)得到session,才能从session中getAttribute值,其中的sessionId从request请求中get出,目前我还在测试怎么让它支持EL表达式,所以页面上还是用的<%%>这种取值方法。 以上就是action的部分代码,sessionId指的是页面上session.getId(),通过URL参数的方式传到后台,http://localhost:8080/project/xxx.do?session=<%=session.getId()%>,链接是这样的。url是自己组装。这个url方式是仿照开心网中的手机版本(wml.kaixin001.com),至此,一个手机登录的session问题是完美解决了,这里没有加权限判断。只提供了处理手机的登录session问题,相信有了session,其余的对我们来说不是什么难点。后期有时间再来写权限验证。 wap开发,页面展示必须是符合wml规范的文件,可以是jsp文件,只不过头部要把头部的contentType类型改成wml形式的, <%@ page contentType="text/vnd.wap.wml;charset=utf-8"%> 然后 <?xml version="1.0" encoding="utf-8" ?> <!DOCTYPE wml PUBLIC "-//WAPFORUM//DTD WML 1.1//EN" "http://www.wapforum.org/DTD/wml_1.1.xml"> <wml> <card id="" title=""> </card> </wml> 记住一点,wml语法的一点就是一定要有结束标签,哪怕是用这样的<br>,在wml语法中也是错误的,必须要有结束。<br/>或者<br></br>,而且wml中严格区分大小写。这些都是必须遵守的。 如果有比这个更好的方法,期待共同探讨。 声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |
发表时间:2010-06-13
<c:url 用标签库中这个标签写Url 不就结了。。干嘛要自己去写。。
重定向就这样写 String url= response.encodeRedirectURL(request.getContextPath(+"/wap/Index_input.action"); response.sendRedirect(url); 自动会检查浏览器是否支持,如果不支持就会重写url 自动带上sessionid 我现在wap就是这样做的。。 楼主你这样我感觉有多余。 而且你还要维护哪个map。 ??? 楼主你这样写 有点误入子弟。。。 |
|
返回顶楼 | |
发表时间:2010-06-13
楼主提到
url重写又分几种,有jstl实现,struts实现,普通传参实现 普通实现应该就是 response.encodeURL(url); 可以了 。 |
|
返回顶楼 | |
发表时间:2010-06-15
liweixw 写道 <c:url 用标签库中这个标签写Url 不就结了。。干嘛要自己去写。。
重定向就这样写 String url= response.encodeRedirectURL(request.getContextPath(+"/wap/Index_input.action"); response.sendRedirect(url); 自动会检查浏览器是否支持,如果不支持就会重写url 自动带上sessionid 我现在wap就是这样做的。。 楼主你这样我感觉有多余。 而且你还要维护哪个map。 ??? 楼主你这样写 有点误入子弟。。。 哦,弱弱的问下,请问你这种session要怎么管理呢?我看了你写的文章,90%是网络上抄袭的,还有就是没有写session的管理。我没有恶意,只是我想问下你session是怎么管理的,我还没用过项目中,只是在研究阶段,第一次做wap开发,没什么经验。既然你有这方面的经验,那么我虚心请教下你。 |
|
返回顶楼 | |
发表时间:2010-06-15
没有必要对session进行手动管理,encodeURL()就可以达到你上面的几十行代码的效果了。
另外singleton的实现有点问题 |
|
返回顶楼 | |
发表时间:2010-06-16
如果浏览器不支持Cookie,就直接是URL rewrite就行了。
|
|
返回顶楼 | |
发表时间:2010-06-17
mercyblitz 写道 如果浏览器不支持Cookie,就直接是URL rewrite就行了。
恩,知道了,是我多此一举了,我想复杂了。 |
|
返回顶楼 | |
发表时间:2010-06-17
herryhaixiao 写道 liweixw 写道 <c:url 用标签库中这个标签写Url 不就结了。。干嘛要自己去写。。
重定向就这样写 String url= response.encodeRedirectURL(request.getContextPath(+"/wap/Index_input.action"); response.sendRedirect(url); 自动会检查浏览器是否支持,如果不支持就会重写url 自动带上sessionid 我现在wap就是这样做的。。 楼主你这样我感觉有多余。 而且你还要维护哪个map。 ??? 楼主你这样写 有点误入子弟。。。 哦,弱弱的问下,请问你这种session要怎么管理呢?我看了你写的文章,90%是网络上抄袭的,还有就是没有写session的管理。我没有恶意,只是我想问下你session是怎么管理的,我还没用过项目中,只是在研究阶段,第一次做wap开发,没什么经验。既然你有这方面的经验,那么我虚心请教下你。 是的。我是网上找的资料,为了以后方便查阅,其实也就是一时兴起, 我原来考虑也和你一样,我是参考的网易是怎么做的,(wap.163.com opera访问的) 我发现在禁用cookie的时候url网易会自动带上这个sessionid。 综合我现在的项目实践 我是这样做的。 1.在jsp中涉及到url是用的是标签库 <c:url 标签 填写url(这个标签自动会检查浏览器是否支持cookie,支持就原样返回,不支持自动带上sessionid) 2。在涉及后台转发时候用 首先用response.encodeURL()方法重写,和上面的标签一样的功能; 3.后台重定向用response.encodeRedirectURL()方法重写后转发。 |
|
返回顶楼 | |