redis之spring应用
前言
读本文之前,需要大家对redis有所了解,大家可以去看一下我之前分享的redis安装及简单使用这一随笔,而本文我将跟大家分享学习一下redis与spring的集成。当然,首先需要打开我们的redis服务,之后才可以继续进行我们的集成。
项目主要是将从mysql数据库查询出来的数据缓存到redis数据库中,第二次查询就直接查询redis缓存,然后增删改操作将删除数据的缓存,下一次查询操作继续缓存,避免连接mysql进行查询,从而提高性能。redis的查询速度跟Mysql查询速度可以这么比较 内存读写速度 / 磁盘读写速度
一、项目结构
二、Maven构建项目
用maven来构建项目环境,下载所依赖的JAR包
<?xml version="1.0" encoding="UTF-8"?> <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.stonegeek</groupId> <artifactId>RedisSpringDemo</artifactId> <version>1.0-SNAPSHOT</version> <packaging>war</packaging> <name>RedisSpringDemo Maven Webapp</name> <!-- FIXME change it to the project's website --> <url>http://www.example.com</url> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <maven.compiler.source>1.7</maven.compiler.source> <maven.compiler.target>1.7</maven.compiler.target> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <spring.version>4.2.0.RELEASE</spring.version> </properties> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.11</version> <scope>test</scope> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-aop</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-web</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>jstl</artifactId> <version>1.2</version> </dependency> <dependency> <groupId>commons-logging</groupId> <artifactId>commons-logging</artifactId> <version>1.1.3</version> </dependency> <dependency> <groupId>org.codehaus.jackson</groupId> <artifactId>jackson-mapper-asl</artifactId> <version>1.9.13</version> </dependency> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-annotations</artifactId> <version>2.6.1</version> </dependency> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-core</artifactId> <version>2.6.1</version> </dependency> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>2.6.1</version> </dependency> <!-- spring mvc related.....end --> <!-- mybatis orm related.....start --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-orm</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis-spring</artifactId> <version>1.2.3</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.36</version> </dependency> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.3.0</version> </dependency> <dependency> <groupId>c3p0</groupId> <artifactId>c3p0</artifactId> <version>0.9.1.2</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId> <version>1.7.12</version> </dependency> <!-- mybatis orm related.....end --> <!-- project log related.....start --> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.17</version> </dependency> <!-- project log related.....end --> <!-- redis cache related.....start --> <dependency> <groupId>org.springframework.data</groupId> <artifactId>spring-data-redis</artifactId> <version>1.6.0.RELEASE</version> </dependency> <dependency> <groupId>redis.clients</groupId> <artifactId>jedis</artifactId> <version>2.7.3</version> </dependency> </dependencies> <build> <finalName>RedisSpringDemo</finalName> <pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) --> <plugins> <plugin> <artifactId>maven-clean-plugin</artifactId> <version>3.0.0</version> </plugin> <!-- see http://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_war_packaging --> <plugin> <artifactId>maven-resources-plugin</artifactId> <version>3.0.2</version> </plugin> <plugin> <artifactId>maven-compiler-plugin</artifactId> <version>3.7.0</version> </plugin> <plugin> <artifactId>maven-surefire-plugin</artifactId> <version>2.20.1</version> </plugin> <plugin> <artifactId>maven-war-plugin</artifactId> <version>3.2.0</version> </plugin> <plugin> <artifactId>maven-install-plugin</artifactId> <version>2.5.2</version> </plugin> <plugin> <artifactId>maven-deploy-plugin</artifactId> <version>2.8.2</version> </plugin> </plugins> </pluginManagement> </build> </project>
三、配置信息properties文件
1、jdbc.properties
jdbc.host=127.0.0.1 jdbc.database=bjsxt jdbc.port=3306 jdbc.username=root jdbc.password=xiaokai960201
2、redis.properties
# Redis settings redis.host=192.168.43.230 redis.port=6379 #redis.pass=password redis.dbIndex=0 redis.expiration=3000 redis.maxIdle=300 redis.maxActive=600 redis.maxWait=1000 redis.testOnBorrow=true
3、log4j.properties
#设置日志的级别,定义日志信息的输出目的 log4j.rootLogger=DEBUG, A1 ,R #定义A1的输出目的地为控制台 log4j.appender.A1=org.apache.log4j.ConsoleAppender #布局为 PatternLayout 可以灵活地指定布局模式。 log4j.appender.A1.layout=org.apache.log4j.PatternLayout #设置输出格式 log4j.appender.A1.layout.ConversionPattern=%-d{yyyy-MM-dd HH\:mm\:ss} [%c]-[%p] %m%n #定义R的输出目的地为文件,并且文件大小到达指定尺寸的时候产生一个新的文件 log4j.appender.R=org.apache.log4j.RollingFileAppender #设置输出的文件地址 log4j.appender.R.File=D:\\Test_Log4j.log #设置文件大小伟100 kb 文件到达100时,产生一个新文件, #MaxBackupIndex 最大记录的文件数为1 查过一个文件删除文件较早的。 log4j.appender.R.MaxFileSize=100KB log4j.appender.R.MaxBackupIndex=1 #以下和上面一样 log4j.appender.R.layout=org.apache.log4j.PatternLayout log4j.appender.R.layout.ConversionPattern=%p %t %c - %m%n
四、配置文件
1、applicationContext.xml
<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:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" 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"> <!-- 使用注解的自扫描功能--> <context:component-scan base-package="com.stonegeek.serviceImpl" /> <context:component-scan base-package="com.stonegeek.utils" />
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"> <property name="locations"> <list> <value>classpath:jdbc.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="com.mysql.jdbc.Driver" /> <property name="jdbcUrl" value="jdbc:mysql://${jdbc.host}:${jdbc.port}/${jdbc.database}?useUnicode=true&characterEncoding=utf8" /> <property name="user" value="${jdbc.username}" /> <property name="password" value="${jdbc.password}" /> </bean> <!-- mybatis的配置映射文件--> <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <property name="dataSource" ref="dataSource" /> <property name="mapperLocations" value="classpath:Mapper/*.xml" /> </bean> <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"> <property name="basePackage" value="com.stonegeek.dao" /> <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory" /> </bean> <!-- redis config start --> <!-- 配置JedisPoolConfig实例 --> <bean id="poolConfig" class="redis.clients.jedis.JedisPoolConfig"> <property name="maxIdle" value="${redis.maxIdle}" /> <property name="maxTotal" value="${redis.maxActive}" /> <property name="maxWaitMillis" value="${redis.maxWait}" /> <property name="testOnBorrow" value="${redis.testOnBorrow}" /> </bean> <!-- 配置JedisConnectionFactory --> <bean id="jedisConnectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory"> <property name="hostName" value="${redis.host}" /> <property name="port" value="${redis.port}" /> <!-- <property name="password" value="${redis.pass}" /> --> <property name="database" value="${redis.dbIndex}" /> <property name="poolConfig" ref="poolConfig" /> </bean> <!-- 配置RedisTemplate --> <bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate"> <property name="connectionFactory" ref="jedisConnectionFactory" /> </bean> <!-- 配置RedisCacheManager --> <bean id="redisCacheManager" class="org.springframework.data.redis.cache.RedisCacheManager"> <constructor-arg name="redisOperations" ref="redisTemplate" /> <property name="defaultExpiration" value="${redis.expiration}" /> </bean> <!-- 配置RedisCacheConfig --> <bean id="redisCacheConfig" class="com.stonegeek.utils.RedisCacheConfig"> <constructor-arg ref="jedisConnectionFactory" /> <constructor-arg ref="redisTemplate" /> <constructor-arg ref="redisCacheManager" /> </bean> <!-- redis config end --> </beans>
2、springmvc.xml
<?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:p="http://www.springframework.org/schema/p" xmlns:context="http://www.springframework.org/schema/context" xmlns:mvc="http://www.springframework.org/schema/mvc" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd"> <!-- 添加注解驱动 使用注解标注的类生效--> <mvc:annotation-driven /> <!-- 设置能访问静态资源 --> <mvc:default-servlet-handler/> <!--扫描controller--> <context:component-scan base-package="com.stonegeek.controller" /> <!-- jsp page related... start --> <bean id="viewResolver" class="org.springframework.web.servlet.view.UrlBasedViewResolver"> <property name="viewClass" value="org.springframework.web.servlet.view.JstlView" /> <property name="prefix" value="/WEB-INF/jsp/" /> <property name="suffix" value=".jsp" /> </bean> <bean id="mappingJacksonHttpMessageConverter" class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter"> <property name="supportedMediaTypes"> <list> <value>application/json;charset=UTF-8</value> </list> </property> </bean> <bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter"> <property name="messageConverters"> <list> <ref bean="mappingJacksonHttpMessageConverter" /> </list> </property> </bean> </beans>
3、web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
version="3.1">
<display-name>Archetype Created Web Application</display-name>
<welcome-file-list>
<welcome-file>/index.jsp</welcome-file>
</welcome-file-list>
<!-- 加载spring bean -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring/applicationContext.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- 编码过滤器 -->
<filter>
<filter-name>springfilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>springfilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<servlet>
<servlet-name>SpringMVC</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring/springmvc.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
<async-supported>true</async-supported>
</servlet>
<servlet-mapping>
<servlet-name>SpringMVC</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
五、项目主要代码
1、dao层
package com.stonegeek.dao; import com.stonegeek.pojo.User; import java.util.List; public interface UserMapper { List<User> selectAll(); User selectByPrimaryKey(String unumber); int insert(User record); int insertSelective(User record); int deleteOne(String unumber); }
<?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.stonegeek.dao.UserMapper" > <resultMap id="BaseResultMap" type="com.stonegeek.pojo.User" > <result column="unumber" property="unumber" jdbcType="VARCHAR" /> <result column="uname" property="uname" jdbcType="VARCHAR" /> <result column="pwd" property="pwd" jdbcType="VARCHAR" /> <result column="sex" property="sex" jdbcType="VARCHAR" /> <result column="fav" property="fav" jdbcType="VARCHAR" /> </resultMap> <select id="selectAll" resultMap="BaseResultMap"> select * from user </select> <select id="selectByPrimaryKey" resultMap="BaseResultMap" parameterType="java.lang.String" > select * from user where unumber = #{unumber,jdbcType=VARCHAR} </select> <insert id="insert" parameterType="com.stonegeek.pojo.User" > insert into user (unumber, uname, pwd, sex, fav) values (#{unumber,jdbcType=VARCHAR}, #{uname,jdbcType=VARCHAR}, #{pwd,jdbcType=VARCHAR}, #{sex,jdbcType=VARCHAR}, #{fav,jdbcType=VARCHAR}) </insert> <insert id="insertSelective" parameterType="com.stonegeek.pojo.User" > insert into user <trim prefix="(" suffix=")" suffixOverrides="," > <if test="unumber != null" > unumber, </if> <if test="uname != null" > uname, </if> <if test="pwd != null" > pwd, </if> <if test="sex != null" > sex, </if> <if test="fav != null" > fav, </if> </trim> <trim prefix="values (" suffix=")" suffixOverrides="," > <if test="unumber != null" > #{unumber,jdbcType=VARCHAR}, </if> <if test="uname != null" > #{uname,jdbcType=VARCHAR}, </if> <if test="pwd != null" > #{pwd,jdbcType=VARCHAR}, </if> <if test="sex != null" > #{sex,jdbcType=VARCHAR}, </if> <if test="fav != null" > #{fav,jdbcType=VARCHAR}, </if> </trim> </insert> <delete id="deleteOne" parameterType="java.lang.String"> delete from user where unumber = #{unumber} </delete> </mapper>
2、model层
package com.stonegeek.pojo; import java.io.Serializable; public class User implements Serializable{ private static final long serialVersionUID = 1L; private String unumber; private String uname; private String pwd; private String sex; private String fav; public String getUnumber() { return unumber; } public void setUnumber(String unumber) { this.unumber = unumber == null ? null : unumber.trim(); } public String getUname() { return uname; } public void setUname(String uname) { this.uname = uname == null ? null : uname.trim(); } public String getPwd() { return pwd; } public void setPwd(String pwd) { this.pwd = pwd == null ? null : pwd.trim(); } public String getSex() { return sex; } public void setSex(String sex) { this.sex = sex == null ? null : sex.trim(); } public String getFav() { return fav; } public void setFav(String fav) { this.fav = fav == null ? null : fav.trim(); } }
注意:
要想使用redis存对象,一定要让实体类实现Serializable接口,否则会报错。
3、controller层
package com.stonegeek.controller; import com.stonegeek.pojo.User; import com.stonegeek.service.IUserService; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.ResponseBody; import javax.annotation.Resource; import java.util.ArrayList; import java.util.List; /** * Created by StoneGeek on 2018/5/2. */ @Controller @RequestMapping("/redisTest") public class UserController { @Resource private IUserService userService; @RequestMapping(value = "/selectall", method = RequestMethod.GET) @ResponseBody public Object showUsers() { List<User> userList = new ArrayList<User>(); userList = userService.selectAll(); System.out.println("--------------------------"); System.out.println(userList); System.out.println("--------------------------"); return userList; } @RequestMapping(value = "/delUser/{unumber}", method = RequestMethod.GET) @ResponseBody public Object delUser(@PathVariable String unumber) { System.out.println(unumber); userService.deleteOne(unumber); return "ok"; } }
4、service层
package com.stonegeek.service; import com.stonegeek.dao.UserMapper; import com.stonegeek.pojo.User; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Propagation; import org.springframework.transaction.annotation.Transactional; import javax.annotation.Resource; import java.util.List; /** * Created by StoneGeek on 2018/5/2. */ public interface IUserService { public User getUserById(String unumber); public List<User> selectAll(); public int deleteOne(String unumber); }
package com.stonegeek.serviceImpl; import com.stonegeek.dao.UserMapper; import com.stonegeek.pojo.User; import com.stonegeek.service.IUserService; import org.springframework.cache.annotation.CacheEvict; import org.springframework.cache.annotation.Cacheable; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Propagation; import org.springframework.transaction.annotation.Transactional; import javax.annotation.Resource; import java.util.List; /** * Created by Xiaokai on 2018/5/2. */ @Service("userService") @Transactional(propagation= Propagation.REQUIRED, rollbackFor=Exception.class) public class UserServiceImpl implements IUserService{ @Resource private UserMapper iUserDao;
@Cacheable("getUserById") @Override public User getUserById(String unumber) { return this.iUserDao.selectByPrimaryKey(unumber); } @Cacheable("selectAll") @Override public List<User> selectAll() { return iUserDao.selectAll(); } @CacheEvict(value= {"selectAll","getUserById"},allEntries=true) @Override public int deleteOne(String unumber) { return iUserDao.deleteOne(unumber); } }
@Cacheable("a")注解的意义就是把该方法的查询结果放到redis中去,下一次再发起查询就去redis中去取,存在redis中的数据的key就是a; @CacheEvict(value={"a","b"},allEntries=true) 的意思就是执行该方法后要清除redis中key名称为a,b的数据;
5、utils工具类
package com.stonegeek.utils; /** * Created by StoneGeek on 2018/5/2. * 通过spring管理redis缓存配置 */ import java.lang.reflect.Method; import org.springframework.cache.annotation.CachingConfigurerSupport; import org.springframework.cache.annotation.EnableCaching; import org.springframework.cache.interceptor.KeyGenerator; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.data.redis.cache.RedisCacheManager; import org.springframework.data.redis.connection.jedis.JedisConnectionFactory; import org.springframework.data.redis.core.RedisTemplate; @Configuration @EnableCaching public class RedisCacheConfig extends CachingConfigurerSupport { private volatile JedisConnectionFactory jedisConnectionFactory; private volatile RedisTemplate<String, String> redisTemplate; private volatile RedisCacheManager redisCacheManager; public RedisCacheConfig() { super(); } /** * 带参数的构造方法 初始化所有的成员变量 * * @param jedisConnectionFactory * @param redisTemplate * @param redisCacheManager */ public RedisCacheConfig(JedisConnectionFactory jedisConnectionFactory, RedisTemplate<String, String> redisTemplate, RedisCacheManager redisCacheManager) { this.jedisConnectionFactory = jedisConnectionFactory; this.redisTemplate = redisTemplate; this.redisCacheManager = redisCacheManager; } public JedisConnectionFactory getJedisConnecionFactory() { return jedisConnectionFactory; } public RedisTemplate<String, String> getRedisTemplate() { return redisTemplate; } public RedisCacheManager getRedisCacheManager() { return redisCacheManager; } @Bean public KeyGenerator customKeyGenerator() { return new KeyGenerator() { @Override public Object generate(Object target, Method method, Object... objects) { StringBuilder sb = new StringBuilder(); sb.append(target.getClass().getName()); sb.append(method.getName()); for (Object obj : objects) { sb.append(obj.toString()); } return sb.toString(); } }; } }
六、项目结果展示及说明
访问http://localhost:8080/redisTest/selectall
控制台输出(部分):
2018-05-03 11:08:23 [org.springframework.web.servlet.DispatcherServlet]-[DEBUG] DispatcherServlet with name 'SpringMVC' processing GET request for [/redisTest/selectall] 2018-05-03 11:08:23 [org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping]-[DEBUG] Looking up handler method for path /redisTest/selectall 2018-05-03 11:08:23 [org.springframework.cache.annotation.AnnotationCacheOperationSource]-[DEBUG] Adding cacheable method 'selectAll' with attribute: [CacheableOperation[public java.util.List com.stonegeek.serviceImpl.UserServiceImpl.selectAll()] caches=[selectAll] | key='' | keyGenerator='' | cacheManager='' | cacheResolver='' | condition='' | unless=''] 2018-05-03 11:08:23 [org.springframework.data.redis.core.RedisConnectionUtils]-[DEBUG] Opening RedisConnection 2018-05-03 11:08:23 [org.springframework.data.redis.core.RedisConnectionUtils]-[DEBUG] Closing Redis Connection 2018-05-03 11:08:23 [org.mybatis.spring.SqlSessionUtils]-[DEBUG] Creating a new SqlSession 2018-05-03 11:08:25 [com.stonegeek.dao.UserMapper.selectAll]-[DEBUG] ==> Preparing: select * from user 2018-05-03 11:08:26 [com.stonegeek.dao.UserMapper.selectAll]-[DEBUG] ==> Parameters: 2018-05-03 11:08:26 [com.stonegeek.dao.UserMapper.selectAll]-[DEBUG] <== Total: 2 2018-05-03 11:08:26 [org.mybatis.spring.SqlSessionUtils]-[DEBUG] Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@2ca4c9ac] 2018-05-03 11:08:26 [org.springframework.jdbc.datasource.DataSourceUtils]-[DEBUG] Returning JDBC Connection to DataSource 2018-05-03 11:08:26 [com.mchange.v2.resourcepool.BasicResourcePool]-[DEBUG] trace com.mchange.v2.resourcepool.BasicResourcePool@5259cb3b [managed: 3, unused: 2, excluded: 0] (e.g. com.mchange.v2.c3p0.impl.NewPooledConnection@7f53b569) 2018-05-03 11:08:26 [org.springframework.data.redis.core.RedisConnectionUtils]-[DEBUG] Opening RedisConnection 2018-05-03 11:08:26 [org.springframework.data.redis.core.RedisConnectionUtils]-[DEBUG] Closing Redis Connection -------------------------- [com.stonegeek.pojo.User@104d8d17, com.stonegeek.pojo.User@52389362] -------------------------- 2018-05-03 11:08:26 [org.springframework.web.servlet.DispatcherServlet]-[DEBUG] Successfully completed request
此结果是第一次进行查询时log4j打印在console上的日志信息(挑选的部分重要信息),从这日志信息大概可以看出先连接到myql跟redis、然后将mysql查出的selectAll数据缓存到redis上并打印到控制台上
再次访问http://localhost:8080/redisTest/selectall
2018-05-03 11:16:11 [org.springframework.web.servlet.DispatcherServlet]-[DEBUG] DispatcherServlet with name 'SpringMVC' processing GET request for [/redisTest/selectall] 2018-05-03 11:16:11 [org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping]-[DEBUG] Looking up handler method for path /redisTest/selectall 2018-05-03 11:16:11 [org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping]-[DEBUG] Returning handler method [public java.lang.Object com.stonegeek.controller.UserController.showUsers()] 2018-05-03 11:16:11 [org.springframework.beans.factory.support.DefaultListableBeanFactory]-[DEBUG] Returning cached instance of singleton bean 'userController' 2018-05-03 11:16:11 [org.springframework.web.servlet.DispatcherServlet]-[DEBUG] Last-Modified value for [/redisTest/selectall] is: -1 2018-05-03 11:16:11 [org.springframework.data.redis.core.RedisConnectionUtils]-[DEBUG] Opening RedisConnection 2018-05-03 11:16:11 [org.springframework.data.redis.core.RedisConnectionUtils]-[DEBUG] Closing Redis Connection -------------------------- [com.stonegeek.pojo.User@5aee0851, com.stonegeek.pojo.User@68bdcc8a] -------------------------- 2018-05-03 11:16:11 [org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor]-[DEBUG] Written [[com.stonegeek.pojo.User@5aee0851, com.stonegeek.pojo.User@68bdcc8a]] as "application/json;charset=UTF-8" using [org.springframework.http.converter.json.MappingJackson2HttpMessageConverter@27f9bd05] 2018-05-03 11:16:11 [org.springframework.web.servlet.DispatcherServlet]-[DEBUG] Null ModelAndView returned to DispatcherServlet with name 'SpringMVC': assuming HandlerAdapter completed request handling 2018-05-03 11:16:11 [org.springframework.web.servlet.DispatcherServlet]-[DEBUG] Successfully completed request
可以看出,此次操作并没有与mysql交互,直接从打开redis连接查询缓存所得
之后在进行一次删除操作
访问http://localhost:8080/redisTest/delUser/20180103
2018-05-03 11:18:14 [org.springframework.web.servlet.DispatcherServlet]-[DEBUG] DispatcherServlet with name 'SpringMVC' processing GET request for [/redisTest/delUser/20180103] 2018-05-03 11:18:14 [org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping]-[DEBUG] Looking up handler method for path /redisTest/delUser/20180103 2018-05-03 11:18:14 [org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping]-[DEBUG] Returning handler method [public java.lang.Object com.stonegeek.controller.UserController.delUser(java.lang.String)] 2018-05-03 11:18:14 [org.springframework.beans.factory.support.DefaultListableBeanFactory]-[DEBUG] Returning cached instance of singleton bean 'userController' 2018-05-03 11:18:14 [org.springframework.web.servlet.DispatcherServlet]-[DEBUG] Last-Modified value for [/redisTest/delUser/20180103] is: -1 20180103 2018-05-03 11:18:14 [org.mybatis.spring.SqlSessionUtils]-[DEBUG] Creating a new SqlSession 2018-05-03 11:18:14 [org.mybatis.spring.SqlSessionUtils]-[DEBUG] SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@2566bd74] was not registered for synchronization because synchronization is not active 2018-05-03 11:18:14 [org.springframework.jdbc.datasource.DataSourceUtils]-[DEBUG] Fetching JDBC Connection from DataSource 2018-05-03 11:18:14 [com.mchange.v2.resourcepool.BasicResourcePool]-[DEBUG] trace com.mchange.v2.resourcepool.BasicResourcePool@5259cb3b [managed: 3, unused: 2, excluded: 0] (e.g. com.mchange.v2.c3p0.impl.NewPooledConnection@7f53b569) 2018-05-03 11:18:14 [org.mybatis.spring.transaction.SpringManagedTransaction]-[DEBUG] JDBC Connection [com.mchange.v2.c3p0.impl.NewProxyConnection@3d69c864] will not be managed by Spring 2018-05-03 11:18:14 [com.stonegeek.dao.UserMapper.deleteOne]-[DEBUG] ==> Preparing: delete from user where unumber = ? 2018-05-03 11:18:14 [com.stonegeek.dao.UserMapper.deleteOne]-[DEBUG] ==> Parameters: 20180103(String) 2018-05-03 11:18:15 [com.stonegeek.dao.UserMapper.deleteOne]-[DEBUG] <== Updates: 1 2018-05-03 11:18:15 [org.mybatis.spring.SqlSessionUtils]-[DEBUG] Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@2566bd74] 2018-05-03 11:18:15 [org.springframework.jdbc.datasource.DataSourceUtils]-[DEBUG] Returning JDBC Connection to DataSource 2018-05-03 11:18:15 [com.mchange.v2.resourcepool.BasicResourcePool]-[DEBUG] trace com.mchange.v2.resourcepool.BasicResourcePool@5259cb3b [managed: 3, unused: 2, excluded: 0] (e.g. com.mchange.v2.c3p0.impl.NewPooledConnection@7f53b569) 2018-05-03 11:18:15 [org.springframework.data.redis.core.RedisConnectionUtils]-[DEBUG] Opening RedisConnection 2018-05-03 11:18:15 [org.springframework.data.redis.core.RedisConnectionUtils]-[DEBUG] Closing Redis Connection 2018-05-03 11:18:15 [org.springframework.data.redis.core.RedisConnectionUtils]-[DEBUG] Opening RedisConnection 2018-05-03 11:18:15 [org.springframework.data.redis.core.RedisConnectionUtils]-[DEBUG] Closing Redis Connection 2018-05-03 11:18:15 [org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor]-[DEBUG] Written [ok] as "text/html" using [org.springframework.http.converter.StringHttpMessageConverter@7065def5] 2018-05-03 11:18:15 [org.springframework.web.servlet.DispatcherServlet]-[DEBUG] Null ModelAndView returned to DispatcherServlet with name 'SpringMVC': assuming HandlerAdapter completed request handling 2018-05-03 11:18:15 [org.springframework.web.servlet.DispatcherServlet]-[DEBUG] Successfully completed request
然后再次查询所有用户信息
访问http://localhost:8080/redisTest/selectall
可以发现删除操作确实删除了缓存,本次查询查询数据库并重新缓存数据到redis内存
2018-05-03 11:19:58 [org.springframework.web.servlet.DispatcherServlet]-[DEBUG] DispatcherServlet with name 'SpringMVC' processing GET request for [/redisTest/selectall] 2018-05-03 11:19:58 [org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping]-[DEBUG] Looking up handler method for path /redisTest/selectall 2018-05-03 11:19:58 [org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping]-[DEBUG] Returning handler method [public java.lang.Object com.stonegeek.controller.UserController.showUsers()] 2018-05-03 11:19:58 [org.springframework.beans.factory.support.DefaultListableBeanFactory]-[DEBUG] Returning cached instance of singleton bean 'userController' 2018-05-03 11:19:58 [org.springframework.web.servlet.DispatcherServlet]-[DEBUG] Last-Modified value for [/redisTest/selectall] is: -1 2018-05-03 11:19:58 [org.springframework.data.redis.core.RedisConnectionUtils]-[DEBUG] Opening RedisConnection 2018-05-03 11:19:58 [org.springframework.data.redis.core.RedisConnectionUtils]-[DEBUG] Closing Redis Connection 2018-05-03 11:19:58 [org.mybatis.spring.SqlSessionUtils]-[DEBUG] Creating a new SqlSession 2018-05-03 11:19:58 [org.mybatis.spring.SqlSessionUtils]-[DEBUG] SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@22fb1e63] was not registered for synchronization because synchronization is not active 2018-05-03 11:19:58 [org.springframework.jdbc.datasource.DataSourceUtils]-[DEBUG] Fetching JDBC Connection from DataSource 2018-05-03 11:19:58 [com.mchange.v2.resourcepool.BasicResourcePool]-[DEBUG] trace com.mchange.v2.resourcepool.BasicResourcePool@5259cb3b [managed: 3, unused: 2, excluded: 0] (e.g. com.mchange.v2.c3p0.impl.NewPooledConnection@7f53b569) 2018-05-03 11:19:58 [org.mybatis.spring.transaction.SpringManagedTransaction]-[DEBUG] JDBC Connection [com.mchange.v2.c3p0.impl.NewProxyConnection@2a67a803] will not be managed by Spring 2018-05-03 11:19:58 [com.stonegeek.dao.UserMapper.selectAll]-[DEBUG] ==> Preparing: select * from user 2018-05-03 11:19:58 [com.stonegeek.dao.UserMapper.selectAll]-[DEBUG] ==> Parameters: 2018-05-03 11:19:58 [com.stonegeek.dao.UserMapper.selectAll]-[DEBUG] <== Total: 1 2018-05-03 11:19:58 [org.mybatis.spring.SqlSessionUtils]-[DEBUG] Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@22fb1e63] 2018-05-03 11:19:58 [org.springframework.jdbc.datasource.DataSourceUtils]-[DEBUG] Returning JDBC Connection to DataSource 2018-05-03 11:19:58 [com.mchange.v2.resourcepool.BasicResourcePool]-[DEBUG] trace com.mchange.v2.resourcepool.BasicResourcePool@5259cb3b [managed: 3, unused: 2, excluded: 0] (e.g. com.mchange.v2.c3p0.impl.NewPooledConnection@7f53b569) 2018-05-03 11:19:58 [org.springframework.data.redis.core.RedisConnectionUtils]-[DEBUG] Opening RedisConnection 2018-05-03 11:19:58 [org.springframework.data.redis.core.RedisConnectionUtils]-[DEBUG] Closing Redis Connection -------------------------- [com.stonegeek.pojo.User@5eecc6cd] -------------------------- 2018-05-03 11:19:58 [org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor]-[DEBUG] Written [[com.stonegeek.pojo.User@5eecc6cd]] as "application/json;charset=UTF-8" using [org.springframework.http.converter.json.MappingJackson2HttpMessageConverter@27f9bd05] 2018-05-03 11:19:58 [org.springframework.web.servlet.DispatcherServlet]-[DEBUG] Null ModelAndView returned to DispatcherServlet with name 'SpringMVC': assuming HandlerAdapter completed request handling 2018-05-03 11:19:58 [org.springframework.web.servlet.DispatcherServlet]-[DEBUG] Successfully completed request
七、总结
首先我们先进行了第一次查询,然后将从mysql查询出来的结果缓存到redis内存中,第二次查询直接从redis内存中取出数据,之后我们又做了一次删除操作,此时会把redis上的缓存清空,之后又进行了一次查询操作,可以看到,确实是删除操作将redis缓存清空,然后又重新将mysql数据缓存到了redis内存上。
这样redis的好处显露无疑:每次加载所有用户信息时,如果都要请求数据库,数据库编译并执行你的查询语句,这样效率就会低下很多,针对这种信息不经常变动并且数据量较大的情况,通常做法,就是把他加入redis缓存,每次取数据先去判断,如果缓存不为空,那么就从缓存取值,如果为空,再去请求数据库,并将数据加入缓存,这样大大提高系统访问效率。