前言:本文章为慕课网上Java企业级电商项目架构演进之路Tomcat集群与Redis分布式的学习笔记.
目录
第一章 思路与配置概要
1.1 思路概要
用户的http请求通过nginx反向代理到tomcat集群上,tomcat根据用户发送来的cookie中的id(自己设置的)去redis数据库中进行查找,如果找到即等于用户登陆了.
1.2 配置概要
windows服务器放nginx1.14.2
两台centos7.3服务器,一台放一个tomcat应用,另一台放一个tomcat应用+一个redis.
第二章 springboot连接操作redis数据库
2.1 引入redis的包
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>3.0.0</version>
</dependency>
2.2 对redis进行配置
在application.properties中对填写如下.
#redis
redis.maxtotal = 20
redis.maxIdle = 10
redis.minIdle = 2
redis.testOnReturn = true
redis.testOnBorrow = true
redis.redisPort = 6379
redis.redisIp = 202.112.88.1
2.3 获得redis连接池
将刚才在application.properties中的配置注入类中.
@Component
@ConfigurationProperties(prefix = "redis")
@Slf4j
@Getter
@Setter
public class RedisPool {
private JedisPool pool;//jedis连接池
private Integer maxtotal; //最大连接数
private Integer maxIdle ; //在jedispool中最大的idle(空闲的)状态的jedis实例的个数
private Integer minIdle ; //在jedispool中最小的idle(空闲的)状态的jedis实例的个数
private Boolean testOnBorrow ;
private Boolean testOnReturn ;
private Integer redisPort ;
private String redisIp;
public RedisPool(){
log.info("构造方法开始执行");
}
@PostConstruct
public void initPool(){
if(maxtotal==20) log.info("属性已经注入");
log.info("开始创建连接池");
JedisPoolConfig config = new JedisPoolConfig();
config.setMaxTotal(maxtotal);
config.setMaxIdle(maxIdle);
config.setMinIdle(minIdle);
config.setTestOnBorrow(testOnBorrow);
config.setTestOnReturn(testOnReturn);
config.setBlockWhenExhausted(true);
pool = new JedisPool(config,redisIp,redisPort,1000*2);
}
public Jedis getJedis(){
return pool.getResource();
}
}
2.4 操作redis数据库
通过连接池获得jedis对象,然后就可以操作redis数据库了.
@Component
@Slf4j
public class RedisPoolUtil {
//注入刚才的redis连接池
@Autowired
RedisPool redisPool;
//获取redis数据库中key的值
public String get(String key){
Jedis jedis = null;
String result = null;
try {
jedis = redisPool.getJedis();
result = jedis.get(key);
} catch (Exception e) {
log.error("get key:{} error",key,e);
}
jedis.close();
return result;
}
//增加redis数据库中的值
public String set(String key,String value){
Jedis jedis = null;
String result = null;
try {
jedis = redisPool.getJedis();
result = jedis.set(key,value);
} catch (Exception e) {
log.error("set key:{} error",key,e);
}
jedis.close();
return result;
}
//增加redis数据库中的值并设置时间 30*60就是30分钟
public String setEx(String key,String value,int exTime){
Jedis jedis = null;
String result = null;
try {
jedis = redisPool.getJedis();
result = jedis.setex(key,exTime,value);
} catch (Exception e) {
log.error("setex key:{} value:{} error",key,value,e);
}
jedis.close();
return result;
}
//设置redis数据库中hey的时间
public Long expire(String key,int exTime){
Jedis jedis = null;
Long result = null;
try {
jedis = redisPool.getJedis();
result = jedis.expire(key,exTime);
} catch (Exception e) {
log.error("expire key:{} error",key,e);
}
jedis.close();
return result;
}
//删除redis数据库中的key
public Long del(String key){
Jedis jedis = null;
Long result = null;
try {
jedis = redisPool.getJedis();
result = jedis.del(key);
} catch (Exception e) {
log.error("del key:{} error",key,e);
}
jedis.close();
return result;
}
//判断redis数据库中是否存在某个key
public Boolean exists(String key){
Jedis jedis = null;
Boolean result = null;
try {
jedis = redisPool.getJedis();
result = jedis.exists(key);
} catch (Exception e) {
log.error("exists key:{} error",key,e);
}
jedis.close();
return result;
}
}
第三章 应用配置与nginx服务器与redis服务器的配置
打开centos服务器的的8079端口与6379端口
3.1 应用配置
运行mvn clean package,将jar放到两台centos7.3服务器上并用java -jar运行应用.
#Server
server.servlet.context-path=/tarcluster
server.port=8079
3.2 nginx服务器的配置
将端口80的请求反向代理到两个tomcat服务器上.
upstream zhang {
server 202.112.99.1:8079;
server 202.112.99.2:8079;
}
server {
listen 80;
server_name zhangsan;
location / {
proxy_pass http://zhang;
proxy_read_timeout 150;
add_header Access-Control-Allow-Origin *;
}
}
3.3 redis服务器的配置
在后台启动redis服务器,并关闭安全模式即可.
关闭安全模式:
1.我们需要修改配置文件../redis.conf
# bind 127.0.0.1
2.在redis.conf中设置保护模式为no
protected-mode no
启动redis服务器: ./redis-server ../redis.conf
第四章 模拟登陆展示session的存储
4.1 CookieUtil类的设置
@Slf4j
public class CookieUtil {
private final static String COOKIE_DOMAIN = "";
public static final String COOKIE_NAME = "mmall_login_token";
//将cookie写入response
public static void writeLoginToken(HttpServletResponse response,String token){
Cookie ck = new Cookie(COOKIE_NAME,token);
ck.setMaxAge(60*60*24);
ck.setPath("/");
ck.setHttpOnly(true);
log.info("已设置cookie:{},value:{}",ck.getName(),ck.getValue());
response.addCookie(ck);
}
//将cookie从request中读出
public static String readLoginToken(HttpServletRequest request){
Cookie[] cookies = request.getCookies();
if(cookies!=null){
for (Cookie ck :cookies) {
if(StringUtils.equals(ck.getName(),COOKIE_NAME)){
log.info("已读取到cookie:{},value:{}",ck.getName(),ck.getValue());
return ck.getValue();
}
}
}
return null;
}
//删除cookie
public static void delLoginToken(HttpServletRequest request,HttpServletResponse response){
Cookie[] cookies = request.getCookies();
if(cookies!=null){
for (Cookie ck:cookies
) {
if(StringUtils.equals(ck.getName(),COOKIE_NAME)){
ck.setMaxAge(0);
ck.setPath("/");
response.addCookie(ck);
}
}
}
}
}
4.2 Controller登陆模拟
@RequestMapping("/login")
public String login(String username, Model model, HttpSession session, HttpServletResponse response, HttpServletRequest request){
String key = CookieUtil.readLoginToken(request);
model.addAttribute("sessionid",session.getId());
//key为null证明request中不存在我们设置的cookieName
//cookie中存在我们设置的cookieName,但是reids库中不找不到对应的记录
//key既不为null,在redis中也能根据key查找到值,表示用户已不用登陆.
if(key!=null&&redisPoolUtil.exists(key)){
redisPoolUtil.expire(key,30*60);
log.info("检测到key,直接登陆");
model.addAttribute("keyValue",redisPoolUtil.get(key));
}else{
log.info("请求登陆");
User user = new User();
user.setAddress("shijiazhuang");
user.setName("张晨");
user.setAge(24);
user.setSchool("bnu");
//模拟登陆成功找到user,将user序列化成字符串,以当次请求的sessionid为
//key,将其存储到redis数据库中,再将sessionid为value,mmall_login_token为
//key存储到cookie中返回.以后用户每次请求从cookie中根据mmall_login_token
//读取出sessionid,再根据sessionid拿到序列化后的字符串.
//obj2String是将对象序列化为字符串
log.info("登陆成功");
redisPoolUtil.setEx(session.getId(),JsonUtil.obj2String(user),30*60);
CookieUtil.writeLoginToken(response,session.getId());
}
return "index";
}