Windows上两个tomcat, 虚拟机中ip为192.168.0.30的centos上一个(测试用三台就够了, 为了测试看见端口所以没有使用nginx转发请求)

开始

1.windows上开启两个tomcat端口分别为:8888和9999

2.使用ssh文件传输工具将项目放到centos的tomcat中

3.使用putty链接上centos后进入tomcat的bin目录执行./startup.sh后使用wget http://192.168.0.30测试是否启动成功如下图 1-1

1-1

4.使用浏览器访问项目登(输入用户名密码登录, 涉及到cookie跨域) 图 1-2

1-2

登录成功 图1-3

1-3

切换到9999端口的项目, 如果直接跳转到和上图1-3一样的页面取的是memcache的缓存如下图1-4

1-4

再试另外一个8888端口的tomcat(这个项目被放到ROOT目录了所以我直接127.0.0.1:8888)也是成功的图1-5

1-5

8888端口的tomcat对应的控制台

关闭9999端口的tomcat然后重启过滤器中拦截到了该请求在Memcache中存在共享的user实例直接跳转到首页

如果拦截到了请求然后发现Memcache中存在user实例那么久转发到对应的页面比如我访问8888的时候点击了'日拒转单'页面然后我再去访问9999的时候发现memcache中有user实例那么久根据拦截到的路径转到'日拒转单' 页面而不会转发到其它页面; 如下图a和b

a

b

最后退出后不同的端口时都应该看到都是登录页面(因为退出时memcache中的user被删除, 过滤器中在接到请求后发现memcache中对应请求的user实例没有了直接跳到登录页)

登录代码:

package yingyue.web.controller;

import java.io.IOException;
import java.util.Date;
import java.util.HashMap;
import java.util.Map; import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import yingyue.utils.MemCacheUtil;
import yingyue.web.form.User;
/**
*
* @author YingYue
* @date 2016-1-1 下午4:13:09
* @file LoginController.java
*
* 步骤:
* 1.获取浏览器的自定义的cookie
* 1.1如果该cookie不存在这add
* 1.2存在则set更新; set等效于(add和replace)即: 存在则replace不存在则add, 这一步思考一直使用replace的, 我还比较钟情set的;
*
* cookie的四个属性
* max-age 指定Ccookie的生存周期(以秒为单位)!默认情况下,Cookie的值只在浏览器的会话期间存在,当用户退出浏览器这些值就消失了!
* path 指定与Cookie关联在一起的网页.默认情况下,cookie会和创建它的网页以及与这个网页处于同一个目录下的网页和处于该目录下的子目录关联。
* domain 设置访问域 举个例子:位于order.example.com的服务器要读取catalog.example.com设置的cookie.这里就要引入domain属性,假定由位于catalog.example.com的页面创 的cookie把自己的path属性设置为"/",把domain属性设置为".example.com",那么所有位于"catalog.example.com"的网页和所有位于"orders.example.com"的网页以及所有位于example.com域的其他服务器上得网页都能够访问这个cookie.如果没有设置cookie的domain值,该属性的默认值就是创建cookie的网页所在的 服务器的主机名。 注意:不能将一个cookie的域设置成服务器所在的域之外的域.
* seure 指定在网络上如何传输cookie的值
* secure值为true时,在http中是无效的;在https中才有效。
*/
@WebServlet(urlPatterns={"/login/LoginController.yingyue", "/login/LoginServlet"})
public class LoginController extends HttpServlet {
private static final long serialVersionUID = -8517127272218599956L; public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doPost(request, response);
} public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
request.setCharacterEncoding("UTF-8"); /* 模拟数据库用户;*/
Map<String, String> items = new HashMap<String, String>();
items.put("zhoujianxu", "000000");
items.put("盈月", "000000");
items.put("test", "123456");
items.put("admin", "123456");
items.put("yingyue", "123456");
items.put("zuobiexitianyuncai", "000000"); /* 验证登录;*/
String userName = request.getParameter("userName"),
password = request.getParameter("password"); /* 验证开始*/
if (userName != null && !"".equals(userName)) {
if (password == null || "".equals(password)) {
request.setAttribute("tips", "密码不能为空!");
} else {
// 验证用户名密码是否正确;
if (items.containsKey(userName) && password.equalsIgnoreCase(items.get(userName))) {
/** 写入Memcache缓存;*/
User user = new User(userName, password, "15001027805", userName.concat("@163.com")); /**
* 如果不同用户使用同一个浏览器登录成功后都要为该用户重新 '创建' 一个key相同value值不同的cookie是多么的不合理啊,
* 解决办法:
* 当key不存在时则创建一个带有该key的cookie
* 当key存在时则更新key对应的value
*
* 如下:
*/
// 1.设置 key 为 'MEMCACHE_AND_BROWSER_KEY' value值为 '登录用户名+部门名称'的cookie 并Response到请求的客户端浏览器 '响应响应头信息'
String memcacheAndBrowserKey = "MEMCACHE_AND_BROWSER_KEY";
String memcacheAndBrowserForeignKey = userName.concat("IT");
Cookie[] cookies = request.getCookies();
if (cookies.length > 0 && cookies != null) {
for (Cookie cookie : cookies) {
boolean b = isContainsKeyCookies(memcacheAndBrowserKey, cookies);
if (!b) { Cookie newCookie = new Cookie(memcacheAndBrowserKey, memcacheAndBrowserForeignKey);
newCookie.setMaxAge(7 * 24 * 60 * 60);
newCookie.setPath("/");
response.addCookie(newCookie);
System.out.println("[登录时key名为MEMCACHE_AND_BROWSER_KEY的cookie不存在执行添加操作]\r\n 详情--> key名称为 " +
cookie.getName() + "的value值为 " + cookie.getValue() +
"的cookie已经响应到浏览器 '响应头信息' 中请看Set-Cookie");
break; } else {// 更新cookie的key对应的value; if (memcacheAndBrowserKey.equals(cookie.getName())) {
cookie.setValue(memcacheAndBrowserForeignKey);// 设置新的memcacheAndBrowserForeignKey
cookie.setPath("/");
cookie.setMaxAge(7 * 24 * 60 * 60);// 设置为1周
response.addCookie(cookie);// 更新key为'MEMCACHE_AND_BROWSER_KEY'的cookie的value值;
System.out.println("[登录时key名为MEMCACHE_AND_BROWSER_KEY的cookie存在执行更新操作]\r\n 详情--> key名称为 " +
cookie.getName() + "的value值为 " + cookie.getValue() +
"的cookie已经响应到浏览器 '响应头信息' 中请看Set-Cookie");
break;
} }
} // 2.将 'MEMCACHE_AND_BROWSER_KEY' 的value
Date expiry = new Date(7 * 24 * 60 * 60 * 1000);// 设置存到memcache中数据的失效时间, 这里设置为1周与cookie失效时间保持相同;
boolean b = MemCacheUtil.getInstance().set(memcacheAndBrowserForeignKey, user, expiry);
if (b) {
System.out.println("登录成功");
} } else {
System.out.println("cookie为空!");
}
request.setAttribute("user", user);
request.getRequestDispatcher("/WEB-INF/index.jsp").forward(request, response);
return;
} else {
if (!items.containsKey(userName)) {
request.setAttribute("tips", "用户不存在!");
} else {
request.setAttribute("tips", "用户名或密码错误!");
}
}
}
} else {
request.setAttribute("tips", "用户名不能为空!");
}
request.getRequestDispatcher("/index.jsp").forward(request, response);
} private boolean isContainsKeyCookies(String key, Cookie[] cookies) {
boolean b = false;
for (Cookie cookie : cookies) {
if (key.equals(cookie.getName())) {
b = true;
break;
}
}
return b;
} }

