Session详解之web服务开发
来源:互联网 发布:js代码怎么用 编辑:程序博客网 时间:2024/04/28 20:00
1.先了解一下java中session的简单用法:
import javax.servlet.http.HttpSession; 需要引入servlet-api.jar
HttpSession session = request.getSession();
session.setAttribute("变量名", 值对象);
session.getAttribute("变量名"); 此时取出来的是Object, 一般需要强转
session.removeAttribute("变量名");
session.invalidate(); 删除所有session中保存的键
上一次我们已经实现了一个简单的web服务器版本,能够实现一些基本功能,但是在最后也提到了这个版本由于不支持session并不能实现真正的动态交互,这一次我们就来完成这一功能。
2.介绍Session实现原理
凡是搞过web开发的都知道,多数情况下浏览器请求服务器使用的是http请求,而http请求是无状态的,也就是说每次请求服务器都会新建连接,当得到响应后连接就关闭了,虽然http1.1支持持久连接(keep-alive),但是其最用主要是避免每次重建连接,而非解决用户在线状态等业务上的需求。而如果服务器想知道客户端的状态或是识别客户端,那么就不能像长连接那样通过连接本身实现,而是要通过每次请求时的数据来判断。
流程图如下
3.关于session的生命周期
以下情况,Session结束生命周期,Servlet容器将Session所占资源释放:
1.客户端关闭浏览器
2.Session过期
3.服务器端调用了HttpSession的invalidate()方法。
"一个浏览器就是一个新session,关了浏览器session就结束了" session 是在服务器端建立的,浏览器访问服务器会有一个sessionid,浏览器端通过sessionid定位服务器端的session,session的创建 和销毁由服务器端控制。当浏览器关闭后,session还存在在服务器端,只不过你新开的浏览器去访问服务器会创建另一个session,这个时候的 sessionid已经不一样了。也就不能访问上一次的哪个session里面的内容了。
"session的创建和销毁由服务器端控制",服务器端才有session,客户端只是通过sessionid来匹配session. 那服务器端session如何建的呢?
普通html不会创建,jsp默认是创建的,只要你访问任何一个jsp就会创建(不过只创建一次),你关闭浏览器重新访问又会创建一个,这些创建的session由服务器自己控制销毁,你也可以在服务器端代码中销毁。 什么情况下需要用上这种服务器端的session方式?
默认情况下,jsp被访问就会创建session(最开始是空的没有数据的),你的应用中的代码只是往session里面put数据。网上说可以 通过 <%@ page session="false"%>来不让jsp自动创session.我自己测试了一下(用sessionlistener),根本不起作用, session照样创建成功。 最后说一下,只有服务器端才有session.客户端被存到本地的是cookie.不过安全性低。所以不能放重要的数据。
=====================================================================
=======
sesion其实简单: 先 request.getsession(),当已有一个session与前request相关时就返回对这个 session的引用,当没有时就生成一个.一个session在server通过一个sessionid来标识的。也就是说在一个server是不会有 两个相同sessionid的session.
4.案例详解
** * session数据 * @author guojing * @date 2014-3-17 *
public class HttpSession {
Map String, Object map = new HashMapString, Object ();
Date lastVisitTime = new Date(); 最后访问时间
** * session数据 * @author guojing * @date 2014-3-17 *
public class HttpSession {
Map map = new HashMap();
Date lastVisitTime = new Date(); 最后访问时间
public void addAttribute(String name, Object value) {
map.put(name, value);
}
public Object getAttribute(String name) {
return map.get(name);
}
public Map getAllAttribute() {
return map;
}
public Set getAllNames() {
return map.keySet();
}
public boolean containsName(String name) {
return map.containsKey(name);
}
public Map getMap() {
return map;
}
public void setMap(Map map) {
this.map = map;
}
public Date getLastVisitTime() {
return lastVisitTime;
}
public void setLastVisitTime(Date lastVisitTime) {
this.lastVisitTime = lastVisitTime;
}
}** * 全局数据和会话相关数据,单例 * @author guojing * @date 2014-3-17 *
public class ApplicationContext {
private Map appMap = new HashMap();
ApplicationContext全局数据 ** * 这里自己也有点搞不清sessionMap是不是有必要考虑线程安全,还请指教 *
private ConcurrentMap sessionMap = new ConcurrentHashMap();
session数据
private ApplicationContext(){ }
** * 内部类实现单例 *
private static class ApplicationContextHolder {
private static ApplicationContext instance = new ApplicationContext();
}
TAG:
public static ApplicationContext getApplicationContext() {
return ApplicationContextHolder.instance; }
public void addAttribute(String name, Object value) {
ApplicationContextHolder.instance.appMap.pu
public static ApplicationContext getApplicationContext() {
return ApplicationContextHolder.instance;
}
public void addAttribute(String name, Object value) {
ApplicationContextHolder.instance.appMap.put(name, value);
} public Object getAttribute(String name) {
return ApplicationContextHolder.instance.appMap.get(name);
} public Map getAllAttribute() {
return ApplicationContextHolder.instance.appMap;
} public Set getAllNames() {
return ApplicationContextHolder.instance.appMap.keySet();
} public boolean containsName(String name) {
return ApplicationContextHolder.instance.appMap.containsKey(name);
} public void addSession(String sessionId) {
HttpSession httpSession = new HttpSession();
httpSession.setLastVisitTime(new Date());
ApplicationContextHolder.instance.sessionMap.put(sessionId, httpSession);
} ** * 获取session *
public HttpSession getSession(HttpExchange httpExchange) {
String sessionId = getSessionId(httpExchange);
if (StringUtil.isEmpty(sessionId)) {
return null;
}
HttpSession httpSession = ApplicationContextHolder.instance.sessionMap.get(sessionId);
if (null == httpSession) {
httpSession = new HttpSession();
ApplicationContextHolder.instance.sessionMap.put(sessionId, httpSession);
} return {
httpSession;
} ** * 获取sessionId *
public String getSessionId(HttpExchange httpExchange) {
String cookies = httpExchange.getRequestHeaders().getFirst("Cookie");
String sessionId = "";
if (StringUtil.isEmpty(cookies)) {
cookies = httpExchange.getResponseHeaders().getFirst("Set-Cookie");
} if (StringUtil.isEmpty(cookies)) {
return null;
}
String[] cookiearry = cookies.split(";");
for(String cookie : cookiearry){
cookie = cookie.replaceAll(" ", "");
if (cookie.startsWith("EH_SESSION=")) {
sessionId = cookie.replace("EH_SESSION=", "").replace(";", "");
} } return sessionId;
} ** * 获取所有session *
public ConcurrentMapString, HttpSession getAllSession() {
return ApplicationContextHolder.instance.sessionMap;
} ** * 设置session最后访问时间 * public void setSessionLastTime(String sessionI
public ConcurrentMap getAllSession() {
return ApplicationContextHolder.instance.sessionMap;
}
** * 设置session最后访问时间 *
public void setSessionLastTime(
String sessionId) {
HttpSession httpSession = ApplicationContextHolder.instance.sessionMap.get(sessionId);
httpSession.setLastVisitTime(new Date()); }}View Code
可以看出这两部分代码十分简单,下边看一下handle中如何处理session:
public void handle(HttpExchange httpExchange) throws IOException {
try {
String path = httpExchange.getRequestURI().getPath();
log.info("Receive a request,Request path:" + path); 设置sessionId
String sessionId = ApplicationContext.getApplicationContext() .getSessionId(httpExchange);
if (StringUtil.isEmpty(sessionId)) {
sessionId = StringUtil.creatSession();
ApplicationContext.getApplicationContext().addSession(sessionId);
} .....其他代码省略
}
catch (Exception e) {
httpExchange.close();
log.error("响应请求失败:", e);
}
}
** * 调用对应Controller处理业务 * @throws UnsupportedEncodingException * private ResultInfo invokController(HttpExchange httpExchange) throws UnsupportedEncodingException { 获取参数
Map map = analysisParms(httpExchange); IndexController controller = new IndexController();
设置session HttpSession httpSession = ApplicationContext.getApplicationContext().getSession(
httpExchange); log.info(httpSession);
map.put("session", httpSession);
return controller.process(map); }
View Code
最后看一下定时任务的实现:
** * 定时清理过期session * @author guojing * @date 2014-3-17 *public class
SessionCleanTask extends TimerTask { private final Log log = LogFactory.getLog(SessionCleanTask. class );
@Override public void run() { log.info( 清理session...... );
ConcurrentMap String, HttpSes
SessionCleanTask extends TimerTask { private final Log log = LogFactory.getLog(SessionCleanTask.class);
@Override public void run() { log.info("清理session......");
ConcurrentMap sessionMap = ApplicationContext.getApplicationContext() .getAllSession();
Iterator<map.entry> it = sessionMap.entrySet().iterator();
while (it.hasNext()) { ConcurrentMap.Entry entry= (Entry) it.next();
HttpSession httpSession= entry.getValue();
Date nowDate = new Date(); int diff = (int) ((nowDate.getTime() - httpSession.getLastVisitTime().getTime())100060);
if (
diff > Constants.SESSION_TIMEOUT) { it.remove(); }
}
log.info("清理session结束");
}
}
View Code
此次改动的代码就这么多。
本次实现的功能应该说是点睛之笔,session的实现从根本上提供了动态交互的支持,现在我们能够实现登陆之类的功能的。但是正如上边提到的,现在整个项目还很死板,我们目前只能使用一个controller,想要实现多个则需要根据请求参数进行判断,那么下一版本我们就来处理这一问题,我们将通过注解配置多个controller,并通过反射来进行加载。
5、最后来测试代码
下边我们来测试一下是否有效。由于目前controller是写死的,只有一个IndexController可用,那么我们就将就着用这个来测试吧,我们先来改一下其process方法的代码:
public ResultInfo process(Map map){
ResultInfo result =new ResultInfo(); 这里我们判断请求中是否有name参数,如果有则放入session,没有则从session中取出name放入map
HttpSession session = (HttpSession) map.get("session");
if (map.get("name") != null) {
Object name = map.get("name");
session.addAttribute("name", name);
} else {
Object name = session.getAttribute("name");
if (name != null) {
map.put("name", name);
}
}
result.setView("index");
result.setResultMap(map);
return result;
}
(文章来源:http://www.mfqyw.com/)
- Session详解之web服务开发
- Axis Web Service开发之旅 (七) --跨服务会话(Session)管理
- Axis Web Service开发之旅 (七) --跨服务会话(Session)管理
- 【WEB开发原理】Session与Cookie详解
- web开发之cookie与session
- WEB开发之[1]SESSION工作原理
- Web开发之Cookie and Session
- Web开发之Cookie and Session
- Web开发之端口详解
- iPhone开发技巧之网络--- Web服务
- Go 开发WEB服务之hello world
- web项目Session详解
- web session详解
- axis2开发webservice之跨服务会话(Session)管理
- axis2开发webservice之跨服务会话(Session)管理
- Web服务中的Session对象
- Web服务中的Session对象
- Web开发中的session
- ACM Backward Digit Sums(挑战程序设计竞赛)
- HTML里margin-left和left的区别
- python wsgi 网络编程3 出错
- 题解053-443(V13.02版本,711题)
- cocos2dx面试题整理
- Session详解之web服务开发
- Fei-Fei Li—— De-mystifying Good Research and Good Papers
- SpingMVC中的HandlerMapping
- web之相关servlet与android函数讲解
- 《Linux程序设计》——进程间通信:管道
- CGPath简单使用
- iOS开发UI篇章使用UItableview完成一个简单的QQ好友列表(一)
- java平衡搜索树AVL实现
- Maven使用(一)——Maven使用入门