Redis整合Spring实现缓存调度
来源:互联网 发布:mysql community 编辑:程序博客网 时间:2024/05/29 15:35
Redis
redis是一个key-value存储系统。和Memcached类似,它支持存储的value类型相对更多,包括string(字符串)、list(链表)、set(集合)、zset(sorted set --有序集合)和hash(哈希类型)。这些数据类型都支持push/pop、add/remove及取交集并集和差集及更丰富的操作,而且这些操作都是原子性的。在此基础上,redis支持各种不同方式的排序。与memcached一样,为了保证效率,数据都是缓存在内存中。区别的是redis会周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录文件,并且在此基础上实现了master-slave(主从)同步。
特点
(1)Redis数据库完全在内存中,使用磁盘仅用于持久性。(2)相比许多键值数据存储,Redis拥有一套较为丰富的数据类型。(3)Redis可以将数据复制到任意数量的从服务器。
优点
(1)异常快速:Redis的速度非常快,每秒能执行约11万集合,每秒约81000+条记录。(2)支持丰富的数据类型:Redis支持最大多数开发人员已经知道像列表,集合,有序集合,散列数据类型。这使得它非常容易解决各种各样的问题,因为我们知道哪些问题是可以处理通过它的数据类型更好。(3)操作都是原子性:所有Redis操作是原子的,这保证了如果两个客户端同时访问的Redis服务器将获得更新后的值。(4)多功能实用工具:Redis是一个多实用的工具,可以在多个用例如缓存,消息,队列使用(Redis原生支持发布/订阅),任何短暂的数据,应用程序,如Web应用程序会话,网页命中计数等。
缺点
(1)单线程(2)耗内存
以上是Redis的简介,我们日常公司的项目开发很多时候要用到redis,原因之一是由于它的反应速度比我们数据库服务器可要快的多,虽然它也是一种高性能的键值对数据库;其二是由于一些常用的不常改动的数据如果放入redis中那么用户访问的时候可以不用走数据库,我们只需要在这些数据更新或者删除的时候走消息队列或者直接调用redis的操作对象直接覆盖原来的数据或者删除即可,这样做的好处是对我们数据库的服务器的访问压力就小了很多,其次就是redis也可以集群,这些对于构建一个高性能的平台来说非常好的。下面我们就来看看如何构建redis和Spring的整合项目。
技术选型
我们用到的注项目还是ssm框架,即spring4.0.2,mybatis 3 以及redis2.7 ,我们采用将redis写成工具jar包的形式将其放入需要依赖它的主项目中,然后通过配置方法拦截器以及配置文件的形式对第一次访问资源并需要加入到缓存的方法或者Bean组件自动录入到redis中。
第一步:导依赖
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.cache</groupId> <artifactId>spring-redis</artifactId> <version>0.0.1-SNAPSHOT</version> <properties> <spring.version>4.0.2.RELEASE</spring.version> <jedis.version>2.7.3</jedis.version> <slf4j.version>1.6.1</slf4j.version> <spring-data-redis.version>1.6.1.RELEASE</spring-data-redis.version> <comLog.version>1.1.1</comLog.version> <fastJackson.version>2.8.6</fastJackson.version> </properties> <dependencies> <dependency> <groupId>org.springframework.data</groupId> <artifactId>spring-data-redis</artifactId> <version>${spring-data-redis.version}</version> </dependency> <dependency> <groupId>redis.clients</groupId> <artifactId>jedis</artifactId> <version>${jedis.version}</version> </dependency> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-core</artifactId> <version>${fastJackson.version}</version> </dependency> <dependency> <groupId>com.fasterxml.jackson.module</groupId> <artifactId>jackson-module-jaxb-annotations</artifactId> <version>${fastJackson.version}</version> </dependency> <dependency> <groupId>net.sf.json-lib</groupId> <artifactId>json-lib</artifactId> <version>2.4</version> <!-- 指定jdk版本 --> <classifier>jdk15</classifier> </dependency> <dependency> <groupId>commons-logging</groupId> <artifactId>commons-logging</artifactId> <version>${comLog.version}</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> <version>${slf4j.version}</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId> <version>${slf4j.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-aop</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-beans</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context-support</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-expression</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-orm</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-tx</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>1.6.8</version> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <configuration> <source>1.8</source> <target>1.8</target> <encoding>UTF-8</encoding> </configuration> </plugin> </plugins> </build></project>
由于打的是jar包,那么此工具jar中只需要定义好方法和拦截器即可,具体整合看后面。
第二步:工具类封装
package com.zhy.redis.utils;import java.io.Serializable;import java.util.Set;import java.util.concurrent.TimeUnit;import org.apache.log4j.Logger;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.data.redis.core.RedisTemplate;import org.springframework.data.redis.core.ValueOperations;/** * @ClassName: RedisUtil * @Description: redis cache 工具类* @author John Hawkings* @date 2017年5月4日 下午2:08:12 */public final class RedisUtil { private Logger log = Logger.getLogger(RedisUtil.class); @Autowired private RedisTemplate<Serializable, Object> redisTemplate; /** * @Title: remove * @Description: 批量删除对应的value * @param @param keys 设定文件 * @return void 返回类型 * @throws */ public void remove(final String... keys){ for (String string : keys) { remove(string); } } /** * @Title: removePattern * @Description: 批量删除key * @param @param pattern 设定文件 * @return void 返回类型 * @throws */ public void removePattern(final String pattern){ Set<Serializable> keys = redisTemplate.keys(pattern); if(keys.size()>0){ redisTemplate.delete(keys); } } /** * @Title: remove * @Description: 删除指定key的value * @param @param key 设定文件 * @return void 返回类型 * @throws */ public void remove(final String key){ if(exists(key)){ redisTemplate.delete(key); } } /** * @Title: exists * @Description: 判断缓存中是否存在此key * @param @return 设定文件 * @return boolean 返回类型 * @throws */ public boolean exists(final String key){ return redisTemplate.hasKey(key); } public Object get(final String key){ ValueOperations<Serializable, Object> operations = redisTemplate.opsForValue(); Object result = operations.get(key); return result; } /** * @Title: set * @Description: 写入缓存 * @param @param key * @param @param value * @param @return 设定文件 * @return boolean 返回类型 * @throws */ public boolean set(final String key, Object value) { boolean result = false; try { ValueOperations<Serializable, Object> operations = redisTemplate .opsForValue(); operations.set(key, value); result = true; } catch (Exception e) { log.error(e.getCause()); } return result; } /** * @Title: set * @Description: 写入缓存并设置此缓存过期时间 * @param @param key * @param @param value * @param @param expireTime * @param @return 设定文件 * @return boolean 返回类型 * @throws */ public boolean set(final String key, Object value, Long expireTime) { boolean result = false; try { ValueOperations<Serializable, Object> operations = redisTemplate .opsForValue(); operations.set(key, value); redisTemplate.expire(key, expireTime, TimeUnit.SECONDS); result = true; } catch (Exception e) { log.error(e.getCause()); } return result; } }
这里要注意的是redis采用序列化方案存对象,Redis不支持直接将Java对象存储到数据库中,所以需要将java对象进行序列化得到字节数组,然后将字节数组存入到redis中,需要数据的时候就从redis数据库中取出字节数组,再经过反序列化将自己数组转换成对象使用,所以我们的使用对象必须都要实现序列化接口;还有就是ValueOperations,这个接口的实现类为:DefaultValueOperations. 它是RedisTemplate中提供的几个常用的操作K-V的接口,在RedisTemplate中,已经提供了一个工厂方法:opsForValue()。这个方法会返回一个默认的操作类;简单的来说它就是一个操作K-V的一个对象。
第三步:方法拦截器的自定义
package com.zhy.redis.core;import java.io.InputStream;import java.util.ArrayList;import java.util.List;import java.util.Properties;import org.aopalliance.intercept.MethodInterceptor;import org.aopalliance.intercept.MethodInvocation;import org.apache.log4j.Logger;import org.springframework.beans.factory.annotation.Autowired;import com.zhy.redis.utils.RedisUtil;/** * @ClassName: MethodCacheInterceptor * @Description: 此拦截器是为了过滤那些不需要加入缓存的方法或者类* @author John Hawkings* @date 2017年5月4日 下午4:03:57 */public class MethodCacheInterceptor implements MethodInterceptor { @Autowired private RedisUtil redisUtil; private Logger logger = Logger.getLogger(MethodCacheInterceptor.class); private List<String> targetNamesList; // 不加入缓存的service名称 private List<String> methodNamesList; // 不加入缓存的方法名称 private Long defaultCacheExpireTime; // 缓存默认的过期时间 private Long xxxRecordManagerTime; // private Long xxxSetRecordManagerTime; // /** * 初始化读取不需要加入缓存的类名和方法名称 */ public MethodCacheInterceptor() { try { ClassLoader loader = MethodCacheInterceptor.class.getClassLoader(); InputStream in = loader.getResourceAsStream("redis.properties"); Properties p = new Properties(); p.load(in); // 分割字符串 String[] targetNames = null; String[] methodNames = null; if(p.getProperty("targetNames").contains(",")){ targetNames = p.getProperty("targetNames").split(","); }else{ targetNames = new String[]{p.getProperty("targetNames")}; } if(p.getProperty("methodNames").contains(",")){ methodNames = p.getProperty("methodNames").split(","); }else{ methodNames = new String[]{p.getProperty("methodNames")}; } // 加载过期时间设置 defaultCacheExpireTime = Long.valueOf(p.getProperty("defaultCacheExpireTime")); xxxRecordManagerTime = Long.valueOf(p.getProperty("com.lyt.usermanage.service.impl.xxxRecordManager")); xxxSetRecordManagerTime = Long.valueOf(p.getProperty("com.lyt.usermanage.service.impl.xxxSetRecordManager")); // 创建list targetNamesList = new ArrayList<String>(targetNames.length); methodNamesList = new ArrayList<String>(methodNames.length); Integer maxLen = targetNames.length > methodNames.length ? targetNames.length : methodNames.length; // 将不需要缓存的类名和方法名添加到list中 for (int i = 0; i < maxLen; i++) { if (i < targetNames.length) { targetNamesList.add(targetNames[i]); } if (i < methodNames.length) { methodNamesList.add(methodNames[i]); } } } catch (Exception e) { logger.error(e.getCause());; } } @Override public Object invoke(MethodInvocation invocation) throws Throwable { Object value = null; String targetName = invocation.getThis().getClass().getName(); String methodName = invocation.getMethod().getName(); // 不需要缓存的内容 if (!isAddCache(targetName, methodName)) { // 执行方法返回结果 return invocation.proceed(); } Object[] arguments = invocation.getArguments(); String key = getCacheKey(targetName, methodName, arguments); logger.info(key); try { // 判断是否有缓存 System.out.println(redisUtil.exists(key)); if (redisUtil.exists(key)) { return redisUtil.get(key); } // 写入缓存 //通过invocation.proceed()方法完成调用链的推进 value = invocation.proceed(); if (value != null) { final String tkey = key; final Object tvalue = value; new Thread(new Runnable() { @Override public void run() { if (tkey.startsWith("com.lyt.usermanage.service.impl.xxxRecordManager")) { redisUtil.set(tkey, tvalue, xxxRecordManagerTime); } else if (tkey.startsWith("com.lyt.usermanage.service.impl.xxxSetRecordManager")) { redisUtil.set(tkey, tvalue, xxxSetRecordManagerTime); } else { redisUtil.set(tkey, tvalue, defaultCacheExpireTime); } } }).start(); } } catch (Exception e) { logger.error(e.getCause()); if (value == null) { return invocation.proceed(); } } return value; } /** * 是否加入缓存 * * @return */ private boolean isAddCache(String targetName, String methodName) { boolean flag = true; if (targetNamesList.contains(targetName) || methodNamesList.contains(methodName)) { flag = false; } return flag; } /** * 创建缓存key * * @param targetName * @param methodName * @param arguments */ private String getCacheKey(String targetName, String methodName, Object[] arguments) { StringBuffer sbu = new StringBuffer(); sbu.append(targetName).append("_").append(methodName); if ((arguments != null) && (arguments.length != 0)) { for (int i = 0; i < arguments.length; i++) { sbu.append("_").append(arguments[i]); } } return sbu.toString(); } }
这个拦截器的原理就是读取配置文件配置的不需要加入缓存的方法或者bean文件,然后通过当前正在获取的数据取匹配这个集合,如果存在说明他是不需要缓存的数据直接放过走数据库获取,不存在则范,那么就走线程通过设置自定义的主键名将这个对象序列坏后存储在redis中,第二次进来查询的时候就直接走redis不走数据库,很大的减轻了数据库压力,同时可以通过配置文件给一些特殊的数据设置redis存储的过期时间,可以完成不同的业务需求。
第四步:整合spring
<dependency> <groupId>com.cache</groupId> <artifactId>spring-redis</artifactId> <version>0.0.1-SNAPSHOT</version> </dependency>
直接将其作为一个依赖放入到要使用到他的项目上。
spring-redis.xml整合文件:被缓存扫描到的package都会被拦截器拦截
<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:task="http://www.springframework.org/schema/task" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-4.0.xsd "> <!-- jedis 配置 --> <bean id="poolConfig" class="redis.clients.jedis.JedisPoolConfig" > <property name="maxIdle" value="${redis.maxIdle}" /> <property name="maxWaitMillis" value="${redis.maxWait}" /> <property name="testOnBorrow" value="${redis.testOnBorrow}" /> </bean > <!-- redis服务器中心 --> <bean id="connectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory" > <property name="poolConfig" ref="poolConfig" /> <property name="port" value="${redis.port}" /> <property name="hostName" value="${redis.host}" /> <property name="password" value="${redis.password}" /> <property name="timeout" value="${redis.timeout}" ></property> </bean > <bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate" > <property name="connectionFactory" ref="connectionFactory" /> <!-- 开启事务,可以通过transcational注解控制 --> <property name="enableTransactionSupport" value="true" /> <property name="keySerializer" > <bean class="org.springframework.data.redis.serializer.StringRedisSerializer" /> </property> <property name="valueSerializer" > <bean class="org.springframework.data.redis.serializer.JdkSerializationRedisSerializer" /> </property> </bean> <bean id="redisUtil" class="com.zhy.redis.utils.RedisUtil" /> <!-- cache配置 --> <bean id="methodCacheInterceptor" class="com.zhy.redis.core.MethodCacheInterceptor" /> <!-- 需要加入缓存的类或方法 --> <bean id="methodCachePointCut" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor" > <property name="advice" ref="methodCacheInterceptor"/> <property name="patterns" > <list> <!-- 确定正则表达式列表 --> <value>com\.lyt\.usermanage\.service\.impl\...*ServiceImpl.*</value > </list> </property> </bean></beans>
主xml配置,扫描redis组件
<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" xmlns:p="http://www.springframework.org/schema/p" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.0.xsd"> <!-- 配置注解扫描器 --> <context:component-scan base-package="com.lyt.usermanage.service,com.zhy.redis"/> <!-- 加载资源文件 --> <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"> <!-- 配置资源文件 --> <property name="locations"> <list> <value>classpath:jdbc.properties</value> <value>classpath:httpclient.properties</value> <value>classpath:redis.properties</value> </list> </property> </bean> <!-- 配置连接池,数据源 --> <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close"> <property name="driverClass" value="${driver}"></property> <property name="jdbcUrl" value="${url}"></property> <property name="user" value="${username}"></property> <property name="password" value="${password}"></property> </bean></beans>
redis.properties参数:
#redis configredis.host=XXX.XXX.XXX.XXXredis.port=6379redis.password=XXXXredis.maxIdle=100redis.maxActive=300redis.maxWait=1000redis.testOnBorrow=trueredis.timeout=100000# Don't need to join the cache classes targetNames=xxxRecordManager,xxxSetRecordManager,xxxStatisticsIdentificationManager # Don't need to join the cache methodsmethodNames= 这里是你需要加缓存的方法名以逗号分隔# Sets the cache invalidation time# 可以给每个方法设置在redis的存在时间,如果是长期存在那么就调用不设时间的方法com.lyt.usermanage.service.impl.xxxRecordManager= 60com.lyt.usermanage.service.impl.xxxSetRecordManager= 60# redis中数据的默认生命周期defaultCacheExpireTime=3600fep.local.cache.capacity =10000
下面就是一套的代码测试:
Controller:
package com.lyt.usermanage.controller;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Controller;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.ResponseBody;import org.springframework.web.servlet.ModelAndView;import com.lyt.usermanage.model.HomeResultBasic;import com.lyt.usermanage.pojo.SitUser;import com.lyt.usermanage.service.IUserService;@Controller@RequestMapping("user")public class BaseController { @Autowired private IUserService userService; @RequestMapping("basic") public ModelAndView toBasicPage(){ ModelAndView mv = new ModelAndView(); mv.setViewName("user-add"); mv.addObject(mv); return mv; } @RequestMapping("getInfo") @ResponseBody public HomeResultBasic getUserInfo(Long userId){ HomeResultBasic hb = new HomeResultBasic(); SitUser sitUser = userService.select(userId); if(sitUser!=null){ hb.setId(Integer.valueOf(userId.toString())); hb.setMsg("success"); hb.setStatus(0); return hb; }else{ hb.setId(null); hb.setMsg("failed"); hb.setStatus(1); return hb; } }}
Service:
package com.lyt.usermanage.service;import com.lyt.usermanage.pojo.SitUser;public interface IUserService { SitUser select(Long userId);}
实现类:
package com.lyt.usermanage.service.impl;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Service;import com.lyt.usermanage.dao.SitUserDao;import com.lyt.usermanage.pojo.SitUser;import com.lyt.usermanage.service.IUserService;@Servicepublic class UserServiceImple implements IUserService{ @Autowired private SitUserDao userDao; @Override public SitUser select(Long userId) { return userDao.select(userId); }}
持久层:
package com.lyt.usermanage.dao;import com.lyt.usermanage.pojo.SitUser;public interface SitUserDao { public SitUser select(Long userId);}
mapper文件:
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"><mapper namespace="com.lyt.usermanage.dao.SitUserDao"> <resultMap id="UserResult" type="com.lyt.usermanage.pojo.SitUser"> <id property="userId" column="user_id"/> <result property="mobile" column="mobile"/> <result property="password" column="password"/> <result property="email" column="email"/> <result property="realName" column="real_name"/> <result property="nickName" column="nick_name"/> <result property="gender" column="gender"/> <result property="birthday" column="birthday"/> <result property="districtId" column="district_id"/> <result property="userAddr" column="user_addr"/> <result property="avatar" column="avatar"/> <result property="signature" column="signature"/> <result property="accountType" column="account_type"/> <result property="isDisable" column="is_disable"/> <result property="isVip" column="is_vip"/> <result property="isOms" column="is_oms"/> <result property="disableReason" column="disable_reason"/> <result property="createTime" column="create_time"/> <result property="updateTime" column="update_time"/> </resultMap> <sql id="userSql"> user_id,mobile, email, real_name, nick_name, gender, birthday, district_id, user_addr, avatar, account_type, is_disable, is_vip, is_oms, disable_reason, create_time, update_time </sql> <select id="select" resultMap="UserResult" parameterType="long"> SELECT * FROM sit_user WHERE user_id = #{userId} </select></mapper>
model:
package com.lyt.usermanage.pojo;import java.io.Serializable;import java.util.Date;public class SitUser implements Serializable{ /** * @Fields serialVersionUID : TODO(用一句话描述这个变量表示什么) */ private static final long serialVersionUID = 1L; private Long userId; private String mobile; private String password; private String email; private String realName; private String nickName; private Short gender; private String birthday; private Integer districtId; private String userAddr; private String avatar; private String signature; private Short accountType; private String disableReason; private Short isVip;//是否是推广人员 private Short isOms;//是否是后台人员 private Short isDisable; //是否封号 private Date createTime; private Date updateTime; private String curPwd; //当前密码,修改密码用 private Long fansNum;//粉丝数 private Long postFollowNum;//帖子被喜欢数 private Long postNum;//发布的帖子数 private Boolean hasPwd;//查看用户是否有密码,用于区别猜他导入数据 private String province;//所在省市区后台所需 private String registerType; private String from; private Date lastLoginTime; private Date registerTime; public Long getUserId() { return userId; } public void setUserId(Long userId) { this.userId = userId; } public String getMobile() { return mobile; } public void setMobile(String mobile) { this.mobile = mobile; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } public String getRealName() { return realName; } public void setRealName(String realName) { this.realName = realName; } public String getNickName() { return nickName; } public void setNickName(String nickName) { this.nickName = nickName; } public Short getGender() { return gender; } public void setGender(Short gender) { this.gender = gender; } public String getBirthday() { return birthday; } public void setBirthday(String birthday) { this.birthday = birthday; } public Integer getDistrictId() { return districtId; } public void setDistrictId(Integer districtId) { this.districtId = districtId; } public String getUserAddr() { return userAddr; } public void setUserAddr(String userAddr) { this.userAddr = userAddr; } public String getAvatar() { return avatar; } public void setAvatar(String avatar) { this.avatar = avatar; } public String getSignature() { return signature; } public void setSignature(String signature) { this.signature = signature; } public Short getAccountType() { return accountType; } public void setAccountType(Short accountType) { this.accountType = accountType; } public String getDisableReason() { return disableReason; } public void setDisableReason(String disableReason) { this.disableReason = disableReason; } public Short getIsDisable() { return isDisable; } public void setIsDisable(Short isDisable) { this.isDisable = isDisable; } public Date getCreateTime() { return createTime; } public void setCreateTime(Date createTime) { this.createTime = createTime; } public Date getUpdateTime() { return updateTime; } public void setUpdateTime(Date updateTime) { this.updateTime = updateTime; } public String getCurPwd() { return curPwd; } public void setCurPwd(String curPwd) { this.curPwd = curPwd; } public Long getFansNum() { return fansNum; } public void setFansNum(Long fansNum) { this.fansNum = fansNum; } public Long getPostFollowNum() { return postFollowNum; } public void setPostFollowNum(Long postFollowNum) { this.postFollowNum = postFollowNum; } public Short getIsVip() { return isVip; } public void setIsVip(Short isVip) { this.isVip = isVip; } public Short getIsOms() { return isOms; } public void setIsOms(Short isOms) { this.isOms = isOms; } public Long getPostNum() { return postNum; } public void setPostNum(Long postNum) { this.postNum = postNum; } public String getProvince() { return province; } public void setProvince(String province) { this.province = province; } public String getRegisterType() { return registerType; } public void setRegisterType(String registerType) { this.registerType = registerType; } public String getFrom() { return from; } public void setFrom(String from) { this.from = from; } public Date getLastLoginTime() { return lastLoginTime; } public void setLastLoginTime(Date lastLoginTime) { this.lastLoginTime = lastLoginTime; } public Date getRegisterTime() { return registerTime; } public void setRegisterTime(Date registerTime) { this.registerTime = registerTime; } public Boolean getHasPwd() { return hasPwd; } public void setHasPwd(Boolean hasPwd) { this.hasPwd = hasPwd; }}
他的执行效果是这样的:
可以很清楚的看到第一次没有加入缓存,缓存中没有命中那么是直接走的数据库,第二次由于自动加入到了缓存他直接在缓存中命中了没有走数据库。
如果你有些数据要更改获新增你只需自如redis工具类对新增或修改删除的数据进行相关操作即可。
整体框架如下:
redis工具jar:
主项目:
具体整合资源下载:redis
- Redis整合Spring实现缓存调度
- Spring整合Redis实现数据缓存
- spring boot整合redis实现缓存机制
- Spring Boot 整合 Redis 实现缓存操作
- Spring Boot 整合 Redis 实现缓存操作
- Spring Boot 整合 Redis 实现缓存操作
- Spring Boot 整合 Redis 实现缓存操作
- Spring+Redis+MyBatis实现缓存整合
- Spring Boot 整合 Redis 实现缓存操作
- Spring整合Redis缓存
- spring整合redis缓存
- Spring整合Redis作为缓存
- Spring AOP 整合Redis 缓存
- spring整合redis缓存配置
- Spring整合Redis作为缓存
- spring mvc整合redis缓存
- Spring整合Redis作为缓存
- Spring整合Redis作为缓存
- 发布项目总结(一)
- Aladdin and the Flying Carpet (算术基本定理)
- 集合
- Tomcat 7 参数性能调优
- CSDN Markdown 编辑器使用详细
- Redis整合Spring实现缓存调度
- Linux下的SVN服务器搭建
- 1.求第n个斐波那契数(非递归实现)。 2.一个数组中只有两个数字是出现一次,其他所有数字都出现 了两次。 找出这两个数字,编程实现。
- UIWidget是所有UI组件的抽象基类,作为基类当然定义了必须的成员变量和函数,接触过MFC或其他UI组件开发,想必都知道有一堆参数设置,尤其是Visual Studio的可视化界面,
- 《Android攻防实战》——实践App安全
- Top100论文导读:深入理解卷积神经网络CNN(Part Ⅱ)
- Android游戏编程之GameView1
- Java与Unix时间戳的相互转换
- Js 删掉所有的html标签