过滤器代码:

package yingyue.web.controller;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List; import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import yingyue.utils.MemCacheUtil;
import yingyue.web.form.User; /*
* @WebFilter(filterName = "AuthenticateFilter",
* urlPatterns = {"/login/LoginController", "/login/LoginServlet"})
* 或使用下面这种过滤我自定义的 '.yingyue' 的后缀
*/
@WebFilter(filterName="AuthenticateFilter", urlPatterns={"*.yingyue", "*.love", "*.^o^", "/index.jsp"})
public class AuthenticateFilter implements Filter { private FilterConfig config;
private List<String> releases = new ArrayList<String>(); @Override
public void init(FilterConfig filterConfig) throws ServletException {
this.config = filterConfig;
releases.add("/login/LoginController.yingyue");
} @Override
public void doFilter(ServletRequest req, ServletResponse res,
FilterChain chain) throws IOException, ServletException { // 获取ServletContext 对象,用于记录日志
ServletContext context = this.config.getServletContext(); HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;
request.setCharacterEncoding("UTF-8"); String path = request.getServletPath();
String methodValue = request.getParameter("method"); if(releases.contains(path)){
chain.doFilter(request, response);
return;
}
if (methodValue != null && !"".equals(methodValue)) {
path = path + "?method=" + request.getParameter("method");
}
System.out.println("已拦截到请求: ".concat(path)); /* 1.从请求中获取和Memcache关联的key*/
String memcacheAndBrowserForeignKey = "";
String memcacheAndBrowserKey = "MEMCACHE_AND_BROWSER_KEY";
Cookie[] cookies = request.getCookies();
if (cookies != null && cookies.length > 0) {
for (Cookie cookie : cookies) {
if (memcacheAndBrowserKey.equals(cookie.getName())) {
memcacheAndBrowserForeignKey = cookie.getValue();
break;
}
}
} else {
context.log("cookie为空!");
} // 2.根据上述获取的key获取Memcache中的user对象
User loginUser = null;
if (memcacheAndBrowserForeignKey != null && !"".equals(memcacheAndBrowserForeignKey)) {
loginUser = (User) MemCacheUtil.getInstance().get(memcacheAndBrowserForeignKey);
}
if(loginUser != null){
request.setAttribute("user", loginUser);// 每次过滤后都将user对象放到request中, 以便每个页面取值;
if ("/index.jsp".equals(path)) {
System.out.println("直接跳转到首页");
request.getRequestDispatcher("/WEB-INF/index.jsp").forward(request, response);
}
chain.doFilter(request, response);
System.out.println("Memcache中存在该user用户放行该请求链接: " + path);
return;
} System.out.println("登录用户为空跳转到登录页");
request.getRequestDispatcher("/index.jsp").forward(request, response);
} @Override
public void destroy() {
this.config = null;
}
}

