redisはサーバ間セッション共有を実現
一般的に、サーバクラスタを作成するときにnginx逆プロキシサーバを構成します.しかし、問題が発生しました.複数のサーバ間のセッションはどのように共有されていますか?
私がここで使っているのはredisで、構想を実現しています.
1.sessionId生成ポリシーを自分で定義し、session.setAttribute操作の際、CSESSIONIDを生成してサーバーに書き込みます.
2.filterブロッキング要求、拡張HttpServertRequest、エージェントsession実装クラス、拡張setAttributeメソッド、getAttributeメソッドを定義します.
3.クッキーのライフサイクルとredisのキーのライフサイクルの更新を要求するたびに、私がここで設定したのは30分です.
私のコードは優雅ではなく、拡張も行われていません.以下に私の実装を貼ります.
1.簡単なredis実現:
実際の開発ではspringとプールを統合して構成してください
2.CookieUtil
私がここで使っているのはredisで、構想を実現しています.
1.sessionId生成ポリシーを自分で定義し、session.setAttribute操作の際、CSESSIONIDを生成してサーバーに書き込みます.
2.filterブロッキング要求、拡張HttpServertRequest、エージェントsession実装クラス、拡張setAttributeメソッド、getAttributeメソッドを定義します.
3.クッキーのライフサイクルとredisのキーのライフサイクルの更新を要求するたびに、私がここで設定したのは30分です.
私のコードは優雅ではなく、拡張も行われていません.以下に私の実装を貼ります.
1.簡単なredis実現:
実際の開発ではspringとプールを統合して構成してください
import redis.clients.jedis.Jedis;
public class JedisProvider {
private static Jedis jedis;
public static Jedis getJedis() {
jedis = new Jedis("127.0.0.1", 6379);
return jedis;
}
// public static void main(String[] args) {
// Jedis jedis = getJedis();
// jedis.set("name", "tanlei");
// }
}
2.CookieUtil
</pre><p><pre name="code" class="java">import java.util.UUID;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class CookieUtil {
public static String cacheCSessionId = null;
public static Integer KEY_EXPIRE_TIME = 30 * 60;
/**
* JessionId
*
* @param request
* @return
*/
public static String getJsessionId(HttpServletRequest request) {
Cookie[] cookies = request.getCookies();
// 2: Cookie CSESSIONID
if (null != cookies && cookies.length > 0) {
for (Cookie cookie : cookies) {
if ("CSESSIONID".equals(cookie.getName())) {
//
return cookie.getValue();
}
}
}
return null;
}
<pre name="code" class="java">public static String addCookie(HttpServletRequest request, HttpServletResponse response, Integer KEY_EXPIRE_TIME) {
String csessionId = getJsessionId(request);
if(csessionId == null || "".equals(csessionId)) {
csessionId = UUID.randomUUID().toString().replaceAll("-", "");
}
Cookie cookie = new Cookie("CSESSIONID", csessionId);
cookie.setPath("/");
cookie.setMaxAge(KEY_EXPIRE_TIME);
response.addCookie(cookie);
return csessionId;
}
}
3.sessionfilter
import java.io.IOException; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; import java.util.HashMap; import java.util.Map; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequestWrapper; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import com.tanlei.bean.User; import com.tanlei.jedis.provider.CookieUtil; import com.tanlei.jedis.provider.JedisProvider; import redis.clients.jedis.Jedis; public class SessionFilter implements Filter{ private Jedis jedis = JedisProvider.getJedis(); @Override public void destroy() { }
@Override public void doFilter(ServletRequest req, ServletResponse rep, FilterChain chain) throws IOException, ServletException { // session , cookie redis String csessionId = CookieUtil.getJsessionId((HttpServletRequest) req); if(csessionId != null && !"".equals(csessionId)) { jedis.expire(csessionId, CookieUtil.KEY_EXPIRE_TIME); CookieUtil.addCookie((HttpServletRequest) req, (HttpServletResponse)rep, CookieUtil.KEY_EXPIRE_TIME); } // HttpSession session = ((HttpServletRequest)req).getSession(); // if(session != null) { // String jSessionId = CookieUtil.getJessionId((HttpServletRequest)req); // cookie , cookie 30 // jedis.expire(jSessionId, 60 * 30); // } chain.doFilter(new RemoteSessionRequest((HttpServletRequest) req, (HttpServletResponse)rep), rep); CookieUtil.cacheCSessionId= null; } @Override public void init(FilterConfig arg0) throws ServletException { } }
4.RemoteSessionRequestclass RemoteSessionRequest extends HttpServletRequestWrapper { private HttpServletRequest request; private HttpServletResponse response; public RemoteSessionRequest(HttpServletRequest request, HttpServletResponse response) { super(request); this.request = request; this.response = response; } @Override public HttpSession getSession() { return RemoteSessionHandler.getInstance(super.getSession(),request, response); } }
5.RemoteSessionHandlerclass RemoteSessionHandler implements InvocationHandler { private Jedis jedis = JedisProvider.getJedis(); private HttpSession session = null; private HttpServletRequest request = null; private HttpServletResponse response = null; private RemoteSessionHandler(HttpSession httpSession, HttpServletRequest request, HttpServletResponse response) { this.session = httpSession; this.request = request; this.response = response; }; public static HttpSession getInstance(HttpSession httpSession, HttpServletRequest request,HttpServletResponse response) { InvocationHandler handler = new RemoteSessionHandler(httpSession, request, response); return (HttpSession) Proxy.newProxyInstance(httpSession.getClass().getClassLoader(), httpSession.getClass().getInterfaces(), handler); }
@Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { if ("setAttribute".equals(method.getName())) { String csessionId = CookieUtil.getJsessionId(request); // cookie,csessionId if(csessionId == null || "".equals(csessionId)) { csessionId = CookieUtil.addCookie(request, response, CookieUtil.KEY_EXPIRE_TIME); CookieUtil.cacheCSessionId = csessionId; } <pre name="code" class="java"> } else if ("getAttribute".equals(method.getName())) { String csessionId = CookieUtil.getJsessionId(request); // cookie if(csessionId == null || "".equals(csessionId)) { // cacheCSessionId , if(CookieUtil.cacheCSessionId == null || "".equals(CookieUtil.cacheCSessionId)) { return null; } else { csessionId = CookieUtil.cacheCSessionId; } } // csessionid redis Set<String> userIds = jedis.hkeys(csessionId); String userId = null; for(String id : userIds) { userId = id; } User user = null; if(userIds.size() > 0) { String userName = jedis.hget(csessionId, userId); user = new User(Integer.parseInt(userId), userName); } // , CookieUtil.cacheCSessionId = null; return user; }
//キーがある場合は、設定する必要はなく、requestのブロッキングでセッションの有効期限if(jedis.exists(csessionId)){return null;を設定します.String userName = ((User)args[1]).getUserName();//csessionidをkeyとし、ユーザー名はfield、ユーザーidはvalueである.String userId = ((User)args[1]).getId().toString(); jedis.hset(csessionId, userId, userName); jedis.expire(csessionId, CookieUtil.KEY_EXPIRE_TIME); return null;} return method.invoke(session, args); } }
6.web.xml<filter> <filter-name>SessionFilter</filter-name> <filter-class> com.tanlei.filter.SessionFilter </filter-class> </filter> <filter-mapping> <filter-name>SessionFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <servlet> <servlet-name>sessionSetServlet</servlet-name> <servlet-class>com.tanlei.controller.SessionSetServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>sessionSetServlet</servlet-name> <url-pattern>/sessionSetServlet</url-pattern> </servlet-mapping>
<welcome-file-list> <welcome-file>index.jsp</welcome-file> </welcome-file-list>
7.controller(servlet)public class SessionSetServlet extends HttpServlet { private static final long serialVersionUID = 1L; protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { System.out.println("1111"); HttpSession session= request.getSession(); session.setAttribute("user", new User(2, "ergou")); System.out.println(request.getContextPath()); //response.sendRedirect(request.getContextPath() + "/index.jsp"); request.getRequestDispatcher("index.jsp").forward(request, response); } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } }
8.jarパッケージに依存する:
commons-logging-1.1.3.jar
jedis-2.7.2.jar
redisをテストするには、次のようにします.
redis 64-3.0.501(windowsベース)
9.Userエンティティ:public class User { private Integer id; private String userName; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getUserName() { return userName; } public User(Integer id, String userName) { super(); this.id = id; this.userName = userName; } public void setUserName(String userName) { this.userName = userName; } }