上一次咱们已经实现了一个简单的web服务器版本,可以实现一些基本功能,可是在最后也提到了这个版本因为不支持session并不能实现真正的动态交互,这一次咱们就来完成这一功能。 html
/** * session数据 * @author guojing * @date 2014-3-17 */ public class HttpSession { Map<String, Object> map = new HashMap<String, Object>(); 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<String, Object> getAllAttribute() { return map; } public Set<String> getAllNames() { return map.keySet(); } public boolean containsName(String name) { return map.containsKey(name); } public Map<String, Object> getMap() { return map; } public void setMap(Map<String, Object> 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<String, Object> appMap = new HashMap<String, Object>(); // ApplicationContext全局数据 /** * 这里本身也有点搞不清sessionMap是否是有必要考虑线程安全,还请指教 */ private ConcurrentMap<String, HttpSession> sessionMap = new ConcurrentHashMap<String, HttpSession>(); // session数据 private ApplicationContext(){ } /** * 内部类实现单例 */ private static class ApplicationContextHolder { private static ApplicationContext instance = new ApplicationContext(); } 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<String, Object> getAllAttribute() { return ApplicationContextHolder.instance.appMap; } public Set<String> 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 ConcurrentMap<String, HttpSession> getAllSession() { return ApplicationContextHolder.instance.sessionMap; } /** * 设置session最后访问时间 */ public void setSessionLastTime(String sessionId) { HttpSession httpSession = ApplicationContextHolder.instance.sessionMap.get(sessionId); httpSession.setLastVisitTime(new Date()); } }能够看出这两部分代码十分简单,下边看一下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<String, Object> 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); }最后看一下定时任务的实现:
/** * 定时清理过时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, HttpSession> sessionMap = ApplicationContext.getApplicationContext() .getAllSession(); Iterator<Map.Entry<String, HttpSession>> it = sessionMap.entrySet().iterator(); while (it.hasNext()) { ConcurrentMap.Entry<String, HttpSession> entry= (Entry<String, HttpSession>) it.next(); HttpSession httpSession= entry.getValue(); Date nowDate = new Date(); int diff = (int) ((nowDate.getTime() - httpSession.getLastVisitTime().getTime())/1000/60); if (diff > Constants.SESSION_TIMEOUT) { it.remove(); } } log.info("清理session结束"); } }这次改动的代码就这么多。
public ResultInfo process(Map<String, Object> 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://localhost:8899/page/index.page,请求结果以下(我那高大上的logo就不截了^_^):
说明session已经起做用了,你还能够等sesion清理后看下是否还有效。ApplicationContext测试方法同样。 java