├── README.md
├── servlet3.x-webapp
├── src
│ └── main
│ │ ├── webapp
│ │ ├── js
│ │ │ └── welcome.js
│ │ ├── index.jsp
│ │ └── WEB-INF
│ │ │ ├── weblogic.xml
│ │ │ ├── views
│ │ │ └── greeting.jsp
│ │ │ └── web.xml
│ │ └── java
│ │ └── com
│ │ └── github
│ │ └── loafer
│ │ └── servlet
│ │ └── HelloServlet.java
└── pom.xml
├── servlet2.x-webapp
├── src
│ └── main
│ │ └── webapp
│ │ ├── index.jsp
│ │ └── WEB-INF
│ │ ├── views
│ │ └── greeting.jsp
│ │ └── web.xml
└── pom.xml
├── 10.5-servlet3.x-directory-structure
├── src
│ └── main
│ │ ├── resources
│ │ └── META-INF
│ │ │ └── resources
│ │ │ ├── css
│ │ │ └── test.css
│ │ │ ├── js
│ │ │ └── hello.js
│ │ │ ├── views
│ │ │ └── greeting.jsp
│ │ │ └── index.jsp
│ │ └── java
│ │ └── com
│ │ └── github
│ │ └── loafer
│ │ └── servlet
│ │ └── GreetingServlet.java
└── pom.xml
├── servlet3.x-servletContainerInitializer
├── src
│ └── main
│ │ ├── resources
│ │ └── META-INF
│ │ │ └── services
│ │ │ └── javax.servlet.ServletContainerInitializer.bak
│ │ └── java
│ │ └── com
│ │ └── github
│ │ └── loafer
│ │ └── servlet
│ │ ├── WebApplicationInitializer.java
│ │ └── CustomServletContextListener.java
└── pom.xml
├── .gitignore
├── servlet3.x-session
├── src
│ └── main
│ │ └── java
│ │ └── com
│ │ └── github
│ │ └── loafer
│ │ ├── session
│ │ ├── LifeCycle.java
│ │ ├── SessionIdManager.java
│ │ ├── SessionStore.java
│ │ ├── SessionManager.java
│ │ ├── metadata
│ │ │ └── SessionMetaData.java
│ │ └── support
│ │ │ ├── RedisHttpSession.java
│ │ │ ├── DefaultSessionIdManager.java
│ │ │ ├── SessionManagerImpl.java
│ │ │ ├── RedisSessionStore.java
│ │ │ └── AbstractDistributedHttpSession.java
│ │ ├── servlet
│ │ └── GreetingServlet.java
│ │ ├── util
│ │ └── SerializationUtils.java
│ │ ├── helper
│ │ └── CookieHelper.java
│ │ └── filter
│ │ └── DistributableSessionFilter.java
└── pom.xml
├── webapp
├── src
│ └── main
│ │ └── webapp
│ │ └── WEB-INF
│ │ └── web.xml
└── pom.xml
├── simple-distributed-sessions-manager
├── src
│ └── main
│ │ └── java
│ │ └── com
│ │ └── github
│ │ └── loafer
│ │ ├── distributed
│ │ └── httpsession
│ │ │ ├── LifeCycle.java
│ │ │ ├── SessionIDManager.java
│ │ │ ├── SessionManager.java
│ │ │ ├── SessionStorage.java
│ │ │ ├── manager
│ │ │ ├── task
│ │ │ │ ├── ClearInvalidSessionScheduledTask.java
│ │ │ │ └── ClearInvalidSessionTask.java
│ │ │ ├── NoStickySessionManager.java
│ │ │ ├── StickySessionManager.java
│ │ │ ├── DefaultSessionIDManager.java
│ │ │ └── AbstractSessionManager.java
│ │ │ ├── metadata
│ │ │ └── SessionMetaData.java
│ │ │ ├── util
│ │ │ └── SerializationUtils.java
│ │ │ ├── helper
│ │ │ └── CookieHelper.java
│ │ │ ├── session
│ │ │ ├── NoStickyHttpSession.java
│ │ │ ├── StickyHttpSession.java
│ │ │ └── DistributedHttpSession.java
│ │ │ ├── filter
│ │ │ └── DistributableSessionFilter.java
│ │ │ └── storage
│ │ │ └── RedisSessionStorage.java
│ │ └── greeting
│ │ └── GreetingServlet.java
└── pom.xml
└── servlet2.x-session
├── src
└── main
│ └── java
│ └── com
│ └── github
│ └── loafer
│ ├── listener
│ └── HttpSessionLifecycle.java
│ ├── servlet
│ └── GreetingServlet.java
│ └── bean
│ └── User.java
└── pom.xml
/README.md:
--------------------------------------------------------------------------------
1 | # servlet3-tutorials
2 |
--------------------------------------------------------------------------------
/servlet3.x-webapp/src/main/webapp/js/welcome.js:
--------------------------------------------------------------------------------
1 | function sayHello(){
2 | alert('Hello Servlet 3.0');
3 | }
--------------------------------------------------------------------------------
/servlet2.x-webapp/src/main/webapp/index.jsp:
--------------------------------------------------------------------------------
1 |
2 |
3 | Hello World!
4 |
5 |
6 |
--------------------------------------------------------------------------------
/10.5-servlet3.x-directory-structure/src/main/resources/META-INF/resources/css/test.css:
--------------------------------------------------------------------------------
1 | body{
2 | background-color: #c0c0c0;
3 | }
--------------------------------------------------------------------------------
/10.5-servlet3.x-directory-structure/src/main/resources/META-INF/resources/js/hello.js:
--------------------------------------------------------------------------------
1 | function sayHello(){
2 | alert('Hello World!');
3 | }
--------------------------------------------------------------------------------
/servlet3.x-servletContainerInitializer/src/main/resources/META-INF/services/javax.servlet.ServletContainerInitializer.bak:
--------------------------------------------------------------------------------
1 | com.github.loafer.servlet.WebApplicationInitializer
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | *.iml
2 | *.ipr
3 | *.iws
4 | .idea/
5 | target/
6 | pom.xml.tag
7 | pom.xml.releaseBackup
8 | pom.xml.versionsBackup
9 | pom.xml.next
10 | release.properties
11 |
--------------------------------------------------------------------------------
/servlet3.x-session/src/main/java/com/github/loafer/session/LifeCycle.java:
--------------------------------------------------------------------------------
1 | package com.github.loafer.session;
2 |
3 | /**
4 | * @author zhaojh
5 | */
6 | public interface LifeCycle {
7 | void start();
8 | void stop();
9 | }
10 |
--------------------------------------------------------------------------------
/webapp/src/main/webapp/WEB-INF/web.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 | Archetype Created Web Application
7 |
8 |
--------------------------------------------------------------------------------
/simple-distributed-sessions-manager/src/main/java/com/github/loafer/distributed/httpsession/LifeCycle.java:
--------------------------------------------------------------------------------
1 | package com.github.loafer.distributed.httpsession;
2 |
3 | /**
4 | * @author zhaojh
5 | */
6 | public interface LifeCycle {
7 | void start();
8 | void stop();
9 | }
10 |
--------------------------------------------------------------------------------
/servlet3.x-session/src/main/java/com/github/loafer/session/SessionIdManager.java:
--------------------------------------------------------------------------------
1 | package com.github.loafer.session;
2 |
3 | import javax.servlet.http.HttpServletRequest;
4 |
5 | /**
6 | * @author zhaojh
7 | */
8 | public interface SessionIdManager extends LifeCycle{
9 | String newSessionId(HttpServletRequest request,long created);
10 | }
11 |
--------------------------------------------------------------------------------
/10.5-servlet3.x-directory-structure/src/main/resources/META-INF/resources/views/greeting.jsp:
--------------------------------------------------------------------------------
1 | <%@ page contentType="text/html;charset=UTF-8" language="java" %>
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | Hello Everyone!
10 |
11 |
12 |
--------------------------------------------------------------------------------
/simple-distributed-sessions-manager/src/main/java/com/github/loafer/distributed/httpsession/SessionIDManager.java:
--------------------------------------------------------------------------------
1 | package com.github.loafer.distributed.httpsession;
2 |
3 | import javax.servlet.http.HttpServletRequest;
4 |
5 | /**
6 | * @author zhaojh
7 | */
8 | public interface SessionIDManager extends LifeCycle{
9 | String newSessionId(HttpServletRequest request,long created);
10 | }
11 |
--------------------------------------------------------------------------------
/10.5-servlet3.x-directory-structure/src/main/resources/META-INF/resources/index.jsp:
--------------------------------------------------------------------------------
1 | <%@ page contentType="text/html;charset=UTF-8" language="java" %>
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 | Hello World!
11 |
12 |
13 |
--------------------------------------------------------------------------------
/servlet2.x-webapp/src/main/webapp/WEB-INF/views/greeting.jsp:
--------------------------------------------------------------------------------
1 | <%@ page contentType="text/html;charset=UTF-8" language="java" %>
2 | <%@page import="com.github.loafer.bean.User" %>
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 | Hello, <%=((User)request.getSession().getAttribute("user")).getName()%>
11 |
12 |
13 |
--------------------------------------------------------------------------------
/servlet3.x-webapp/src/main/webapp/index.jsp:
--------------------------------------------------------------------------------
1 | <%@ page contentType="text/html;charset=UTF-8" language="java" %>
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 | Hello Servlet 3.0!
12 |
13 |
14 |
--------------------------------------------------------------------------------
/servlet3.x-webapp/src/main/webapp/WEB-INF/weblogic.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
12 |
13 | /app1
14 |
15 |
16 |
17 | true
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/simple-distributed-sessions-manager/src/main/java/com/github/loafer/distributed/httpsession/SessionManager.java:
--------------------------------------------------------------------------------
1 | package com.github.loafer.distributed.httpsession;
2 |
3 | import javax.servlet.http.HttpServletRequest;
4 | import javax.servlet.http.HttpSession;
5 |
6 | /**
7 | * @author zhaojh
8 | */
9 | public interface SessionManager extends LifeCycle{
10 | String DISTRIBUTED_SESSION_ID = "JSESSIONID";
11 |
12 | HttpSession newHttpSession(HttpServletRequest request);
13 | HttpSession getHttpSession(String id);
14 | boolean isValid(HttpSession session);
15 | void removeHttpSession(HttpSession session);
16 | SessionStorage getSessionStorage();
17 | }
18 |
--------------------------------------------------------------------------------
/webapp/pom.xml:
--------------------------------------------------------------------------------
1 |
3 | 4.0.0
4 |
5 | com.github.loafer
6 | webapp
7 | war
8 | 1.0-SNAPSHOT
9 |
10 |
11 |
12 |
13 |
14 | com.github.loafer
15 | servlet3.x-directory-structure
16 | 1.0-SNAPSHOT
17 |
18 |
19 |
20 |
21 | webapp
22 |
23 |
24 |
--------------------------------------------------------------------------------
/servlet3.x-session/src/main/java/com/github/loafer/session/SessionStore.java:
--------------------------------------------------------------------------------
1 | package com.github.loafer.session;
2 |
3 | import com.github.loafer.session.metadata.SessionMetaData;
4 |
5 | import javax.servlet.http.HttpSession;
6 | import java.util.List;
7 |
8 | /**
9 | * @author zhaojh
10 | */
11 | public interface SessionStore extends LifeCycle{
12 | void putSessionMetaData(HttpSession session);
13 | SessionMetaData getSessionMetaData(String sessionid);
14 | void removeSessionMetaData(String sessionid);
15 | void updateSessionMetaData(String sessionid, String name, Object value);
16 |
17 | void setAttribute(String sessionid, String name, Object value);
18 | void removeAttribute(String sessionid, String name);
19 | Object getAttribute(String sessionid, String name);
20 | List getAttributeNames(String sessionid);
21 | }
22 |
--------------------------------------------------------------------------------
/servlet2.x-webapp/src/main/webapp/WEB-INF/web.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 | Archetype Created Web Application
7 |
8 |
9 | com.github.loafer.listener.HttpSessionLifecycle
10 |
11 |
12 |
13 | greeting
14 | com.github.loafer.servlet.GreetingServlet
15 |
16 |
17 |
18 | greeting
19 | /greeting
20 |
21 |
22 |
23 | 1
24 |
25 |
26 |
--------------------------------------------------------------------------------
/servlet2.x-webapp/pom.xml:
--------------------------------------------------------------------------------
1 |
3 | 4.0.0
4 |
5 | com.github.loafer
6 | servlet2.x-webapp
7 | war
8 | 1.0-SNAPSHOT
9 |
10 | servlet2.x-webapp
11 | http://maven.apache.org
12 |
13 |
14 |
15 | com.github.loafer
16 | servlet2.x-session
17 | 1.0-SNAPSHOT
18 |
19 |
20 |
21 |
22 | servlet2.x-webapp
23 |
24 |
25 |
--------------------------------------------------------------------------------
/servlet3.x-servletContainerInitializer/src/main/java/com/github/loafer/servlet/WebApplicationInitializer.java:
--------------------------------------------------------------------------------
1 | package com.github.loafer.servlet;
2 |
3 | import javax.servlet.ServletContainerInitializer;
4 | import javax.servlet.ServletContext;
5 | import javax.servlet.ServletException;
6 | import javax.servlet.ServletRegistration;
7 | import java.util.Set;
8 |
9 | /**
10 | * 动态注册servlet
11 | * 注意:
12 | * 1、在META-INF/services/中放入javax.servlet.ServletContainerInitializer文件
13 | * 2、只会在容器启动时加载一次
14 | * @author zhaojh
15 | */
16 | public class WebApplicationInitializer implements ServletContainerInitializer {
17 |
18 | @Override
19 | public void onStartup(Set> classes, ServletContext servletContext) throws ServletException {
20 | ServletRegistration.Dynamic dynamic = servletContext.addServlet("greeting", GreetingServlet.class);
21 | dynamic.addMapping("/greeting");
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/servlet3.x-session/src/main/java/com/github/loafer/session/SessionManager.java:
--------------------------------------------------------------------------------
1 | package com.github.loafer.session;
2 |
3 | import org.slf4j.Logger;
4 |
5 | import javax.servlet.ServletContext;
6 | import javax.servlet.http.HttpServletRequest;
7 | import javax.servlet.http.HttpServletResponse;
8 | import javax.servlet.http.HttpSession;
9 |
10 | /**
11 | * @author zhaojh
12 | */
13 | public interface SessionManager extends LifeCycle{
14 | String DISTRIBUTED_SESSION_ID = "JDSESSIONID";
15 |
16 | void add(HttpSession session);
17 | void remove(HttpSession session);
18 | void setMaxInactiveInterval(int interval);
19 | HttpSession newHttpSession(HttpServletRequest request, HttpServletResponse response);
20 | HttpSession getHttpSession(String id);
21 | ServletContext getServletContext();
22 | String getRequestedSessionId(HttpServletRequest request);
23 | SessionStore getSessionStore();
24 | }
25 |
--------------------------------------------------------------------------------
/10.5-servlet3.x-directory-structure/pom.xml:
--------------------------------------------------------------------------------
1 |
3 | 4.0.0
4 |
5 | com.github.loafer
6 | servlet3.x-directory-structure
7 | 1.0-SNAPSHOT
8 | jar
9 |
10 | servlet3.x-directory-structure
11 | http://maven.apache.org
12 |
13 |
14 | UTF-8
15 |
16 |
17 |
18 |
19 | javax.servlet
20 | javax.servlet-api
21 | 3.1.0
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/servlet3.x-servletContainerInitializer/src/main/java/com/github/loafer/servlet/CustomServletContextListener.java:
--------------------------------------------------------------------------------
1 | package com.github.loafer.servlet;
2 |
3 | import javax.servlet.ServletContext;
4 | import javax.servlet.ServletContextEvent;
5 | import javax.servlet.ServletContextListener;
6 | import javax.servlet.ServletRegistration;
7 |
8 | /**
9 | * 动态注册servlet
10 | * 注意:
11 | * 1、只会在容器启动时加载一次
12 | *
13 | * @author zhaojh
14 | */
15 | public class CustomServletContextListener implements ServletContextListener{
16 | @Override
17 | public void contextInitialized(ServletContextEvent servletContextEvent) {
18 | ServletContext context = servletContextEvent.getServletContext();
19 | ServletRegistration.Dynamic dynamic = context.addServlet("greeting", GreetingServlet.class);
20 | dynamic.addMapping("/greeting");
21 | }
22 |
23 | @Override
24 | public void contextDestroyed(ServletContextEvent servletContextEvent) {
25 |
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/servlet3.x-webapp/src/main/java/com/github/loafer/servlet/HelloServlet.java:
--------------------------------------------------------------------------------
1 | package com.github.loafer.servlet;
2 |
3 | import javax.servlet.ServletException;
4 | import javax.servlet.http.HttpServlet;
5 | import javax.servlet.http.HttpServletRequest;
6 | import javax.servlet.http.HttpServletResponse;
7 | import java.io.IOException;
8 | import java.net.URL;
9 |
10 | /**
11 | * @author zhaojh.
12 | */
13 | public class HelloServlet extends HttpServlet {
14 |
15 | @Override
16 | protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
17 | doPost(request, response);
18 | }
19 |
20 | @Override
21 | protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
22 | URL root = Thread.currentThread().getContextClassLoader().getResource("/");
23 | System.out.println("HelloServlet ====> " + root.toString());
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/servlet2.x-session/src/main/java/com/github/loafer/listener/HttpSessionLifecycle.java:
--------------------------------------------------------------------------------
1 | package com.github.loafer.listener;
2 |
3 | import org.slf4j.Logger;
4 | import org.slf4j.LoggerFactory;
5 |
6 | import javax.servlet.http.HttpSession;
7 | import javax.servlet.http.HttpSessionEvent;
8 | import javax.servlet.http.HttpSessionListener;
9 |
10 | /**
11 | * @author zhaojh
12 | */
13 | public class HttpSessionLifecycle implements HttpSessionListener {
14 | private static final Logger logger = LoggerFactory.getLogger(HttpSessionLifecycle.class);
15 |
16 | @Override
17 | public void sessionCreated(HttpSessionEvent event) {
18 | HttpSession session = event.getSession();
19 | logger.info("HttpSession [{}] 被创建。", session.getId());
20 | }
21 |
22 | @Override
23 | public void sessionDestroyed(HttpSessionEvent event) {
24 | HttpSession session = event.getSession();
25 | logger.info("HttpSession [{}] 已销毁。", session.getId());
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/simple-distributed-sessions-manager/src/main/java/com/github/loafer/greeting/GreetingServlet.java:
--------------------------------------------------------------------------------
1 | package com.github.loafer.greeting;
2 |
3 | import javax.servlet.RequestDispatcher;
4 | import javax.servlet.ServletException;
5 | import javax.servlet.http.HttpServlet;
6 | import javax.servlet.http.HttpServletRequest;
7 | import javax.servlet.http.HttpServletResponse;
8 | import java.io.IOException;
9 |
10 | /**
11 | * Created by zhaojh on 14-10-22.
12 | */
13 | public class GreetingServlet extends HttpServlet {
14 | @Override
15 | protected void doGet(HttpServletRequest request, HttpServletResponse response)
16 | throws ServletException, IOException {
17 |
18 | String name = request.getParameter("name");
19 | if(null != name){
20 | request.getSession().setAttribute("name", name);
21 | }
22 | RequestDispatcher dispatcher = request.getRequestDispatcher("WEB-INF/views/greeting.jsp");
23 | dispatcher.forward(request, response);
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/servlet3.x-session/src/main/java/com/github/loafer/servlet/GreetingServlet.java:
--------------------------------------------------------------------------------
1 | package com.github.loafer.servlet;
2 |
3 | import javax.servlet.RequestDispatcher;
4 | import javax.servlet.ServletException;
5 | import javax.servlet.http.HttpServlet;
6 | import javax.servlet.http.HttpServletRequest;
7 | import javax.servlet.http.HttpServletResponse;
8 | import java.io.IOException;
9 |
10 | /**
11 | * @author zhaojh
12 | */
13 | public class GreetingServlet extends HttpServlet {
14 | @Override
15 | protected void doPost(HttpServletRequest request, HttpServletResponse response)
16 | throws ServletException, IOException {
17 | doGet(request, response);
18 | }
19 |
20 | @Override
21 | protected void doGet(HttpServletRequest request, HttpServletResponse response)
22 | throws ServletException, IOException {
23 | request.getSession().setAttribute("hello", "balabala~~");
24 | RequestDispatcher dispatcher = request.getRequestDispatcher("WEB-INF/views/greeting.jsp");
25 | dispatcher.forward(request, response);
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/servlet3.x-webapp/src/main/webapp/WEB-INF/views/greeting.jsp:
--------------------------------------------------------------------------------
1 | <%@ page contentType="text/html;charset=UTF-8" language="java" session="true" %>
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | Welcome Everyone!
10 |
11 | -
12 |
Page Session
13 |
14 | Hello, <%= null == session.getAttribute("name")?"World" : session.getAttribute("name")%>
15 |
16 | Session ID: <%=session.getId()%>
17 |
18 | -
19 |
request.getSession()
20 |
21 | Hello, <%= null == request.getSession().getAttribute("name")? "World" : request.getSession().getAttribute("name")%>
22 |
23 | Session ID: <%=request.getSession().getId()%>
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/servlet3.x-session/src/main/java/com/github/loafer/session/metadata/SessionMetaData.java:
--------------------------------------------------------------------------------
1 | package com.github.loafer.session.metadata;
2 |
3 | import java.io.Serializable;
4 |
5 | /**
6 | * @author zhaojh
7 | */
8 | public class SessionMetaData implements Serializable{
9 | private String id;
10 | private long creationTime;
11 | private long lastAccessedTime;
12 | private int maxInactiveInterval;
13 |
14 | public SessionMetaData(String id, long creationTime, long lastAccessedTime, int maxInactiveInterval) {
15 | this.id = id;
16 | this.creationTime = creationTime;
17 | this.lastAccessedTime = lastAccessedTime;
18 | this.maxInactiveInterval = maxInactiveInterval;
19 | }
20 |
21 | public String getId() {
22 | return id;
23 | }
24 |
25 | public long getCreationTime() {
26 | return creationTime;
27 | }
28 |
29 |
30 | public long getLastAccessedTime() {
31 | return lastAccessedTime;
32 | }
33 |
34 |
35 | public int getMaxInactiveInterval() {
36 | return maxInactiveInterval;
37 | }
38 |
39 | }
40 |
--------------------------------------------------------------------------------
/servlet2.x-session/pom.xml:
--------------------------------------------------------------------------------
1 |
3 | 4.0.0
4 |
5 | com.github.loafer
6 | servlet2.x-session
7 | 1.0-SNAPSHOT
8 | jar
9 |
10 | servlet2.x-session
11 | http://maven.apache.org
12 |
13 |
14 | UTF-8
15 |
16 |
17 |
18 |
19 | javax.servlet
20 | servlet-api
21 | 2.4
22 | provided
23 |
24 |
25 |
26 | org.slf4j
27 | slf4j-simple
28 | 1.7.5
29 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/simple-distributed-sessions-manager/src/main/java/com/github/loafer/distributed/httpsession/SessionStorage.java:
--------------------------------------------------------------------------------
1 | package com.github.loafer.distributed.httpsession;
2 |
3 | import com.github.loafer.distributed.httpsession.metadata.SessionMetaData;
4 |
5 | import javax.servlet.http.HttpSession;
6 | import java.util.List;
7 | import java.util.Map;
8 |
9 | /**
10 | * @author zhaojh
11 | */
12 | public interface SessionStorage extends LifeCycle{
13 | boolean isStored(HttpSession session);
14 | void storeSessionMetaData(HttpSession session);
15 | SessionMetaData getSessionMetaData(String sessionid);
16 | void updateSessionMetaDataField(String sessionid, String name, Object value);
17 | Object getSessionMetaDataField(String sessionid, String name);
18 | void removeSession(String sessionid);
19 |
20 | void storeSessionAttribute(String sessionid, String name, Object value);
21 | void removeSessionAttribute(String sessionid, String name);
22 | Object getSessionAttribute(String sessionid, String name);
23 | List getSessionAttributeNames(String sessionid);
24 | Map getSessionAttributes(String sessionid);
25 | }
26 |
--------------------------------------------------------------------------------
/servlet3.x-servletContainerInitializer/pom.xml:
--------------------------------------------------------------------------------
1 |
3 | 4.0.0
4 |
5 | com.github.loafer
6 | servlet3.x-servletContainerInitializer
7 | 1.0-SNAPSHOT
8 | jar
9 |
10 | servlet3.x-servletContainerInitializer
11 | http://maven.apache.org
12 |
13 |
14 | UTF-8
15 |
16 |
17 |
18 |
19 | javax.servlet
20 | javax.servlet-api
21 | 3.1.0
22 |
23 |
24 |
25 | com.github.loafer
26 | servlet3.x-directory-structure
27 | 1.0-SNAPSHOT
28 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/simple-distributed-sessions-manager/src/main/java/com/github/loafer/distributed/httpsession/manager/task/ClearInvalidSessionScheduledTask.java:
--------------------------------------------------------------------------------
1 | package com.github.loafer.distributed.httpsession.manager.task;
2 |
3 | import com.github.loafer.distributed.httpsession.session.DistributedHttpSession;
4 | import org.slf4j.Logger;
5 | import org.slf4j.LoggerFactory;
6 |
7 | import javax.servlet.http.HttpSession;
8 | import java.util.Map;
9 |
10 | /**
11 | * @author zhaojh
12 | */
13 | public class ClearInvalidSessionScheduledTask implements Runnable{
14 | private static final Logger logger = LoggerFactory.getLogger(ClearInvalidSessionScheduledTask.class);
15 | private Map localSessionContainer;
16 |
17 | public ClearInvalidSessionScheduledTask(Map localSessionContainer) {
18 | this.localSessionContainer = localSessionContainer;
19 | }
20 |
21 | @Override
22 | public void run() {
23 | // logger.info("执行清除过期Session任务。");
24 | for (HttpSession session: localSessionContainer.values()){
25 | if(!((DistributedHttpSession)session).isValid()){
26 | logger.info("Clear session[{}]", session.getId());
27 | session.invalidate();
28 | }
29 | }
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/simple-distributed-sessions-manager/src/main/java/com/github/loafer/distributed/httpsession/manager/task/ClearInvalidSessionTask.java:
--------------------------------------------------------------------------------
1 | package com.github.loafer.distributed.httpsession.manager.task;
2 |
3 | import com.github.loafer.distributed.httpsession.session.DistributedHttpSession;
4 | import org.slf4j.Logger;
5 | import org.slf4j.LoggerFactory;
6 |
7 | import javax.servlet.http.HttpSession;
8 | import java.util.concurrent.TimeUnit;
9 |
10 | /**
11 | * @author zhaojh
12 | */
13 | public class ClearInvalidSessionTask implements Runnable{
14 | private static final Logger logger = LoggerFactory.getLogger(ClearInvalidSessionTask.class);
15 | private static final int SLEEP_TIME = 10;
16 | private HttpSession session;
17 |
18 | public ClearInvalidSessionTask(HttpSession session) {
19 | this.session = session;
20 | }
21 |
22 | @Override
23 | public void run() {
24 | while (true){
25 | try {
26 | if(((DistributedHttpSession)session).isValid()){
27 | session.invalidate();
28 | break;
29 | }
30 | TimeUnit.SECONDS.sleep(SLEEP_TIME);
31 | } catch (InterruptedException e) {
32 | e.printStackTrace();
33 | }
34 | }
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/servlet3.x-session/pom.xml:
--------------------------------------------------------------------------------
1 |
3 | 4.0.0
4 |
5 | com.github.loafer
6 | servlet3.x-session
7 | 1.0-SNAPSHOT
8 | jar
9 |
10 | servlet3.x-session
11 | http://maven.apache.org
12 |
13 |
14 | UTF-8
15 |
16 |
17 |
18 |
19 | javax.servlet
20 | javax.servlet-api
21 | 3.1.0
22 | provided
23 |
24 |
25 |
26 | org.slf4j
27 | slf4j-simple
28 | 1.7.5
29 |
30 |
31 |
32 | redis.clients
33 | jedis
34 | 2.6.0
35 |
36 |
37 |
38 |
39 |
--------------------------------------------------------------------------------
/simple-distributed-sessions-manager/src/main/java/com/github/loafer/distributed/httpsession/metadata/SessionMetaData.java:
--------------------------------------------------------------------------------
1 | package com.github.loafer.distributed.httpsession.metadata;
2 |
3 | /**
4 | * @author zhaojh
5 | */
6 | public class SessionMetaData {
7 | public static final String CREATION_TIME_KEY = "creationTime";
8 | public static final String LAST_ACCESSED_TIME_KEY = "lastAccessedTime";
9 | public static final String MAX_INACTIVE_INTERVAL_KEY = "maxInactiveInterval";
10 |
11 | private String id;
12 | private long creationTime;
13 | private long lastAccessedTime;
14 | private int maxInactiveInterval;
15 |
16 | public SessionMetaData(String id, long creationTime, long lastAccessedTime, int maxInactiveInterval) {
17 | this.id = id;
18 | this.creationTime = creationTime;
19 | this.lastAccessedTime = lastAccessedTime;
20 | this.maxInactiveInterval = maxInactiveInterval;
21 | }
22 |
23 | public String getId() {
24 | return id;
25 | }
26 |
27 | public long getCreationTime() {
28 | return creationTime;
29 | }
30 |
31 |
32 | public long getLastAccessedTime() {
33 | return lastAccessedTime;
34 | }
35 |
36 |
37 | public int getMaxInactiveInterval() {
38 | return maxInactiveInterval;
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/10.5-servlet3.x-directory-structure/src/main/java/com/github/loafer/servlet/GreetingServlet.java:
--------------------------------------------------------------------------------
1 | package com.github.loafer.servlet;
2 |
3 |
4 | import javax.servlet.RequestDispatcher;
5 | import javax.servlet.ServletException;
6 | import javax.servlet.http.HttpServlet;
7 | import javax.servlet.http.HttpServletRequest;
8 | import javax.servlet.http.HttpServletResponse;
9 | import javax.servlet.http.HttpSession;
10 | import java.io.IOException;
11 | import java.net.URL;
12 |
13 | /**
14 | * @author zhaojh
15 | */
16 | public class GreetingServlet extends HttpServlet {
17 | @Override
18 | protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
19 | doPost(req, resp);
20 | }
21 |
22 | @Override
23 | protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
24 | URL root = Thread.currentThread().getContextClassLoader().getResource("/");
25 | System.out.println("GreetingServlet ====> " + root.toString());
26 |
27 | HttpSession session = request.getSession();
28 | session.setAttribute("hello", "balabala~~~");
29 | RequestDispatcher dispatcher = request.getRequestDispatcher("/WEB-INF/views/greeting.jsp");
30 | dispatcher.forward(request, response);
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/servlet2.x-session/src/main/java/com/github/loafer/servlet/GreetingServlet.java:
--------------------------------------------------------------------------------
1 | package com.github.loafer.servlet;
2 |
3 | import com.github.loafer.bean.User;
4 |
5 | import javax.servlet.RequestDispatcher;
6 | import javax.servlet.ServletException;
7 | import javax.servlet.http.HttpServlet;
8 | import javax.servlet.http.HttpServletRequest;
9 | import javax.servlet.http.HttpServletResponse;
10 | import javax.servlet.http.HttpSession;
11 | import java.io.IOException;
12 |
13 | /**
14 | * @author zhaojh
15 | */
16 | public class GreetingServlet extends HttpServlet {
17 | @Override
18 | protected void doPost(HttpServletRequest request, HttpServletResponse response)
19 | throws ServletException, IOException {
20 | HttpSession session = request.getSession();
21 | String name = request.getParameter("name");
22 | if(null != name){
23 | User user = new User(name);
24 | session.setAttribute("user", user);
25 | }
26 |
27 | RequestDispatcher dispatcher = request.getRequestDispatcher("WEB-INF/views/greeting.jsp");
28 | dispatcher.forward(request, response);
29 | }
30 |
31 | @Override
32 | protected void doGet(HttpServletRequest request, HttpServletResponse response)
33 | throws ServletException, IOException {
34 | doPost(request, response);
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/servlet3.x-session/src/main/java/com/github/loafer/util/SerializationUtils.java:
--------------------------------------------------------------------------------
1 | package com.github.loafer.util;
2 |
3 | import java.io.*;
4 |
5 | /**
6 | * @author zhaojh
7 | */
8 | public abstract class SerializationUtils {
9 | public static byte[] serialize(Object object) {
10 | if (object == null) {
11 | return null;
12 | }
13 | ByteArrayOutputStream baos = new ByteArrayOutputStream(1024);
14 | try {
15 | ObjectOutputStream oos = new ObjectOutputStream(baos);
16 | oos.writeObject(object);
17 | oos.flush();
18 | }
19 | catch (IOException ex) {
20 | throw new IllegalArgumentException("Failed to serialize object of type: " + object.getClass(), ex);
21 | }
22 | return baos.toByteArray();
23 | }
24 |
25 | public static Object deserialize(byte[] bytes) {
26 | if (bytes == null) {
27 | return null;
28 | }
29 | try {
30 | ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(bytes));
31 | return ois.readObject();
32 | }
33 | catch (IOException ex) {
34 | throw new IllegalArgumentException("Failed to deserialize object", ex);
35 | }
36 | catch (ClassNotFoundException ex) {
37 | throw new IllegalStateException("Failed to deserialize object type", ex);
38 | }
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/simple-distributed-sessions-manager/src/main/java/com/github/loafer/distributed/httpsession/util/SerializationUtils.java:
--------------------------------------------------------------------------------
1 | package com.github.loafer.distributed.httpsession.util;
2 |
3 | import java.io.*;
4 |
5 | /**
6 | * @author zhaojh
7 | */
8 | public abstract class SerializationUtils {
9 | public static byte[] serialize(Object object) {
10 | if (object == null) {
11 | return null;
12 | }
13 | ByteArrayOutputStream baos = new ByteArrayOutputStream(1024);
14 | try {
15 | ObjectOutputStream oos = new ObjectOutputStream(baos);
16 | oos.writeObject(object);
17 | oos.flush();
18 | }
19 | catch (IOException ex) {
20 | throw new IllegalArgumentException("Failed to serialize object of type: " + object.getClass(), ex);
21 | }
22 | return baos.toByteArray();
23 | }
24 |
25 | public static Object deserialize(byte[] bytes) {
26 | if (bytes == null) {
27 | return null;
28 | }
29 | try {
30 | ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(bytes));
31 | return ois.readObject();
32 | }
33 | catch (IOException ex) {
34 | throw new IllegalArgumentException("Failed to deserialize object", ex);
35 | }
36 | catch (ClassNotFoundException ex) {
37 | throw new IllegalStateException("Failed to deserialize object type", ex);
38 | }
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/servlet3.x-webapp/pom.xml:
--------------------------------------------------------------------------------
1 |
3 |
4 | 4.0.0
5 | com.github.loafer
6 | servlet3.x-webapp
7 | war
8 | 1.0-SNAPSHOT
9 |
10 | servlet3.x-webapp
11 | http://maven.apache.org
12 |
13 |
14 | servlet3.x-webapp
15 |
16 |
17 |
18 |
19 |
20 | com.github.loafer
21 | servlet3.x-directory-structure
22 | 1.0-SNAPSHOT
23 |
24 |
25 |
26 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
--------------------------------------------------------------------------------
/servlet2.x-session/src/main/java/com/github/loafer/bean/User.java:
--------------------------------------------------------------------------------
1 | package com.github.loafer.bean;
2 |
3 | import org.slf4j.Logger;
4 | import org.slf4j.LoggerFactory;
5 |
6 | import javax.servlet.http.HttpSessionBindingEvent;
7 | import javax.servlet.http.HttpSessionBindingListener;
8 |
9 | /**
10 | * @author zhaojh
11 | */
12 | public class User implements HttpSessionBindingListener{
13 | private static final Logger logger = LoggerFactory.getLogger(User.class);
14 | private long id;
15 | private String name;
16 | private int age;
17 |
18 | public User(String name) {
19 | this.id = System.currentTimeMillis();
20 | this.name = name;
21 | }
22 |
23 | public long getId() {
24 | return id;
25 | }
26 |
27 | public String getName() {
28 | return name;
29 | }
30 |
31 | public int getAge() {
32 | return age;
33 | }
34 |
35 | public void setAge(int age) {
36 | this.age = age;
37 | }
38 |
39 | @Override
40 | public void valueBound(HttpSessionBindingEvent event) {
41 | logger.info("用户 [{}] 的信息将被绑定在session[{}]中", this.name, event.getSession().getId());
42 | }
43 |
44 | @Override
45 | public void valueUnbound(HttpSessionBindingEvent event) {
46 | logger.info("用户 [{}] 的信息已被从session[{}]中删除", this.name, event.getSession().getId());
47 | }
48 |
49 | @Override
50 | public boolean equals(Object o) {
51 | if (this == o) return true;
52 | if (o == null || getClass() != o.getClass()) return false;
53 |
54 | User user = (User) o;
55 |
56 | if (id != user.id) return false;
57 |
58 | return true;
59 | }
60 |
61 | @Override
62 | public int hashCode() {
63 | return (int) (id ^ (id >>> 32));
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/servlet3.x-session/src/main/java/com/github/loafer/helper/CookieHelper.java:
--------------------------------------------------------------------------------
1 | package com.github.loafer.helper;
2 |
3 | import com.github.loafer.session.SessionManager;
4 |
5 | import javax.servlet.http.Cookie;
6 | import javax.servlet.http.HttpServletRequest;
7 | import javax.servlet.http.HttpServletResponse;
8 |
9 | /**
10 | * @author zhaojh
11 | */
12 | public class CookieHelper {
13 | public static void writeSessionIdToCookie(String id,
14 | HttpServletRequest request,
15 | HttpServletResponse response){
16 |
17 | // Cookie cookie = findCookie(SessionManager.DISTRIBUTED_SESSION_ID, request);
18 | // if(null == cookie){
19 | // cookie = new Cookie(SessionManager.DISTRIBUTED_SESSION_ID, id);
20 | // response.addCookie(cookie);
21 | // }
22 | Cookie cookie = new Cookie(SessionManager.DISTRIBUTED_SESSION_ID, id);
23 | response.addCookie(cookie);
24 | }
25 |
26 | public static String findSessionId(HttpServletRequest request){
27 | return findCookieValue(SessionManager.DISTRIBUTED_SESSION_ID, request);
28 | }
29 |
30 | private static Cookie findCookie(String name, HttpServletRequest request){
31 | Cookie[] cookies = request.getCookies();
32 | if(null == cookies) return null;
33 |
34 | for (Cookie cookie : cookies){
35 | if (cookie.getName().equals(name))
36 | return cookie;
37 | }
38 |
39 | return null;
40 | }
41 |
42 | private static String findCookieValue(String name, HttpServletRequest request) {
43 | Cookie cookie = findCookie(name, request);
44 | if (cookie != null) {
45 | return cookie.getValue();
46 | }
47 | return null;
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/simple-distributed-sessions-manager/src/main/java/com/github/loafer/distributed/httpsession/helper/CookieHelper.java:
--------------------------------------------------------------------------------
1 | package com.github.loafer.distributed.httpsession.helper;
2 |
3 | import com.github.loafer.distributed.httpsession.SessionManager;
4 |
5 | import javax.servlet.http.Cookie;
6 | import javax.servlet.http.HttpServletRequest;
7 | import javax.servlet.http.HttpServletResponse;
8 |
9 | /**
10 | * @author zhaojh
11 | */
12 | public abstract class CookieHelper {
13 | public static void writeSessionIdToCookie(String id,
14 | HttpServletRequest request,
15 | HttpServletResponse response){
16 |
17 | // Cookie cookie = findCookie(SessionManager.DISTRIBUTED_SESSION_ID, request);
18 | // if(null == cookie){
19 | // cookie = new Cookie(SessionManager.DISTRIBUTED_SESSION_ID, id);
20 | // response.addCookie(cookie);
21 | // }
22 | Cookie cookie = new Cookie(SessionManager.DISTRIBUTED_SESSION_ID, id);
23 | response.addCookie(cookie);
24 | }
25 |
26 | public static String findSessionId(HttpServletRequest request){
27 | return findCookieValue(SessionManager.DISTRIBUTED_SESSION_ID, request);
28 | }
29 |
30 | private static Cookie findCookie(String name, HttpServletRequest request){
31 | Cookie[] cookies = request.getCookies();
32 | if(null == cookies) return null;
33 |
34 | for (Cookie cookie : cookies){
35 | if (cookie.getName().equals(name))
36 | return cookie;
37 | }
38 |
39 | return null;
40 | }
41 |
42 | private static String findCookieValue(String name, HttpServletRequest request) {
43 | Cookie cookie = findCookie(name, request);
44 | if (cookie != null) {
45 | return cookie.getValue();
46 | }
47 | return null;
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/servlet3.x-webapp/src/main/webapp/WEB-INF/web.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
9 |
14 |
15 |
55 |
56 |
--------------------------------------------------------------------------------
/simple-distributed-sessions-manager/src/main/java/com/github/loafer/distributed/httpsession/manager/NoStickySessionManager.java:
--------------------------------------------------------------------------------
1 | package com.github.loafer.distributed.httpsession.manager;
2 |
3 | import com.github.loafer.distributed.httpsession.metadata.SessionMetaData;
4 | import com.github.loafer.distributed.httpsession.session.DistributedHttpSession;
5 | import com.github.loafer.distributed.httpsession.session.NoStickyHttpSession;
6 | import com.github.loafer.distributed.httpsession.session.StickyHttpSession;
7 | import org.slf4j.Logger;
8 | import org.slf4j.LoggerFactory;
9 |
10 | import javax.servlet.ServletContext;
11 | import javax.servlet.http.HttpSession;
12 |
13 | /**
14 | * @author zhaojh
15 | */
16 | public class NoStickySessionManager extends AbstractSessionManager {
17 | private static final Logger logger = LoggerFactory.getLogger(NoStickySessionManager.class);
18 |
19 | public NoStickySessionManager(ServletContext servletContext, int maxInactiveInterval) {
20 | super(servletContext, maxInactiveInterval);
21 | }
22 |
23 | @Override
24 | protected HttpSession newHttpSession(String id, int maxInactiveInterval, ServletContext servletContext) {
25 | return new NoStickyHttpSession(id, maxInactiveInterval, this, servletContext);
26 | }
27 |
28 | @Override
29 | protected HttpSession findHttpSession(String id) {
30 | //local
31 | HttpSession session = findSessionFromLocal(id);
32 | if(null != session){
33 | return session;
34 | }else{
35 | logger.info("本地没有session[{}]的信息。", id);
36 | }
37 |
38 | SessionMetaData metaData = getSessionMetaDataFromStorage(id);
39 | if(null != metaData){
40 | logger.debug("Session Storage中持有session[{}]的信息.", id);
41 | session = new NoStickyHttpSession(
42 | id,
43 | metaData.getCreationTime(),
44 | metaData.getLastAccessedTime(),
45 | metaData.getMaxInactiveInterval(),
46 | this,
47 | getServletContext()
48 | );
49 | }
50 | return session;
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/simple-distributed-sessions-manager/src/main/java/com/github/loafer/distributed/httpsession/manager/StickySessionManager.java:
--------------------------------------------------------------------------------
1 | package com.github.loafer.distributed.httpsession.manager;
2 |
3 | import com.github.loafer.distributed.httpsession.metadata.SessionMetaData;
4 | import com.github.loafer.distributed.httpsession.session.DistributedHttpSession;
5 | import com.github.loafer.distributed.httpsession.session.StickyHttpSession;
6 | import org.slf4j.Logger;
7 | import org.slf4j.LoggerFactory;
8 |
9 | import javax.servlet.ServletContext;
10 | import javax.servlet.http.HttpSession;
11 |
12 | /**
13 | * @author zhaojh
14 | */
15 | public class StickySessionManager extends AbstractSessionManager{
16 | private static final Logger logger = LoggerFactory.getLogger(StickySessionManager.class);
17 |
18 | public StickySessionManager(ServletContext servletContext, int maxInactiveInterval) {
19 | super(servletContext, maxInactiveInterval);
20 | }
21 |
22 | @Override
23 | protected HttpSession newHttpSession(String id, int maxInactiveInterval, ServletContext servletContext) {
24 | return new StickyHttpSession(id, maxInactiveInterval, this, servletContext);
25 | }
26 |
27 | @Override
28 | public HttpSession findHttpSession(String id) {
29 | //local
30 | HttpSession session = findSessionFromLocal(id);
31 | if(null != session){
32 | return session;
33 | }else{
34 | logger.info("本地没有session[{}]的信息。", id);
35 | }
36 |
37 | //storage
38 | SessionMetaData metaData = getSessionMetaDataFromStorage(id);
39 | if(null != metaData){
40 | logger.debug("Session Storage中持有session[{}]的信息.", id);
41 | session = new StickyHttpSession(
42 | id,
43 | metaData.getCreationTime(),
44 | metaData.getLastAccessedTime(),
45 | metaData.getMaxInactiveInterval(),
46 | this,
47 | getServletContext()
48 | );
49 |
50 | logger.info("根据Session Storage中的信息构建session[{}].", id);
51 | ((DistributedHttpSession)session).refresh();
52 | }
53 |
54 | logger.debug("未找到Session[{}]", id);
55 | return session;
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/simple-distributed-sessions-manager/src/main/java/com/github/loafer/distributed/httpsession/manager/DefaultSessionIDManager.java:
--------------------------------------------------------------------------------
1 | package com.github.loafer.distributed.httpsession.manager;
2 |
3 | import com.github.loafer.distributed.httpsession.SessionIDManager;
4 | import org.slf4j.Logger;
5 | import org.slf4j.LoggerFactory;
6 |
7 | import javax.servlet.http.HttpServletRequest;
8 | import java.security.SecureRandom;
9 | import java.util.Random;
10 |
11 | /**
12 | * @author zhaojh
13 | */
14 | public class DefaultSessionIDManager implements SessionIDManager {
15 | private static final Logger logger = LoggerFactory.getLogger(DefaultSessionIDManager.class);
16 |
17 | // private final static String __NEW_SESSION_ID = "com.github.loafer.newSessionId";
18 | private Random random;
19 | private boolean weakRandom;
20 | private long reseed=100000L;
21 |
22 | @Override
23 | public String newSessionId(HttpServletRequest request, long created) {
24 | if(request == null){
25 | return newSessionId(created);
26 | }
27 |
28 | return newSessionId(request.hashCode());
29 | }
30 |
31 | @Override
32 | public void start() {
33 | logger.info("启动Session ID Manager.");
34 | try{
35 | random = new SecureRandom();
36 | }catch (Exception e){
37 | logger.warn("Could not generate SecureRandom for httpsession-id randomness", e);
38 | random = new Random();
39 | weakRandom = true;
40 | }
41 | }
42 |
43 | @Override
44 | public void stop() {
45 |
46 | }
47 |
48 | private String newSessionId(long seedTerm){
49 | String id = null;
50 | while (id == null || id.length() == 0){
51 | long r0 = weakRandom ? (hashCode() ^ Runtime.getRuntime().freeMemory() ^ random.nextInt() ^ (seedTerm<<32))
52 | : random.nextLong();
53 |
54 | if(r0 < 0) r0 = -r0;
55 |
56 | if (reseed>0 && (r0 % reseed)== 1L){
57 | logger.info("Reseeding {}", this);
58 |
59 | if(random instanceof SecureRandom){
60 | SecureRandom secure = (SecureRandom) random;
61 | secure.setSeed(secure.generateSeed(8));
62 | }else{
63 | random.setSeed(random.nextLong() ^ System.currentTimeMillis() ^ seedTerm ^ Runtime.getRuntime().freeMemory());
64 | }
65 | }
66 |
67 | long r1 = weakRandom ?
68 | (hashCode() ^ Runtime.getRuntime().freeMemory() ^ random.nextInt() ^ (seedTerm<<32))
69 | : random.nextLong();
70 |
71 | if(r1 < 0) r1 = -r1;
72 |
73 | id = Long.toString(r0, 36) + Long.toString(r1, 36);
74 | }
75 |
76 | return id + ".quick4j";
77 | }
78 | }
79 |
--------------------------------------------------------------------------------
/servlet3.x-session/src/main/java/com/github/loafer/session/support/RedisHttpSession.java:
--------------------------------------------------------------------------------
1 | package com.github.loafer.session.support;
2 |
3 | import com.github.loafer.session.SessionManager;
4 | import org.slf4j.Logger;
5 | import org.slf4j.LoggerFactory;
6 |
7 | import javax.servlet.http.HttpSessionBindingEvent;
8 | import javax.servlet.http.HttpSessionBindingListener;
9 | import java.util.Collections;
10 | import java.util.Enumeration;
11 | import java.util.Map;
12 | import java.util.concurrent.ConcurrentHashMap;
13 |
14 | /**
15 | * @author zhaojh
16 | */
17 | public class RedisHttpSession extends AbstractDistributedHttpSession {
18 | private static final Logger logger = LoggerFactory.getLogger(RedisHttpSession.class);
19 | public RedisHttpSession(String id,
20 | long creationTm,
21 | long lastAccessedTm,
22 | int maxInactiveInterval,
23 | SessionManager sessionManager) {
24 | super(id, creationTm, lastAccessedTm, maxInactiveInterval, sessionManager);
25 | }
26 |
27 | public RedisHttpSession(String id, int maxInactiveInterval, SessionManager sessionManager) {
28 | super(id, maxInactiveInterval, sessionManager);
29 | }
30 |
31 | @Override
32 | public Object getAttribute(String name) {
33 | access(false);
34 | return sessionStore.getAttribute(getId(), name);
35 | }
36 |
37 | @Override
38 | public Enumeration getAttributeNames() {
39 | access(false);
40 | return Collections.enumeration(sessionStore.getAttributeNames(getId()));
41 | }
42 |
43 | @Override
44 | public void setAttribute(String name, Object value) {
45 | access(true);
46 |
47 | Object oldValue = sessionStore.getAttribute(getId(), name);
48 | if(value instanceof HttpSessionBindingListener){
49 | if(value != oldValue){
50 | try{
51 | ((HttpSessionBindingListener)value).valueBound(new HttpSessionBindingEvent(this, name, value));
52 | }catch (Exception e){
53 | logger.error("bingEvent error:", e);
54 | }
55 | }
56 | }
57 |
58 | sessionStore.setAttribute(getId(), name, value);
59 |
60 | if(oldValue != null && oldValue != value &&
61 | oldValue instanceof HttpSessionBindingListener){
62 | try{
63 | ((HttpSessionBindingListener)oldValue).valueUnbound(new HttpSessionBindingEvent(this, name));
64 | }catch (Exception e){
65 | logger.error("bingEvent error:", e);
66 | }
67 | }
68 | }
69 |
70 | @Override
71 | public void removeAttribute(String name) {
72 | access(false);
73 | sessionStore.removeAttribute(getId(), name);
74 | }
75 | }
76 |
--------------------------------------------------------------------------------
/servlet3.x-session/src/main/java/com/github/loafer/filter/DistributableSessionFilter.java:
--------------------------------------------------------------------------------
1 | package com.github.loafer.filter;
2 |
3 | import com.github.loafer.session.SessionManager;
4 | import com.github.loafer.session.support.SessionManagerImpl;
5 | import org.slf4j.Logger;
6 | import org.slf4j.LoggerFactory;
7 |
8 | import javax.servlet.*;
9 | import javax.servlet.http.HttpServletRequest;
10 | import javax.servlet.http.HttpServletRequestWrapper;
11 | import javax.servlet.http.HttpServletResponse;
12 | import javax.servlet.http.HttpSession;
13 | import java.io.IOException;
14 |
15 | /**
16 | * @author zhaojh
17 | */
18 | public class DistributableSessionFilter implements Filter{
19 | private static Logger logger = LoggerFactory.getLogger(DistributableSessionFilter.class);
20 | private SessionManager sessionManager;
21 |
22 | @Override
23 | public void init(FilterConfig filterConfig) throws ServletException {
24 | sessionManager = new SessionManagerImpl(filterConfig.getServletContext());
25 | sessionManager.start();
26 | }
27 |
28 | @Override
29 | public void doFilter(final ServletRequest request,
30 | final ServletResponse response,
31 | FilterChain chain)
32 | throws IOException, ServletException {
33 |
34 | final HttpServletRequest httpRequest = (HttpServletRequest) request;
35 | final HttpServletResponse httpReponse = (HttpServletResponse) response;
36 |
37 | logger.info("servlet path: {}",((HttpServletRequest) request).getServletPath());
38 | logger.info("cookies: {}", ((HttpServletRequest) request).getCookies());
39 |
40 | HttpServletRequest newRequest = new HttpServletRequestWrapper(httpRequest){
41 | @Override
42 | public HttpSession getSession(boolean create) {
43 | HttpSession session = null;
44 |
45 | //查找与当前requset关联的session
46 | String sessionid = sessionManager.getRequestedSessionId(httpRequest);
47 | logger.info("==========================================");
48 | logger.info("与当前请求相关联的session为[{}]。", sessionid);
49 | if(sessionid != null){
50 | session = sessionManager.getHttpSession(sessionid);
51 | if(session != null){
52 | logger.info("检索到[{}]标记的session。", sessionid);
53 | }else{
54 | logger.info("没有检索到[{}]标记的session。", sessionid);
55 | }
56 | }
57 |
58 | //如果session不存在,并且create=true,则创建新session,否则返回null
59 | if(session == null && create){
60 | session = sessionManager.newHttpSession(httpRequest, httpReponse);
61 | logger.info("创建一个新session[{}]。", session.getId());
62 | }
63 |
64 | logger.info("==========================================");
65 | return session;
66 | }
67 |
68 | @Override
69 | public HttpSession getSession() {
70 | return getSession(true);
71 | }
72 | };
73 |
74 | chain.doFilter(newRequest, response);
75 | }
76 |
77 | @Override
78 | public void destroy() {
79 | sessionManager.stop();
80 | }
81 | }
82 |
--------------------------------------------------------------------------------
/simple-distributed-sessions-manager/pom.xml:
--------------------------------------------------------------------------------
1 |
3 | 4.0.0
4 |
5 | com.github.loafer
6 | simple-distributed-sessions-manager
7 | 1.0-SNAPSHOT
8 | jar
9 |
10 | simple-distributed-sessions-manager
11 | http://maven.apache.org
12 |
13 |
14 | UTF-8
15 |
16 |
17 |
18 |
19 | javax.servlet
20 | javax.servlet-api
21 | 3.1.0
22 | provided
23 |
24 |
25 |
26 | org.slf4j
27 | slf4j-simple
28 | 1.7.5
29 |
30 |
31 |
32 | redis.clients
33 | jedis
34 | 2.6.0
35 |
36 |
37 |
38 | junit
39 | junit
40 | 4.11
41 | test
42 |
43 |
44 |
45 |
46 |
47 |
48 | org.apache.maven.plugins
49 | maven-compiler-plugin
50 | 3.2
51 |
52 | 1.6
53 | 1.6
54 | utf-8
55 |
56 |
57 |
58 |
59 | org.apache.maven.plugins
60 | maven-source-plugin
61 | 2.4
62 |
63 |
64 | package
65 |
66 | jar-no-fork
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
--------------------------------------------------------------------------------
/servlet3.x-session/src/main/java/com/github/loafer/session/support/DefaultSessionIdManager.java:
--------------------------------------------------------------------------------
1 | package com.github.loafer.session.support;
2 |
3 | import com.github.loafer.session.SessionIdManager;
4 | import org.slf4j.Logger;
5 | import org.slf4j.LoggerFactory;
6 |
7 | import javax.servlet.http.HttpServletRequest;
8 | import java.security.SecureRandom;
9 | import java.util.Random;
10 |
11 | /**
12 | * @author zhaojh
13 | */
14 | public class DefaultSessionIdManager implements SessionIdManager {
15 | private static final Logger logger = LoggerFactory.getLogger(DefaultSessionIdManager.class);
16 |
17 | // private final static String __NEW_SESSION_ID = "com.github.loafer.newSessionId";
18 | private Random random;
19 | private boolean weakRandom;
20 | private long reseed=100000L;
21 |
22 | @Override
23 | public void start() {
24 | try{
25 | random = new SecureRandom();
26 | }catch (Exception e){
27 | logger.warn("Could not generate SecureRandom for httpsession-id randomness", e);
28 | random = new Random();
29 | weakRandom = true;
30 | }
31 | }
32 |
33 | @Override
34 | public void stop() {
35 |
36 | }
37 |
38 | @Override
39 | public String newSessionId(HttpServletRequest request, long created) {
40 | if(request == null){
41 | return newSessionId(created);
42 | }
43 |
44 | return newSessionId(request.hashCode());
45 | }
46 |
47 | private String newSessionId(long seedTerm){
48 | String id = null;
49 | while (id == null || id.length() == 0){
50 | long r0 = weakRandom ? (hashCode() ^ Runtime.getRuntime().freeMemory() ^ random.nextInt() ^ (seedTerm<<32))
51 | : random.nextLong();
52 |
53 | if(r0 < 0) r0 = -r0;
54 |
55 | if (reseed>0 && (r0 % reseed)== 1L){
56 | logger.info("Reseeding {}", this);
57 |
58 | if(random instanceof SecureRandom){
59 | SecureRandom secure = (SecureRandom) random;
60 | secure.setSeed(secure.generateSeed(8));
61 | }else{
62 | random.setSeed(random.nextLong() ^ System.currentTimeMillis() ^ seedTerm ^ Runtime.getRuntime().freeMemory());
63 | }
64 | }
65 |
66 | long r1 = weakRandom ?
67 | (hashCode() ^ Runtime.getRuntime().freeMemory() ^ random.nextInt() ^ (seedTerm<<32))
68 | : random.nextLong();
69 |
70 | if(r1 < 0) r1 = -r1;
71 |
72 | id = Long.toString(r0, 36) + Long.toString(r1, 36);
73 | }
74 |
75 | logger.info("new httpsession id: {}", id);
76 | return id + ".quick4j";
77 | }
78 |
79 | public static void main(String[] args){
80 | final DefaultSessionIdManager manager = new DefaultSessionIdManager();
81 | manager.start();
82 |
83 | for(int i=0; i<10; i++){
84 | Runnable t = new Runnable() {
85 | @Override
86 | public void run() {
87 | String id = manager.newSessionId(this.hashCode());
88 | logger.info("id: {}, length: {}", id, id.length());
89 | }
90 | };
91 |
92 | t.run();
93 | }
94 |
95 | manager.stop();
96 | }
97 | }
98 |
--------------------------------------------------------------------------------
/servlet3.x-session/src/main/java/com/github/loafer/session/support/SessionManagerImpl.java:
--------------------------------------------------------------------------------
1 | package com.github.loafer.session.support;
2 |
3 | import com.github.loafer.helper.CookieHelper;
4 | import com.github.loafer.session.SessionIdManager;
5 | import com.github.loafer.session.SessionManager;
6 | import com.github.loafer.session.SessionStore;
7 | import com.github.loafer.session.metadata.SessionMetaData;
8 | import org.slf4j.Logger;
9 | import org.slf4j.LoggerFactory;
10 |
11 | import javax.servlet.ServletContext;
12 | import javax.servlet.http.HttpServletRequest;
13 | import javax.servlet.http.HttpServletResponse;
14 | import javax.servlet.http.HttpSession;
15 |
16 | /**
17 | * @author zhaojh
18 | */
19 | public class SessionManagerImpl implements SessionManager {
20 | private final Logger logger = LoggerFactory.getLogger(SessionManagerImpl.class);
21 |
22 | private SessionIdManager sessionIdManager;
23 | private SessionStore sessionStore;
24 | private int maxInactiveInterval = 30;
25 | private ServletContext servletContext;
26 |
27 | public SessionManagerImpl(ServletContext servletContext) {
28 | this.servletContext = servletContext;
29 | }
30 |
31 | @Override
32 | public void start() {
33 | sessionIdManager = new DefaultSessionIdManager();
34 | sessionStore = new RedisSessionStore();
35 | sessionIdManager.start();
36 | sessionStore.start();
37 | }
38 |
39 | @Override
40 | public void stop() {
41 | sessionIdManager.stop();
42 | sessionStore.stop();
43 | }
44 |
45 | @Override
46 | public void setMaxInactiveInterval(int interval) {
47 | this.maxInactiveInterval = interval;
48 | }
49 |
50 | @Override
51 | public ServletContext getServletContext() {
52 | return servletContext;
53 | }
54 |
55 | @Override
56 | public void add(HttpSession session) {
57 | sessionStore.putSessionMetaData(session);
58 | }
59 |
60 | @Override
61 | public void remove(HttpSession session) {
62 | sessionStore.removeSessionMetaData(session.getId());
63 | }
64 |
65 | @Override
66 | public HttpSession newHttpSession(HttpServletRequest request, HttpServletResponse response) {
67 | String id = newSessionId(request);
68 | HttpSession httpSession = new RedisHttpSession(id, maxInactiveInterval, this);
69 | CookieHelper.writeSessionIdToCookie(httpSession.getId(), request, response);
70 | return httpSession;
71 | }
72 |
73 | @Override
74 | public HttpSession getHttpSession(String id) {
75 | SessionMetaData metaData = sessionStore.getSessionMetaData(id);
76 | if(null != metaData){
77 | return new RedisHttpSession(
78 | id,
79 | metaData.getCreationTime(),
80 | metaData.getLastAccessedTime(),
81 | metaData.getMaxInactiveInterval(),
82 | this
83 | );
84 | }
85 |
86 | return null;
87 | }
88 |
89 | @Override
90 | public String getRequestedSessionId(HttpServletRequest request) {
91 | String sessionid = request.getParameter(DISTRIBUTED_SESSION_ID);
92 | if(null == sessionid){
93 | sessionid = CookieHelper.findSessionId(request);
94 | }
95 | return sessionid;
96 | }
97 |
98 | @Override
99 | public SessionStore getSessionStore() {
100 | return sessionStore;
101 | }
102 |
103 | private String newSessionId(HttpServletRequest request) {
104 | return sessionIdManager.newSessionId(request, System.currentTimeMillis());
105 | }
106 | }
107 |
--------------------------------------------------------------------------------
/simple-distributed-sessions-manager/src/main/java/com/github/loafer/distributed/httpsession/session/NoStickyHttpSession.java:
--------------------------------------------------------------------------------
1 | package com.github.loafer.distributed.httpsession.session;
2 |
3 | import com.github.loafer.distributed.httpsession.SessionManager;
4 | import com.github.loafer.distributed.httpsession.metadata.SessionMetaData;
5 | import org.slf4j.Logger;
6 | import org.slf4j.LoggerFactory;
7 |
8 | import javax.servlet.ServletContext;
9 | import javax.servlet.http.HttpSessionBindingEvent;
10 | import javax.servlet.http.HttpSessionBindingListener;
11 | import java.util.Collections;
12 | import java.util.Enumeration;
13 |
14 | /**
15 | * @author zhaojh
16 | */
17 | public class NoStickyHttpSession extends DistributedHttpSession{
18 | private static final Logger logger = LoggerFactory.getLogger(NoStickyHttpSession.class);
19 |
20 | public NoStickyHttpSession(String id,
21 | int maxInactiveInterval,
22 | SessionManager sessionManager,
23 | ServletContext servletContext) {
24 | super(id, maxInactiveInterval, sessionManager, servletContext);
25 | }
26 |
27 | public NoStickyHttpSession(String id,
28 | long creationTime,
29 | long lastAccessedTime,
30 | int maxInactiveInterval,
31 | SessionManager sessionManager,
32 | ServletContext servletContext) {
33 | super(id, creationTime, lastAccessedTime, maxInactiveInterval, sessionManager, servletContext);
34 | }
35 |
36 | @Override
37 | public Object getAttribute(String name) {
38 | access();
39 | return sessionManager.getSessionStorage().getSessionAttribute(getId(), name);
40 | }
41 |
42 | @Override
43 | public Enumeration getAttributeNames() {
44 | access();
45 | return Collections.enumeration(sessionManager.getSessionStorage().getSessionAttributeNames(getId()));
46 | }
47 |
48 | @Override
49 | public void setAttribute(String name, Object value) {
50 | access();
51 |
52 | Object oldValue = getAttribute(name);
53 | if(value instanceof HttpSessionBindingListener){
54 | if(value != oldValue){
55 | try{
56 | ((HttpSessionBindingListener)value).valueBound(new HttpSessionBindingEvent(this, name, value));
57 | }catch (Exception e){
58 | logger.error("bingEvent error:", e);
59 | throw new RuntimeException(e);
60 | }
61 | }
62 | }
63 |
64 | sessionManager.getSessionStorage().storeSessionAttribute(getId(), name, value);
65 |
66 | if(null != oldValue && oldValue != value && oldValue instanceof HttpSessionBindingListener){
67 | try{
68 | ((HttpSessionBindingListener)oldValue).valueUnbound(new HttpSessionBindingEvent(this, name));
69 | }catch (Exception e){
70 | logger.error("bingEvent error:", e);
71 | throw new RuntimeException(e);
72 | }
73 | }
74 | }
75 |
76 | @Override
77 | public void removeAttribute(String name) {
78 | access();
79 | Object oldValue = getAttribute(name);
80 | sessionManager.getSessionStorage().removeSessionAttribute(getId(), name);
81 | if(null != oldValue && oldValue instanceof HttpSessionBindingListener){
82 | try{
83 | ((HttpSessionBindingListener)oldValue).valueUnbound(new HttpSessionBindingEvent(this, name));
84 | }catch (Exception e){
85 | logger.error("bingEvent error:", e);
86 | throw new RuntimeException(e);
87 | }
88 | }
89 | }
90 |
91 | @Override
92 | protected void reloadAttributes() {}
93 |
94 | @Override
95 | protected void reloadMetaData() {
96 | SessionMetaData metaData = sessionManager.getSessionStorage().getSessionMetaData(getId());
97 | lastAccessedTime = metaData.getLastAccessedTime();
98 | }
99 | }
100 |
--------------------------------------------------------------------------------
/simple-distributed-sessions-manager/src/main/java/com/github/loafer/distributed/httpsession/session/StickyHttpSession.java:
--------------------------------------------------------------------------------
1 | package com.github.loafer.distributed.httpsession.session;
2 |
3 | import com.github.loafer.distributed.httpsession.SessionManager;
4 | import org.slf4j.Logger;
5 | import org.slf4j.LoggerFactory;
6 |
7 | import javax.servlet.ServletContext;
8 | import javax.servlet.http.HttpSessionBindingEvent;
9 | import javax.servlet.http.HttpSessionBindingListener;
10 | import java.util.Collections;
11 | import java.util.Enumeration;
12 | import java.util.Map;
13 | import java.util.concurrent.ConcurrentHashMap;
14 |
15 | /**
16 | * @author zhaojh
17 | */
18 | public class StickyHttpSession extends DistributedHttpSession{
19 | private static final Logger logger = LoggerFactory.getLogger(StickyHttpSession.class);
20 | private final Map attributes = new ConcurrentHashMap();
21 |
22 | public StickyHttpSession(String id,
23 | int maxInactiveInterval,
24 | SessionManager sessionManager,
25 | ServletContext servletContext) {
26 | super(id, maxInactiveInterval, sessionManager, servletContext);
27 | }
28 |
29 | public StickyHttpSession(String id,
30 | long creationTime,
31 | long lastAccessedTime,
32 | int maxInactiveInterval,
33 | SessionManager sessionManager,
34 | ServletContext servletContext) {
35 | super(id, creationTime, lastAccessedTime,
36 | maxInactiveInterval, sessionManager, servletContext);
37 | }
38 |
39 | @Override
40 | public Object getAttribute(String name) {
41 | access();
42 | return attributes.get(name);
43 | }
44 |
45 | @Override
46 | public Enumeration getAttributeNames() {
47 | access();
48 | return Collections.enumeration(attributes.keySet());
49 | }
50 |
51 | @Override
52 | public void setAttribute(String name, Object value) {
53 | access();
54 |
55 | Object oldValue = attributes.get(name);
56 | if(oldValue instanceof HttpSessionBindingListener){
57 | if(value != oldValue){
58 | try{
59 | ((HttpSessionBindingListener)value).valueBound(new HttpSessionBindingEvent(this, name, value));
60 | }catch (Exception e){
61 | logger.error("bingEvent error:", e);
62 | throw new RuntimeException(e);
63 | }
64 | }
65 | }
66 |
67 | Object unbound = attributes.put(name, value);
68 | sessionManager.getSessionStorage().storeSessionAttribute(getId(), name, value);
69 |
70 | if(null != unbound && unbound != value && unbound instanceof HttpSessionBindingListener){
71 | try{
72 | ((HttpSessionBindingListener)unbound).valueUnbound(new HttpSessionBindingEvent(this, name));
73 | }catch (Exception e){
74 | logger.error("bingEvent error:", e);
75 | throw new RuntimeException(e);
76 | }
77 | }
78 | }
79 |
80 | @Override
81 | public void removeAttribute(String name) {
82 | access();
83 | sessionManager.getSessionStorage().removeSessionAttribute(getId(), name);
84 | Object unbound = attributes.remove(name);
85 | if(null != unbound && unbound instanceof HttpSessionBindingListener){
86 | try{
87 | ((HttpSessionBindingListener)unbound).valueUnbound(new HttpSessionBindingEvent(this, name));
88 | }catch (Exception e){
89 | logger.error("bingEvent error:", e);
90 | throw new RuntimeException(e);
91 | }
92 | }
93 | }
94 |
95 | /**
96 | * 注意:将Session Storage上的内容刷新到本地时,
97 | * 不再触发HttpSessionBindingListener的valueBound和valueUnbound事件。
98 | */
99 | @Override
100 | protected void reloadAttributes() {
101 | attributes.clear();
102 | attributes.putAll(sessionManager.getSessionStorage().getSessionAttributes(getId()));
103 | }
104 |
105 | @Override
106 | public void reloadMetaData() {
107 |
108 | }
109 | }
110 |
--------------------------------------------------------------------------------
/servlet3.x-session/src/main/java/com/github/loafer/session/support/RedisSessionStore.java:
--------------------------------------------------------------------------------
1 | package com.github.loafer.session.support;
2 |
3 | import com.github.loafer.session.SessionStore;
4 | import com.github.loafer.session.metadata.SessionMetaData;
5 | import com.github.loafer.util.SerializationUtils;
6 | import org.slf4j.Logger;
7 | import org.slf4j.LoggerFactory;
8 | import redis.clients.jedis.Jedis;
9 |
10 | import javax.servlet.http.HttpSession;
11 | import java.util.*;
12 |
13 | /**
14 | * @author zhaojh
15 | */
16 | public class RedisSessionStore implements SessionStore {
17 | private static final Logger logger = LoggerFactory.getLogger(RedisSessionStore.class);
18 | private static final String SESSION_METADATA_KEY = "httpsession:%s:metadata";
19 | private static final String SESSION_ATTRIBUTE_KEY = "httpsession:%s:attribute";
20 | private Jedis jedis;
21 |
22 | @Override
23 | public void start() {
24 | jedis = new Jedis("192.168.56.110");
25 | }
26 |
27 | @Override
28 | public void stop() {
29 | jedis.quit();
30 | }
31 |
32 | @Override
33 | public void putSessionMetaData(HttpSession session) {
34 | Map sessionAttributes = new HashMap();
35 | sessionAttributes.put(AbstractDistributedHttpSession.CREATION_TIME_KEY, String.valueOf(session.getCreationTime()));
36 | sessionAttributes.put(AbstractDistributedHttpSession.LAST_ACCESSED_TIME_KEY, String.valueOf(session.getLastAccessedTime()));
37 | sessionAttributes.put(AbstractDistributedHttpSession.MAX_INACTIVE_INTERVAL_KEY, String.valueOf(session.getMaxInactiveInterval()));
38 |
39 | String key = String.format(SESSION_METADATA_KEY, session.getId());
40 | jedis.hmset(key, sessionAttributes);
41 | }
42 |
43 | @Override
44 | public SessionMetaData getSessionMetaData(String sessionid) {
45 | String key = String.format(SESSION_METADATA_KEY, sessionid);
46 | Map sessionAttributes = jedis.hgetAll(key);
47 | if (null != sessionAttributes && !sessionAttributes.isEmpty()){
48 | return new SessionMetaData(
49 | sessionid,
50 | Long.parseLong(sessionAttributes.get("CreationTime")),
51 | Long.parseLong(sessionAttributes.get("LastAccessedTime")),
52 | Integer.parseInt(sessionAttributes.get("MaxInactiveInterval"))
53 | );
54 | }
55 | return null;
56 | }
57 |
58 | @Override
59 | public void removeSessionMetaData(String sessionid) {
60 | String metakey = String.format(SESSION_METADATA_KEY, sessionid);
61 | String attributekey = String.format(SESSION_ATTRIBUTE_KEY, sessionid);
62 | jedis.del(metakey);
63 | jedis.del(attributekey.getBytes());
64 | }
65 |
66 | @Override
67 | public void updateSessionMetaData(String sessionid, String name, Object value) {
68 | String metakey = String.format(SESSION_METADATA_KEY, sessionid);
69 | jedis.hset(metakey, name, String.valueOf(value));
70 | }
71 |
72 | @Override
73 | public void setAttribute(String sessionid, String name, Object value) {
74 | String key = String.format(SESSION_ATTRIBUTE_KEY, sessionid);
75 | jedis.hset(key.getBytes(), name.getBytes(), SerializationUtils.serialize(value));
76 | }
77 |
78 | @Override
79 | public void removeAttribute(String sessionid, String name) {
80 | String key = String.format(SESSION_ATTRIBUTE_KEY, sessionid);
81 | jedis.hdel(key.getBytes(), name.getBytes());
82 | }
83 |
84 | @Override
85 | public Object getAttribute(String sessionid, String name) {
86 | String key = String.format(SESSION_ATTRIBUTE_KEY, sessionid);
87 | return SerializationUtils.deserialize(jedis.hget(key.getBytes(), name.getBytes()));
88 | }
89 |
90 | @Override
91 | public List getAttributeNames(String sessionid) {
92 | String key = String.format(SESSION_ATTRIBUTE_KEY, sessionid);
93 | Map attributes = jedis.hgetAll(key.getBytes());
94 | if(!attributes.isEmpty()){
95 | Iterator iterator = attributes.keySet().iterator();
96 | List attributeNames = new ArrayList();
97 | while (iterator.hasNext()){
98 | attributeNames.add(new String(iterator.next()));
99 | }
100 |
101 | return attributeNames;
102 | }
103 |
104 | return Collections.emptyList();
105 | }
106 | }
107 |
--------------------------------------------------------------------------------
/simple-distributed-sessions-manager/src/main/java/com/github/loafer/distributed/httpsession/session/DistributedHttpSession.java:
--------------------------------------------------------------------------------
1 | package com.github.loafer.distributed.httpsession.session;
2 |
3 | import com.github.loafer.distributed.httpsession.SessionManager;
4 | import com.github.loafer.distributed.httpsession.metadata.SessionMetaData;
5 |
6 | import javax.servlet.ServletContext;
7 | import javax.servlet.http.HttpSession;
8 | import javax.servlet.http.HttpSessionContext;
9 | import java.util.Collections;
10 |
11 | /**
12 | * @author zhaojh
13 | */
14 | public abstract class DistributedHttpSession implements HttpSession{
15 | private String id;
16 | private final long creationTime;
17 | private int maxInactiveInterval;
18 | private boolean newSession;
19 | private boolean persistent;
20 | private boolean validate = true;
21 | private ServletContext servletContext;
22 |
23 | protected SessionManager sessionManager;
24 | protected long lastAccessedTime;
25 |
26 |
27 |
28 | public DistributedHttpSession(String id,
29 | int maxInactiveInterval,
30 | SessionManager sessionManager,
31 | ServletContext servletContext) {
32 | this.id = id;
33 | this.creationTime = System.currentTimeMillis();
34 | this.lastAccessedTime = this.creationTime;
35 | this.maxInactiveInterval = maxInactiveInterval;
36 | this.sessionManager = sessionManager;
37 | this.newSession = true;
38 | this.persistent = false;
39 | this.servletContext = servletContext;
40 | }
41 |
42 | public DistributedHttpSession(String id,
43 | long creationTime,
44 | long lastAccessedTime,
45 | int maxInactiveInterval,
46 | SessionManager sessionManager,
47 | ServletContext servletContext) {
48 | this.id = id;
49 | this.creationTime = creationTime;
50 | this.lastAccessedTime = lastAccessedTime;
51 | this.maxInactiveInterval = maxInactiveInterval;
52 | this.sessionManager = sessionManager;
53 | this.newSession = false;
54 | this.persistent = true;
55 | this.servletContext = servletContext;
56 | }
57 |
58 | @Override
59 | public long getCreationTime() {
60 | return creationTime;
61 | }
62 |
63 | @Override
64 | public String getId() {
65 | return id;
66 | }
67 |
68 | @Override
69 | public long getLastAccessedTime() {
70 | return lastAccessedTime;
71 | }
72 |
73 | @Override
74 | public ServletContext getServletContext() {
75 | return servletContext;
76 | }
77 |
78 | @Override
79 | public void setMaxInactiveInterval(int interval) {
80 | maxInactiveInterval = interval;
81 | }
82 |
83 | @Override
84 | public int getMaxInactiveInterval() {
85 | return maxInactiveInterval;
86 | }
87 |
88 | @Override
89 | public HttpSessionContext getSessionContext() {
90 | return null;
91 | }
92 |
93 | @Override
94 | public Object getValue(String name) {
95 | return getAttribute(name);
96 | }
97 |
98 | @Override
99 | public String[] getValueNames() {
100 | return Collections.list(getAttributeNames()).toArray(new String[]{});
101 | }
102 |
103 | @Override
104 | public void putValue(String name, Object value) {
105 | setAttribute(name, value);
106 | }
107 |
108 | @Override
109 | public void removeValue(String name) {
110 | removeAttribute(name);
111 | }
112 |
113 | @Override
114 | public void invalidate() {
115 | sessionManager.removeHttpSession(this);
116 | }
117 |
118 | @Override
119 | public boolean isNew() {
120 | return newSession;
121 | }
122 |
123 | public boolean isValid(){
124 | if(maxInactiveInterval >0 && (lastAccessedTime + maxInactiveInterval * 1000) < System.currentTimeMillis()){
125 | validate = false;
126 | }
127 | return validate;
128 | }
129 |
130 | public void refresh(){
131 | reloadMetaData();
132 | reloadAttributes();
133 | }
134 |
135 | protected abstract void reloadAttributes();
136 | protected abstract void reloadMetaData();
137 |
138 | protected void access(){
139 | synchronized (this){
140 | if(!persistent || !sessionManager.getSessionStorage().isStored(this)){
141 | sessionManager.getSessionStorage().storeSessionMetaData(this);
142 | persistent = true;
143 | }
144 |
145 | newSession = false;
146 | updateLastAccessedTime();
147 | }
148 | }
149 |
150 | private void updateLastAccessedTime(){
151 | lastAccessedTime = System.currentTimeMillis();
152 | if(persistent){
153 | sessionManager.getSessionStorage().updateSessionMetaDataField(getId(), SessionMetaData.LAST_ACCESSED_TIME_KEY, lastAccessedTime);
154 | }
155 | }
156 | }
157 |
--------------------------------------------------------------------------------
/simple-distributed-sessions-manager/src/main/java/com/github/loafer/distributed/httpsession/filter/DistributableSessionFilter.java:
--------------------------------------------------------------------------------
1 | package com.github.loafer.distributed.httpsession.filter;
2 |
3 | import com.github.loafer.distributed.httpsession.SessionManager;
4 | import com.github.loafer.distributed.httpsession.helper.CookieHelper;
5 | import com.github.loafer.distributed.httpsession.manager.NoStickySessionManager;
6 | import com.github.loafer.distributed.httpsession.manager.StickySessionManager;
7 | import com.github.loafer.distributed.httpsession.session.NoStickyHttpSession;
8 | import org.slf4j.Logger;
9 | import org.slf4j.LoggerFactory;
10 |
11 | import javax.servlet.*;
12 | import javax.servlet.http.HttpServletRequest;
13 | import javax.servlet.http.HttpServletRequestWrapper;
14 | import javax.servlet.http.HttpServletResponse;
15 | import javax.servlet.http.HttpSession;
16 | import java.io.IOException;
17 |
18 | /**
19 | * @author zhaojh
20 | */
21 | public class DistributableSessionFilter implements Filter {
22 | private static Logger logger = LoggerFactory.getLogger(DistributableSessionFilter.class);
23 | private SessionManager sessionManager;
24 | private int maxInactiveInterval = 60 * 30;
25 | private String loadBalancingStrategy = "sticky";
26 |
27 | @Override
28 | public void init(FilterConfig filterConfig) throws ServletException {
29 | String sessionTimeout = filterConfig.getInitParameter("sessionTimeout");
30 | //默认最大有效期30分钟
31 | try{
32 | maxInactiveInterval = 60 * Integer.parseInt(sessionTimeout);
33 | }catch (NumberFormatException e){}
34 |
35 |
36 | loadBalancingStrategy = filterConfig.getInitParameter("loadBalancingStrategy");
37 | if(loadBalancingStrategy.equalsIgnoreCase("sticky")){
38 | logger.info("应用负载均衡策略为: Sticky Session");
39 | sessionManager = new StickySessionManager(filterConfig.getServletContext(), maxInactiveInterval);
40 | }else{
41 | logger.info("应用负载均衡策略为: 非Sticky Session");
42 | sessionManager = new NoStickySessionManager(filterConfig.getServletContext(), maxInactiveInterval);
43 | }
44 | sessionManager.start();
45 | }
46 |
47 | @Override
48 | public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
49 | throws IOException, ServletException {
50 |
51 | final HttpServletRequest httpRequest = (HttpServletRequest) request;
52 | final HttpServletResponse httpReponse = (HttpServletResponse) response;
53 |
54 | HttpServletRequest requestWrapper = new HttpServletRequestWrapper(httpRequest){
55 | private HttpSession session;
56 |
57 | @Override
58 | public HttpSession getSession(boolean create) {
59 | if(null != session) return session;
60 |
61 | logger.info("============================");
62 | String sessionid = getRequestedSessionId();
63 |
64 | if(null == sessionid){
65 | logger.info("当前request还未与Session关联.");
66 | }
67 |
68 | if(sessionid != null){
69 | logger.info("当前request与session[{}]关联.", sessionid);
70 | session = sessionManager.getHttpSession(sessionid);
71 |
72 | if(null == session){
73 | logger.info("session[{}]已失效.", sessionid);
74 | }
75 |
76 | if(sessionManager.isValid(session)){
77 | logger.info("session[{}]有效。", sessionid);
78 | return session;
79 | }else{
80 | logger.info("session[{}]已失效。", sessionid);
81 | }
82 | }
83 |
84 | logger.info("create: {}", create);
85 | if(!create){
86 | logger.info("未要求创建新session. 返回null");
87 | return null;
88 | }
89 |
90 | session = sessionManager.newHttpSession(this);
91 | logger.info("为当前request创建一个新session[{}].", session.getId());
92 | CookieHelper.writeSessionIdToCookie(session.getId(), httpRequest, httpReponse);
93 | return session;
94 | }
95 |
96 | @Override
97 | public HttpSession getSession() {
98 | return this.getSession(true);
99 | }
100 |
101 | @Override
102 | public String getRequestedSessionId() {
103 | String sessionid = httpRequest.getParameter(SessionManager.DISTRIBUTED_SESSION_ID);
104 | if(null == sessionid){
105 | sessionid = CookieHelper.findSessionId(httpRequest);
106 | if(null != sessionid){
107 | logger.info("客户端Cookie中持有与当前request关联的session[{}]标识.", sessionid);
108 | }
109 | }else{
110 | logger.info("url中持有与当前request关联的session[{}]标识.", sessionid);
111 | }
112 | return sessionid;
113 | }
114 | };
115 |
116 | chain.doFilter(requestWrapper, httpReponse);
117 | }
118 |
119 | @Override
120 | public void destroy() {
121 | sessionManager.stop();
122 | }
123 | }
124 |
--------------------------------------------------------------------------------
/servlet3.x-session/src/main/java/com/github/loafer/session/support/AbstractDistributedHttpSession.java:
--------------------------------------------------------------------------------
1 | package com.github.loafer.session.support;
2 |
3 | import com.github.loafer.session.SessionManager;
4 | import com.github.loafer.session.SessionStore;
5 | import org.slf4j.Logger;
6 | import org.slf4j.LoggerFactory;
7 |
8 | import javax.servlet.ServletContext;
9 | import javax.servlet.http.HttpSession;
10 | import javax.servlet.http.HttpSessionContext;
11 | import java.util.Collections;
12 |
13 | /**
14 | * @author zhaojh
15 | */
16 | public abstract class AbstractDistributedHttpSession implements HttpSession{
17 | private static final Logger logger = LoggerFactory.getLogger(AbstractDistributedHttpSession.class);
18 | public static final String LAST_ACCESSED_TIME_KEY = "lastAccessedTime";
19 | public static final String CREATION_TIME_KEY = "creationTime";
20 | public static final String MAX_INACTIVE_INTERVAL_KEY = "maxInactiveInterval";
21 | private String id;
22 | private final long creationTm;
23 | private long lastAccessedTm;
24 | private int maxInactiveInterval;
25 | private boolean newSession;
26 | private boolean persistent;
27 | protected SessionManager sessionManager;
28 | protected SessionStore sessionStore;
29 |
30 | /**
31 | * 创建一个新session
32 | * @param id
33 | * @param maxInactiveInterval
34 | * @param sessionManager
35 | */
36 | public AbstractDistributedHttpSession(String id,
37 | int maxInactiveInterval,
38 | SessionManager sessionManager) {
39 | this.id = id;
40 | this.creationTm = System.currentTimeMillis();
41 | this.lastAccessedTm = this.creationTm;
42 | this.maxInactiveInterval = maxInactiveInterval;
43 | this.newSession = true;
44 | this.persistent = false;
45 | this.sessionManager = sessionManager;
46 | this.sessionStore = this.sessionManager.getSessionStore();
47 | }
48 |
49 | /**
50 | * 根据sessionMetaData还原一个已存在的session
51 | * @param id
52 | * @param creationTm
53 | * @param lastAccessedTm
54 | * @param maxInactiveInterval
55 | * @param sessionManager
56 | */
57 | public AbstractDistributedHttpSession(String id,
58 | long creationTm,
59 | long lastAccessedTm,
60 | int maxInactiveInterval,
61 | SessionManager sessionManager) {
62 | this.id = id;
63 | this.creationTm = creationTm;
64 | this.lastAccessedTm = lastAccessedTm;
65 | this.maxInactiveInterval = maxInactiveInterval;
66 | this.newSession = false;
67 | this.persistent = true;
68 | this.sessionManager = sessionManager;
69 | this.sessionStore = this.sessionManager.getSessionStore();
70 | }
71 |
72 | // @Override
73 | // public Object getAttribute(String name) {
74 | // return null;
75 | // }
76 |
77 | // @Override
78 | // public Enumeration getAttributeNames() {
79 | // return null;
80 | // }
81 |
82 | @Override
83 | public long getCreationTime() {
84 | return 0;
85 | }
86 |
87 | @Override
88 | public String getId() {
89 | return id;
90 | }
91 |
92 | @Override
93 | public long getLastAccessedTime() {
94 | return lastAccessedTm;
95 | }
96 |
97 | @Override
98 | public int getMaxInactiveInterval() {
99 | return maxInactiveInterval;
100 | }
101 |
102 | @Override
103 | public ServletContext getServletContext() {
104 | return null;
105 | }
106 |
107 | @Override
108 | public HttpSessionContext getSessionContext() {
109 | return null;
110 | }
111 |
112 | @Override
113 | public Object getValue(String name) {
114 | return getAttribute(name);
115 | }
116 |
117 | @Override
118 | public String[] getValueNames() {
119 | return Collections.list(getAttributeNames()).toArray(new String[]{});
120 | }
121 |
122 | @Override
123 | public void invalidate() {
124 | sessionManager.remove(this);
125 | }
126 |
127 | @Override
128 | public boolean isNew() {
129 | return newSession;
130 | }
131 |
132 | @Override
133 | public void putValue(String name, Object value) {
134 | setAttribute(name, value);
135 | }
136 |
137 | // @Override
138 | // public void removeAttribute(String name) {
139 | //
140 | // }
141 |
142 | @Override
143 | public void removeValue(String name) {
144 | removeAttribute(name);
145 | }
146 |
147 | // @Override
148 | // public void setAttribute(String name, Object value) {
149 | //
150 | // }
151 |
152 | @Override
153 | public void setMaxInactiveInterval(int interval) {
154 | maxInactiveInterval = interval;
155 | }
156 |
157 | public void access(boolean joined){
158 | if(newSession && joined){
159 | logger.info("保存[{}]的元数据。", getId());
160 | sessionManager.add(this);
161 | newSession = false;
162 | persistent = true;
163 | }
164 | updateLastAccessedTime();
165 | }
166 |
167 | private void updateLastAccessedTime(){
168 | lastAccessedTm = System.currentTimeMillis();
169 | if(persistent){
170 | sessionStore.updateSessionMetaData(getId(), LAST_ACCESSED_TIME_KEY, lastAccessedTm);
171 | }
172 | }
173 | }
174 |
--------------------------------------------------------------------------------
/simple-distributed-sessions-manager/src/main/java/com/github/loafer/distributed/httpsession/storage/RedisSessionStorage.java:
--------------------------------------------------------------------------------
1 | package com.github.loafer.distributed.httpsession.storage;
2 |
3 | import com.github.loafer.distributed.httpsession.SessionStorage;
4 | import com.github.loafer.distributed.httpsession.metadata.SessionMetaData;
5 | import com.github.loafer.distributed.httpsession.util.SerializationUtils;
6 | import org.slf4j.Logger;
7 | import org.slf4j.LoggerFactory;
8 | import redis.clients.jedis.Jedis;
9 |
10 | import javax.servlet.http.HttpSession;
11 | import java.util.*;
12 |
13 | /**
14 | * @author zhaojh
15 | */
16 | public class RedisSessionStorage implements SessionStorage{
17 | private static final Logger logger = LoggerFactory.getLogger(RedisSessionStorage.class);
18 | private static final String SESSION_METADATA_KEY = "httpsession:%s:metadata";
19 | private static final String SESSION_ATTRIBUTE_KEY = "httpsession:%s:attribute";
20 | private Jedis jedis;
21 |
22 | @Override
23 | public void start() {
24 | logger.info("启动Session Storage for redis.");
25 | jedis = new Jedis("192.168.56.110");
26 | }
27 |
28 | @Override
29 | public void stop() {
30 | jedis.quit();
31 | }
32 |
33 | @Override
34 | public boolean isStored(HttpSession session) {
35 | String key = String.format(SESSION_METADATA_KEY, session.getId());
36 | return jedis.exists(key);
37 | }
38 |
39 | @Override
40 | public void storeSessionMetaData(HttpSession session) {
41 | Map sessionAttributes = new HashMap();
42 | sessionAttributes.put(SessionMetaData.CREATION_TIME_KEY, String.valueOf(session.getCreationTime()));
43 | sessionAttributes.put(SessionMetaData.LAST_ACCESSED_TIME_KEY, String.valueOf(session.getLastAccessedTime()));
44 | sessionAttributes.put(SessionMetaData.MAX_INACTIVE_INTERVAL_KEY, String.valueOf(session.getMaxInactiveInterval()));
45 |
46 | String key = String.format(SESSION_METADATA_KEY, session.getId());
47 | jedis.hmset(key, sessionAttributes);
48 | }
49 |
50 | @Override
51 | public void removeSession(String sessionid) {
52 | String metakey = String.format(SESSION_METADATA_KEY, sessionid);
53 | String attributekey = String.format(SESSION_ATTRIBUTE_KEY, sessionid);
54 | jedis.del(metakey);
55 | jedis.del(attributekey.getBytes());
56 | }
57 |
58 | @Override
59 | public SessionMetaData getSessionMetaData(String sessionid) {
60 | String key = String.format(SESSION_METADATA_KEY, sessionid);
61 | Map sessionAttributes = jedis.hgetAll(key);
62 | if (null != sessionAttributes && !sessionAttributes.isEmpty()){
63 | return new SessionMetaData(
64 | sessionid,
65 | Long.parseLong(sessionAttributes.get(SessionMetaData.CREATION_TIME_KEY)),
66 | Long.parseLong(sessionAttributes.get(SessionMetaData.LAST_ACCESSED_TIME_KEY)),
67 | Integer.parseInt(sessionAttributes.get(SessionMetaData.MAX_INACTIVE_INTERVAL_KEY))
68 | );
69 | }
70 | return null;
71 | }
72 |
73 | @Override
74 | public void updateSessionMetaDataField(String sessionid, String name, Object value) {
75 | String key = String.format(SESSION_METADATA_KEY, sessionid);
76 | jedis.hset(key, name, String.valueOf(value));
77 | }
78 |
79 | @Override
80 | public Object getSessionMetaDataField(String sessionid, String name) {
81 | String key = String.format(SESSION_METADATA_KEY, sessionid);
82 | return jedis.hget(key, name);
83 | }
84 |
85 | @Override
86 | public void storeSessionAttribute(String sessionid, String name, Object value) {
87 | String key = String.format(SESSION_ATTRIBUTE_KEY, sessionid);
88 | jedis.hset(key.getBytes(), name.getBytes(), SerializationUtils.serialize(value));
89 | }
90 |
91 | @Override
92 | public void removeSessionAttribute(String sessionid, String name) {
93 | String key = String.format(SESSION_ATTRIBUTE_KEY, sessionid);
94 | jedis.hdel(key.getBytes(), name.getBytes());
95 | }
96 |
97 | @Override
98 | public Object getSessionAttribute(String sessionid, String name) {
99 | String key = String.format(SESSION_ATTRIBUTE_KEY, sessionid);
100 | return SerializationUtils.deserialize(jedis.hget(key.getBytes(), name.getBytes()));
101 | }
102 |
103 | @Override
104 | public List getSessionAttributeNames(String sessionid) {
105 | String key = String.format(SESSION_ATTRIBUTE_KEY, sessionid);
106 | Map attributes = jedis.hgetAll(key.getBytes());
107 | if(!attributes.isEmpty()){
108 | Iterator iterator = attributes.keySet().iterator();
109 | List attributeNames = new ArrayList();
110 | while (iterator.hasNext()){
111 | attributeNames.add(new String(iterator.next()));
112 | }
113 |
114 | return attributeNames;
115 | }
116 |
117 | return Collections.emptyList();
118 | }
119 |
120 | @Override
121 | public Map getSessionAttributes(String sessionid) {
122 | String key = String.format(SESSION_ATTRIBUTE_KEY, sessionid);
123 | Map attributes = jedis.hgetAll(key.getBytes());
124 | if(!attributes.isEmpty()){
125 | Map result = new HashMap();
126 | for (Iterator> iterator = attributes.entrySet().iterator(); iterator.hasNext();){
127 | Map.Entry entry = iterator.next();
128 | result.put(new String(entry.getKey()), SerializationUtils.deserialize(entry.getValue()));
129 | }
130 | return result;
131 | }
132 | return Collections.EMPTY_MAP;
133 | }
134 | }
135 |
--------------------------------------------------------------------------------
/simple-distributed-sessions-manager/src/main/java/com/github/loafer/distributed/httpsession/manager/AbstractSessionManager.java:
--------------------------------------------------------------------------------
1 | package com.github.loafer.distributed.httpsession.manager;
2 |
3 | import com.github.loafer.distributed.httpsession.SessionIDManager;
4 | import com.github.loafer.distributed.httpsession.SessionManager;
5 | import com.github.loafer.distributed.httpsession.SessionStorage;
6 | import com.github.loafer.distributed.httpsession.manager.task.ClearInvalidSessionScheduledTask;
7 | import com.github.loafer.distributed.httpsession.metadata.SessionMetaData;
8 | import com.github.loafer.distributed.httpsession.session.DistributedHttpSession;
9 | import com.github.loafer.distributed.httpsession.session.StickyHttpSession;
10 | import com.github.loafer.distributed.httpsession.storage.RedisSessionStorage;
11 | import org.slf4j.Logger;
12 | import org.slf4j.LoggerFactory;
13 |
14 | import javax.servlet.ServletContext;
15 | import javax.servlet.http.HttpServlet;
16 | import javax.servlet.http.HttpServletRequest;
17 | import javax.servlet.http.HttpSession;
18 | import java.util.Map;
19 | import java.util.concurrent.ConcurrentHashMap;
20 | import java.util.concurrent.Executors;
21 | import java.util.concurrent.ScheduledExecutorService;
22 | import java.util.concurrent.TimeUnit;
23 |
24 | /**
25 | * @author zhaojh
26 | */
27 | public abstract class AbstractSessionManager implements SessionManager {
28 | private final Logger logger = LoggerFactory.getLogger(AbstractSessionManager.class);
29 |
30 | private int maxInactiveInterval;
31 | private ServletContext servletContext;
32 |
33 | private Map localSessionContainer = new ConcurrentHashMap();
34 | private SessionStorage sessionStorage;
35 | private SessionIDManager sessionIdManager;
36 | private ScheduledExecutorService scheduledExecutorService;
37 |
38 |
39 | public AbstractSessionManager(ServletContext servletContext, int maxInactiveInterval) {
40 | this.servletContext = servletContext;
41 | this.maxInactiveInterval = maxInactiveInterval;
42 | }
43 |
44 | protected abstract HttpSession newHttpSession(String id, int maxInactiveInterval, ServletContext servletContext);
45 | protected abstract HttpSession findHttpSession(String id);
46 |
47 | @Override
48 | public HttpSession newHttpSession(HttpServletRequest request) {
49 | String id = newSessionId(request);
50 | HttpSession session = newHttpSession(id, maxInactiveInterval, servletContext);
51 | addSessionToLocal(session);
52 | return session;
53 | }
54 |
55 | @Override
56 | public HttpSession getHttpSession(String id) {
57 | HttpSession session = findHttpSession(id);
58 | addSessionToLocal(session);
59 | return session;
60 | }
61 |
62 | @Override
63 | public void removeHttpSession(HttpSession session) {
64 | removeSessionFromStorage(session);
65 | removeSessionFromLocal(session);
66 | }
67 |
68 | @Override
69 | public boolean isValid(HttpSession session) {
70 | if(null == session) return false;
71 |
72 | return ((DistributedHttpSession)session).isValid();
73 | }
74 |
75 | @Override
76 | public void start() {
77 | logger.info("启动Session Manager.");
78 | sessionIdManager = new DefaultSessionIDManager();
79 | sessionIdManager.start();
80 |
81 | sessionStorage = new RedisSessionStorage();
82 | sessionStorage.start();
83 |
84 | scheduledExecutorService = Executors.newScheduledThreadPool(1);
85 | scheduledExecutorService.scheduleWithFixedDelay(
86 | new ClearInvalidSessionScheduledTask(localSessionContainer),
87 | 10, 10, TimeUnit.SECONDS);
88 | }
89 |
90 | @Override
91 | public void stop() {
92 | scheduledExecutorService.shutdown();
93 | sessionIdManager.stop();
94 | sessionStorage.stop();
95 | }
96 |
97 | @Override
98 | public SessionStorage getSessionStorage() {
99 | return sessionStorage;
100 | }
101 |
102 | protected ServletContext getServletContext(){
103 | return servletContext;
104 | }
105 |
106 | protected boolean isStaleSession(HttpSession session){
107 | Object lastAccessedTime = session.getLastAccessedTime();
108 | if(sessionStorage.isStored(session)){
109 | lastAccessedTime = sessionStorage.getSessionMetaDataField(session.getId(), SessionMetaData.LAST_ACCESSED_TIME_KEY);
110 | }
111 | return session.getLastAccessedTime() != Long.valueOf(String.valueOf(lastAccessedTime)).longValue();
112 | }
113 |
114 | protected SessionMetaData getSessionMetaDataFromStorage(String id){
115 | return sessionStorage.getSessionMetaData(id);
116 | }
117 |
118 | protected HttpSession findSessionFromLocal(String id){
119 | HttpSession session = localSessionContainer.get(id);
120 | if(null != session){
121 | logger.info("本地持有session[{}]的信息.", id);
122 | logger.debug("检查是否需要刷新session.");
123 | if(isStaleSession(session)){
124 | logger.debug("更新本地session内容与Session Storage中内容一致.");
125 | ((DistributedHttpSession)session).refresh();
126 | }else{
127 | logger.debug("无需刷新.");
128 | }
129 | }
130 | return session;
131 | }
132 |
133 | private String newSessionId(HttpServletRequest request){
134 | return sessionIdManager.newSessionId(request, System.currentTimeMillis());
135 | }
136 |
137 | private void addSessionToLocal(HttpSession session){
138 | if (null == session) return;
139 | localSessionContainer.put(session.getId(), session);
140 | }
141 |
142 | private void removeSessionFromLocal(HttpSession session){
143 | localSessionContainer.remove(session.getId());
144 | }
145 |
146 | private void removeSessionFromStorage(HttpSession session){
147 | sessionStorage.removeSession(session.getId());
148 | }
149 | }
150 |
--------------------------------------------------------------------------------