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. Android渠道汇总

    序号 渠道名  渠道说明 特殊渠道   1 googleplay  google市场 2 umeng  自动更新 3 office_web  官方网络 4 office_qrcode 官方二维码 硬件 ...

  2. C#读取shp的属性信息

    一个完整的ESRI的shape文件包括一个主文件,一个索引文件,和一个dBASE表文件.主文件是一个直接存取,变记录长度文件,其中每个记录描述一 个由其顶点列表组成的shape.在索引文件中,每条记录 ...

  3. js 数组的length(javascript教程四)

    这是一个简单的函数,就是利用length来判断数组再遍历数组了. <script language="javascript" type="text/javascri ...

  4. Dicom格式文件解析器

    转自:http://www.cnblogs.com/assassinx/archive/2013/01/09/dicomViewer.html Dicom全称是医学数字图像与通讯,这里讲的暂不涉及通讯 ...

  5. 如何让R代码按计划执行

    应用场景:你编写了R代码,每天对提交的数据进行分析,你希望它你吃饭的时候执行完毕,生成图表. 那么你需要安装taskscheduleR的包. 怎么操作,看帮助呗.

  6. ThinkPHP中的模型

    ThinkPHP中的模型 1.什么是模型(Model) 模型表示企业数据和业务规则,实际项目开发中,主要实现与数据库进行操作. 2.模型的定义规则 模型类的命名规则是除去表前缀的数据表名称,采用驼峰法 ...

  7. AD查询1000条限制和解决方案

      公司的一个项目要从AD上取数据,为了测试性能,批量在AD上创建了2000多个用户.但是用java程序获取所有用户的时候会报错或者只能取到1000条数据.   条数据. 用org.springfra ...

  8. 阿里云服务器 ECS Ubuntu系统安装配置

    1. 登陆服务器 系统开通成功后手机会收到阿里云发来的短信,包含公网IP及root登录密码. WEB管理后台方式 可通过阿里云管理后台选择“连接管理终端…”进行登录 提示输入VNC密码 登录成功后显示 ...

  9. 2015.1写留言板的时用的 知识点和函数 --->总结

    一:时间函数和uniqid() 1:uniqid():生成唯一的id, 无参数返回的字符串的长度为13,有参数为23 2:时间和时间戳相互转换的php函数 ①:time()  返回当前unix的时间戳 ...

  10. iOS相机操作笔记

    最近忙于项目,需要拍摄图片,这里先列出部分测试代码. // // FirstViewController.m // UiTest // // Created by Tang Huaming on 16 ...