Redis使用教程(二)

spring整合Redis

1.Spring使用原生redisTemplate(数据一致性要求不高)
2.Spring基于注解整合Redis实现内容缓存(要求一致性高)

统一配置项目pom.xml文件(在整合项目dao层)
1.添加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>
	<parent>
		<groupId>com.wwj</groupId>
		<artifactId>small</artifactId>
		<version>0.0.1-SNAPSHOT</version>
	</parent>
	<artifactId>small-dao</artifactId>
	<properties>
		<!--jar包版本 -->
		<mybatis.version>3.4.5</mybatis.version>
		<mybatis-spring.version>1.3.1</mybatis-spring.version>
		<pagehelper.version>4.1.4</pagehelper.version>
		<mysql-connector.version>5.1.41</mysql-connector.version>
		<c3p0>0.9.5.3</c3p0>
		<spring-redis>1.6.0.RELEASE</spring-redis>
		<jredis-version>2.7.3</jredis-version>

		<!--编译级别 -->
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
	</properties>
	<dependencies>
		<!-- mybatis核心包 -->
		<dependency>
			<groupId>org.mybatis</groupId>
			<artifactId>mybatis</artifactId>
			<version>${mybatis.version}</version>
		</dependency>

		<!-- mybatis集成spring包 -->
		<dependency>
			<groupId>org.mybatis</groupId>
			<artifactId>mybatis-spring</artifactId>
			<version>${mybatis-spring.version}</version>
		</dependency>

		<!-- Mysql数据库链接jar包 -->
		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
			<version>${mysql-connector.version}</version>
			<scope>runtime</scope>
		</dependency>

		<!-- mybatis分页插件 -->
		<dependency>
			<groupId>com.github.pagehelper</groupId>
			<artifactId>pagehelper</artifactId>
			<version>${pagehelper.version}</version>
		</dependency>

		<!-- c3p0 -->
		<dependency>
			<groupId>com.mchange</groupId>
			<artifactId>c3p0</artifactId>
			<version>${c3p0}</version>
		</dependency>

		<!--Spring redis 缓存 -->
		<dependency>
			<groupId>org.springframework.data</groupId>
			<artifactId>spring-data-redis</artifactId>
			<version>${spring-redis}</version>
		</dependency>
		<!--redis 客户端 -->
		<dependency>
			<groupId>redis.clients</groupId>
			<artifactId>jedis</artifactId>
			<version>${jredis-version}</version>
		</dependency>
	</dependencies>
</project>
2.添加redis配置文件
# Redis settings  
redis.host=144.202.3.120
redis.port=6379  
redis.pass=redis
redis.dbIndex=0  
redis.expiration=3000  
redis.maxIdle=300  
redis.maxActive=600  
redis.maxWait=1000
# check data  有效性
redis.testOnBorrow=true

3.在web层添加utils
package com.wwj.utils;

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;
/**
 * 重写的generate()方法为数据存入缓存的无参的方法指定存入缓存中的数据的key
 * @author Yun
 *
 */
@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 keyGenerator() {
		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());
				if(objects.length != 0){
					sb.append("_");
					for (Object obj : objects) {
						sb.append(obj.toString());
					}
				}
				return sb.toString();
			}
		};
	}
}
4.在容器中配置redis实例
<?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:tx="http://www.springframework.org/schema/tx"
       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/tx http://www.springframework.org/schema/tx/spring-tx.xsd">
    <!-- 自动扫描 -->
    <context:component-scan base-package="com.wwj"/>

    <!-- 引入配置文件 -->
    <bean id="propertyConfigurer"
          class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">    
        <property name="locations">
            <list>
                <value>classpath:jdbc.properties</value>
                <value>classpath:redis.properties</value>
            </list>
        </property>
    </bean>

	<!-- 配置c3p0数据源 -->
	<bean class="com.mchange.v2.c3p0.ComboPooledDataSource" id="dataSource">
		<property name="driverClass" value="${jdbc.driver}"></property>
		<property name="jdbcUrl" value="${jdbc.url}"></property>
		<property name="user" value="${jdbc.username}"></property>
		<property name="password" value="${jdbc.password}"></property>
	</bean>
    <!-- spring和MyBatis整合 -->
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="dataSource"/>
        <!--mybatis分页插件-->
        <property name="configLocation" value="classpath:spring/mybatis-config.xml"></property>
        <!-- 自动扫描mapping.xml文件 -->
        <property name="mapperLocations" value="classpath:Mapper/*.xml"></property>
    </bean>

    <!-- DAO接口所在包名,Spring会自动查找其下的类 -->
    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <property name="basePackage" value="com.wwj.mapper"/>
        <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"></property>
    </bean>

    <!-- 事务管理 -->
    <bean id="transactionManager"
          class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"/>
    </bean>
    
    <!--支持事务注解的(@Transactional)-->
    <tx:annotation-driven transaction-manager="transactionManager"/>
    
    <!-- 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>
 
	<bean id="stringRedisSerializer" class="org.springframework.data.redis.serializer.StringRedisSerializer"/>
 
    <!-- 配置RedisTemplate -->
    <bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate">
        <property name="connectionFactory" ref="jedisConnectionFactory" />
        <property name="hashKeySerializer" ref="stringRedisSerializer"/>
        <property name="keySerializer" ref="stringRedisSerializer"/>
    </bean>
 
    <!-- 配置RedisCacheManager -->
    <bean id="redisCacheManager" class="org.springframework.data.redis.cache.RedisCacheManager">
        <constructor-arg name="redisOperations" ref="redisTemplate" />
        <property name="defaultExpiration" value="${redis.expiration}" />
        <!-- 可选配置缓存区间
        <property name="cacheNames">
        	<list>
        		<value>xxx</value>
        	</list>
        </property> -->
    </bean>
    
    
	<!-- 配置RedisCacheConfig -->
