之前项目使用spring进行注入redis,连接需要每调用一次进行连接,所以代码改成直接通过spring初始化连接池,并封装基本的jedis操作,写了一个测试,将医师所有的信息放在hash中,医师信息使用json保存,men集合存放的是性别为男的医师id,women为性别为女的医师,organ集合中存放不同机构下的医师id。查询某机构下的男医师,只需要求该机构和男医师两个set的交集,在hash中查询便可获取数据。具体代码如下:
redis.config中配置:
##redis数据库的相关配置
##连接地址ip
redis.addr = ip
##端口号
redis.port = 6379
##访问密码
redis.auth = 密码
##控制一个pool最多可以有多少个状态为Idle(空)的jedis实例默认值为8
redis.maxIdle = 200
##可用的最大连接实例数 默认为8
redis.maxActive = 1024
##等待可用连接的最大时间单位为毫秒 默认为-1表示永不超时,一旦超过等待时间则直接抛出
redis.maxWait = 10000
redis.timeOut = 10000
##设置为true则会在borrow一个jedis实例时,提前做validate操作
redis.testOnBorrow =true
##连接最小空闲时间(毫秒)
redis.minEvictableIdleTimeMillis=1800000
##释放连接的扫描间隔(毫秒)
redis.timeBetweenEvictionRunsMillis=30000
##每次释放连接的最大数目
redis.numTestsPerEvictionRun=1024
##最大连接数
redis.maxTotal=30
##在空闲时检查有效性, 默认false
redis.testWhileIdle=true
##连接耗尽时是否阻塞, false报异常,ture阻塞直到超时, 默认true
redis.blockWhenExhausted=false
applicationContext.xml中代码:
<context:property-placeholder location="classpath:redis.properties" />
<!-- redis连接池配置 -->
<bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig">
<!-- 最大连接数 -->
<property name="maxTotal" value="${redis.maxTotal}"/>
<!-- 最大空闲连接数 -->
<property name="maxIdle" value="${redis.maxIdle}"/>
<!-- 每次释放连接的最大数目 -->
<property name="numTestsPerEvictionRun" value="${redis.numTestsPerEvictionRun}"/>
<!-- 释放连接的扫描间隔(毫秒) -->
<property name="timeBetweenEvictionRunsMillis" value="${redis.timeBetweenEvictionRunsMillis}"/>
<!-- 连接最小空闲时间 -->
<property name="minEvictableIdleTimeMillis" value="${redis.minEvictableIdleTimeMillis}"/>
<!-- 连接空闲多久后释放, 当空闲时间>该值且空闲连接>最大空闲连接数时直接释放 -->
<property name="softMinEvictableIdleTimeMillis" value="10000"/>
<!-- 获取连接时的最大等待毫秒数,小于零:阻塞不确定的时间,默认-1 -->
<property name="maxWaitMillis" value="${redis.maxWait}"/>
<!-- 在获取连接的时候检查有效性, 默认false -->
<property name="testOnBorrow" value="${redis.testOnBorrow}"/>
<!-- 在空闲时检查有效性, 默认false -->
<property name="testWhileIdle" value="${redis.testWhileIdle}"/>
<!-- 连接耗尽时是否阻塞, false报异常,ture阻塞直到超时, 默认true -->
<property name="blockWhenExhausted" value="${redis.blockWhenExhausted}"/>
</bean>
<!-- redis连接 -->
<bean id="jedisPool" class="redis.clients.jedis.JedisPool"
destroy-method="close">
<constructor-arg index="0" ref="jedisPoolConfig"/>
<constructor-arg index="1" value="${redis.addr}"/>
<constructor-arg index="2" value="${redis.port}" type="int"/>
<constructor-arg index="3" value="${redis.timeOut}" type="int"/>
<constructor-arg index="4" value="${redis.auth}"/>
</bean>
basicRedisDao中封装基本的jedis操作
package com.wellness.platfront.common.util;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.annotation.Resource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
/**
* 用于连接redis的基本操作类
* @author
* @since 2017/11/21
*/
@Service("basicRedisDao")
public class BasicRedisDao{
//通过spring注入jedisPool
@Resource
private JedisPool jedisPool;
private Jedis jedis;
private static Map<String, String> map;
/**
* 获取jedis
* @return
*/
public Jedis getJedis(){
if (jedis == null) {
jedis = jedisPool.getResource();
}
return jedis;
}
/**
* 清空数据库
*/
public void flushDB(){
jedis = getJedis();
if (jedis !=null ) {
jedis.flushDB();
}
}
/**
* 保存string的数据
*/
public void saveString(String key,String value){
jedis = getJedis();
if (jedis!=null) {
jedis.set(key, value);
}
}
/**
* 删除某个键
*/
public void removeKey(String key){
jedis = getJedis();
if (jedis!=null) {
jedis.del(key);
}
}
/**
* 设置某个带时间的key
*/
public void saveTimeKey(String key,String value,int seconds){
jedis = getJedis();
if (jedis!=null) {
jedis.setex(key, seconds, value);
}
}
/**
* 查询某个key是否存在
*/
public Boolean existKey(String key){
jedis = getJedis();
if (jedis!=null) {
return jedis.exists(key);
}else {
return null;
}
}
/**
* 更新某个key并返回原来的值
*/
public String updateKey(String key,String value){
jedis = getJedis();
if (jedis!=null) {
String old = jedis.getSet(key, value);
return old;
}
return null;
}
/**
* 往某个hash表中存放数据
*/
public void hset(String key,String field,String value){
jedis = getJedis();
if (jedis != null) {
jedis.hset(key, field, value);
}
}
/**
* 获取某个hash中的所有filed和value
*/
public Map<String, String> getHashValues(String key){
jedis = getJedis();
map = new HashMap<String, String>();
if (jedis != null ) {
map = jedis.hgetAll(key);
}
return map;
}
/**
* 判断hash中某个field是否已经存在
*/
public Boolean existsField(String key,String field){
jedis = getJedis();
Boolean hexists = null;
if (jedis != null) {
hexists = jedis.hexists(key, field);
}
return hexists;
}
/**
* 删除hash中的某个field
*/
public void removeField(String key,String field){
jedis = getJedis();
if (jedis!=null) {
jedis.hdel(key, field);
}
}
/**
* 获取hash中某个field的值
*/
public String getHashFieldValue(String key,String field){
jedis = getJedis();
if (jedis !=null) {
return jedis.hget(key, field);
}
return null;
}
/**
* 查询hash中的所有filed
*/
public Set<String> getFields(String key){
jedis = getJedis();
if (jedis != null ) {
return jedis.hkeys(key);
}
return null;
}
/**
* 获取key中一个或多个field的值
*/
public List<String> hmgets(String key,String fields[]){
jedis = getJedis();
if (jedis != null && fields != null && fields.length >0) {
return jedis.hmget(key, fields);
}
return null;
}
/**
* 同时存入多个field到某个key中
*/
public void hmset(String key,Map<String, String> map){
jedis = getJedis();
if (jedis != null) {
jedis.hmset(key, map);
}
}
/**
* 往集合中压数据(多条数据用空格隔开)
*/
public void saveList(String key,String value){
jedis = getJedis();
if (jedis != null) {
jedis.lpush(key, value);
}
}
/**
* 取出集合中的所有元素
*/
public List<String> getListAllValues(String key){
jedis = getJedis();
if (jedis != null) {
List<String> lrange = jedis.lrange(key, 0, -1);
return lrange;
}
return null;
}
/**
* 获取两个集合的交集
*/
public Set<String> getSinter(String set1,String set2){
jedis = getJedis();
if (jedis != null ) {
return jedis.sinter(set1,set2);
}
return null;
}
/**
* 向集合中添加多条数据
*/
public void sadd(String key,String member[]){
jedis = getJedis();
if (jedis != null ) {
jedis.sadd(key, member);
}
}
/**
* 向集合中添加单条数据
*/
public void sadd(String key,String member){
jedis = getJedis();
if (jedis != null ) {
jedis.sadd(key, member);
}
}
/**
* 判断member是否为某个集合的元素
*/
public Boolean sismember(String key,String member){
jedis = getJedis();
if (jedis != null ) {
return jedis.sismember(key, member);
}
return null;
}
/**
* 删除hash中的某个field
*/
public void hdel(String key,String field){
jedis = getJedis();
if (jedis != null ) {
jedis.hdel(key, field);
}
}
/**
* 删除set中的某个member
*/
public void srem(String key,String member){
jedis = getJedis();
if (jedis != null ) {
jedis.srem(key, member);
}
}
}
RedisService中为具体的操作:保存对象时应当封装vo进行保存,因为这里只是测试,所以没有封装。
package com.wellness.platfront.common.redis;
/**
* 具体redis业务的service
* @author yangfuren
* @Since 2017/12/05
*/
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.annotation.Resource;
import org.springframework.stereotype.Service;
import com.alibaba.fastjson.JSON;
import com.wellness.platfront.common.util.BasicRedisDao;
import com.wellness.platfront.entity.physician.doctor.DoctorAccount;
@Service("redisService")
public class RedisService {
@Resource
private BasicRedisDao basicRedisDao;
public void flushDb(){
basicRedisDao.flushDB();
}
/**
* 获取organ集合和性别集合的交集
*/
public List<String> getDoctorByOrganAndSex(String organId,String sex){
List<String> sinters = new ArrayList<>();
String doctorSex = null ;
if (sex.equals("男")) {
doctorSex= "man";
}else if (sex.equals("女")) {
doctorSex= "women";
}
Set<String> sinter = basicRedisDao.getSinter("organ"+organId, doctorSex);
if (sinter !=null) {
sinters.addAll(sinter);
}
return sinters;
}
/**
* 根据id查询所有的医师
*/
public List<Object> getDoctorAccount(String organId,String sex){
List<String> doctorId = getDoctorByOrganAndSex(organId,sex);
List<Object> doctorAccounts = new ArrayList<>();
//将list转成数组
String doctorIds[] = doctorId.toArray(new String[doctorId.size()]);
if (doctorIds != null && doctorIds.length > 0) {
List<String> hmget = basicRedisDao.hmgets("doctorAlls", doctorIds);
//将查询出来的json串转成对象放入集合中
if (hmget != null && hmget.size() > 0) {
for (String string : hmget) {
doctorAccounts.add(JSON.parse(string));
}
}
}
return doctorAccounts;
}
/**
* 将医师的信息存放到map
*/
public void saveDoctors(List<DoctorAccount> doctorAccounts){
Map<String,String> map1 = new HashMap<>();
for (int i = 0; i < doctorAccounts.size(); i++) {
map1.put(String.valueOf(doctorAccounts.get(i).getDoctorId()), JSON.toJSONString(doctorAccounts.get(i)));
basicRedisDao.hmset("doctorAlls", map1);
}
}
/**
* 将所有的机构查询出来放入set中
*/
public void saveOrgan(List<DoctorAccount> doctorAccounts,String organId){
if (doctorAccounts != null && doctorAccounts.size() > 0 ) {
List<String> doctorIds = new ArrayList<>();
for (int j = 0; j < doctorAccounts.size(); j++) {
doctorIds.add(String.valueOf(doctorAccounts.get(j).getDoctorId()));
}
String doctorId[] = doctorIds.toArray(new String[doctorIds.size()]);
basicRedisDao.sadd(organId, doctorId);
}
}
/**
* 按性别保存医师 1 男 2 女
*/
public void savedoctorBySex(List<DoctorAccount> doctorAccounts,
String sex) {
if (doctorAccounts != null && doctorAccounts.size() > 0) {
List<String> doctorIds = new ArrayList<>();
for (int j = 0; j < doctorAccounts.size(); j++) {
doctorIds.add(String.valueOf(doctorAccounts.get(j)
.getDoctorId()));
}
String doctorId[] = doctorIds.toArray(new String[doctorIds
.size()]);
basicRedisDao.sadd(sex, doctorId);
}
}
/**
* 更新医师信息 先用一次删除在调用新增
*/
public void uploadDoctor(DoctorAccount doctorAccount){
basicRedisDao.hset("doctorAlls", String.valueOf(doctorAccount.getDoctorId()), JSON.toJSONString(doctorAccount));
if (!basicRedisDao.sismember("organ"+doctorAccount.getDoctorBasicInfo().getOrgan().getOrgan_id(), String.valueOf(doctorAccount.getDoctorId()))) {
basicRedisDao.sadd("organ"+doctorAccount.getDoctorBasicInfo().getOrgan().getOrgan_id(), String.valueOf(doctorAccount.getDoctorId()));
}
}
/**
* 删除医师信息
*/
public void removeDoctor(DoctorAccount doctorAccount){
basicRedisDao.hdel("doctorAlls", String.valueOf(doctorAccount.getDoctorId()));
basicRedisDao.srem("organ"+doctorAccount.getDoctorBasicInfo().getOrgan().getOrgan_id(), String.valueOf(doctorAccount.getDoctorId()));
}
/**
* 新增医师信息
*/
public void saveDoctor(DoctorAccount doctorAccount){
basicRedisDao.hset("doctorAlls",String.valueOf(doctorAccount.getDoctorId()), JSON.toJSONString(doctorAccount));
basicRedisDao.sadd("organ"+doctorAccount.getDoctorBasicInfo().getOrgan().getOrgan_id(), String.valueOf(doctorAccount.getDoctorId()));
}
}
测试的RedisAction代码:
package com.wellness.platfront.physician.redis;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.annotation.Resource;
import org.apache.struts2.convention.annotation.Action;
import org.apache.struts2.convention.annotation.Namespace;
import com.wellness.platfront.business.doctor.service.IOrganService;
import com.wellness.platfront.business.physician.doctor.DoctorAccountService;
import com.wellness.platfront.common.redis.RedisDbUtils;
import com.wellness.platfront.common.redis.RedisService;
import com.wellness.platfront.common.util.SerializaUtil;
import com.wellness.platfront.common.util.Struts2Utils;
import com.wellness.platfront.entity.doctor.Organ;
import com.wellness.platfront.entity.physician.doctor.DoctorAccount;
import com.wellness.platfront.outInterface.util.MsgCode;
@Namespace("/redisTest")
@SuppressWarnings("unused")
public class RedisAction {
@Resource
private DoctorAccountService doctorAccountService;
@Resource
private IOrganService iOrganService;
private Map<String, String> map = new HashMap<String, String>();
Map<String, Object> msg = new HashMap<String, Object>();
@Resource(name="redisService")
private RedisService redisService;
@Action("saveDoctor")
public String saveDoctor() {
List<DoctorAccount> doctors = doctorAccountService.listAllDoctor();
redisService.saveDoctors(doctors);
List<DoctorAccount> doctorAccounts = doctorAccountService
.listDoctorBySex("男");
redisService.savedoctorBySex(doctorAccounts, "man");
List<DoctorAccount> doctorAccounts2 = doctorAccountService
.listDoctorBySex("女");
redisService.savedoctorBySex(doctorAccounts2, "women");
List<Organ> organs = iOrganService.listOrgan();
for (int i = 0; i < organs.size(); i++) {
List<DoctorAccount> doctorAccounts3 = doctorAccountService
.getDoctorAccountsByOrganId(organs.get(i).getOrgan_id());
redisService.saveOrgan(doctorAccounts3,
"organ" + String.valueOf(organs.get(i).getOrgan_id()));
}
return null;
}
@Action("selectDoctor")
public String selectDoctor() {
String organId = Struts2Utils.getRequest().getParameter("organId");
String doctorSex = Struts2Utils.getRequest().getParameter("sex");
List<Object> doctorAccount = redisService.getDoctorAccount(organId,
doctorSex);
msg.put("doctorAccount", doctorAccount);
Struts2Utils.renderJson(msg);
return null;
}
}
调用action中的方法就可以保存和查询,因为只是测试,所以代码并不完善,其中的action方法测试能够使用。
以上代码频繁调用会出现java.net.SocketException: Broken pipe
redis.clients.jedis.exceptions.JedisConnectionException: java.net.SocketException: Broken pipe
后来修改将redisdao去掉,直接在service中使用jedis调用,在使用完后及时释放jedis并加线程同步:
@Resource
private JedisPool jedisPool;
private Jedis jedis;
/**
* 判断医师是否已被冻结
*/
public synchronized Boolean isPerssion(String doctorId){
Boolean perssion = null;
if (jedisPool != null ) {
try {
jedis = jedisPool.getResource();
if (doctorId != null) {
perssion = jedis.sismember("NoPerssion", doctorId);
jedis.close();;
}
} catch (Exception e) {
e.printStackTrace();
throw new BasicRuntimeException(this, "redis判断医师是否已被冻结异常" + e.getMessage());
}
}
return perssion;
}