├── .gitignore ├── .settings ├── org.eclipse.wst.jsdt.ui.superType.name ├── org.eclipse.wst.validation.prefs ├── org.eclipse.wst.jsdt.ui.superType.container ├── org.eclipse.m2e.core.prefs ├── org.eclipse.core.resources.prefs ├── org.eclipse.wst.common.project.facet.core.xml ├── .jsdtscope ├── org.eclipse.wst.common.component └── org.eclipse.jdt.core.prefs ├── src ├── main │ ├── resources │ │ ├── redis.psc │ │ ├── redis的使用规范.docx │ │ ├── redis简介和安装.docx │ │ ├── 说明.txt │ │ ├── hibernate │ │ │ ├── hibernate.cfg.xml │ │ │ └── bean │ │ │ │ ├── noteBookGroup.hbm.xml │ │ │ │ ├── noteBook.hbm.xml │ │ │ │ └── note.hbm.xml │ │ ├── druidpool.properties │ │ ├── dubbo-provider.xml │ │ ├── spring-dispatcherservlet.xml │ │ ├── log4j.properties │ │ ├── redis.properties │ │ └── spring-context.xml │ ├── java │ │ └── com │ │ │ └── msds │ │ │ ├── dubbo │ │ │ ├── service │ │ │ │ ├── NoteBookService.java │ │ │ │ ├── NoteBookGroupService.java │ │ │ │ ├── imp │ │ │ │ │ ├── NoteBookServiceImp.java │ │ │ │ │ └── NoteServiceImp.java │ │ │ │ ├── BaseService.java │ │ │ │ └── NoteService.java │ │ │ ├── common │ │ │ │ └── BeanField.java │ │ │ └── bean │ │ │ │ ├── NoteBookGroup.java │ │ │ │ ├── NoteBook.java │ │ │ │ └── Note.java │ │ │ └── redis │ │ │ ├── util │ │ │ ├── RedisDataBaseType.java │ │ │ ├── RedisCachePool.java │ │ │ ├── BeanField.java │ │ │ ├── RedisCacheManager.java │ │ │ └── RedisCacheManagers.java │ │ │ ├── annation │ │ │ ├── RedisQuery.java │ │ │ ├── RedisFieldNotCache.java │ │ │ └── RedisCache.java │ │ │ ├── synchronize │ │ │ ├── RedisUpdateToDataBase.java │ │ │ └── NotifyDataBase.java │ │ │ └── dao │ │ │ └── RedisDao.java │ └── webapp │ │ └── WEB-INF │ │ └── logs │ │ └── mylog.log └── test │ └── java │ └── com │ └── msds │ ├── test │ ├── InitDubborProvider.java │ ├── MonitorSql.java │ ├── PutArticelUrlByPage.java │ ├── InitDataToDataBase.java │ ├── InitDataToRedis.java │ ├── StoreToDataBaseByThread.java │ └── JuitTest.java │ └── redis │ └── performance │ ├── RedisEasyTest.java │ └── RedisCompareDataBase.java ├── target ├── m2e-wtp │ └── web-resources │ │ └── META-INF │ │ └── maven │ │ └── redis │ │ └── redis │ │ └── pom.properties └── classes │ ├── druidpool.properties │ ├── log4j.properties │ └── redis.properties ├── .project ├── .classpath └── pom.xml /.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | -------------------------------------------------------------------------------- /.settings/org.eclipse.wst.jsdt.ui.superType.name: -------------------------------------------------------------------------------- 1 | Window -------------------------------------------------------------------------------- /.settings/org.eclipse.wst.validation.prefs: -------------------------------------------------------------------------------- 1 | disabled=06target 2 | eclipse.preferences.version=1 3 | -------------------------------------------------------------------------------- /.settings/org.eclipse.wst.jsdt.ui.superType.container: -------------------------------------------------------------------------------- 1 | org.eclipse.wst.jsdt.launching.baseBrowserLibrary -------------------------------------------------------------------------------- /src/main/resources/redis.psc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ggj2010/redis/HEAD/src/main/resources/redis.psc -------------------------------------------------------------------------------- /src/main/resources/redis的使用规范.docx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ggj2010/redis/HEAD/src/main/resources/redis的使用规范.docx -------------------------------------------------------------------------------- /src/main/resources/redis简介和安装.docx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ggj2010/redis/HEAD/src/main/resources/redis简介和安装.docx -------------------------------------------------------------------------------- /.settings/org.eclipse.m2e.core.prefs: -------------------------------------------------------------------------------- 1 | activeProfiles= 2 | eclipse.preferences.version=1 3 | resolveWorkspaceProjects=true 4 | version=1 5 | -------------------------------------------------------------------------------- /src/main/java/com/msds/dubbo/service/NoteBookService.java: -------------------------------------------------------------------------------- 1 | package com.msds.dubbo.service; 2 | 3 | public interface NoteBookService { 4 | 5 | } 6 | -------------------------------------------------------------------------------- /src/main/java/com/msds/dubbo/service/NoteBookGroupService.java: -------------------------------------------------------------------------------- 1 | package com.msds.dubbo.service; 2 | 3 | public interface NoteBookGroupService { 4 | 5 | } 6 | -------------------------------------------------------------------------------- /src/main/java/com/msds/dubbo/service/imp/NoteBookServiceImp.java: -------------------------------------------------------------------------------- 1 | package com.msds.dubbo.service.imp; 2 | 3 | public class NoteBookServiceImp { 4 | 5 | } 6 | -------------------------------------------------------------------------------- /.settings/org.eclipse.core.resources.prefs: -------------------------------------------------------------------------------- 1 | eclipse.preferences.version=1 2 | encoding//src/main/java=UTF-8 3 | encoding//src/main/resources=UTF-8 4 | encoding//src/test/java=UTF-8 5 | encoding//src/test/resources=UTF-8 6 | encoding/=UTF-8 7 | -------------------------------------------------------------------------------- /target/m2e-wtp/web-resources/META-INF/maven/redis/redis/pom.properties: -------------------------------------------------------------------------------- 1 | #Generated by Maven Integration for Eclipse 2 | #Wed May 27 19:50:12 CST 2015 3 | version=0.0.1-SNAPSHOT 4 | groupId=redis 5 | m2e.projectName=redis 6 | m2e.projectLocation=F\:\\IdeaProjects\\redis 7 | artifactId=redis 8 | -------------------------------------------------------------------------------- /src/main/java/com/msds/redis/util/RedisDataBaseType.java: -------------------------------------------------------------------------------- 1 | package com.msds.redis.util; 2 | 3 | /** 4 | * @ClassName:RedisDataBaseType.java 5 | * @Description: 业务库 6 | * @author gaoguangjin 7 | * @Date 2015-5-25 下午2:30:40 8 | */ 9 | public enum RedisDataBaseType { 10 | defaultType 11 | } 12 | -------------------------------------------------------------------------------- /.settings/org.eclipse.wst.common.project.facet.core.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /src/main/java/com/msds/dubbo/service/BaseService.java: -------------------------------------------------------------------------------- 1 | package com.msds.dubbo.service; 2 | 3 | import java.util.List; 4 | 5 | public interface BaseService { 6 | /* 查询所有 */ 7 | public List findAll(); 8 | 9 | /* 删除 */ 10 | void delete(String id); 11 | 12 | /* 更新 */ 13 | void update(T t); 14 | 15 | /**/ 16 | void insert(T t); 17 | } 18 | -------------------------------------------------------------------------------- /src/main/webapp/WEB-INF/logs/mylog.log: -------------------------------------------------------------------------------- 1 | 2015-05-19 16:52:18,104 -0 [main] com.msds.redis.util.RedisPool ERROR - 获取Jedis失败!Could not get a resource from the pool [com.msds.redis.util.RedisPool.getJedis(RedisPool.java:59)] 2 | 2015-05-19 16:57:19,586 -0 [main] com.msds.redis.util.RedisPool ERROR - 获取Jedis失败!Could not get a resource from the pool [com.msds.redis.util.RedisPool.getJedis(RedisPool.java:59)] 3 | -------------------------------------------------------------------------------- /src/main/java/com/msds/dubbo/service/NoteService.java: -------------------------------------------------------------------------------- 1 | package com.msds.dubbo.service; 2 | 3 | import java.util.List; 4 | 5 | import com.msds.dubbo.bean.Note; 6 | 7 | public interface NoteService { 8 | /* 根据主键 */ 9 | Note queryById(String i); 10 | 11 | /** 12 | * @Description: 13 | * @see:例如 select * from tcnote where note_name="文本名称" and author_name="高广金" 14 | * @param note 15 | * @return:List 16 | */ 17 | List queryParamAnd(Note note); 18 | 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/com/msds/redis/annation/RedisQuery.java: -------------------------------------------------------------------------------- 1 | package com.msds.redis.annation; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | /** 9 | * @ClassName:Query.java 10 | * @Description: 查询条件 需要缓存到redis 11 | * @author gaoguangjin 12 | * @Date 2015-5-19 下午10:10:17 13 | */ 14 | @Retention(RetentionPolicy.RUNTIME) 15 | @Target(ElementType.FIELD) 16 | public @interface RedisQuery { 17 | } 18 | -------------------------------------------------------------------------------- /src/main/resources/说明.txt: -------------------------------------------------------------------------------- 1 | ###本代码主要实现内容##### 2 | 1、将数据库数据 按照规定的key/value 协议存储到 3 | 4 | 5 | 1、数据库用的是mysql,在druidpool.properties 可以自行添加别的数据源,记得要同步hibernate的方言。 6 | 2、redis.psc 是mysql的数据备份文件,直接在mysql里面建立redis数据库,然后还原备份就有数据了。 7 | 8 | 3、com.msds.test.InitDataToDataBase 9 | 这个类主要实现初始化网站数据到数据库的作用,写了一个多线程爬去 http://www.tuicool.com/ 推酷网站上面的文章 10 | 11 | 4、com.msds.test.InitDataToRedis 12 | 这个类主要是实现 将数据库的数据初始化到redis里面。按照规定的key/value格式存储 13 | 14 | 15 | 【1】、Monitorql是用来监控的sql变化的,可以用来异步更新到数据 这是一个pub/sub模式 16 | 【2】、删除redi里面的数据 其实是走初始化的逆向过程 17 | 【3】、更新其实是先删除 再插入 -------------------------------------------------------------------------------- /src/main/java/com/msds/redis/annation/RedisFieldNotCache.java: -------------------------------------------------------------------------------- 1 | package com.msds.redis.annation; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | /** 9 | * @ClassName:RedisFieldNotCache.java 10 | * @Description: 某些字段不用缓存 11 | * @author gaoguangjin 12 | * @Date 2015-5-20 上午12:33:22 13 | */ 14 | @Retention(RetentionPolicy.RUNTIME) 15 | @Target(ElementType.FIELD) 16 | public @interface RedisFieldNotCache { 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/com/msds/redis/annation/RedisCache.java: -------------------------------------------------------------------------------- 1 | package com.msds.redis.annation; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | /** 9 | * @ClassName:Cache.java 10 | * @Description: 需要缓存到redis实体类 11 | * @author gaoguangjin 12 | * @Date 2015-5-19 下午10:09:38 13 | */ 14 | @Retention(RetentionPolicy.RUNTIME) 15 | @Target(ElementType.TYPE) 16 | public @interface RedisCache { 17 | public boolean need() default true; 18 | } 19 | -------------------------------------------------------------------------------- /.settings/.jsdtscope: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /.settings/org.eclipse.wst.common.component: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /.settings/org.eclipse.jdt.core.prefs: -------------------------------------------------------------------------------- 1 | eclipse.preferences.version=1 2 | org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled 3 | org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 4 | org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve 5 | org.eclipse.jdt.core.compiler.compliance=1.6 6 | org.eclipse.jdt.core.compiler.debug.lineNumber=generate 7 | org.eclipse.jdt.core.compiler.debug.localVariable=generate 8 | org.eclipse.jdt.core.compiler.debug.sourceFile=generate 9 | org.eclipse.jdt.core.compiler.problem.assertIdentifier=error 10 | org.eclipse.jdt.core.compiler.problem.enumIdentifier=error 11 | org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning 12 | org.eclipse.jdt.core.compiler.source=1.6 13 | -------------------------------------------------------------------------------- /src/main/resources/hibernate/hibernate.cfg.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | true 8 | false 9 | false 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /target/classes/druidpool.properties: -------------------------------------------------------------------------------- 1 | #dataSource 2 | driver=com.mysql.jdbc.Driver 3 | url=jdbc:mysql://localhost:3306/redis?useUnicode=true&characterEncoding=utf-8 4 | username=root 5 | password=root 6 | filters=config,stat 7 | #connectionProperties=config.decrypt=true;druid.stat.slowSqlMillis=300000;druid.stat.logSlowSql=true;druid.stat.mergeSql=true 8 | initialSize=20 9 | minIdle=20 10 | maxActive=200 11 | maxWait=60000 12 | timeBetweenEvictionRunsMillis=900000 13 | minEvictableIdleTimeMillis=900000 14 | validationQueryTimeout=900000 15 | validationQuery=SELECT sysdate from dual 16 | testWhileIdle=true 17 | testOnBorrow=false 18 | testOnReturn=false 19 | poolPreparedStatements=true 20 | maxPoolPreparedStatementPerConnectionSize=80 21 | 22 | 23 | -------------------------------------------------------------------------------- /src/main/resources/druidpool.properties: -------------------------------------------------------------------------------- 1 | #dataSource 2 | driver=com.mysql.jdbc.Driver 3 | url=jdbc:mysql://localhost:3306/redis?useUnicode=true&characterEncoding=utf-8 4 | username=root 5 | password=root 6 | filters=config,stat 7 | #connectionProperties=config.decrypt=true;druid.stat.slowSqlMillis=300000;druid.stat.logSlowSql=true;druid.stat.mergeSql=true 8 | initialSize=20 9 | minIdle=20 10 | maxActive=200 11 | maxWait=60000 12 | timeBetweenEvictionRunsMillis=900000 13 | minEvictableIdleTimeMillis=900000 14 | validationQueryTimeout=900000 15 | validationQuery=SELECT sysdate from dual 16 | testWhileIdle=true 17 | testOnBorrow=false 18 | testOnReturn=false 19 | poolPreparedStatements=true 20 | maxPoolPreparedStatementPerConnectionSize=80 21 | 22 | 23 | -------------------------------------------------------------------------------- /src/main/resources/hibernate/bean/noteBookGroup.hbm.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /src/main/java/com/msds/dubbo/common/BeanField.java: -------------------------------------------------------------------------------- 1 | package com.msds.dubbo.common; 2 | 3 | import java.lang.reflect.Field; 4 | 5 | public class BeanField { 6 | String primaryKey; 7 | String className; 8 | Field[] fieldList; 9 | 10 | public BeanField(String primaryKey, String className, Field[] fieldList) { 11 | this.primaryKey = primaryKey; 12 | this.className = className; 13 | this.fieldList = fieldList; 14 | } 15 | 16 | public String getPrimaryKey() { 17 | return primaryKey; 18 | } 19 | 20 | public void setPrimaryKey(String primaryKey) { 21 | this.primaryKey = primaryKey; 22 | } 23 | 24 | public String getClassName() { 25 | return className; 26 | } 27 | 28 | public void setClassName(String className) { 29 | this.className = className; 30 | } 31 | 32 | public Field[] getFieldList() { 33 | return fieldList; 34 | } 35 | 36 | public void setFieldList(Field[] fieldList) { 37 | this.fieldList = fieldList; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/main/resources/hibernate/bean/noteBook.hbm.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /src/main/java/com/msds/redis/util/RedisCachePool.java: -------------------------------------------------------------------------------- 1 | package com.msds.redis.util; 2 | 3 | import redis.clients.jedis.Jedis; 4 | import redis.clients.jedis.JedisPool; 5 | 6 | /** 7 | * @ClassName:RedisCachePool.java 8 | * @Description: 9 | * @author gaoguangjin 10 | * @Date 2015-5-25 下午2:30:33 11 | */ 12 | public class RedisCachePool { 13 | 14 | private JedisPool jedisPool = null; 15 | private Integer db; 16 | 17 | public RedisCachePool(Integer db, JedisPool jedisPool) { 18 | this.db = db; 19 | this.jedisPool = jedisPool; 20 | 21 | } 22 | 23 | public Jedis getResource() { 24 | Jedis jedisInstance = null; 25 | if (jedisPool != null) { 26 | jedisInstance = jedisPool.getResource(); 27 | if (db > 0) {// 每次获得连接之前,切换到对应的数据库。默认的是0 28 | jedisInstance.select(db); 29 | } 30 | } 31 | return jedisInstance; 32 | } 33 | 34 | /** 35 | * 释放jedis资源 36 | * @param jedis 37 | */ 38 | public void returnResource(final Jedis jedis) { 39 | if (jedis != null) { 40 | jedisPool.returnResource(jedis); 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/main/java/com/msds/redis/util/BeanField.java: -------------------------------------------------------------------------------- 1 | package com.msds.redis.util; 2 | 3 | import java.lang.reflect.Field; 4 | 5 | /** 6 | * @ClassName:BeanField.java 7 | * @Description: bean工具类 8 | * @author gaoguangjin 9 | * @Date 2015-5-25 下午2:30:58 10 | */ 11 | public class BeanField { 12 | String primaryKey; 13 | String className; 14 | Field[] fieldList; 15 | 16 | public BeanField(String primaryKey, String className, Field[] fieldList) { 17 | this.primaryKey = primaryKey; 18 | this.className = className; 19 | this.fieldList = fieldList; 20 | } 21 | 22 | public String getPrimaryKey() { 23 | return primaryKey; 24 | } 25 | 26 | public void setPrimaryKey(String primaryKey) { 27 | this.primaryKey = primaryKey; 28 | } 29 | 30 | public String getClassName() { 31 | return className; 32 | } 33 | 34 | public void setClassName(String className) { 35 | this.className = className; 36 | } 37 | 38 | public Field[] getFieldList() { 39 | return fieldList; 40 | } 41 | 42 | public void setFieldList(Field[] fieldList) { 43 | this.fieldList = fieldList; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/main/resources/dubbo-provider.xml: -------------------------------------------------------------------------------- 1 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /src/main/java/com/msds/dubbo/bean/NoteBookGroup.java: -------------------------------------------------------------------------------- 1 | package com.msds.dubbo.bean; 2 | 3 | import java.io.Serializable; 4 | import java.util.Date; 5 | 6 | import lombok.Getter; 7 | import lombok.Setter; 8 | 9 | import com.msds.redis.annation.RedisCache; 10 | import com.msds.redis.annation.RedisFieldNotCache; 11 | import com.msds.redis.annation.RedisQuery; 12 | 13 | /** 14 | * @ClassName:NoteBookGroup.java 15 | * @Description: 笔记本组实体类 16 | * @author gaoguangjin 17 | * @Date 2015-5-19 下午10:18:40 18 | */ 19 | @Getter 20 | @Setter 21 | @RedisCache 22 | public class NoteBookGroup implements Serializable { 23 | @RedisFieldNotCache 24 | private static final long serialVersionUID = 1L; 25 | @RedisFieldNotCache 26 | private static final String className = "NoteBookGroup"; 27 | @RedisFieldNotCache 28 | private static final String primaryKey = "noteBookGroupId"; 29 | 30 | private int noteBookGroupId; 31 | @RedisQuery 32 | private String noteBookGroupName; 33 | private int textSum;// 统计该笔记本组下面有多少文本 34 | @RedisQuery 35 | private Integer flag; 36 | @RedisQuery 37 | private Date createdate; 38 | 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/com/msds/dubbo/bean/NoteBook.java: -------------------------------------------------------------------------------- 1 | package com.msds.dubbo.bean; 2 | 3 | import java.io.Serializable; 4 | import java.util.Date; 5 | 6 | import lombok.Getter; 7 | import lombok.Setter; 8 | 9 | import com.msds.redis.annation.RedisCache; 10 | import com.msds.redis.annation.RedisFieldNotCache; 11 | import com.msds.redis.annation.RedisQuery; 12 | 13 | /** 14 | * @ClassName:NoteBook.java 15 | * @Description: 笔记本实体类 16 | * @author gaoguangjin 17 | * @Date 2015-5-19 下午10:18:23 18 | */ 19 | @Getter 20 | @Setter 21 | @RedisCache 22 | public class NoteBook implements Serializable { 23 | 24 | @RedisFieldNotCache 25 | private static final long serialVersionUID = 1L; 26 | @RedisFieldNotCache 27 | private static final String className = "NoteBook"; 28 | @RedisFieldNotCache 29 | private static final String primaryKey = "noteBookId"; 30 | 31 | private int noteBookId; 32 | @RedisQuery 33 | private String noteBookName; 34 | private int textSum;// 统计该笔记本下面有多少文本 35 | private NoteBookGroup noteBookGroup; 36 | @RedisQuery 37 | private Integer flag; 38 | @RedisQuery 39 | private Date createdate; 40 | } 41 | -------------------------------------------------------------------------------- /src/main/java/com/msds/redis/synchronize/RedisUpdateToDataBase.java: -------------------------------------------------------------------------------- 1 | package com.msds.redis.synchronize; 2 | 3 | import java.util.List; 4 | 5 | import lombok.extern.slf4j.Slf4j; 6 | 7 | import org.hibernate.Session; 8 | import org.hibernate.SessionFactory; 9 | import org.springframework.beans.factory.annotation.Autowired; 10 | import org.springframework.stereotype.Service; 11 | import org.springframework.transaction.annotation.Transactional; 12 | 13 | /** 14 | * @ClassName:RedisUpdateToDataBase.java 15 | * @Description: redis异步更新到数据库 16 | * @author gaoguangjin 17 | * @Date 2015-5-22 上午10:09:48 18 | */ 19 | @Service 20 | @Slf4j 21 | @Transactional 22 | public class RedisUpdateToDataBase { 23 | @Autowired 24 | SessionFactory sessionFactory; 25 | 26 | public boolean excuteUpdate(List list) { 27 | try { 28 | Session session = sessionFactory.getCurrentSession(); 29 | for (String string : list) { 30 | session.createSQLQuery(string).executeUpdate(); 31 | } 32 | log.info("redis更新到数据库成功!"); 33 | return true; 34 | } catch (Exception e) { 35 | log.info("redis更新到数据库失败!" + e.getLocalizedMessage()); 36 | } 37 | return false; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/main/resources/hibernate/bean/note.hbm.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | redis 4 | 5 | 6 | 7 | 8 | 9 | org.eclipse.wst.jsdt.core.javascriptValidator 10 | 11 | 12 | 13 | 14 | org.eclipse.jdt.core.javabuilder 15 | 16 | 17 | 18 | 19 | org.eclipse.wst.common.project.facet.core.builder 20 | 21 | 22 | 23 | 24 | org.eclipse.wst.validation.validationbuilder 25 | 26 | 27 | 28 | 29 | org.eclipse.m2e.core.maven2Builder 30 | 31 | 32 | 33 | 34 | 35 | org.eclipse.jem.workbench.JavaEMFNature 36 | org.eclipse.wst.common.modulecore.ModuleCoreNature 37 | org.eclipse.jdt.core.javanature 38 | org.eclipse.m2e.core.maven2Nature 39 | org.eclipse.wst.common.project.facet.core.nature 40 | org.eclipse.wst.jsdt.core.jsNature 41 | 42 | 43 | -------------------------------------------------------------------------------- /src/test/java/com/msds/test/InitDubborProvider.java: -------------------------------------------------------------------------------- 1 | package com.msds.test; 2 | 3 | import java.io.IOException; 4 | 5 | import lombok.extern.slf4j.Slf4j; 6 | 7 | import org.junit.Test; 8 | import org.junit.runner.RunWith; 9 | import org.springframework.test.context.ContextConfiguration; 10 | import org.springframework.test.context.TestExecutionListeners; 11 | import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; 12 | import org.springframework.test.context.support.DependencyInjectionTestExecutionListener; 13 | import org.springframework.test.context.transaction.TransactionConfiguration; 14 | import org.springframework.test.context.transaction.TransactionalTestExecutionListener; 15 | 16 | /** 17 | * @ClassName:InitDubborProvider.java 18 | * @Description: 启动dubbo服务 19 | * @author gaoguangjin 20 | * @Date 2015-5-20 下午12:56:10 21 | */ 22 | @Slf4j 23 | @RunWith(SpringJUnit4ClassRunner.class) 24 | @ContextConfiguration({ "classpath:spring-context.xml", "classpath:dubbo-provider.xml" }) 25 | @TransactionConfiguration(transactionManager = "transactionManager", defaultRollback = false) 26 | @TestExecutionListeners(listeners = { DependencyInjectionTestExecutionListener.class, TransactionalTestExecutionListener.class }) 27 | public class InitDubborProvider { 28 | 29 | @Test 30 | // 发布服务 31 | public void provider() throws IOException { 32 | System.in.read(); // 为保证服务一直开着,利用输入流的阻塞来模拟 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /src/test/java/com/msds/test/MonitorSql.java: -------------------------------------------------------------------------------- 1 | package com.msds.test; 2 | 3 | import lombok.extern.slf4j.Slf4j; 4 | 5 | import org.springframework.context.ApplicationContext; 6 | import org.springframework.context.support.ClassPathXmlApplicationContext; 7 | 8 | import redis.clients.jedis.Jedis; 9 | import redis.clients.jedis.JedisPubSub; 10 | 11 | import com.msds.redis.util.RedisCacheManager; 12 | import com.msds.redis.util.RedisCachePool; 13 | import com.msds.redis.util.RedisDataBaseType; 14 | 15 | /** 16 | * @ClassName:MonitorSql.java 17 | * @Description: 监控对redis的更新和删除 18 | * @author gaoguangjin 19 | * @Date 2015-5-21 上午10:32:23 20 | */ 21 | @Slf4j 22 | public class MonitorSql { 23 | 24 | public static void main(String[] args) { 25 | ApplicationContext application = new ClassPathXmlApplicationContext("spring-context.xml"); 26 | RedisCacheManager redisCacheManager = (RedisCacheManager) application.getBean("redisCacheManager"); 27 | RedisCachePool pool = redisCacheManager.getRedisPoolMap().get(RedisDataBaseType.defaultType.toString()); 28 | final Jedis jedis = pool.getResource(); 29 | 30 | final JedisPubSub ndb = (JedisPubSub) application.getBean("notifyDataBase"); 31 | // final Jedis jedis = RedisPool.getJedis(); 32 | // final JedisPubSub ndb = new NotifyDataBase(); 33 | new Thread() { 34 | public void run() {// 会广播形式打印log日志 35 | jedis.subscribe(ndb, "publog"); 36 | } 37 | }.start(); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/com/msds/dubbo/bean/Note.java: -------------------------------------------------------------------------------- 1 | package com.msds.dubbo.bean; 2 | 3 | import java.io.Serializable; 4 | import java.sql.Blob; 5 | import java.util.Date; 6 | 7 | import lombok.Getter; 8 | import lombok.Setter; 9 | 10 | import com.msds.redis.annation.RedisCache; 11 | import com.msds.redis.annation.RedisFieldNotCache; 12 | import com.msds.redis.annation.RedisQuery; 13 | 14 | /** 15 | * @ClassName:Note.java 16 | * @Description: 笔记实体类 17 | * @author gaoguangjin 18 | * @Date 2015-3-4 上午11:31:38 19 | */ 20 | @Getter 21 | @Setter 22 | @RedisCache 23 | public class Note implements Serializable { 24 | @RedisFieldNotCache 25 | private static final long serialVersionUID = 1L; 26 | @RedisFieldNotCache 27 | private static final String className = "Note"; 28 | @RedisFieldNotCache 29 | private static final String primaryKey = "noteId"; 30 | 31 | private int noteId; 32 | private String noteName;// 笔记名称 33 | @RedisQuery 34 | private String authorName;// 作者名称 35 | @RedisQuery 36 | private String fromUrl;// 文本来源 37 | private String content;// 文本内容 38 | private NoteBook noteBook;// 笔记本id 39 | private NoteBookGroup noteBookGroup;// 笔记本组 40 | @RedisQuery 41 | private Integer flag;// 放到BaseBean里面,反射获取不到field值 42 | @RedisQuery 43 | private Date createdate; 44 | @RedisFieldNotCache 45 | private Blob blobContent; 46 | 47 | public String toString() { 48 | return "输出值==>id=" + noteId + " 笔记本名称:" + noteName + " 文本来源:" + fromUrl + " 作者名称:" + authorName; 49 | } 50 | 51 | } 52 | -------------------------------------------------------------------------------- /.classpath: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /src/main/resources/spring-dispatcherservlet.xml: -------------------------------------------------------------------------------- 1 | 2 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /target/classes/log4j.properties: -------------------------------------------------------------------------------- 1 | #1、配置根Logger ,语法为log4j.rootLogger = [ level ] , appenderName1, appenderName2, 2 | #appenderName: 就是指定日志信息输出到哪个地方 3 | 4 | #这里设置的日志级别权限最高,如果设置了INFO那么所有的debug就打印不出来了 5 | log4j.rootLogger=INFO,A1,ROLLING_FILE 6 | 7 | #配置日志信息输出目的地 8 | log4j.appender.A1=org.apache.log4j.ConsoleAppender 9 | log4j.appender.A1.layout=org.apache.log4j.PatternLayout 10 | log4j.appender.A1.layout.ConversionPattern=%d %5p [%t] (%F:%L) - %m%n 11 | 12 | #指定日志消息的输出最低层次,这个测试的时候 可以不写,或者级别设置为debug 13 | log4j.appender.A1.layout.ConversionPattern.Threshold=DEBUG 14 | 15 | 16 | #当输出信息于回滚文件时 17 | #指定以文件的方式输出日志 18 | log4j.appender.ROLLING_FILE=org.apache.log4j.RollingFileAppender 19 | #显示日志的级别,这个日志级别在log4j.rootLogger之下。例如设置了ERROR就只输出ERROR级别的 20 | log4j.appender.ROLLING_FILE.Threshold=ERROR 21 | #存放日志文件地址,${youdao.root}这样tomact启动之后日志就写到tomact编译的目录下面 例如*\apache-tomcat-7.0.2\webapps\TeamStudy\WEB-INF\logs 22 | log4j.appender.ROLLING_FILE.File=${youdao.root}/WEB-INF/logs/mylog.log 23 | #手动测试加载日志文件 我们可以指定这个目录 24 | #log4j.appender.ROLLING_FILE.File=src/main/webapp/WEB-INF/logs/mylog.log 25 | log4j.appender.ROLLING_FILE.Append=true 26 | #文件最大的尺寸 27 | log4j.appender.ROLLING_FILE.MaxFileSize=512KB 28 | #最大备份数 29 | log4j.appender.ROLLING_FILE.MaxBackupIndex=20 30 | log4j.appender.ROLLING_FILE.layout=org.apache.log4j.PatternLayout 31 | #配置日志信息的格式 以下四种格式 32 | #1.org.apache.log4j.HTMLLayout (以HTML 表格形式布局), 33 | #2.org.apache.log4j.PatternLayout (可以灵活地指定布局模式), 34 | #3.org.apache.log4j.SimpleLayout (包含日志信息的级别和信息字符串), 35 | # 4.org.apache.log4j.TTCCLayout (包含日志产生的时间、线程、类别等等信息) 36 | log4j.appender.ROLLING_FILE.layout.ConversionPattern= %d -%-4r [%t] %c %x %-5p - %m [%l] %n 37 | 38 | 39 | #Log4J 对应用性能的影响 40 | #如果在程序运行中输出大量日志,显然会对应用的性能造成一定的影响。Log4J 对性能的影响取决于以下因素: 41 | #日志输出目的地:输出到控制台的速度和输出到文件系统的速度是不一样的。 42 | #日志输出格式:格式简单,速度也更快。 43 | #日志级别:日志级别设置的越低,输出的日志内容越多,对性能的影响也越大 44 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /src/main/resources/log4j.properties: -------------------------------------------------------------------------------- 1 | #1、配置根Logger ,语法为log4j.rootLogger = [ level ] , appenderName1, appenderName2, 2 | #appenderName: 就是指定日志信息输出到哪个地方 3 | 4 | #这里设置的日志级别权限最高,如果设置了INFO那么所有的debug就打印不出来了 5 | log4j.rootLogger=INFO,A1,ROLLING_FILE 6 | 7 | #配置日志信息输出目的地 8 | log4j.appender.A1=org.apache.log4j.ConsoleAppender 9 | log4j.appender.A1.layout=org.apache.log4j.PatternLayout 10 | log4j.appender.A1.layout.ConversionPattern=%d %5p [%t] (%F:%L) - %m%n 11 | 12 | #指定日志消息的输出最低层次,这个测试的时候 可以不写,或者级别设置为debug 13 | log4j.appender.A1.layout.ConversionPattern.Threshold=DEBUG 14 | 15 | 16 | #当输出信息于回滚文件时 17 | #指定以文件的方式输出日志 18 | log4j.appender.ROLLING_FILE=org.apache.log4j.RollingFileAppender 19 | #显示日志的级别,这个日志级别在log4j.rootLogger之下。例如设置了ERROR就只输出ERROR级别的 20 | log4j.appender.ROLLING_FILE.Threshold=ERROR 21 | #存放日志文件地址,${youdao.root}这样tomact启动之后日志就写到tomact编译的目录下面 例如*\apache-tomcat-7.0.2\webapps\TeamStudy\WEB-INF\logs 22 | log4j.appender.ROLLING_FILE.File=${youdao.root}/WEB-INF/logs/mylog.log 23 | #手动测试加载日志文件 我们可以指定这个目录 24 | #log4j.appender.ROLLING_FILE.File=src/main/webapp/WEB-INF/logs/mylog.log 25 | log4j.appender.ROLLING_FILE.Append=true 26 | #文件最大的尺寸 27 | log4j.appender.ROLLING_FILE.MaxFileSize=512KB 28 | #最大备份数 29 | log4j.appender.ROLLING_FILE.MaxBackupIndex=20 30 | log4j.appender.ROLLING_FILE.layout=org.apache.log4j.PatternLayout 31 | #配置日志信息的格式 以下四种格式 32 | #1.org.apache.log4j.HTMLLayout (以HTML 表格形式布局), 33 | #2.org.apache.log4j.PatternLayout (可以灵活地指定布局模式), 34 | #3.org.apache.log4j.SimpleLayout (包含日志信息的级别和信息字符串), 35 | # 4.org.apache.log4j.TTCCLayout (包含日志产生的时间、线程、类别等等信息) 36 | log4j.appender.ROLLING_FILE.layout.ConversionPattern= %d -%-4r [%t] %c %x %-5p - %m [%l] %n 37 | 38 | 39 | #Log4J 对应用性能的影响 40 | #如果在程序运行中输出大量日志,显然会对应用的性能造成一定的影响。Log4J 对性能的影响取决于以下因素: 41 | #日志输出目的地:输出到控制台的速度和输出到文件系统的速度是不一样的。 42 | #日志输出格式:格式简单,速度也更快。 43 | #日志级别:日志级别设置的越低,输出的日志内容越多,对性能的影响也越大 44 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /src/main/resources/redis.properties: -------------------------------------------------------------------------------- 1 | #redis\u6570\u636e\u5e93\u7c7b\u578b type\u548cnumber\u4e00\u4e00\u5bf9\u5e94 2 | redisdbtype=defaultType, 3 | redisdbnumber=0, 4 | 5 | 6 | 7 | #\u5176\u5b9e\u6211\u4eec\u53ef\u4ee5\u6bcf\u4e00\u4e2a\u4e1a\u52a1db \u90fd\u5bf9\u5e94\u5404\u81ea\u7684redis\u670d\u52a1\u5668\uff0c\u5305\u62ecip\u3001port \u7b49\u7b49\u3002\u76ee\u524d\u6211\u662f\u516c\u7528\u4e00\u4e2a 8 | #redis\u670d\u52a1\u5668\u5730\u5740 \u7aef\u53e3\u53f7\u3001\u5ef6\u8fdf\u65f6\u95f4\u3001\u5bc6\u7801 9 | #host=123.56.118.135 10 | host=10.1.9.231 11 | port=6379 12 | timeout=10000 13 | passwords=msds 14 | 15 | 16 | #\u53ef\u7528\u8fde\u63a5\u5b9e\u4f8b\u7684\u6700\u5927\u6570\u76ee\uff0c\u9ed8\u8ba4\u503c\u4e3a8,\u5982\u679c\u8d4b\u503c\u4e3a-1\uff0c\u5219\u8868\u793a\u4e0d\u9650\u5236\uff1b\u5982\u679cpool\u5df2\u7ecf\u5206\u914d\u4e86maxActive\u4e2ajedis\u5b9e\u4f8b\uff0c\u5219\u6b64\u65f6pool\u7684\u72b6\u6001\u4e3aexhausted(\u8017\u5c3d)\u3002 17 | maxtotal=36 18 | 19 | #\u63a7\u5236\u4e00\u4e2apool\u6700\u591a\u6709\u591a\u5c11\u4e2a\u72b6\u6001\u4e3aidle(\u7a7a\u95f2\u7684)\u7684jedis\u5b9e\u4f8b\uff0c\u9ed8\u8ba4\u503c\u4e5f\u662f8\u3002 20 | maxidle=20 21 | #\u63a7\u5236\u4e00\u4e2apool\u6700\u5c11\u6709\u591a\u5c11\u4e2a\u72b6\u6001\u4e3aidle(\u7a7a\u95f2\u7684)\u7684jedis\u5b9e\u4f8b 22 | minidle=5 23 | 24 | #\u7b49\u5f85\u53ef\u7528\u8fde\u63a5\u7684\u6700\u5927\u65f6\u95f4\uff0c\u5355\u4f4d\u6beb\u79d2\uff0c\u9ed8\u8ba4\u503c\u4e3a-1\uff0c\u8868\u793a\u6c38\u4e0d\u8d85\u65f6\u3002\u5982\u679c\u8d85\u8fc7\u7b49\u5f85\u65f6\u95f4\uff0c\u5219\u76f4\u63a5\u629b\u51faJedisConnectionException\uff1b 25 | maxwaitmillis=1000 26 | 27 | #\u5728borrow\u4e00\u4e2ajedis\u5b9e\u4f8b\u65f6\uff0c\u662f\u5426\u63d0\u524d\u8fdb\u884cvalidate\u64cd\u4f5c\uff1b\u5982\u679c\u4e3atrue\uff0c\u5219\u5f97\u5230\u7684jedis\u5b9e\u4f8b\u5747\u662f\u53ef\u7528\u7684\uff1b 28 | testonborrow=true 29 | 30 | #\u95f2\u7f6e\u65f6\u6d4b\u8bd5 31 | testwhileidle=true 32 | 33 | -------------------------------------------------------------------------------- /target/classes/redis.properties: -------------------------------------------------------------------------------- 1 | #redis\u6570\u636e\u5e93\u7c7b\u578b type\u548cnumber\u4e00\u4e00\u5bf9\u5e94 2 | redisdbtype=defaultType, 3 | redisdbnumber=0, 4 | 5 | 6 | 7 | #\u5176\u5b9e\u6211\u4eec\u53ef\u4ee5\u6bcf\u4e00\u4e2a\u4e1a\u52a1db \u90fd\u5bf9\u5e94\u5404\u81ea\u7684redis\u670d\u52a1\u5668\uff0c\u5305\u62ecip\u3001port \u7b49\u7b49\u3002\u76ee\u524d\u6211\u662f\u516c\u7528\u4e00\u4e2a 8 | #redis\u670d\u52a1\u5668\u5730\u5740 \u7aef\u53e3\u53f7\u3001\u5ef6\u8fdf\u65f6\u95f4\u3001\u5bc6\u7801 9 | #host=123.56.118.135 10 | host=10.1.9.231 11 | port=6379 12 | timeout=10000 13 | passwords=msds 14 | 15 | 16 | #\u53ef\u7528\u8fde\u63a5\u5b9e\u4f8b\u7684\u6700\u5927\u6570\u76ee\uff0c\u9ed8\u8ba4\u503c\u4e3a8,\u5982\u679c\u8d4b\u503c\u4e3a-1\uff0c\u5219\u8868\u793a\u4e0d\u9650\u5236\uff1b\u5982\u679cpool\u5df2\u7ecf\u5206\u914d\u4e86maxActive\u4e2ajedis\u5b9e\u4f8b\uff0c\u5219\u6b64\u65f6pool\u7684\u72b6\u6001\u4e3aexhausted(\u8017\u5c3d)\u3002 17 | maxtotal=36 18 | 19 | #\u63a7\u5236\u4e00\u4e2apool\u6700\u591a\u6709\u591a\u5c11\u4e2a\u72b6\u6001\u4e3aidle(\u7a7a\u95f2\u7684)\u7684jedis\u5b9e\u4f8b\uff0c\u9ed8\u8ba4\u503c\u4e5f\u662f8\u3002 20 | maxidle=20 21 | #\u63a7\u5236\u4e00\u4e2apool\u6700\u5c11\u6709\u591a\u5c11\u4e2a\u72b6\u6001\u4e3aidle(\u7a7a\u95f2\u7684)\u7684jedis\u5b9e\u4f8b 22 | minidle=5 23 | 24 | #\u7b49\u5f85\u53ef\u7528\u8fde\u63a5\u7684\u6700\u5927\u65f6\u95f4\uff0c\u5355\u4f4d\u6beb\u79d2\uff0c\u9ed8\u8ba4\u503c\u4e3a-1\uff0c\u8868\u793a\u6c38\u4e0d\u8d85\u65f6\u3002\u5982\u679c\u8d85\u8fc7\u7b49\u5f85\u65f6\u95f4\uff0c\u5219\u76f4\u63a5\u629b\u51faJedisConnectionException\uff1b 25 | maxwaitmillis=1000 26 | 27 | #\u5728borrow\u4e00\u4e2ajedis\u5b9e\u4f8b\u65f6\uff0c\u662f\u5426\u63d0\u524d\u8fdb\u884cvalidate\u64cd\u4f5c\uff1b\u5982\u679c\u4e3atrue\uff0c\u5219\u5f97\u5230\u7684jedis\u5b9e\u4f8b\u5747\u662f\u53ef\u7528\u7684\uff1b 28 | testonborrow=true 29 | 30 | #\u95f2\u7f6e\u65f6\u6d4b\u8bd5 31 | testwhileidle=true 32 | 33 | -------------------------------------------------------------------------------- /src/main/java/com/msds/redis/synchronize/NotifyDataBase.java: -------------------------------------------------------------------------------- 1 | package com.msds.redis.synchronize; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | import lombok.extern.slf4j.Slf4j; 7 | 8 | import org.springframework.beans.factory.annotation.Autowired; 9 | import org.springframework.stereotype.Service; 10 | 11 | import redis.clients.jedis.Jedis; 12 | import redis.clients.jedis.JedisPubSub; 13 | 14 | import com.msds.redis.dao.RedisDao; 15 | import com.msds.redis.util.RedisCacheManager; 16 | import com.msds.redis.util.RedisCachePool; 17 | import com.msds.redis.util.RedisDataBaseType; 18 | 19 | /** 20 | * @ClassName:NotifyDataBase.java 21 | * @Description: pub/sub 异步调用类 22 | * @author gaoguangjin 23 | * @Date 2015-5-22 上午10:13:29 24 | */ 25 | @Slf4j 26 | @Service("notifyDataBase") 27 | public class NotifyDataBase extends JedisPubSub { 28 | @Autowired 29 | RedisUpdateToDataBase redisUpdateToDataBase; 30 | 31 | @Autowired 32 | RedisCacheManager redisCacheManager; 33 | 34 | @Override 35 | public void onMessage(String channel, String sql) { 36 | log.info("redis更新转换成数据库==》sql:" + sql); 37 | 38 | RedisCachePool pool = redisCacheManager.getRedisPoolMap().get(RedisDataBaseType.defaultType.toString()); 39 | final Jedis jedis = pool.getResource(); 40 | 41 | Long length = jedis.llen(RedisDao.LOG); 42 | int n = 2;// 如果log的list size 达到n 的时候就一次性执行更新。测试的时候就弄成2 43 | List list = new ArrayList(); 44 | if (length >= n) { 45 | for (int i = 0; i < n; i++) { 46 | String sqlStr = jedis.lpop(RedisDao.LOG);// 删除list首元素 47 | list.add(sqlStr); 48 | } 49 | 50 | // 是否执行成功 51 | boolean flag = redisUpdateToDataBase.excuteUpdate(list); 52 | if (!flag) { 53 | for (String oldSql : list) { 54 | jedis.lpush(RedisDao.LOG, oldSql);// 更新失败重新添加到list里面 55 | } 56 | } 57 | } 58 | } 59 | 60 | @Override 61 | public void onPMessage(String pattern, String channel, String message) { 62 | log.info("onPMessage"); 63 | } 64 | 65 | @Override 66 | public void onSubscribe(String channel, int subscribedChannels) { 67 | log.info("开始监控redis变化!"); 68 | 69 | } 70 | 71 | @Override 72 | public void onUnsubscribe(String channel, int subscribedChannels) { 73 | log.info("onUnsubscribe"); 74 | 75 | } 76 | 77 | @Override 78 | public void onPUnsubscribe(String pattern, int subscribedChannels) { 79 | log.info("onPUnsubscribe"); 80 | 81 | } 82 | 83 | @Override 84 | public void onPSubscribe(String pattern, int subscribedChannels) { 85 | log.info("onPSubscribe"); 86 | } 87 | 88 | } 89 | -------------------------------------------------------------------------------- /src/test/java/com/msds/test/PutArticelUrlByPage.java: -------------------------------------------------------------------------------- 1 | package com.msds.test; 2 | 3 | import java.io.IOException; 4 | import java.util.concurrent.ConcurrentHashMap; 5 | 6 | import org.apache.http.HttpEntity; 7 | import org.apache.http.client.ClientProtocolException; 8 | import org.apache.http.client.methods.CloseableHttpResponse; 9 | import org.apache.http.client.methods.HttpGet; 10 | import org.apache.http.impl.client.CloseableHttpClient; 11 | import org.apache.http.impl.client.HttpClients; 12 | import org.apache.http.util.EntityUtils; 13 | 14 | public class PutArticelUrlByPage implements Runnable { 15 | public static final String BEGIN_URL = "http://www.tuicool.com/articles/"; 16 | // 推酷上面的 科技和数码栏目 pageNumber 0到20 17 | // http://www.tuicool.com/ah/0/20?lang=0//科技 18 | // http://www.tuicool.com/ah/101050000/20?lang=0//数码 19 | public static final String BEGIN_KJ_URL = "http://www.tuicool.com/ah/0/pageNumber?lang=0"; 20 | public static final String BEGIN_SM_URL = "http://www.tuicool.com/ah/101050000/pageNumber?lang=0"; 21 | 22 | ConcurrentHashMap currentHashMap; 23 | int number; 24 | 25 | public PutArticelUrlByPage(ConcurrentHashMap currentHashMap, int i) { 26 | this.number = i; 27 | this.currentHashMap = currentHashMap; 28 | } 29 | 30 | public void run() { 31 | try { 32 | // 每一个主页开启两个线程 33 | praseHtml(BEGIN_KJ_URL.replace("pageNumber", "" + number)); 34 | praseHtml(BEGIN_SM_URL.replace("pageNumber", "" + number)); 35 | } catch (ClientProtocolException e) { 36 | e.printStackTrace(); 37 | } catch (IOException e) { 38 | e.printStackTrace(); 39 | } 40 | } 41 | 42 | private void praseHtml(String url) throws ClientProtocolException, IOException { 43 | CloseableHttpClient httpClients = HttpClients.createDefault(); 44 | HttpGet httpGet = new HttpGet(url);// get 45 | CloseableHttpResponse response = httpClients.execute(httpGet); 46 | HttpEntity entity = response.getEntity(); 47 | String html = EntityUtils.toString(entity); 48 | putUrl(html); 49 | } 50 | 51 | private void putUrl(String html) { 52 | String[] bb = html.split(" currentHashMap = new ConcurrentHashMap(); 47 | 48 | @Test 49 | @Transactional 50 | public void test() throws IOException { 51 | final Session session = sessionFactory.getCurrentSession(); 52 | ExecutorService pool = Executors.newFixedThreadPool(10); 53 | try { 54 | for (int i = 0; i < 20; i++) {// 总共20也 开启20个线程去爬去链接 55 | pool.execute(new PutArticelUrlByPage(currentHashMap, i)); 56 | } 57 | pool.shutdown(); 58 | pool.awaitTermination(Long.MAX_VALUE, TimeUnit.DAYS);// 线程池里面线程所有执行完之后执行下面 59 | 60 | // 处理map里面的链接,保存到数据库。大概有1123个url 61 | System.out.println("map大小:" + currentHashMap.size()); 62 | long beginTime = System.currentTimeMillis(); 63 | 64 | // 【2】多线程插入、CountDownLatch是用来解决防止session关闭的问题 65 | CountDownLatch latch = new CountDownLatch(currentHashMap.size()); 66 | List listNote = new StoreToDataBaseByThread(currentHashMap, session, latch).insertToDatabase(); 67 | latch.await(); 68 | // 因为用的是durid连接池,获取数据库连接和创建jdbc 必须要在一个线程里面。所以采用串行保存 69 | for (Note note : listNote) { 70 | session.save(note); 71 | } 72 | 73 | long endTime = System.currentTimeMillis(); 74 | log.info("插入数据库耗时:" + (endTime - beginTime) + "ms"); 75 | 76 | System.out.println("end"); 77 | } catch (InterruptedException e) { 78 | log.error("" + e.getLocalizedMessage()); 79 | } 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /src/main/java/com/msds/redis/util/RedisCacheManager.java: -------------------------------------------------------------------------------- 1 | package com.msds.redis.util; 2 | 3 | import java.util.concurrent.ConcurrentHashMap; 4 | 5 | import org.springframework.beans.factory.annotation.Value; 6 | import org.springframework.stereotype.Service; 7 | 8 | import redis.clients.jedis.Jedis; 9 | import redis.clients.jedis.JedisPool; 10 | import redis.clients.jedis.JedisPoolConfig; 11 | 12 | @Service("redisCacheManager") 13 | // @Slf4j 14 | public class RedisCacheManager { 15 | @Value("${redisdbtype}") 16 | private String redisdbtype; 17 | 18 | @Value("${redisdbnumber}") 19 | private String redisdbnumber; 20 | 21 | @Value("${host}") 22 | private String host; 23 | @Value("${port}") 24 | private int port; 25 | @Value("${timeout}") 26 | private int timeout; 27 | @Value("${passwords}") 28 | private String passwords; 29 | 30 | @Value("${maxtotal}") 31 | private String maxtotal; 32 | @Value("${maxidle}") 33 | private String maxidle; 34 | @Value("${minidle}") 35 | private String minidle; 36 | @Value("${maxwaitmillis}") 37 | private String maxwaitmillis; 38 | @Value("${testonborrow}") 39 | private String testonborrow; 40 | @Value("${testwhileidle}") 41 | private String testwhileidle; 42 | 43 | private static JedisPoolConfig poolConfig = null; 44 | 45 | // 保存不同的数据库连接 46 | private ConcurrentHashMap redisPoolMap = new ConcurrentHashMap(); 47 | 48 | public ConcurrentHashMap getRedisPoolMap() { 49 | if (redisPoolMap.size() < 1) { 50 | initConfig(); 51 | initPoolMap(); 52 | } 53 | return redisPoolMap; 54 | } 55 | 56 | /** 57 | * @Description:共享的poolconfig 58 | * @return:void 59 | */ 60 | private void initConfig() { 61 | poolConfig = new JedisPoolConfig(); 62 | poolConfig.setTestOnBorrow(testwhileidle.equals("true") ? true : false); 63 | poolConfig.setTestWhileIdle(testonborrow.equals("true") ? true : false); 64 | poolConfig.setMaxIdle(Integer.parseInt(maxidle)); 65 | poolConfig.setMaxTotal(Integer.parseInt(maxtotal)); 66 | poolConfig.setMinIdle(Integer.parseInt(minidle)); 67 | poolConfig.setMaxWaitMillis(Integer.parseInt(maxwaitmillis)); 68 | } 69 | 70 | private void initPoolMap() { 71 | try { 72 | if (null != redisdbtype && null != redisdbnumber) { 73 | String[] dbs = redisdbtype.split(","); 74 | String[] numbers = redisdbnumber.split(","); 75 | for (int i = 0; i < dbs.length; i++) { 76 | // 得到redis连接池对象 77 | JedisPool jedisPool = new JedisPool(poolConfig, host, port, timeout, passwords); 78 | // 存放不同redis数据库 79 | redisPoolMap.put(dbs[i], new RedisCachePool(Integer.parseInt(numbers[i]), jedisPool)); 80 | } 81 | } 82 | } catch (Exception e) { 83 | // log.error("redisCacheManager初始化失败!" + e.getLocalizedMessage()); 84 | } 85 | } 86 | 87 | /** 88 | * @Description: 得到jedis连接 89 | * @param dbtypeName 90 | * @return:Jedis 91 | */ 92 | public Jedis getResource(RedisDataBaseType dbtypeName) { 93 | Jedis jedisResource = null; 94 | RedisCachePool pool = redisPoolMap.get(dbtypeName.toString()); 95 | if (pool != null) { 96 | jedisResource = pool.getResource(); 97 | } 98 | return jedisResource; 99 | } 100 | 101 | /** 102 | * @Description: 返回连接池 103 | * @param dbtypeName 104 | * @param jedis 105 | * @return:void 106 | */ 107 | public void returnResource(RedisDataBaseType dbtypeName, Jedis jedis) { 108 | RedisCachePool pool = redisPoolMap.get(dbtypeName.toString()); 109 | if (pool != null) 110 | pool.returnResource(jedis); 111 | } 112 | } 113 | -------------------------------------------------------------------------------- /src/test/java/com/msds/test/InitDataToRedis.java: -------------------------------------------------------------------------------- 1 | package com.msds.test; 2 | 3 | import java.io.IOException; 4 | import java.lang.reflect.Field; 5 | import java.util.ArrayList; 6 | import java.util.List; 7 | 8 | import lombok.extern.slf4j.Slf4j; 9 | 10 | import org.hibernate.Query; 11 | import org.hibernate.Session; 12 | import org.hibernate.SessionFactory; 13 | import org.junit.Test; 14 | import org.junit.runner.RunWith; 15 | import org.springframework.beans.factory.annotation.Autowired; 16 | import org.springframework.core.io.Resource; 17 | import org.springframework.core.io.support.PathMatchingResourcePatternResolver; 18 | import org.springframework.core.io.support.ResourcePatternResolver; 19 | import org.springframework.test.context.ContextConfiguration; 20 | import org.springframework.test.context.TestExecutionListeners; 21 | import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; 22 | import org.springframework.test.context.support.DependencyInjectionTestExecutionListener; 23 | import org.springframework.test.context.transaction.TransactionConfiguration; 24 | import org.springframework.test.context.transaction.TransactionalTestExecutionListener; 25 | import org.springframework.transaction.annotation.Transactional; 26 | 27 | import redis.clients.jedis.Jedis; 28 | import redis.clients.jedis.Transaction; 29 | 30 | import com.msds.redis.annation.RedisCache; 31 | import com.msds.redis.dao.RedisDao; 32 | import com.msds.redis.util.RedisCacheManager; 33 | import com.msds.redis.util.RedisCachePool; 34 | import com.msds.redis.util.RedisDataBaseType; 35 | 36 | @Slf4j 37 | @RunWith(SpringJUnit4ClassRunner.class) 38 | @ContextConfiguration({ "classpath:spring-context.xml" }) 39 | @TransactionConfiguration(transactionManager = "transactionManager", defaultRollback = false) 40 | @TestExecutionListeners(listeners = { DependencyInjectionTestExecutionListener.class, TransactionalTestExecutionListener.class }) 41 | /** 42 | * @ClassName:InitDataToRedis.java 43 | * @Description: 初始化数据库数据到redis 44 | * @author gaoguangjin 45 | * @Date 2015-5-21 上午10:02:00 46 | */ 47 | public class InitDataToRedis { 48 | @Autowired 49 | SessionFactory sessionFactory; 50 | @Autowired 51 | RedisCacheManager redisCacheManager; 52 | 53 | @Test 54 | @Transactional 55 | public void init() throws IOException, ClassNotFoundException, NoSuchMethodException, SecurityException { 56 | Jedis jedis = null; 57 | RedisCachePool pool = null; 58 | try { 59 | pool = redisCacheManager.getRedisPoolMap().get(RedisDataBaseType.defaultType.toString()); 60 | jedis = pool.getResource(); 61 | Transaction tx = jedis.multi(); 62 | tx.flushDB();// 清空所有数据 63 | ResourcePatternResolver rp = new PathMatchingResourcePatternResolver(); 64 | Resource[] resources = rp.getResources("classpath:com/msds/dubbo/**/*.class"); 65 | for (Resource resource : resources) { 66 | String className = resource.getFile().getPath().split("classes\\\\")[1].replaceAll("\\\\", ".").replaceAll(".class", ""); 67 | Class clzz = Thread.currentThread().getContextClassLoader().loadClass(className); 68 | if (clzz.getAnnotation(RedisCache.class) != null) { 69 | List listObject = getData(clzz); 70 | RedisDao rd = new RedisDao(tx); 71 | rd.insertListToredis(listObject); 72 | } 73 | } 74 | tx.exec();// 提交事物 75 | } catch (Exception e) { 76 | pool.returnResource(jedis); 77 | log.error("" + e.getLocalizedMessage()); 78 | } 79 | } 80 | 81 | private List getData(Class clzz) throws IllegalArgumentException, IllegalAccessException, NoSuchFieldException { 82 | Field field = clzz.getDeclaredField("className"); 83 | field.setAccessible(true); 84 | String tableName = field.get(clzz).toString(); 85 | final Session session = sessionFactory.getCurrentSession(); 86 | Query query = session.createQuery("from " + tableName); 87 | List objectList = query.list(); 88 | if (objectList.size() > 3) { 89 | objectList = objectList.subList(0, 1); 90 | } 91 | 92 | if (!tableName.equals("Note")) { 93 | objectList = new ArrayList(); 94 | } 95 | return objectList; 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /src/test/java/com/msds/test/StoreToDataBaseByThread.java: -------------------------------------------------------------------------------- 1 | package com.msds.test; 2 | 3 | import java.io.UnsupportedEncodingException; 4 | import java.sql.Blob; 5 | import java.util.Date; 6 | import java.util.Iterator; 7 | import java.util.List; 8 | import java.util.Random; 9 | import java.util.concurrent.ConcurrentHashMap; 10 | import java.util.concurrent.CopyOnWriteArrayList; 11 | import java.util.concurrent.CountDownLatch; 12 | 13 | import lombok.extern.slf4j.Slf4j; 14 | 15 | import org.apache.http.HttpEntity; 16 | import org.apache.http.client.config.RequestConfig; 17 | import org.apache.http.client.methods.CloseableHttpResponse; 18 | import org.apache.http.client.methods.HttpGet; 19 | import org.apache.http.impl.client.CloseableHttpClient; 20 | import org.apache.http.impl.client.HttpClients; 21 | import org.apache.http.impl.conn.PoolingHttpClientConnectionManager; 22 | import org.apache.http.util.EntityUtils; 23 | import org.hibernate.Session; 24 | 25 | import com.msds.dubbo.bean.Note; 26 | import com.msds.dubbo.bean.NoteBook; 27 | import com.msds.dubbo.bean.NoteBookGroup; 28 | 29 | /** 30 | * @ClassName:StoreToDataBase.java 31 | * @Description: 根据url 读取内容写入到表里面 32 | * @author gaoguangjin 33 | * @Date 2015-5-15 下午6:08:19 34 | */ 35 | @Slf4j 36 | public class StoreToDataBaseByThread { 37 | private ConcurrentHashMap currentHashMap; 38 | private Session session; 39 | private CountDownLatch latch; 40 | // 默认笔记本组id是1 41 | private NoteBookGroup noteBookGroup = new NoteBookGroup(); 42 | 43 | // 多线程httpclient解决超时连接 44 | private static RequestConfig defaultRequestConfig = RequestConfig.custom().setSocketTimeout(500000).setConnectTimeout(500000).build(); 45 | // http请求连接池 46 | private PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager(); 47 | // 一个服务器只有一个客户端 48 | private CloseableHttpClient httpClients = HttpClients.custom().setConnectionManager(cm).setDefaultRequestConfig(defaultRequestConfig).build(); 49 | 50 | public StoreToDataBaseByThread(ConcurrentHashMap currentHashMap, Session session, CountDownLatch latch) { 51 | this.currentHashMap = currentHashMap; 52 | this.session = session; 53 | this.latch = latch; 54 | } 55 | 56 | /** 57 | * @Description: 58 | * @see:多单线程插入==》map大小: 插入数据库耗时:50103ms 59 | * @return:void 60 | */ 61 | public List insertToDatabase() { 62 | final Random random = new Random(); 63 | noteBookGroup.setNoteBookGroupId(1); 64 | final List noteList = new CopyOnWriteArrayList(); 65 | Iterator iter = currentHashMap.keySet().iterator(); 66 | try { 67 | while (iter.hasNext()) { 68 | final String title = iter.next(); 69 | final String path = currentHashMap.get(title); 70 | new Thread() { 71 | public void run() { 72 | Note note = new Note(); 73 | NoteBook nb = new NoteBook(); 74 | String content = getHtmlByPath(path); 75 | Blob clobContent; 76 | try { 77 | clobContent = session.getLobHelper().createBlob(content.getBytes("utf-8")); 78 | note.setBlobContent(clobContent); 79 | } catch (UnsupportedEncodingException e) { 80 | e.printStackTrace(); 81 | } 82 | note.setFromUrl(path); 83 | 84 | note.setNoteName(title); 85 | note.setAuthorName("高广金"); 86 | note.setCreatedate(new Date()); 87 | if (content.contains("error:httpClients读取网页内容失败")) { 88 | note.setFlag(1); 89 | } else { 90 | note.setFlag(0); 91 | } 92 | // 随机存放笔记本名称 93 | if (random.nextInt(2) == 1) { 94 | nb.setNoteBookId(1); 95 | } else { 96 | nb.setNoteBookId(2); 97 | } 98 | 99 | note.setNoteBookGroup(noteBookGroup); 100 | note.setNoteBook(nb); 101 | noteList.add(note); 102 | latch.countDown(); 103 | } 104 | }.start(); 105 | } 106 | 107 | } catch (Exception e) { 108 | log.error("爬虫抓取网页内容写入到数据库失败!" + e.getLocalizedMessage()); 109 | } 110 | return noteList; 111 | } 112 | 113 | private String getHtmlByPath(String url) { 114 | HttpGet httpGet = null; 115 | try { 116 | httpGet = new HttpGet(url);// get 117 | // 解决超时 118 | RequestConfig requestConfig = RequestConfig.copy(defaultRequestConfig).build(); 119 | httpGet.setConfig(requestConfig); 120 | CloseableHttpResponse response = httpClients.execute(httpGet); 121 | HttpEntity entity = response.getEntity(); 122 | return EntityUtils.toString(entity, "utf-8"); 123 | 124 | } catch (Exception e) { 125 | log.error("httpClients读取网页内容失败!" + e.getLocalizedMessage() + ":" + url); 126 | return "error:httpClients读取网页内容失败:失败地址" + url + "===错误信息" + e.getLocalizedMessage(); 127 | } 128 | finally { 129 | httpGet.releaseConnection(); 130 | } 131 | } 132 | 133 | } 134 | -------------------------------------------------------------------------------- /src/main/java/com/msds/redis/util/RedisCacheManagers.java: -------------------------------------------------------------------------------- 1 | package com.msds.redis.util; 2 | 3 | import java.io.IOException; 4 | import java.io.InputStream; 5 | import java.util.Properties; 6 | import java.util.concurrent.ConcurrentHashMap; 7 | 8 | import org.springframework.context.ApplicationContext; 9 | import org.springframework.context.support.ClassPathXmlApplicationContext; 10 | import org.springframework.core.io.DefaultResourceLoader; 11 | import org.springframework.core.io.Resource; 12 | import org.springframework.core.io.ResourceLoader; 13 | 14 | import redis.clients.jedis.Jedis; 15 | import redis.clients.jedis.JedisPool; 16 | import redis.clients.jedis.JedisPoolConfig; 17 | 18 | /** 19 | * @ClassName:RedisCacheManagers.java 20 | * @Description: redisMap 封装不同的db 21 | * @author gaoguangjin 22 | * @Date 2015-5-27 下午7:49:54 23 | */ 24 | public class RedisCacheManagers { 25 | private static String redisdbtype; 26 | private static String redisdbnumber; 27 | 28 | private static String host; 29 | private static String port; 30 | private static String timeout; 31 | private static String passwords; 32 | 33 | private static String maxtotal; 34 | private static String maxidle; 35 | private static String minidle; 36 | private static String maxwaitmillis; 37 | private static String testonborrow; 38 | private static String testwhileidle; 39 | 40 | private static JedisPoolConfig poolConfig = null; 41 | 42 | // 保存不同的数据库连接 43 | private static ConcurrentHashMap redisPoolMap = new ConcurrentHashMap(); 44 | 45 | static { 46 | ResourceLoader resourceLoader = new DefaultResourceLoader(); 47 | Resource resource = resourceLoader.getResource("redis.properties"); 48 | InputStream is; 49 | try { 50 | Properties props = new Properties(); 51 | is = resource.getInputStream(); 52 | props.load(is); 53 | 54 | redisdbtype = props.getProperty("redisdbtype"); 55 | redisdbnumber = props.getProperty("redisdbnumber"); 56 | host = props.getProperty("host"); 57 | port = props.getProperty("port"); 58 | timeout = props.getProperty("timeout"); 59 | passwords = props.getProperty("passwords"); 60 | maxtotal = props.getProperty("maxtotal"); 61 | maxidle = props.getProperty("maxidle"); 62 | minidle = props.getProperty("minidle"); 63 | maxwaitmillis = props.getProperty("maxwaitmillis"); 64 | testonborrow = props.getProperty("testonborrow"); 65 | testwhileidle = props.getProperty("testwhileidle"); 66 | } catch (IOException e) { 67 | System.out.println("初始化redis连接池失败!"); 68 | } 69 | 70 | } 71 | 72 | /** 73 | * @Description: 手动测试 74 | * @param args 75 | * @return:void 76 | */ 77 | public static void main(String[] args) { 78 | ApplicationContext ac = new ClassPathXmlApplicationContext("classpath:spring-context.xml"); 79 | } 80 | 81 | public static ConcurrentHashMap getRedisPoolMap() { 82 | if (redisPoolMap.size() < 1) { 83 | initConfig(); 84 | initPoolMap(); 85 | } 86 | return redisPoolMap; 87 | } 88 | 89 | /** 90 | * @Description:共享的poolconfig 91 | * @return:void 92 | */ 93 | private static void initConfig() { 94 | poolConfig = new JedisPoolConfig(); 95 | poolConfig.setTestOnBorrow(testwhileidle.equals("true") ? true : false); 96 | poolConfig.setTestWhileIdle(testonborrow.equals("true") ? true : false); 97 | poolConfig.setMaxIdle(Integer.parseInt(maxidle)); 98 | poolConfig.setMaxTotal(Integer.parseInt(maxtotal)); 99 | poolConfig.setMinIdle(Integer.parseInt(minidle)); 100 | poolConfig.setMaxWaitMillis(Integer.parseInt(maxwaitmillis)); 101 | } 102 | 103 | private static void initPoolMap() { 104 | try { 105 | if (null != redisdbtype && null != redisdbnumber) { 106 | String[] dbs = redisdbtype.split(","); 107 | String[] numbers = redisdbnumber.split(","); 108 | for (int i = 0; i < dbs.length; i++) { 109 | // 得到redis连接池对象 110 | JedisPool jedisPool = new JedisPool(poolConfig, host, Integer.parseInt(port), Integer.parseInt(timeout), passwords); 111 | // 存放不同redis数据库 112 | redisPoolMap.put(dbs[i], new RedisCachePool(Integer.parseInt(numbers[i]), jedisPool)); 113 | } 114 | } 115 | } catch (Exception e) { 116 | // log.error("redisCacheManager初始化失败!" + e.getLocalizedMessage()); 117 | } 118 | } 119 | 120 | /** 121 | * @Description: 得到jedis连接 122 | * @param dbtypeName 123 | * @return:Jedis 124 | */ 125 | public Jedis getResource(RedisDataBaseType dbtypeName) { 126 | Jedis jedisResource = null; 127 | RedisCachePool pool = redisPoolMap.get(dbtypeName.toString()); 128 | if (pool != null) { 129 | jedisResource = pool.getResource(); 130 | } 131 | return jedisResource; 132 | } 133 | 134 | /** 135 | * @Description: 返回连接池 136 | * @param dbtypeName 137 | * @param jedis 138 | * @return:void 139 | */ 140 | public void returnResource(RedisDataBaseType dbtypeName, Jedis jedis) { 141 | RedisCachePool pool = redisPoolMap.get(dbtypeName.toString()); 142 | if (pool != null) 143 | pool.returnResource(jedis); 144 | } 145 | } 146 | -------------------------------------------------------------------------------- /src/main/resources/spring-context.xml: -------------------------------------------------------------------------------- 1 | 2 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | update 64 | org.hibernate.dialect.MySQLDialect 65 | false 66 | true 1, false 0, yes 1, no 0 67 | 68 | 69 | 70 | classpath:hibernate/hibernate.cfg.xml 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | -------------------------------------------------------------------------------- /src/test/java/com/msds/redis/performance/RedisCompareDataBase.java: -------------------------------------------------------------------------------- 1 | package com.msds.redis.performance; 2 | 3 | import java.util.List; 4 | 5 | import lombok.extern.slf4j.Slf4j; 6 | 7 | import org.hibernate.Query; 8 | import org.hibernate.Session; 9 | import org.hibernate.SessionFactory; 10 | import org.junit.Test; 11 | import org.junit.runner.RunWith; 12 | import org.springframework.beans.factory.annotation.Autowired; 13 | import org.springframework.beans.factory.annotation.Qualifier; 14 | import org.springframework.test.context.ContextConfiguration; 15 | import org.springframework.test.context.TestExecutionListeners; 16 | import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; 17 | import org.springframework.test.context.support.DependencyInjectionTestExecutionListener; 18 | import org.springframework.test.context.transaction.TransactionConfiguration; 19 | import org.springframework.test.context.transaction.TransactionalTestExecutionListener; 20 | import org.springframework.transaction.annotation.Transactional; 21 | 22 | import redis.clients.jedis.Jedis; 23 | 24 | import com.msds.dubbo.bean.Note; 25 | import com.msds.dubbo.service.BaseService; 26 | import com.msds.dubbo.service.NoteService; 27 | import com.msds.redis.util.RedisCacheManager; 28 | import com.msds.redis.util.RedisCachePool; 29 | import com.msds.redis.util.RedisDataBaseType; 30 | 31 | @Slf4j 32 | @RunWith(SpringJUnit4ClassRunner.class) 33 | @ContextConfiguration({ "classpath:spring-context.xml" }) 34 | @TransactionConfiguration(transactionManager = "transactionManager", defaultRollback = false) 35 | @TestExecutionListeners(listeners = { DependencyInjectionTestExecutionListener.class, TransactionalTestExecutionListener.class }) 36 | public class RedisCompareDataBase { 37 | 38 | @Autowired 39 | SessionFactory sessionFactory; 40 | @Autowired 41 | RedisCacheManager redisCacheManager; 42 | 43 | @Qualifier("NoteServiceImp") 44 | @Autowired 45 | BaseService baseService; 46 | 47 | @Autowired 48 | NoteService noteService; 49 | 50 | // @Test 51 | // @Transactional 52 | public void selectAll() { 53 | long time1 = System.currentTimeMillis(); 54 | Query query = sessionFactory.getCurrentSession().createQuery("from Note"); 55 | List objectList = query.list(); 56 | for (Note note : objectList) { 57 | log.info(note.toString()); 58 | } 59 | long time2 = System.currentTimeMillis(); 60 | 61 | List noteList = baseService.findAll(); 62 | for (Note note : objectList) { 63 | log.info(note.toString()); 64 | } 65 | long time3 = System.currentTimeMillis(); 66 | 67 | log.info("jdbc查询 数据大小" + noteList.size() + "耗时:" + (time2 - time1)); 68 | log.info("redis查询 数据大小" + objectList.size() + " 耗时:" + (time3 - time2)); 69 | 70 | } 71 | 72 | // @Test 73 | // @Transactional 74 | public void selectOne() { 75 | long time1 = System.currentTimeMillis(); 76 | Session session = sessionFactory.getCurrentSession(); 77 | for (int i = 1; i < 100; i++) { 78 | Note note = (Note) session.get(Note.class, i); 79 | log.info(note.toString()); 80 | } 81 | long time2 = System.currentTimeMillis(); 82 | 83 | for (int i = 1; i < 100; i++) { 84 | Note note2 = noteService.queryById(i + ""); 85 | log.info(note2.toString()); 86 | } 87 | long time3 = System.currentTimeMillis(); 88 | 89 | log.info("jdbc查询 据单条数据耗时:" + (time2 - time1)); 90 | log.info("redis查询 单条数据 耗时:" + (time3 - time2)); 91 | } 92 | 93 | // redis查询单条数据的某个字段值,循环100是用来放大倍数的 jdbc查询 单条数据的某个字段值耗时:375||redis查询 单条数据的某个字段值 耗时:207 94 | // @Test 95 | // @Transactional 96 | public void selectParam() { 97 | long time1 = System.currentTimeMillis(); 98 | Session session = sessionFactory.getCurrentSession(); 99 | for (int i = 1; i < 100; i++) { 100 | Note note = (Note) session.get(Note.class, i); 101 | log.info(note.getNoteName()); 102 | } 103 | long time2 = System.currentTimeMillis(); 104 | 105 | RedisCachePool pool = redisCacheManager.getRedisPoolMap().get(RedisDataBaseType.defaultType.toString()); 106 | Jedis jedis = pool.getResource(); 107 | 108 | for (int i = 1; i < 100; i++) { 109 | log.info(jedis.get("Note:" + i + ":noteName")); 110 | } 111 | long time3 = System.currentTimeMillis(); 112 | 113 | log.info("jdbc查询 单条数据的某个字段值耗时:" + (time2 - time1)); 114 | log.info("redis查询 单条数据的某个字段值 耗时:" + (time3 - time2)); 115 | } 116 | 117 | // 1706 //1815 118 | @Test 119 | @Transactional 120 | public void update() { 121 | long time1 = System.currentTimeMillis(); 122 | Session session = sessionFactory.getCurrentSession(); 123 | Note note = (Note) session.get(Note.class, 1); 124 | if (null != note) { 125 | note.setAuthorName("张静月1"); 126 | note.setFromUrl("www.ggjlovezjy.com:13141"); 127 | } 128 | session.save(note); 129 | long time2 = System.currentTimeMillis(); 130 | 131 | RedisCachePool pool = redisCacheManager.getRedisPoolMap().get(RedisDataBaseType.defaultType.toString()); 132 | Jedis jedis = pool.getResource(); 133 | Note note2 = noteService.queryById("1"); 134 | if (null != note2) { 135 | note.setAuthorName("张静月2"); 136 | note.setFromUrl("www.ggjlovezjy.com:13142"); 137 | } 138 | baseService.update(note2); 139 | long time3 = System.currentTimeMillis(); 140 | 141 | log.info("jdbc 更新数据的某个字段值耗时:" + (time2 - time1)); 142 | log.info("redis 更新数据的某个字段值 耗时:" + (time3 - time2)); 143 | } 144 | } 145 | -------------------------------------------------------------------------------- /src/test/java/com/msds/test/JuitTest.java: -------------------------------------------------------------------------------- 1 | package com.msds.test; 2 | 3 | import java.util.List; 4 | import java.util.Set; 5 | 6 | import lombok.extern.slf4j.Slf4j; 7 | 8 | import org.junit.Test; 9 | import org.junit.runner.RunWith; 10 | import org.springframework.beans.factory.annotation.Autowired; 11 | import org.springframework.beans.factory.annotation.Qualifier; 12 | import org.springframework.test.context.ContextConfiguration; 13 | import org.springframework.test.context.TestExecutionListeners; 14 | import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; 15 | import org.springframework.test.context.support.DependencyInjectionTestExecutionListener; 16 | import org.springframework.test.context.transaction.TransactionConfiguration; 17 | import org.springframework.test.context.transaction.TransactionalTestExecutionListener; 18 | 19 | import redis.clients.jedis.Jedis; 20 | import redis.clients.jedis.JedisPubSub; 21 | 22 | import com.msds.dubbo.bean.Note; 23 | import com.msds.dubbo.service.BaseService; 24 | import com.msds.dubbo.service.NoteService; 25 | import com.msds.redis.synchronize.NotifyDataBase; 26 | import com.msds.redis.util.RedisCacheManager; 27 | import com.msds.redis.util.RedisCachePool; 28 | import com.msds.redis.util.RedisDataBaseType; 29 | 30 | @Slf4j 31 | @RunWith(SpringJUnit4ClassRunner.class) 32 | @ContextConfiguration({ "classpath:spring-context.xml" }) 33 | @TransactionConfiguration(transactionManager = "transactionManager", defaultRollback = false) 34 | @TestExecutionListeners(listeners = { DependencyInjectionTestExecutionListener.class, TransactionalTestExecutionListener.class }) 35 | /** 36 | * 37 | * @ClassName:JuitTest.java 38 | * @Description: redis测试 39 | * @author gaoguangjin 40 | * @Date 2015-5-21 上午10:03:00 41 | */ 42 | public class JuitTest { 43 | @Autowired 44 | RedisCacheManager redisCacheManager; 45 | @Qualifier("NoteServiceImp") 46 | @Autowired 47 | BaseService baseService; 48 | @Autowired 49 | NoteService noteService; 50 | 51 | // 启动日志监听,用MonitorSql 类代替 因为单元测试里面多线程无法堵塞 52 | // @Before 53 | public void before() { 54 | RedisCachePool pool = redisCacheManager.getRedisPoolMap().get(RedisDataBaseType.defaultType.toString()); 55 | final Jedis jedis = pool.getResource(); 56 | final JedisPubSub ndb = new NotifyDataBase(); 57 | new Thread() { 58 | public void run() {// 会广播形式打印log日志 59 | jedis.subscribe(ndb, "publog"); 60 | } 61 | }.start(); 62 | } 63 | 64 | // 查询所有数据。redis和服务器子同一局域网下 65 | // @Test 66 | public void findAll() { 67 | long time = System.currentTimeMillis(); 68 | List list = baseService.findAll(); 69 | 70 | for (Note note : list) { 71 | log.info(note.toString()); 72 | } 73 | long time2 = System.currentTimeMillis(); 74 | log.info("耗时" + (time2 - time));// 9790 75 | } 76 | 77 | // 查询单条数据 78 | // @Test 79 | public void findOne() { 80 | String id = "1"; 81 | Note note = noteService.queryById(id); 82 | log.info(note.toString()); 83 | } 84 | 85 | @Test 86 | public void insert() throws Exception { 87 | Note note = new Note(); 88 | note.setFlag(0); 89 | note.setFromUrl("www.ggjlovezjy.com:1314"); 90 | note.setNoteName("测试插入"); 91 | note.setAuthorName("高广金测试插入"); 92 | // baseService.insert(note); 93 | 94 | // List noteList = new ArrayList(); 95 | // noteList.add(note); 96 | // Transaction tx = 97 | // redisCacheManager.getRedisPoolMap().get(RedisDataBaseType.defaultType.toString()).getResource().multi(); 98 | // 99 | // RedisDao da = new RedisDao(tx); 100 | // da.insertListToredis(noteList); 101 | // tx.exec(); 102 | 103 | } 104 | 105 | // 查询带参数的 106 | // @Test 107 | public void findByParam() { 108 | Note note = new Note(); 109 | note.setAuthorName("张静月"); 110 | note.setFromUrl("http://www.tuicool.com/"); 111 | List noteList = noteService.queryParamAnd(note); 112 | 113 | for (Note list : noteList) { 114 | log.info(list.toString()); 115 | } 116 | } 117 | 118 | /** 119 | * @Description: 测试删除 120 | */ 121 | // @Test 122 | public void delete() { 123 | for (int i = 0; i < 2; i++) { 124 | baseService.delete(i + ""); 125 | } 126 | } 127 | 128 | /** 129 | * @Description: 测试更新。更新需要注意的细节就是,先从redis里面查询出来的值,然后在上面做修改。 130 | */ 131 | // @Test 132 | public void update() { 133 | String id = "2"; 134 | Note note = noteService.queryById(id); 135 | note.setAuthorName("张静月"); 136 | note.setFromUrl("www.ggjlovezjy.com:1314"); 137 | baseService.update(note); 138 | } 139 | 140 | // @Test 141 | public void after() { 142 | RedisCachePool pool = redisCacheManager.getRedisPoolMap().get(RedisDataBaseType.defaultType.toString()); 143 | Jedis jedis = pool.getResource(); 144 | log.info("======删除之后打印==========="); 145 | display(jedis); 146 | pool.returnResource(jedis); 147 | } 148 | 149 | private void display(Jedis jedis) { 150 | Set aa = jedis.smembers("Note:createdate:2015-05-20 01:04:13.0"); 151 | Set bb = jedis.smembers("Note:fromUrl:http://www.tuicool.com/articles/vquaei"); 152 | Set cc = jedis.smembers("Note:flag:0"); 153 | Set dd = jedis.smembers("Note:authorName:高广金"); 154 | for (String string1 : aa) { 155 | log.info("验证a" + string1);// 日期有重复的 156 | } 157 | for (String string2 : bb) { 158 | log.info("验证b" + string2); 159 | } 160 | for (String string3 : cc) { 161 | log.info("验证c" + string3); 162 | } 163 | for (String string4 : dd) { 164 | log.info("验证d" + string4); 165 | } 166 | } 167 | } 168 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4.0.0 3 | cn.msec.core 4 | redis 5 | 0.0.1 6 | 7 | UTF-8 8 | 4.0.5.RELEASE 9 | 10 | 2.4.10 11 | 0.1 12 | 13 | 14 | 15 | 16 | 17 | cn.msec.common.platform 18 | pom.parent 19 | 0.1.0 20 | 21 | 22 | 23 | 24 | redis.clients 25 | jedis 26 | 2.6.0 27 | 28 | 29 | com.alibaba 30 | fastjson 31 | 1.1.41 32 | 33 | 34 | 35 | 36 | com.alibaba 37 | dubbo 38 | ${dubbo.version} 39 | 40 | 41 | 42 | spring 43 | org.springframework 44 | 45 | 46 | 47 | 48 | 49 | com.github.sgroschupf 50 | zkclient 51 | ${zkclient.version} 52 | 53 | 54 | 55 | junit 56 | junit 57 | 4.9 58 | 59 | 60 | 61 | 62 | mysql 63 | mysql-connector-java 64 | 5.1.30 65 | 66 | 67 | 68 | 69 | org.slf4j 70 | slf4j-log4j12 71 | 1.7.2 72 | 73 | 74 | 75 | 76 | org.projectlombok 77 | lombok 78 | 1.12.6 79 | 80 | 81 | 82 | 83 | org.hibernate 84 | hibernate-core 85 | 4.3.8.Final 86 | 87 | 88 | 89 | 90 | 91 | dom4j 92 | dom4j 93 | 1.6.1 94 | 95 | 96 | org.hibernate.common 97 | hibernate-commons-annotations 98 | 4.0.5.Final 99 | 100 | 101 | org.hibernate.javax.persistence 102 | hibernate-jpa-2.1-api 103 | 1.0.0.Final 104 | 105 | 106 | org.javassist 107 | javassist 108 | 3.18.1-GA 109 | 110 | 111 | org.jboss 112 | jandex 113 | 1.1.0.Final 114 | 115 | 116 | org.jboss.logging 117 | jboss-logging 118 | 3.1.3.GA 119 | 120 | 121 | org.jboss.logging 122 | jboss-logging-annotations 123 | 1.2.0.Beta1 124 | 125 | 126 | org.jboss.spec.javax.transaction 127 | jboss-transaction-api_1.2_spec 128 | 1.0.0.Final 129 | 130 | 131 | c3p0 132 | c3p0 133 | 0.9.1.2 134 | 135 | 136 | 137 | 138 | org.springframework 139 | spring-context 140 | ${spring.version} 141 | 142 | 143 | org.springframework 144 | spring-webmvc-portlet 145 | ${spring.version} 146 | 147 | 148 | 149 | org.springframework 150 | spring-aop 151 | ${spring.version} 152 | 153 | 154 | org.springframework 155 | spring-tx 156 | ${spring.version} 157 | 158 | 159 | org.springframework 160 | spring-context-support 161 | ${spring.version} 162 | 163 | 164 | org.springframework 165 | spring-jdbc 166 | ${spring.version} 167 | 168 | 169 | org.springframework 170 | spring-web 171 | ${spring.version} 172 | 173 | 174 | org.springframework 175 | spring-webmvc 176 | ${spring.version} 177 | 178 | 179 | org.springframework 180 | spring-aspects 181 | ${spring.version} 182 | 183 | 184 | org.springframework 185 | spring-beans 186 | ${spring.version} 187 | 188 | 189 | org.springframework 190 | spring-core 191 | ${spring.version} 192 | 193 | 194 | org.springframework 195 | spring-jms 196 | ${spring.version} 197 | 198 | 199 | org.springframework 200 | spring-expression 201 | ${spring.version} 202 | 203 | 204 | org.springframework 205 | spring-instrument 206 | ${spring.version} 207 | 208 | 209 | org.springframework 210 | spring-orm 211 | ${spring.version} 212 | 213 | 214 | org.springframework 215 | spring-oxm 216 | ${spring.version} 217 | 218 | 219 | org.springframework 220 | spring-test 221 | ${spring.version} 222 | 223 | 224 | 225 | 226 | 227 | cglib 228 | cglib 229 | 2.2.2 230 | 231 | 232 | 233 | aopalliance 234 | aopalliance 235 | 1.0 236 | 237 | 238 | org.aspectj 239 | aspectjweaver 240 | 1.8.4 241 | 242 | 243 | 244 | 245 | com.alibaba 246 | druid 247 | 1.0.5 248 | 249 | 250 | org.apache.httpcomponents 251 | httpclient 252 | 4.3.1 253 | 254 | 255 | 256 | 257 | 258 | 259 | 260 | org.apache.maven.plugins 261 | maven-war-plugin 262 | 2.4 263 | 264 | false 265 | 266 | 267 | 268 | 269 | redis 270 | -------------------------------------------------------------------------------- /src/main/java/com/msds/dubbo/service/imp/NoteServiceImp.java: -------------------------------------------------------------------------------- 1 | package com.msds.dubbo.service.imp; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | import java.util.Set; 6 | 7 | import lombok.extern.slf4j.Slf4j; 8 | 9 | import org.springframework.beans.factory.annotation.Autowired; 10 | import org.springframework.stereotype.Service; 11 | 12 | import redis.clients.jedis.Jedis; 13 | import redis.clients.jedis.Transaction; 14 | 15 | import com.msds.dubbo.bean.Note; 16 | import com.msds.dubbo.service.BaseService; 17 | import com.msds.dubbo.service.NoteService; 18 | import com.msds.redis.dao.RedisDao; 19 | import com.msds.redis.util.BeanField; 20 | import com.msds.redis.util.RedisCacheManager; 21 | import com.msds.redis.util.RedisCachePool; 22 | import com.msds.redis.util.RedisDataBaseType; 23 | 24 | @Service("NoteServiceImp") 25 | @Slf4j 26 | public class NoteServiceImp implements NoteService, BaseService { 27 | @Autowired 28 | RedisCacheManager redisCacheManager; 29 | 30 | public List findAll() { 31 | List noteList = new ArrayList(); 32 | RedisCachePool pool = null; 33 | Jedis jedis = null; 34 | try { 35 | pool = redisCacheManager.getRedisPoolMap().get(RedisDataBaseType.defaultType.toString()); 36 | jedis = pool.getResource(); 37 | // 查询不用开启事物 38 | RedisDao rd = new RedisDao(jedis); 39 | Set sortKey = rd.smembers("Note:index:noteId"); 40 | noteList = (List) rd.getListBean(sortKey, Note.class, jedis); 41 | 42 | // dubbo 调用的时候防止java.sql.Blob cannot be assigned from null ,也就是blob字段不能为空 43 | delalBlob(noteList); 44 | } catch (Exception e) { 45 | log.error(" List findAll()查询失败!" + e.getLocalizedMessage()); 46 | } 47 | finally { 48 | log.info("回收jedis连接"); 49 | pool.returnResource(jedis); 50 | } 51 | return noteList; 52 | } 53 | 54 | public void delete(String id) { 55 | RedisCachePool pool = null; 56 | Jedis jedis = null; 57 | RedisDao rd = null; 58 | try { 59 | pool = redisCacheManager.getRedisPoolMap().get(RedisDataBaseType.defaultType.toString()); 60 | jedis = pool.getResource(); 61 | Object note = RedisDao.getBean("Note:" + id, Note.class, jedis); 62 | 63 | if (null != note) { 64 | // 查询之后开启事物 65 | Transaction transation = jedis.multi(); 66 | 67 | rd = new RedisDao(transation); 68 | rd.delSingleDataFromRedis(note, rd.getBeanField(note)); 69 | 70 | /* 处理之后的数据库sql日志处理 */ 71 | String logs = "delete from tcnote where note_id=" + id; 72 | rd.pubishLog(logs); 73 | rd.log(logs); 74 | 75 | transation.exec(); 76 | } 77 | } catch (Exception e) { 78 | log.error(" delete(String id) 删除失败!" + e.getLocalizedMessage()); 79 | } 80 | finally { 81 | log.info("回收jedis连接"); 82 | pool.returnResource(jedis); 83 | } 84 | } 85 | 86 | /** 87 | * 更新直接调用删除,然后再插入 88 | */ 89 | public void update(Note newNote) { 90 | RedisCachePool pool = null; 91 | Jedis jedis = null; 92 | RedisDao rd = null; 93 | try { 94 | pool = redisCacheManager.getRedisPoolMap().get(RedisDataBaseType.defaultType.toString()); 95 | jedis = pool.getResource(); 96 | 97 | // 获取原来redis里面存储的note 98 | Object orldNote = RedisDao.getBean("Note:" + newNote.getNoteId(), Note.class, jedis); 99 | if (null != orldNote) { 100 | // 查询之后开启事物 101 | Transaction transation = jedis.multi(); 102 | rd = new RedisDao(transation); 103 | BeanField beanField = rd.getBeanField(orldNote); 104 | 105 | // // 先删除原来的 106 | // rd.delSingleDataFromRedis(orldNote, beanField); 107 | // // 再插入新修改的note 108 | // rd.insertSingleDataToredis(newNote, beanField); 109 | 110 | rd.updateSingleFromToredis(orldNote, newNote, beanField); 111 | 112 | /* 处理之后的数据库sql日志处理 */ 113 | String logs = genSql(newNote); 114 | rd.pubishLog(logs); 115 | rd.log(logs); 116 | transation.exec(); 117 | } 118 | } catch (Exception e) { 119 | log.error(" update(Note note) 失败!" + e.getLocalizedMessage()); 120 | } 121 | finally { 122 | // log.info("回收jedis连接"); 123 | pool.returnResource(jedis); 124 | } 125 | } 126 | 127 | /** 128 | * @Description: 组织sql 129 | * @param note 130 | * @return:void 131 | */ 132 | private String genSql(Note note) { 133 | // 组装sql 134 | StringBuilder sb = new StringBuilder(); 135 | sb.append(" update tcnote set "); 136 | 137 | if (note.getAuthorName() != null) { 138 | sb.append(" author_name='" + note.getAuthorName() + "', "); 139 | } 140 | if (note.getFromUrl() != null) { 141 | sb.append(" from_Url='" + note.getFromUrl() + "', "); 142 | } 143 | if (note.getNoteName() != null) { 144 | sb.append(" note_name='" + note.getNoteName() + "', "); 145 | } 146 | // flag=0防止note里面字段都是空的 147 | sb.append(" flag=0 where note_id= " + note.getNoteId()); 148 | 149 | return sb.toString(); 150 | } 151 | 152 | public Note queryById(String i) { 153 | Note note = new Note(); 154 | RedisCachePool pool = redisCacheManager.getRedisPoolMap().get(RedisDataBaseType.defaultType.toString()); 155 | Jedis jedis = pool.getResource(); 156 | // 查询不用开启事物 157 | RedisDao rd = new RedisDao(jedis); 158 | note = (Note) rd.getBean("Note:" + i, note.getClass(), jedis); 159 | pool.returnResource(jedis); 160 | 161 | // dubbo 调用的时候防止java.sql.Blob cannot be assigned from null ,也就是blob字段不能为空 162 | note.setBlobContent(null); 163 | return note; 164 | } 165 | 166 | /** 167 | * select * from tcnote where author_name=? and from_url=? 168 | */ 169 | public List queryParamAnd(Note note) { 170 | List noteList = new ArrayList(); 171 | RedisCachePool pool = null; 172 | Jedis jedis = null; 173 | try { 174 | pool = redisCacheManager.getRedisPoolMap().get(RedisDataBaseType.defaultType.toString()); 175 | jedis = pool.getResource(); 176 | // 查询不用开启事物 177 | RedisDao rd = new RedisDao(jedis); 178 | 179 | String[] kes = genKeys(note);// 获取需要查询的key的值 180 | Set sortKey = rd.sinter(kes);// 获取交集的主键 181 | noteList = (List) rd.getListBean(sortKey, Note.class, jedis); 182 | 183 | // dubbo 调用的时候防止java.sql.Blob cannot be assigned from null ,也就是blob字段不能为空 184 | delalBlob(noteList); 185 | } catch (Exception e) { 186 | log.error(" List findAll()查询失败!" + e.getLocalizedMessage()); 187 | } 188 | finally { 189 | log.info("回收jedis连接"); 190 | pool.returnResource(jedis); 191 | } 192 | return noteList; 193 | } 194 | 195 | /** 196 | * @Description: 组装key值 197 | * @param note 198 | * @return:void 199 | */ 200 | private String[] genKeys(Note note) { 201 | String[] string = null; 202 | StringBuilder sb = new StringBuilder(); 203 | 204 | if (note.getAuthorName() != null) { 205 | sb.append("," + "Note:authorName:" + note.getAuthorName()); 206 | } 207 | if (note.getFromUrl() != null) { 208 | sb.append("," + "Note:fromUrl:" + note.getFromUrl() + ","); 209 | } 210 | if (note.getFlag() != null) { 211 | sb.append("," + "Note:flag:" + note.getFlag() + ","); 212 | } 213 | 214 | if (null != sb.toString()) { 215 | // 去除第一个逗号 216 | String replaceString = sb.toString().replaceFirst(",", ""); 217 | string = replaceString.split(","); 218 | } 219 | return string; 220 | } 221 | 222 | private void delalBlob(List noteList) { 223 | for (Note note : noteList) { 224 | note.setBlobContent(null); 225 | } 226 | } 227 | 228 | public void insert(Note note) { 229 | RedisCachePool pool = null; 230 | Jedis jedis = null; 231 | RedisDao rd = null; 232 | try { 233 | pool = redisCacheManager.getRedisPoolMap().get(RedisDataBaseType.defaultType.toString()); 234 | jedis = pool.getResource(); 235 | 236 | // 获取redis里面最大的主键值 237 | Set sortKey = RedisDao.getRevrangeSortSet("Note:sort:noteId", 0, 0, jedis); 238 | for (String id : sortKey) { 239 | // 新增的主键赋值 240 | note.setNoteId(Integer.parseInt(id) + 1); 241 | break; 242 | } 243 | 244 | Transaction transation = jedis.multi(); 245 | rd = new RedisDao(transation); 246 | BeanField beanField = rd.getBeanField(note); 247 | // 插入新增的 248 | rd.insertSingleDataToredis(note, beanField); 249 | 250 | /* 处理之后的数据库sql日志处理 */ 251 | String logs = insertSql(note); 252 | rd.pubishLog(logs); 253 | rd.log(logs); 254 | transation.exec(); 255 | 256 | } catch (Exception e) { 257 | log.error(" insert(Note note) 失败!" + e.getLocalizedMessage()); 258 | } 259 | finally { 260 | log.info("回收insert==>jedis连接"); 261 | pool.returnResource(jedis); 262 | } 263 | } 264 | 265 | private String insertSql(Note note) { 266 | // 组装sql 267 | StringBuilder sb = new StringBuilder(); 268 | sb.append("insert into tcnote (note_id,note_name,author_name,from_url,flag,noteBook,noteBookGroup) values ( "); 269 | sb.append(note.getNoteId() + ", "); 270 | sb.append("'" + note.getNoteName() + "', "); 271 | sb.append("'" + note.getAuthorName() + "', "); 272 | sb.append("'" + note.getFromUrl() + "', "); 273 | sb.append(note.getFlag() + ", "); 274 | sb.append(" 1, "); 275 | sb.append(" 1 )"); 276 | return sb.toString(); 277 | } 278 | 279 | } 280 | -------------------------------------------------------------------------------- /src/main/java/com/msds/redis/dao/RedisDao.java: -------------------------------------------------------------------------------- 1 | package com.msds.redis.dao; 2 | 3 | import java.lang.reflect.Field; 4 | import java.util.ArrayList; 5 | import java.util.List; 6 | import java.util.Set; 7 | 8 | import redis.clients.jedis.Jedis; 9 | import redis.clients.jedis.Pipeline; 10 | import redis.clients.jedis.Transaction; 11 | 12 | import com.alibaba.fastjson.JSON; 13 | import com.msds.redis.annation.RedisFieldNotCache; 14 | import com.msds.redis.annation.RedisQuery; 15 | import com.msds.redis.util.BeanField; 16 | 17 | /** 18 | * @ClassName:RedisDao.java 19 | * @Description: redisDao公共API 20 | * @author gaoguangjin 21 | * @Date 2015-5-19 下午11:27:29 22 | */ 23 | public class RedisDao { 24 | // 分隔符 25 | private final static String SPLIT_MARK = ":"; 26 | // 排序key里面的标记位 27 | private final static String SORT = "sort"; 28 | // 主键key里面的标记位 29 | private final static String INDEX = "index"; 30 | // list格式存放log的sql 31 | public final static String LOG = "log"; 32 | // pub/sub模式打印log 33 | public final static String PUB_LOG = "publog"; 34 | 35 | private Jedis jedis; 36 | // 事物 37 | private Transaction transaction; 38 | 39 | // 管道 40 | private Pipeline pipeline; 41 | 42 | /** 43 | * redis事物一旦开启之后,所有的命令都会存放都一个队里里面,不会立即执行。 44 | */ 45 | public RedisDao(Transaction transaction) { 46 | this.transaction = transaction; 47 | } 48 | 49 | /** 50 | * 某些查询方法,用不到事物。 51 | */ 52 | public RedisDao(Jedis jedis) { 53 | this.jedis = jedis; 54 | } 55 | 56 | /** 57 | * 管道+事物效率等于Transaction,目前没用到,如果某些操作不需要事物控制,可以用到管道 58 | */ 59 | public RedisDao(Pipeline pipeline) { 60 | this.pipeline = pipeline; 61 | } 62 | 63 | /** 64 | * @Description比较key存储的value 和传入的value是否相等 65 | * @param key 66 | * @return:Boolean 67 | */ 68 | public Boolean existValueByKey(String key, String value) { 69 | return jedis.get(key) == value ? true : false; 70 | } 71 | 72 | /** 73 | * @Description:根据key返回值 74 | * @param key 75 | * @param jedis 76 | * @return:String 77 | */ 78 | public static String get(String key, Jedis jedis) { 79 | return jedis.get(key); 80 | } 81 | 82 | /** 83 | * @Description:set string类型 84 | * @param key 85 | * @param value 86 | */ 87 | public void set(String key, String value) { 88 | transaction.set(key, value); 89 | } 90 | 91 | /** 92 | * @Description: 存放set类型 93 | * @param key 94 | * @param value 95 | */ 96 | public void sadd(String key, String value) { 97 | transaction.sadd(key, value); 98 | } 99 | 100 | /** 101 | * @Description: 存放sortset类型 102 | * @param key 103 | * @param score 104 | * @param member 105 | */ 106 | public void zadd(String key, double score, String member) { 107 | transaction.zadd(key, score, member); 108 | } 109 | 110 | /** 111 | * @Description: 存放list类型 112 | * @param key 113 | * @param value 114 | */ 115 | public void lpush(String key, String value) { 116 | transaction.lpush(key, value); 117 | 118 | } 119 | 120 | /** 121 | * @Description: 返回有序集 key 中,指定区间内的成员。 按照从小到大排序 122 | * @param key key值 Note:sort:noteId 0 -1 123 | * @param start 初始位置 124 | * @param end 结束位置 125 | * @param jedis 126 | * @return:Set 127 | */ 128 | public static Set getRangeSortSet(String key, int start, int end, Jedis jedis) { 129 | return jedis.zrange(key, start, end); 130 | } 131 | 132 | /** 133 | * @Description: 返回有序集 key 中,指定区间内的成员。 按照从大到小排序 134 | * @see: 例如用来插入数据时候获取主键的id 135 | * @param key key值 Note:sort:noteId 0 0 136 | * @param start 初始位置 137 | * @param end 结束位置 138 | * @param jedis 139 | * @return:Set 140 | */ 141 | public static Set getRevrangeSortSet(String key, int start, int end, Jedis jedis) { 142 | return jedis.zrevrange(key, start, end); 143 | } 144 | 145 | /** 146 | * @Description:根据key的set集合,返回多个key对应的stringList。 147 | * @param sortKey 148 | * @param jedis 149 | * @return:List 150 | */ 151 | public static List getListString(Set sortKey, Jedis jedis) { 152 | List list = new ArrayList(); 153 | for (String key : sortKey) { 154 | list.add(jedis.get(key)); 155 | } 156 | return list; 157 | } 158 | 159 | /** 160 | * @Description: 删除string类型数据 161 | * @param key 162 | */ 163 | public void delString(String key) { 164 | transaction.del(key); 165 | } 166 | 167 | /** 168 | * @Description: 删除set类型数据 169 | * @param key 170 | */ 171 | public void delSet(String key, String member) { 172 | transaction.srem(key, member); 173 | } 174 | 175 | /** 176 | * @Description: 删除sortset类型的数据 177 | * @param key 178 | * @param member 179 | */ 180 | public void delSortSet(String key, String member) { 181 | transaction.zrem(key, member); 182 | } 183 | 184 | /** 185 | * @Description:模糊查询key值 186 | * @param pattern 187 | * @return:Set 188 | */ 189 | public Set keys(String pattern) { 190 | return jedis.keys(pattern); 191 | } 192 | 193 | /** 194 | * @Description:根据key值返回set集合 195 | * @param key 196 | * @return:Set 197 | */ 198 | public Set smembers(String key) { 199 | return jedis.smembers(key); 200 | } 201 | 202 | /** 203 | * @Description:根据多个key值返回交集的id 204 | * @param key 205 | * @return:Set 206 | */ 207 | public Set sinter(String... key) { 208 | return jedis.sinter(key); 209 | } 210 | 211 | /** 212 | * @Description:根据多个key值 返回并集的id 213 | * @param key 214 | * @return:Set 215 | */ 216 | public Set sunion(String... key) { 217 | return jedis.sunion(key); 218 | } 219 | 220 | /** 221 | * @Description:初始化将表中数据放到redis,存放格式为tableName:id:column. 222 | * @param tableName 表映射的类名 223 | * @param id 主键ID值 224 | * @param column 表映射的列信息 225 | * @param value 列对应的值 226 | */ 227 | public void setTable(String tableName, String id, String column, String value) { 228 | transaction.set(tableName + SPLIT_MARK + id + SPLIT_MARK + column, value); 229 | } 230 | 231 | /** 232 | * @Description:初始化存放表中所有字段数据,存放格式为tableName:column:columnValue 233 | * @param tableName 234 | * @param column 235 | * @param value 236 | * @param id 237 | */ 238 | public void saddColumn(String tableName, String column, String columnValue, String id) { 239 | transaction.sadd(tableName + SPLIT_MARK + column + SPLIT_MARK + columnValue, tableName + SPLIT_MARK + id); 240 | } 241 | 242 | /** 243 | * @Description:初始化将表中数据放到redis,将bean转换成json格式,存放格式为tableName:id。 244 | * @param tableName 表映射的类名 245 | * @param id 主键id值 246 | * @param json 改id值对应的json字符串 247 | */ 248 | public void setJSON(String tableName, String id, String json) { 249 | transaction.set(tableName + SPLIT_MARK + id, json); 250 | } 251 | 252 | /** 253 | * @Description: 根据jsonKey,获取相应的json字符串,转换成实体类List 254 | * @param key 255 | * @return:List 256 | */ 257 | public static List getListBean(Set sortKey, Class classs, Jedis jedis) { 258 | List list = new ArrayList(); 259 | for (String key : sortKey) { 260 | list.add(getBean(key, classs, jedis)); 261 | } 262 | return list; 263 | } 264 | 265 | /** 266 | * @Description:根据jsonKey,获取相应的json字符串,转换成实体类 267 | * @param key 268 | * @param classs实体类 269 | * @return:T dao层泛型的实体类 270 | */ 271 | public static Object getBean(String key, Class classs, Jedis jedis) { 272 | return JSON.parseObject(jedis.get(key), classs); 273 | } 274 | 275 | /** 276 | * @Description:对指定值加排序 277 | * @param tableName 278 | * @param column 279 | * @param value 280 | * @param id 281 | * @return:void 282 | */ 283 | public void zaddSort(String tableName, String column, String value, String id) { 284 | transaction.zadd(tableName + SPLIT_MARK + SORT + SPLIT_MARK + column, Double.parseDouble(value), id); 285 | } 286 | 287 | /** 288 | * @Description:对表主键加索引 289 | * @param tableName 290 | * @param column 291 | * @param value 292 | * @return:Long 293 | */ 294 | public void zaddIndex(String tableName, String column, String value) { 295 | transaction.sadd(tableName + SPLIT_MARK + INDEX + SPLIT_MARK + column, tableName + SPLIT_MARK + value); 296 | } 297 | 298 | /** 299 | * @Description:操作redis日志转换成对应的sql 300 | * @param value 301 | * @return:Long 302 | */ 303 | public void log(String sql) { 304 | transaction.lpush(LOG, sql); 305 | } 306 | 307 | /** 308 | * @Description: 监听必须在开启事物之前,执行watch命令 309 | * @param keys 310 | * @return:void 311 | */ 312 | public void watch(String... keys) { 313 | jedis.watch(keys); 314 | } 315 | 316 | /** 317 | * @Description: 获取实体类对象list 插入到redis里面 318 | * @param list 实体类集合 319 | */ 320 | public void insertListToredis(List list) throws Exception { 321 | if (null != list && list.size() > 0) { 322 | BeanField bf = getBeanField(list.get(0)); 323 | for (Object tt : list) { 324 | insertSingleDataToredis(tt, bf); 325 | } 326 | } 327 | } 328 | 329 | /** 330 | * @Description:插入单个实体类到redis 331 | * @param t 实体类 332 | * @param fieldList 实体类字段数组 333 | * @param primaryKey 实体类主键的名称 334 | * @param className 实体类的名称 335 | */ 336 | public void insertSingleDataToredis(Object t, BeanField bf) throws Exception { 337 | Field[] fieldList = bf.getFieldList(); 338 | String primaryKey = bf.getPrimaryKey(); 339 | String className = bf.getClassName(); 340 | // 获取主键值 341 | Field pvField = t.getClass().getDeclaredField(primaryKey); 342 | pvField.setAccessible(true); 343 | String primaryValue = pvField.get(t).toString(); 344 | 345 | for (Field field : fieldList) { 346 | field.setAccessible(true); 347 | String fieldName = field.getName(); 348 | Object fieldValue = field.get(t); 349 | // 去除不缓存的 350 | if (null != fieldValue && !field.isAnnotationPresent(RedisFieldNotCache.class)) { 351 | // 1、类型一k/v 352 | setTable(className, primaryValue, fieldName, fieldValue.toString()); 353 | // 对有注解的进行sadd kv存储 354 | if (field.isAnnotationPresent(RedisQuery.class)) { 355 | // 2、类型二 k/v 356 | saddColumn(className, fieldName, fieldValue.toString(), primaryValue); 357 | } 358 | } 359 | } 360 | // 3、 存放映射bean key-jsonValue 361 | setJSON(className, primaryValue, JSON.toJSON(t).toString()); 362 | // 4、所有主键建立索引 363 | zaddIndex(className, primaryKey, primaryValue); 364 | 365 | // 5、按照id大小排序 366 | zaddSort(className, primaryKey, primaryValue, primaryValue); 367 | 368 | } 369 | 370 | /** 371 | * @Description: 从redis删除条数据 372 | * @param list 373 | * @throws Exception 374 | * @return:void 375 | */ 376 | public void delDataListFromRedis(List list) throws Exception { 377 | if (null != list && list.size() > 0) { 378 | // 例如 primaryKey=noteId className=Note 379 | BeanField bf = getBeanField(list.get(0)); 380 | for (Object tt : list) { 381 | delSingleDataFromRedis(tt, bf); 382 | } 383 | } 384 | } 385 | 386 | public BeanField getBeanField(Object t) throws Exception { 387 | // 获取主键名称 388 | Field pkField = t.getClass().getDeclaredField("primaryKey"); 389 | pkField.setAccessible(true); 390 | String primaryKey = pkField.get(t).toString(); 391 | 392 | // 获取类名称 393 | Field cnField = t.getClass().getDeclaredField("className"); 394 | cnField.setAccessible(true); 395 | String className = cnField.get(t).toString(); 396 | 397 | Field[] fieldList = t.getClass().getDeclaredFields(); 398 | return new BeanField(primaryKey, className, fieldList); 399 | } 400 | 401 | /** 402 | * @Description: 从redis里面删除某一条数据 403 | * @param t 404 | * @param fieldList 405 | * @param primaryKey 406 | * @param className 407 | * @throws Exception 408 | * @return:void 409 | */ 410 | public void delSingleDataFromRedis(Object t, BeanField bf) throws Exception { 411 | Field[] fieldList = bf.getFieldList(); 412 | String primaryKey = bf.getPrimaryKey(); 413 | String className = bf.getClassName(); 414 | 415 | // 获取主键值 416 | Field pvField = t.getClass().getDeclaredField(primaryKey); 417 | pvField.setAccessible(true); 418 | String primaryValue = pvField.get(t).toString(); 419 | for (Field field : fieldList) { 420 | field.setAccessible(true); 421 | String fieldName = field.getName(); 422 | Object fieldValue = field.get(t); 423 | // 去除不缓存的 424 | if (null != fieldValue && !field.isAnnotationPresent(RedisFieldNotCache.class)) { 425 | // 1、删除类型一k/v 426 | delString(className + SPLIT_MARK + primaryValue + SPLIT_MARK + fieldName); 427 | 428 | // 对有注解的进行sadd kv存储 429 | if (field.isAnnotationPresent(RedisQuery.class)) { 430 | // 2、删除类型2 431 | delSet(className + SPLIT_MARK + fieldName + SPLIT_MARK + fieldValue.toString(), className + SPLIT_MARK + primaryValue); 432 | } 433 | } 434 | } 435 | // 3、删除类型三 json格式 436 | delString(className + SPLIT_MARK + primaryValue); 437 | // 4、删除索引 438 | delSet(className + SPLIT_MARK + INDEX + SPLIT_MARK + primaryKey, className + SPLIT_MARK + primaryValue); 439 | // 5、删除某个排序 440 | delSortSet(className + SPLIT_MARK + SORT + SPLIT_MARK + primaryKey, primaryValue); 441 | } 442 | 443 | /** 444 | * @Description:pub/sub模式广播sqllog 445 | * @param log 446 | * @return:void 447 | */ 448 | public void pubishLog(String log) { 449 | transaction.publish(PUB_LOG, log); 450 | } 451 | 452 | /** 453 | * @Description:获取redis里面list类型的log。 454 | * @see:lpop命令 返回并删除名称为key的list中的首元素。如果插入数据库失败需要再把log插入进来,调用log(sql)方法 455 | * @return:String 456 | */ 457 | public static String lpopLog(Jedis jedis) { 458 | return jedis.lpop(LOG); 459 | } 460 | 461 | /** 462 | * @Description:清空redis库所有缓存数据 463 | * @return:void 464 | */ 465 | public void flushDB() { 466 | transaction.flushDB(); 467 | } 468 | 469 | /** 470 | * @Description: 更新redis里面的某个数据 471 | * @param oldObject 原来的对象 472 | * @param t 473 | * @param bf 474 | */ 475 | public void updateSingleFromToredis(Object oldObject, Object t, BeanField bf) 476 | throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException { 477 | Field[] fieldList = bf.getFieldList(); 478 | String primaryKey = bf.getPrimaryKey(); 479 | String className = bf.getClassName(); 480 | // 获取主键值 481 | Field pvField = t.getClass().getDeclaredField(primaryKey); 482 | pvField.setAccessible(true); 483 | String primaryValue = pvField.get(t).toString(); 484 | 485 | for (Field field : fieldList) { 486 | field.setAccessible(true); 487 | String fieldName = field.getName(); 488 | Object fieldValue = field.get(t); 489 | // 去除不缓存的 490 | if (null != fieldValue && !field.isAnnotationPresent(RedisFieldNotCache.class)) { 491 | // 1、更新类型一k/v 492 | setTable(className, primaryValue, fieldName, fieldValue.toString()); 493 | // 对有注解的进行sadd kv存储 494 | if (field.isAnnotationPresent(RedisQuery.class)) { 495 | // 删除就的类型2 496 | delSet(className + SPLIT_MARK + fieldName + SPLIT_MARK + field.get(oldObject), className + SPLIT_MARK + primaryValue); 497 | // 2、更新类型二 k/v 498 | saddColumn(className, fieldName, fieldValue.toString(), primaryValue); 499 | } 500 | } 501 | } 502 | // 3、更新 存放映射bean key-jsonValue 503 | setJSON(className, primaryValue, JSON.toJSON(t).toString()); 504 | } 505 | 506 | } 507 | --------------------------------------------------------------------------------