退出代码:

package yingyue.web.controller;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import yingyue.utils.MemCacheUtil;
import yingyue.web.form.User;
/**
* @author YingYue
* @date 2016-1-1 下午10:42:05
* @file LogoutController.java
*/
@WebServlet(urlPatterns={"/logout/LogoutController.yingyue", "/logout/LogoutServlet"})
public class LogoutController extends HttpServlet {
private static final long serialVersionUID = 7799109727234048708L; public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doPost(request, response);
} public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
request.setCharacterEncoding("UTF-8"); /* 1.从请求中获取和Memcache关联的key, 退出清空客户端的key, 强制退出则根据key清空memcache的user实例*/
String memcacheAndBrowserForeignKey = "";
String memcacheAndBrowserKey = "MEMCACHE_AND_BROWSER_KEY";
Cookie[] cookies = request.getCookies();
if (cookies.length > 0 && cookies != null) {
for (Cookie cookie : cookies) {
if (memcacheAndBrowserKey.equals(cookie.getName())) {
memcacheAndBrowserForeignKey = cookie.getValue();
cookie.setMaxAge(0);// 设置为0表示删除cookie
System.out.println("[退出时删除key名为MEMCACHE_AND_BROWSER_KEY的cookie]\r\n 详情--> key名称为 " +
memcacheAndBrowserKey + "value值为 " + memcacheAndBrowserForeignKey +
"的cookie已经从浏览器 '响应头信息' 中删除请看Set-Cookie");
break;
}
}
} else {
System.out.println("退出请求cookie为空!");
} // 根据上述获取的key获取Memcache中的user对象
User loginUser = (User) MemCacheUtil.getInstance().get(memcacheAndBrowserForeignKey);
System.out.println(loginUser != null?"退出前登录用户信息" + loginUser:"");
boolean delete = MemCacheUtil.getInstance().delete(memcacheAndBrowserForeignKey);
if (delete) {
System.out.println("[退出]Memcache中key为 " + memcacheAndBrowserForeignKey + " 的 'user实例' 已被删除");
System.out.println(loginUser != null?"退出后登录用户信息" + (User) MemCacheUtil.
getInstance().get(memcacheAndBrowserForeignKey):"");
} response.sendRedirect(request.getContextPath());
}
}

其它相关跳转(servlet就是讨厌)

package yingyue.web.controller;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; @WebServlet(urlPatterns={"/skip/SkipController.yingyue", "/skip/SkipController.action", "/skip/SkipServlet"})
public class SkipController extends HttpServlet { private static final long serialVersionUID = 9078198285369158430L; public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException { doPost(request, response);
} public synchronized void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException { request.setCharacterEncoding("UTF-8");
String method = request.getParameter("method"); if ("1".equalsIgnoreCase(method)) {
request.getRequestDispatcher("/WEB-INF/pages/1.jsp").forward(request, response);
} else if ("2".equalsIgnoreCase(method)) {
request.getRequestDispatcher("/WEB-INF/pages/2.jsp").forward(request, response);
} else if ("3".equalsIgnoreCase(method)) {
request.getRequestDispatcher("/WEB-INF/pages/3.jsp").forward(request, response);
} else if ("4".equalsIgnoreCase(method)) {
request.getRequestDispatcher("/WEB-INF/pages/4.jsp").forward(request, response);
} else if ("imageslist".equalsIgnoreCase(method)) {
request.getRequestDispatcher("/WEB-INF/pages/images_list.jsp").forward(request, response);
} } }

还有一种通过jar包和配置tomcat的context.xml方式实现自动共享session, 类似于Redis 那种自动配置;

最后配上nginx 就完美了~^o^~