<bean id="redisCacheConfig" class="com.wwj.utils.RedisCacheConfig">
	<constructor-arg ref="jedisConnectionFactory"/>
		<constructor-arg ref="redisTemplate"/>
		<constructor-arg ref="redisCacheManager"/>
	</bean>

</beans>
注解含义

@Cacheable:表明在进入方法之前,Spring会先去缓存服务器中查找对应key的缓存值,如果找到缓存值,那么Spring将不会再调用方法,而是将缓存值独处,返回给调用者;如果没有找到缓存值,那么Spring就会执行你的方法,将最后的结果通过key保存到缓存服务器中。
@CachePut:表明Spring会将该方法返回的值缓存到缓存服务器中,这里需要注意的是,Spring不会事先去缓存服务器中查找,而是直接执行方法,然后缓存。换句话说,该方法始终会被Spring所调用。
@CacheEvict:表示执行方法后从缓存服务器移除对应key的值;

加深理解

@Cacheable(value=“xxx” key=“zzz”)注解:标注该方法查询的结果进入缓存,再次访问时直接读取缓存中的数据
1.对于有参数的方法,指定value(缓存区间)和key(缓存的key);
对于无参数的方法,只需指定value,存到数据库中数据的key通过重写的generate()方法生成。
2.调用该注解标识的方法时,会根据value和key去redis缓存中查找数据,如果查找不到,则去数据库中查找,然后将查找到的数据存放入redis缓存中;
3.向redis中填充的数据分为两部分:
1).用来记录xxx缓存区间中的缓存数据的key的xxx~keys(zset类型)
2).缓存的数据,key:数据的key;value:序列化后的从数据库中得到的数据
4.第一次执行@Cacheable注解标识的方法,会在redis中新增上面两条数据
5.非第一次执行@Cacheable注解标识的方法,若未从redis中查找到数据,则执行从数据库中查询
* @CacheEvict()注解:移除指定缓存区间的一个或者多个缓存对象
* @param value + key 或者 value + allEntries=true
* 1.value + key 移除value缓存区间内的键为key的数据
* 2.value + allEntries=true 移除value缓存区间内的所有数据

代码操作示例(数据一致性不高)

1.建一张用户表模拟数据以及封装的resultmap对应的vo对象(需要被序列化)

在这里插入图片描述

2.构建服务层以及dao层和controller层

package com.wwj.controller;

import java.util.concurrent.TimeUnit;

import javax.annotation.Resource;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import com.wwj.service.RedisService;

@Controller
public class RedisController {
	
	@Autowired
	private  RedisService  redisService;
	
	@Resource
    private RedisTemplate redisTemplate;
	
	@RequestMapping("/selectRedis1")
	@ResponseBody
	public String   selectRedis1(){
		String personCount = null;
		personCount= (String) redisTemplate.opsForValue().get("person_count");
		
		if(personCount == null){
    		//redis缓存中无数据,从数据库中查询,并放入redis缓存中,设置生存时间为1小时
    		personCount = Integer.toString(redisService.getPersonCount());
    		redisTemplate.opsForValue().set("person_count", personCount, 1, TimeUnit.HOURS);
    	} else {
    		System.out.println("从redis拿取数据");
    		personCount=  (String) redisTemplate.opsForValue().get("person_count");
    	}	
		return personCount;
	}

}

代码操作示例(数据一致性高)以及增加或者删除修改数据后清空缓存

package com.wwj.service.impl;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

import com.wwj.mapper.PersonMapper;
import com.wwj.model.Person;
import com.wwj.service.RedisService;

@Service("redisService")
public class RedisServiceImpl  implements  RedisService{
	
	@Autowired
	private  PersonMapper  personMapper;

	@Override
	public Integer getPersonCount() {
		// TODO Auto-generated method stub
		return personMapper.selectCountOfPerson();
	}

	@Cacheable(value="getPersons")
	@Override
	public List<Person> getPersons() {
		// TODO Auto-generated method stub
		return personMapper.selectPersons();
	}

	
	@Cacheable(value="getPersonById",key="'getPersonById_'+#id")
	@Override
	public Person getPersonById(Integer id) {
		// TODO Auto-generated method stub
		return personMapper.selectPersonById(id);
	}

	@CacheEvict(value="getPersons",allEntries=true)
	@Override
	public int savePerson(String name) {
		// TODO Auto-generated method stub
		return personMapper.insertPerson(name);
	}

}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值