Commit 594aa84272d1d0c306524ebdfbb96a89c7dc8f97
1 parent
a3b2772a5d
Exists in
master
添加redis
Showing 6 changed files with 169 additions and 12 deletions
- center.manager/src/main/resources/app-context.xml
- center.manager/src/main/resources/dev/redis.properties
- center.manager/src/main/resources/xml/app-redis.xml
- center.manager/src/test/java/center/manager/test/user/JeditLockTest.java
- core.sdk/src/main/java/com/lyms/spring/redis/operation/RedisLock.java
- core.sdk/src/main/java/com/lyms/web/controller/BaseController.java
center.manager/src/main/resources/app-context.xml
View file @
594aa84
| ... | ... | @@ -16,7 +16,8 @@ |
| 16 | 16 | <context:annotation-config /> |
| 17 | 17 | <!-- 扫描控制器 禁用use-default-filters 不重复扫描@Service,@Repository等..否则将导致事务失效 --> |
| 18 | 18 | <context:component-scan base-package="com.lyms.cm"></context:component-scan> |
| 19 | - <context:property-placeholder location="classpath:jdbc.properties"/> | |
| 19 | + <context:component-scan base-package="com.lyms.util"></context:component-scan> | |
| 20 | + <context:property-placeholder location="classpath:jdbc.properties,classpath:redis.properties"/> | |
| 20 | 21 | |
| 21 | 22 | <bean class="com.lyms.web.listener.StartupListener"/> |
| 22 | 23 | <bean class="com.lyms.context.AppContext"/> |
center.manager/src/main/resources/dev/redis.properties
View file @
594aa84
| 1 | +redis.host1=127.0.0.1 | |
| 2 | +redis.port1=6379 | |
| 3 | +redis.password1= | |
| 4 | +#redis.host1=127.0.0.1 | |
| 5 | +#redis.port1=6379 | |
| 6 | +#redis.password1=Lyms123456 | |
| 7 | + | |
| 8 | + | |
| 9 | +#redis.password1= | |
| 10 | +#redis.host2=192.168.56.254 | |
| 11 | +#redis.port2=6382 | |
| 12 | +#redis.password2= | |
| 13 | +#redis.host3=192.168.56.254 | |
| 14 | +#redis.port3=6383 | |
| 15 | +#redis.password2= | |
| 16 | +#redis.host4=192.168.56.254 | |
| 17 | +#redis.port4=6384 | |
| 18 | +#redis.password4= | |
| 19 | +#redis.host5=192.168.56.254 | |
| 20 | +#redis.port5=6385 | |
| 21 | +#redis.password5= | |
| 22 | +#redis.host6=192.168.56.254 | |
| 23 | +#redis.port6=6386 | |
| 24 | +#redis.password6= | |
| 25 | + | |
| 26 | + | |
| 27 | +redis.minIdle=1 | |
| 28 | +redis.maxIdle=300 | |
| 29 | +redis.maxActive=600 | |
| 30 | +redis.maxWait=1000 | |
| 31 | +redis.testOnBorrow=true | |
| 32 | +redis.HttpSession.redisNamespace=hospital.mac | |
| 33 | +spring.redis.cluster.max-redirects= 3 |
center.manager/src/main/resources/xml/app-redis.xml
View file @
594aa84
| 1 | +<?xml version="1.0" encoding= "UTF-8"?> | |
| 2 | +<beans xmlns="http://www.springframework.org/schema/beans" | |
| 3 | + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" | |
| 4 | + xmlns:p="http://www.springframework.org/schema/p" | |
| 5 | + xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd | |
| 6 | + http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd"> | |
| 7 | + | |
| 8 | + <bean id="redisConnectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory" | |
| 9 | + p:host-name="${redis.host1}" p:port="${redis.port1}" p:password="${redis.password1}" p:pool-config-ref="poolConfig"/> | |
| 10 | + | |
| 11 | + <bean id="poolConfig" class="redis.clients.jedis.JedisPoolConfig"> | |
| 12 | + <property name="minIdle" value="${redis.minIdle}" /> | |
| 13 | + <property name="maxIdle" value="${redis.maxIdle}" /> | |
| 14 | + <property name="maxTotal" value="${redis.maxActive}" /> | |
| 15 | + <property name="maxWaitMillis" value="${redis.maxWait}" /> | |
| 16 | + <property name="testOnBorrow" value="${redis.testOnBorrow}" /> | |
| 17 | + </bean> | |
| 18 | + | |
| 19 | + | |
| 20 | + <!-- Spring Data Redis 设置 --> | |
| 21 | + <!-- redis 序列化策略 ,通常情况下key值采用String序列化策略, --> | |
| 22 | + <!-- 如果不指定序列化策略,StringRedisTemplate的key和value都将采用String序列化策略; --> | |
| 23 | + <bean id="stringRedisSerializer" | |
| 24 | + class="org.springframework.data.redis.serializer.StringRedisSerializer" /> | |
| 25 | + <bean id="jdkRedisSerializer" | |
| 26 | + class="org.springframework.data.redis.serializer.JdkSerializationRedisSerializer" /> | |
| 27 | + | |
| 28 | + <!-- redis template definition p表示对该bean里面的属性进行注入,格式为p:属性名=注入的对象 效果与在bean里面使用<property>标签一样 --> | |
| 29 | + <bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate" | |
| 30 | + p:connectionFactory-ref="redisConnectionFactory" p:keySerializer-ref="stringRedisSerializer" | |
| 31 | + p:hashKeySerializer-ref="stringRedisSerializer" p:valueSerializer-ref="jdkRedisSerializer" | |
| 32 | + p:hashValueSerializer-ref="jdkRedisSerializer" /> | |
| 33 | +</beans> |
center.manager/src/test/java/center/manager/test/user/JeditLockTest.java
View file @
594aa84
| 1 | +package center.manager.test.user; | |
| 2 | + | |
| 3 | +import java.io.Serializable; | |
| 4 | + | |
| 5 | +import org.junit.Before; | |
| 6 | +import org.junit.Test; | |
| 7 | +import org.springframework.beans.factory.annotation.Autowired; | |
| 8 | +import org.springframework.data.redis.core.RedisTemplate; | |
| 9 | + | |
| 10 | +import com.lyms.spring.redis.operation.RedisLock; | |
| 11 | + | |
| 12 | +/** | |
| 13 | + * <li>@ClassName: redis 分布式锁测试 | |
| 14 | + * <li>@Description: TODO(类描述) | |
| 15 | + * <li>@author maliang | |
| 16 | + * <li>@date 2017年3月10日 | |
| 17 | + * <li> | |
| 18 | + */ | |
| 19 | +public class JeditLockTest extends BaseTest { | |
| 20 | + | |
| 21 | + private RedisLock lock = null; | |
| 22 | + | |
| 23 | + @Autowired | |
| 24 | + private RedisTemplate<Serializable, Serializable> redisTemplate; | |
| 25 | + | |
| 26 | + @Before | |
| 27 | + public void bef() { | |
| 28 | + lock = new RedisLock(redisTemplate); | |
| 29 | + } | |
| 30 | + | |
| 31 | + @Test | |
| 32 | + public void tryLock() { | |
| 33 | + for (int i = 0; i < 500; i++) { | |
| 34 | + new Thread(new Runnable() { | |
| 35 | + @Override | |
| 36 | + public void run() { | |
| 37 | + try { | |
| 38 | + if (lock.acquireLock("ack", 50000L)) { | |
| 39 | + System.out.println("thread: " + Thread.currentThread().getName() + " : 执行任务"); | |
| 40 | + try { | |
| 41 | + Thread.sleep(2000); | |
| 42 | + } catch (InterruptedException e) { | |
| 43 | + e.printStackTrace(); | |
| 44 | + } | |
| 45 | + } | |
| 46 | + } catch (Exception e) { | |
| 47 | + e.printStackTrace(); | |
| 48 | + } finally { | |
| 49 | + try { | |
| 50 | + lock.releaseLock(); | |
| 51 | + } catch (Exception e) { | |
| 52 | + e.printStackTrace(); | |
| 53 | + } | |
| 54 | + } | |
| 55 | + } | |
| 56 | + }).start(); | |
| 57 | + } | |
| 58 | + while (true) { | |
| 59 | + | |
| 60 | + } | |
| 61 | + } | |
| 62 | + | |
| 63 | +} |
core.sdk/src/main/java/com/lyms/spring/redis/operation/RedisLock.java
View file @
594aa84
| 1 | 1 | package com.lyms.spring.redis.operation; |
| 2 | 2 | |
| 3 | +import java.util.concurrent.TimeUnit; | |
| 4 | + | |
| 3 | 5 | import org.springframework.dao.DataAccessException; |
| 4 | 6 | import org.springframework.data.redis.connection.RedisConnection; |
| 5 | 7 | import org.springframework.data.redis.core.RedisCallback; |
| 6 | 8 | import org.springframework.data.redis.core.RedisTemplate; |
| 7 | 9 | |
| 8 | -import com.lyms.spring.SpringContextHolder; | |
| 9 | - | |
| 10 | 10 | /** |
| 11 | 11 | * <li>ClassName:RedisLock <br/> |
| 12 | 12 | * <li>@Description: 锁 |
| 13 | 13 | |
| 14 | 14 | |
| ... | ... | @@ -16,15 +16,41 @@ |
| 16 | 16 | @SuppressWarnings({ "rawtypes", "unchecked" }) |
| 17 | 17 | public class RedisLock { |
| 18 | 18 | |
| 19 | - private RedisTemplate redisTemplate = (RedisTemplate) SpringContextHolder | |
| 20 | - .getBean(RedisTemplate.class); | |
| 19 | + private RedisTemplate redisTemplate = null;// (RedisTemplate) | |
| 20 | + // SpringContextHolder.getBean(RedisTemplate.class); | |
| 21 | 21 | |
| 22 | 22 | private static final String PREFIX_KEY = "my_lock:"; |
| 23 | 23 | |
| 24 | + private String lockNode = null; | |
| 25 | + | |
| 24 | 26 | public RedisLock(RedisTemplate redisTemplate) { |
| 25 | 27 | this.redisTemplate = redisTemplate; |
| 26 | 28 | } |
| 27 | 29 | |
| 30 | + /** | |
| 31 | + * <li>@Description:获取锁 | |
| 32 | + * <li>@param lockName 锁地址 | |
| 33 | + * <li>@param waitNano 等待锁时间 | |
| 34 | + * <li>@return | |
| 35 | + * <li>创建人:maliang | |
| 36 | + * <li>创建时间:2017年3月10日 | |
| 37 | + * <li>修改人: | |
| 38 | + * <li>修改时间: | |
| 39 | + */ | |
| 40 | + public boolean acquireLock(String lockName, Long waitmill) throws Exception { | |
| 41 | + Long nano = System.nanoTime(); | |
| 42 | + while (System.nanoTime() - nano < TimeUnit.MILLISECONDS.toNanos(waitmill)) { | |
| 43 | + boolean tag = acquireLock(lockName); | |
| 44 | + // 获取到锁资源 | |
| 45 | + if (tag) | |
| 46 | + return true; | |
| 47 | + // 暂停资源的抢占 | |
| 48 | + System.out.println(Thread.currentThread().getName() + "等待锁..."); | |
| 49 | + Thread.sleep(100); | |
| 50 | + } | |
| 51 | + return false; | |
| 52 | + } | |
| 53 | + | |
| 28 | 54 | // 获取锁 |
| 29 | 55 | public boolean acquireLock(String lockName) throws Exception { |
| 30 | 56 | String redisKey = PREFIX_KEY + lockName; |
| ... | ... | @@ -33,6 +59,7 @@ |
| 33 | 59 | long redisValue = System.currentTimeMillis() + timeout + 1; |
| 34 | 60 | // 通过SETNX试图获取一个lock |
| 35 | 61 | if (setNX(redisKey, String.valueOf(redisValue), expire)) {// SETNX成功,则成功获取一个锁 |
| 62 | + this.lockNode = lockName; | |
| 36 | 63 | return true; |
| 37 | 64 | } else {// SETNX失败,说明锁仍然被其他对象保持,检查其是否已经超时 |
| 38 | 65 | long oldValue = Long.valueOf(get(redisKey).toString()); |
| 39 | 66 | |
| ... | ... | @@ -41,9 +68,10 @@ |
| 41 | 68 | if (oldValue < System.currentTimeMillis()) { |
| 42 | 69 | String getValue = getAndSet(redisKey, String.valueOf(redisValue)); |
| 43 | 70 | // 获取锁成功 |
| 44 | - if (getValue.equals(oldValue)) | |
| 71 | + if (getValue.equals(oldValue)) { | |
| 72 | + this.lockNode = lockName; | |
| 45 | 73 | return true; |
| 46 | - else {// 已被其他进程捷足先登了 | |
| 74 | + } else {// 已被其他进程捷足先登了 | |
| 47 | 75 | return false; |
| 48 | 76 | } |
| 49 | 77 | } else {// 未超时,则直接返回失败 |
| ... | ... | @@ -53,8 +81,8 @@ |
| 53 | 81 | } |
| 54 | 82 | |
| 55 | 83 | // 释放锁 |
| 56 | - public void releaseLock(String lockName) throws Exception { | |
| 57 | - String redisKey = PREFIX_KEY + lockName; | |
| 84 | + public void releaseLock() throws Exception { | |
| 85 | + String redisKey = PREFIX_KEY + this.lockNode; | |
| 58 | 86 | redisTemplate.delete(redisKey); |
| 59 | 87 | } |
| 60 | 88 |
core.sdk/src/main/java/com/lyms/web/controller/BaseController.java
View file @
594aa84
| ... | ... | @@ -12,7 +12,6 @@ |
| 12 | 12 | |
| 13 | 13 | import org.slf4j.Logger; |
| 14 | 14 | import org.slf4j.LoggerFactory; |
| 15 | -import org.springframework.beans.factory.annotation.Autowired; | |
| 16 | 15 | import org.springframework.beans.propertyeditors.CustomDateEditor; |
| 17 | 16 | import org.springframework.util.StringUtils; |
| 18 | 17 | import org.springframework.web.bind.ServletRequestDataBinder; |
| 19 | 18 | |
| ... | ... | @@ -33,10 +32,10 @@ |
| 33 | 32 | |
| 34 | 33 | protected Logger logger = LoggerFactory.getLogger(this.getClass()); |
| 35 | 34 | |
| 36 | - @Autowired | |
| 35 | + // @Autowired | |
| 37 | 36 | protected HttpServletRequest request; |
| 38 | 37 | |
| 39 | - @Autowired | |
| 38 | + // @Autowired | |
| 40 | 39 | protected HttpServletResponse response; |
| 41 | 40 | |
| 42 | 41 | @InitBinder |