多台tomcat 集群的时候 要么ip访问固定指向服务器 要么就只能共享session了
集群
upstream web_tomcats {
ip_hash;// ip访问固定指向服务器
ip_hash;// ip访问固定指向服务器
server 127.0.0.1:7201 weight=10;
server 127.0.0.1:7202 weight=10;
}
这里 讲共享session
我们用redis 启动server ./src/redis-server redis.conf
redis.conf设置下密码 别让谁都能来玩
找到# requirepass 去掉#号 requirepass 后面设置密码
可以启动cli 测试一下
./src/redis-cli 不输入密码
./src/redis-cli -a mima 和输入密码
测试语句 set chen haha
然后spring 配置
<!--jedis pool配置 -->
<bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig">
<property name="maxActive" value="10" />
<property name="maxIdle" value="5" />
<property name="maxWait" value="10" />
<property name="testOnBorrow" value="true" />
</bean>
<!-- jedis pool配置 -->
<bean id="jedisPool" class="redis.clients.jedis.JedisPool">
<constructor-arg index="0" ref="jedisPoolConfig" />
<constructor-arg index="1" value="${Jedis.url}" /> 这个就是ip地址 不要输入http://什么的
<constructor-arg index="2" value="6379" /> 这个是端口号
<constructor-arg index="3" value="3000" /> 这个我也不知道
<constructor-arg index="4" value="${Jedis.pwd}" />
</bean>
pom.xml配置 导个包
然后写个redis的 service封装一些方法 这里的封装来源宋哥 哈哈
pom.xml配置 导个包
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>2.0.0</version>
<type>jar</type>
<scope>compile</scope>
</dependency>
import java.util.List;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.exceptions.JedisConnectionException;
import redis.clients.jedis.exceptions.JedisException;
/**
* Redis封装模板及通用方法;
* /usr/local/bin/redis-server /etc/redis/6380.conf
* @author wei
*
*/
@Service
public class RedisCacheService {
Logger logger = Logger.getLogger(RedisCacheService.class);
/**
* 数据源
*/
@Autowired private JedisPool jedisPool;
/**
* 获取自增id,正整数long 用于jpushsendNo.
* 改用redis自身DB支持,不访问数据库
*
* @param name 业务id, 目前可以使用"jpush","chat_room"
* @return long
*/
public synchronized long getUniqNoSequency(String name){
return incr(name + "sequency");
}
/**
* 用户未读信息计数(消息、分享。。一切推送的消息)
* @param userId
* @param reset 清零标记, ture-归零; 默认false
* @return 0--n
*/
public long getMessageCounter(long userId,boolean reset){
String key= "unreadMessage-"+userId;
//获取缓存里面的数据
if(reset){
del(key);
return 0;
}else {
Long incr = incr(key);
return incr==null ? 0 : incr;
}
}
/****************** 下面开始是模板方法! 上面定义公共函数 ***************************************************/
/**
* 执行有返回结果的action。
*/
protected <T> T execute(JedisAction<T> jedisAction) throws JedisException {
Jedis jedis = null;
boolean broken = false;
try {
jedis = jedisPool.getResource();
return jedisAction.action(jedis);
} catch (JedisConnectionException e) {
logger.error("Redis connection lost.", e);
broken = true;
throw e;
} finally {
closeResource(jedis, broken);
}
}
/**
* 执行无返回结果的action。
*/
protected void execute(JedisActionNoResult jedisAction) throws JedisException {
Jedis jedis = null;
boolean broken = false;
try {
jedis = jedisPool.getResource();
jedisAction.action(jedis);
} catch (JedisConnectionException e) {
logger.error("Redis connection lost.", e);
broken = true;
throw e;
} finally {
closeResource(jedis, broken);
}
}
/**
* 根据连接是否已中断的标志,分别调用returnBrokenResource或returnResource。
*/
protected void closeResource(Jedis jedis, boolean connectionBroken) {
if (jedis != null) {
try {
if (connectionBroken) {
jedisPool.returnBrokenResource(jedis);
} else {
jedisPool.returnResource(jedis);
}
} catch (Exception e) {
logger.error("Error happen when return jedis to pool, try to close it directly.", e);
closeJedis(jedis);
}
}
}
/**
* 获取内部的pool做进一步的动作。
*/
public JedisPool getJedisPool() {
return jedisPool;
}
/**
* 有返回结果的回调接口定义。
*/
public interface JedisAction<T> {
T action(Jedis jedis);
}
/**
* 无返回结果的回调接口定义。
*/
public interface JedisActionNoResult {
void action(Jedis jedis);
}
// // 常用方法的封装 / //
// // 公共 ///
/**
* 删除key, 如果key存在返回true, 否则返回false。
*/
public boolean del(final String key) {
return execute(new JedisAction<Boolean>() {
@Override
public Boolean action(Jedis jedis) {
return jedis.del(key) == 1 ? true : false;
}
});
}
public void flushDB() {
execute(new JedisActionNoResult() {
@Override
public void action(Jedis jedis) {
jedis.flushDB();
}
});
}
// // 关于String ///
/**
* 如果key不存在, 返回null.
*/
public String get(final String key) {
return execute(new JedisAction<String>() {
@Override
public String action(Jedis jedis) {
return jedis.get(key);
}
});
}
/**
* 如果key不存在, 返回0.
*/
public Long getAsLong(final String key) {
String result = get(key);
return result != null ? Long.valueOf(result) : 0;
}
/**
* 如果key不存在, 返回0.
*/
public Integer getAsInt(final String key) {
String result = get(key);
return result != null ? Integer.valueOf(result) : 0;
}
public void set(final String key, final String value) {
execute(new JedisActionNoResult() {
@Override
public void action(Jedis jedis) {
jedis.set(key, value);
}
});
}
public void setex(final String key, final int seconds, final String value) {
execute(new JedisActionNoResult() {
@Override
public void action(Jedis jedis) {
jedis.setex(key, seconds, value);
}
});
}
/**
* 如果key还不存在则进行设置,返回true,否则返回false.
*/
public boolean setnx(final String key, final String value) {
return execute(new JedisAction<Boolean>() {
@Override
public Boolean action(Jedis jedis) {
return jedis.setnx(key, value) == 1 ? true : false;
}
});
}
public Long incr(final String key) {
return execute(new JedisAction<Long>() {
@Override
public Long action(Jedis jedis) {
return jedis.incr(key);
}
});
}
public Long decr(final String key) {
return execute(new JedisAction<Long>() {
@Override
public Long action(Jedis jedis) {
return jedis.decr(key);
}
});
}
// // 关于List ///
public void lpush(final String key, final String value) {
execute(new JedisActionNoResult() {
@Override
public void action(Jedis jedis) {
jedis.lpush(key, value);
}
});
}
/**
* Return the length of the list stored at the specified key. If the key
* does not exist zero is returned (the same behaviour as for empty lists).
* If the value stored at key is not a list an error is returned.
*/
public long llen(final String key) {
return execute(new JedisAction<Long>() {
@Override
public Long action(Jedis jedis) {
return jedis.llen(key);
}
});
}
/**
* 删除List中的第一个等于value的元素,value不存在或key不存在时返回0.
*/
public boolean lremOne(final String key, final String value) {
return execute(new JedisAction<Boolean>() {
@Override
public Boolean action(Jedis jedis) {
Long count = jedis.lrem(key, 1, value);
return (count == 1);
}
});
}
/**
* Return the specified elements of the list stored at the specified key.
* Start and end are zero-based indexes. 0 is the first element of the list
* (the list head), 1 the next element and so on.
*/
public List<String> lrange(final String key, final long start, final long end) {
return execute(new JedisAction<List<String>>() {
@Override
public List<String> action(Jedis jedis) {
return jedis.lrange(key, start, end);
}
});
}
/**
* 删除List中的所有等于value的元素,value不存在或key不存在时返回0.
*/
public boolean lremAll(final String key, final String value) {
return execute(new JedisAction<Boolean>() {
@Override
public Boolean action(Jedis jedis) {
Long count = jedis.lrem(key, 0, value);
return (count > 0);
}
});
}
// // 关于Sorted Set ///
/**
* 加入Sorted set, 如果member在Set里已存在,只更新score并返回false,否则返回true.
*/
public boolean zadd(final String key, final String member, final double score) {
return execute(new JedisAction<Boolean>() {
@Override
public Boolean action(Jedis jedis) {
return jedis.zadd(key, score, member) == 1 ? true : false;
}
});
}
/**
* 删除sorted set中的元素,成功删除返回true,key或member不存在返回false。
*/
public boolean zrem(final String key, final String member) {
return execute(new JedisAction<Boolean>() {
@Override
public Boolean action(Jedis jedis) {
return jedis.zrem(key, member) == 1 ? true : false;
}
});
}
/**
* 返回List长度, key不存在时返回0,key类型不是sorted set时抛出异常.
*/
public long zcard(final String key) {
return execute(new JedisAction<Long>() {
@Override
public Long action(Jedis jedis) {
return jedis.zcard(key);
}
});
}
/**
* Set a timeout on the specified key
* @param key
* @param seconds
*/
public void expire(final String key, final int seconds) {
execute(new JedisActionNoResult() {
@Override
public void action(Jedis jedis) {
jedis.expire(key, seconds);
}
});
}
public boolean exists(final String key) {
return execute(new JedisAction<Boolean>() {
@Override
public Boolean action(Jedis jedis) {
return jedis.exists(key);
}
});
}
/**
* 退出然后关闭Jedis连接。
*/
public static void closeJedis(Jedis jedis) {
if (jedis.isConnected()) {
try {
try {
jedis.quit();
} catch (Exception e) {
}
jedis.disconnect();
} catch (Exception e) {
}
}
}
}
最后就是一些思路上的问题了
用户登录 发送请求 登录成功 生成一个32位的MD5字符戳 和用户对象 User
把他当做key value存在redis里面 User弄成json字符串
比如说
存
redisCacheService.setex(sessionid, 60*120, new Gson().toJson(user)); // 60*120这个是60秒*120 120分钟啦
String cache= redisCacheService.get(token);
user=new Gson().fromJson(cache, User.class);
生成的 MD5字符串传回给用户 浏览器存到cookie里面去 每个请求都会自动带cookie来的 嘿嘿
每次取cache不为null的时候 就再写入一遍 不然过期了 你负责啊
然后基本就成功了