Memcache+Tomcat9集群实现session共享(非jar式配置, 手动编写Memcache客户端)的更多相关文章

  1. Redis+Tomcat+Nginx集群实现Session共享,Tomcat Session共享

    Redis+Tomcat+Nginx集群实现Session共享,Tomcat Session共享 ============================= 蕃薯耀 2017年11月27日 http: ...

  2. 集群中Session共享解决方案分析

    一.为什么要Session共享 Session存储在服务器的内存中,比如Java中,Session存放在JVM的中,Session也可以持久化到file,MySQL,redis等,SessionID存 ...

  3. 集群间Session共享问题解决方案

    两个基本概念的生命周期 session: 当新客户端发现一个HTTP请求时服务端会创建一个session.并分配一个sessionID作为服务端来客户端的识别,session对象会保存在服务端.此时s ...

  4. Tomcat集群的session共享

    配置Tomcat的session共享可以有三种解决方案: 第一种是以负载均衡服务器本身提供的session共享策略,每种服务器的配置是不一样的并且nginx本身是没有的. 第二种是利用web容器本身的 ...

  5. CAS 集群部署session共享配置

    背景 前段时间,项目计划搞独立的登录鉴权中心,由于单独开发一套稳定的登录.鉴权代码,工作量大,最终的方案是对开源鉴权中心CAS(Central Authentication Service)作适配修改 ...

  6. 关于 tomcat 集群中 session 共享的三种方法

    前两种均需要使用 memcached 或redis 存储 session ,最后一种使用 terracotta 服务器共享. 建议使用 redis,不仅仅因为它可以将缓存的内容持久化,还因为它支持的单 ...

  7. Java集群之session共享解决方案

    随着互联网的日益壮大,网站的pv和uv成线性或者指数倍的增加.单服务器单数据库早已经不能满足实际需求.比如像盛大,淘宝这样的大型网络公司,更是如此.     集群,也就是让一组计算机服务器协同工作,达 ...

  8. tomcat集群及session共享

    一般来说,java web app主要用作两个领域: 1.api.api一般是无状态的,所以无需考虑session共享的问题 2.传统web应用和网站,如crm,oa,erp,b2c,bbs等.尤其b ...

  9. 基于tomcat集群做session共享

    前端代理服务器nginx:192.168.223.136 tomcat服务器:采用的一台多实例192.168.223.146:8081,192.168.223.146:8082(如何构建多实例tomc ...

随机推荐

  1. Asp.net绑定带层次下拉框(select控件)

    1.效果图 2.数据库中表数据结构 3.前台页面 <select id="pid" runat="server" style="width:16 ...

  2. 北大ACM(POJ1006-Biorhythms)

    Question:http://poj.org/problem?id=1006 问题点:孙子定理 Memory: 248K Time: 0MS Language: C++ Result: Accept ...

  3. Hadoop集群错误

    1.Hadoop集群所有的DataNode都启动不了解决办法 删除从节点.../usr/hadoop/tmp/dfs/ 下内容,再重新格式化namenode

  4. PHP 布尔类型

    PHP 布尔类型 布尔类型 这是最简单的类型.boolean 表达了真值,可以为 TRUE 或 FALSE. Note: 布尔类型是 PHP 4 引进的. 语法 要指定一个布尔值,使用关键字 TRUE ...

  5. android网络编程

    android的网络编程分为2种:基于socket的,和基于http协议的. 基于socket的用法 服务器端: 先启动一个服务器端的socket     ServerSocket svr = new ...

  6. 使用JDBC向数据库中插入一条数据

    原谅我是初学者,这个方法写的很烂,以后不会改进,谢谢 /** * 通过JDBC向数据库中插入一条数据 1.Statement 用于执行SQL语句的对象 1.1 通过Connection 的 * cre ...

  7. 如何解决win7系统访问共享服务器慢的问题

    最近重新装了win7系统,但发现当访问共享服务器的时候很慢,后来在网上搜索了相关解决办法,在此和大家分享下: 1. 通过“windows键”+“R键”快捷打开“运行”窗口,然后输入cmd命令敲回车,进 ...

  8. ARM公布“物联网”嵌入式mbed OS系统软件平台

    继ARM公司发布了为嵌入式微控制器设计的Cortex-M7架构处理器,ARM又公布了专为廉价低功耗“物联网”设计的新版软件及系统平台,以加速物联网设备的发展及部署.该软件为基于ARM现有Cortex- ...

  9. jQuery Mobile 开发中常见的问题

    目录 页面缩放显示问题 页面跳转后样式丢失js失效 跳转时重复调用pageinit方法的解决办法 如何调用loading效果   1页面缩放显示问题 问题描述: 页面似乎被缩小了,屏幕太宽了. 解决办 ...

  10. Bundle、Intent、SharedPreferences

    Intent与Bundle的共同点:都继承Parcelable Intent传值与Bundle传值的区别 eg:我现在要从A界面   跳转到B界面或者C界面   这样的话 我就需要写2个Intent  ...