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.0modelVersion>
	<parent>
		<groupId>com.wwjgroupId>
		<artifactId>smallartifactId>
		<version>0.0.1-SNAPSHOTversion>
	parent>
	<artifactId>small-daoartifactId>
	<properties>
		
		<mybatis.version>3.4.5mybatis.version>
		<mybatis-spring.version>1.3.1mybatis-spring.version>
		<pagehelper.version>4.1.4pagehelper.version>
		<mysql-connector.version>5.1.41mysql-connector.version>
		<c3p0>0.9.5.3c3p0>
		<spring-redis>1.6.0.RELEASEspring-redis>
		<jredis-version>2.7.3jredis-version>

		
		<project.build.sourceEncoding>UTF-8project.build.sourceEncoding>
	properties>
	<dependencies>
		
		<dependency>
			<groupId>org.mybatisgroupId>
			<artifactId>mybatisartifactId>
			<version>${mybatis.version}version>
		dependency>

		
		<dependency>
			<groupId>org.mybatisgroupId>
			<artifactId>mybatis-springartifactId>
			<version>${mybatis-spring.version}version>
		dependency>

		
		<dependency>
			<groupId>mysqlgroupId>
			<artifactId>mysql-connector-javaartifactId>
			<version>${mysql-connector.version}version>
			<scope>runtimescope>
		dependency>

		
		<dependency>
			<groupId>com.github.pagehelpergroupId>
			<artifactId>pagehelperartifactId>
			<version>${pagehelper.version}version>
		dependency>

		
		<dependency>
			<groupId>com.mchangegroupId>
			<artifactId>c3p0artifactId>
			<version>${c3p0}version>
		dependency>

		
		<dependency>
			<groupId>org.springframework.datagroupId>
			<artifactId>spring-data-redisartifactId>
			<version>${spring-redis}version>
		dependency>
		
		<dependency>
			<groupId>redis.clientsgroupId>
			<artifactId>jedisartifactId>
			<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实例


<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.propertiesvalue>
                <value>classpath:redis.propertiesvalue>
            list>
        property>
    bean>

	
	<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>
    
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="dataSource"/>
        
        <property name="configLocation" value="classpath:spring/mybatis-config.xml">property>
        
        <property name="mapperLocations" value="classpath:Mapper/*.xml">property>
    bean>

    
    <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>
    
    
    <tx:annotation-driven transaction-manager="transactionManager"/>
    
    
    
    <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>
 
    
    <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="database" value="${redis.dbIndex}" />
        <property name="poolConfig" ref="poolConfig" />
    bean>
 
	<bean id="stringRedisSerializer" class="org.springframework.data.redis.serializer.StringRedisSerializer"/>
 
    
    <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>
 
    
    <bean id="redisCacheManager" class="org.springframework.data.redis.cache.RedisCacheManager">
        <constructor-arg name="redisOperations" ref="redisTemplate" />
        <property name="defaultExpiration" value="${redis.expiration}" />
        
    bean>
    
    
	
<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对象(需要被序列化)

Redis使用教程(二)_第1张图片

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);
	}

}

你可能感兴趣的:(数据库)