spring整合redis緩存并以注解(@Cacheable、@CachePut、@CacheEvict)形式使用
maven項(xiàng)目中在pom.xml中依賴2個(gè)jar包,其他的spring的jar包省略:
<dependency> <groupId>redis.clients</groupId> <artifactId>jedis</artifactId> <version>2.8.1</version> </dependency> <dependency> <groupId>org.springframework.data</groupId> <artifactId>spring-data-redis</artifactId> <version>1.7.2.RELEASE</version> </dependency>
spring-Redis.xml中的內(nèi)容:
<?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"
xmlns:cache="http://www.springframework.org/schema/cache"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.2.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.2.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-4.2.xsd
http://www.springframework.org/schema/cache
http://www.springframework.org/schema/cache/spring-cache-4.2.xsd">
<context:property-placeholder location="classpath:redis-config.properties" />
<!-- 啟用緩存注解功能,這個(gè)是必須的,否則注解不會(huì)生效,另外,該注解一定要聲明在spring主配置文件中才會(huì)生效 -->
<cache:annotation-driven cache-manager="cacheManager" />
<!-- redis 相關(guān)配置 -->
<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>
<bean id="JedisConnectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory"
p:host-name="${redis.host}" p:port="${redis.port}" p:password="${redis.pass}" p:pool-config-ref="poolConfig"/>
<bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate">
<property name="connectionFactory" ref="JedisConnectionFactory" />
</bean>
<!-- spring自己的緩存管理器,這里定義了緩存位置名稱 ,即注解中的value -->
<bean id="cacheManager" class="org.springframework.cache.support.SimpleCacheManager">
<property name="caches">
<set>
<!-- 這里可以配置多個(gè)redis -->
<!-- <bean class="com.cn.util.RedisCache">
<property name="redisTemplate" ref="redisTemplate" />
<property name="name" value="default"/>
</bean> -->
<bean class="com.cn.util.RedisCache">
<property name="redisTemplate" ref="redisTemplate" />
<property name="name" value="common"/>
<!-- common名稱要在類或方法的注解中使用 -->
</bean>
</set>
</property>
</bean>
</beans>
redis-config.properties中的內(nèi)容:
# Redis settings # server IP redis.host=127.0.0.1 # server port redis.port=6379 # server pass redis.pass= # use dbIndex redis.database=0 # 控制一個(gè)pool最多有多少個(gè)狀態(tài)為idle(空閑的)的jedis實(shí)例 redis.maxIdle=300 # 表示當(dāng)borrow(引入)一個(gè)jedis實(shí)例時(shí),最大的等待時(shí)間,如果超過等待時(shí)間(毫秒),則直接拋出JedisConnectionException; redis.maxWait=3000 # 在borrow一個(gè)jedis實(shí)例時(shí),是否提前進(jìn)行validate操作;如果為true,則得到的jedis實(shí)例均是可用的 redis.testOnBorrow=true
com.cn.util.RedisCache類中的內(nèi)容:
package com.cn.util;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import org.springframework.cache.Cache;
import org.springframework.cache.support.SimpleValueWrapper;
import org.springframework.dao.DataAccessException;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.RedisTemplate;
public class RedisCache implements Cache{
private RedisTemplate<String, Object> redisTemplate;
private String name;
public RedisTemplate<String, Object> getRedisTemplate() {
return redisTemplate;
}
public void setRedisTemplate(RedisTemplate<String, Object> redisTemplate) {
this.redisTemplate = redisTemplate;
}
public void setName(String name) {
this.name = name;
}
@Override
public String getName() {
// TODO Auto-generated method stub
return this.name;
}
@Override
public Object getNativeCache() {
// TODO Auto-generated method stub
return this.redisTemplate;
}
@Override
public ValueWrapper get(Object key) {
// TODO Auto-generated method stub
System.out.println("get key");
final String keyf = key.toString();
Object object = null;
object = redisTemplate.execute(new RedisCallback<Object>() {
public Object doInRedis(RedisConnection connection)
throws DataAccessException {
byte[] key = keyf.getBytes();
byte[] value = connection.get(key);
if (value == null) {
return null;
}
return toObject(value);
}
});
return (object != null ? new SimpleValueWrapper(object) : null);
}
@Override
public void put(Object key, Object value) {
// TODO Auto-generated method stub
System.out.println("put key");
final String keyf = key.toString();
final Object valuef = value;
final long liveTime = 86400;
redisTemplate.execute(new RedisCallback<Long>() {
public Long doInRedis(RedisConnection connection)
throws DataAccessException {
byte[] keyb = keyf.getBytes();
byte[] valueb = toByteArray(valuef);
connection.set(keyb, valueb);
if (liveTime > 0) {
connection.expire(keyb, liveTime);
}
return 1L;
}
});
}
private byte[] toByteArray(Object obj) {
byte[] bytes = null;
ByteArrayOutputStream bos = new ByteArrayOutputStream();
try {
ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeObject(obj);
oos.flush();
bytes = bos.toByteArray();
oos.close();
bos.close();
}catch (IOException ex) {
ex.printStackTrace();
}
return bytes;
}
private Object toObject(byte[] bytes) {
Object obj = null;
try {
ByteArrayInputStream bis = new ByteArrayInputStream(bytes);
ObjectInputStream ois = new ObjectInputStream(bis);
obj = ois.readObject();
ois.close();
bis.close();
} catch (IOException ex) {
ex.printStackTrace();
} catch (ClassNotFoundException ex) {
ex.printStackTrace();
}
return obj;
}
@Override
public void evict(Object key) {
// TODO Auto-generated method stub
System.out.println("del key");
final String keyf = key.toString();
redisTemplate.execute(new RedisCallback<Long>() {
public Long doInRedis(RedisConnection connection)
throws DataAccessException {
return connection.del(keyf.getBytes());
}
});
}
@Override
public void clear() {
// TODO Auto-generated method stub
System.out.println("clear key");
redisTemplate.execute(new RedisCallback<String>() {
public String doInRedis(RedisConnection connection)
throws DataAccessException {
connection.flushDb();
return "ok";
}
});
}
@Override
public <T> T get(Object key, Class<T> type) {
// TODO Auto-generated method stub
return null;
}
@Override
public ValueWrapper putIfAbsent(Object key, Object value) {
// TODO Auto-generated method stub
return null;
}
}
到了這一步,大部分人會(huì)想在web.xml的啟動(dòng)配置文件地方(context-param)加入了spring-redis.xml,讓項(xiàng)目啟動(dòng)時(shí)加載這個(gè)配置文件吧,但是這樣啟動(dòng)后注解不生效。
正確的做法是:web.xml中配置了servlet控制器:
<servlet> <servlet-name>SpringMVC</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/spring-mvc.xml</param-value> </init-param> <load-on-startup>1</load-on-startup> <async-supported>true</async-supported> </servlet>
在DispatcherServlet的初始化過程中,框架會(huì)在web應(yīng)用的 WEB-INF文件夾下尋找名為spring-mvc.xml的配置文件,如果不指定的話,默認(rèn)是applicationContext.xml
只需要在spring-mvc.xml文件中引入spring-redis配置文件即可,正如spring-redis.xml中的啟用注解說的:<cache:annotation-driven cache-manager="cacheManager" />注解一定要聲明在spring主配置文件中才會(huì)生效。
spring-mvc.xml內(nèi)容,省略了spring與spring MVC整合的那部分:
<?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-4.2.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.2.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-4.2.xsd">
<!-- 自動(dòng)掃描該包,使SpringMVC認(rèn)為包下用了@controller注解的類是控制器 -->
<context:component-scan base-package="com.cn" />
<!-- 引入同文件夾下的redis屬性配置文件 -->
<import resource="spring-redis.xml"/>
</beans>
在service的實(shí)現(xiàn)類中:
@Service
public class UserServiceImpl implements UserService{
@Autowired
private UserBo userBo;
@Cacheable(value="common",key="'id_'+#id")
public User selectByPrimaryKey(Integer id) {
return userBo.selectByPrimaryKey(id);
}
@CachePut(value="common",key="#user.getUserName()")
public void insertSelective(User user) {
userBo.insertSelective(user);
}
@CacheEvict(value="common",key="'id_'+#id")
public void deleteByPrimaryKey(Integer id) {
userBo.deleteByPrimaryKey(id);
}
}
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
Java基于控制臺(tái)界面實(shí)現(xiàn)ATM系統(tǒng)
這篇文章主要為大家詳細(xì)介紹了Java基于控制臺(tái)界面實(shí)現(xiàn)ATM系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-05-05
一文詳解SpringBoot如何同時(shí)監(jiān)聽多個(gè)端口
這篇文章主要為大家詳細(xì)介紹了SpringBoot如何同時(shí)監(jiān)聽多個(gè)端口,文中的示例代碼講解詳細(xì),具有一定的借鑒價(jià)值,感興趣的小伙伴可以了解下2025-10-10
Spring Cloud中使用Feign,@RequestBody無法繼承的解決方案
這篇文章主要介紹了Spring Cloud中使用Feign,@RequestBody無法繼承的解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-10-10
JAVA實(shí)現(xiàn)微信APPV3支付保姆級(jí)教程
微信實(shí)現(xiàn)支付功能與支付寶實(shí)現(xiàn)支付功能是相似的,這篇文章主要介紹了JAVA實(shí)現(xiàn)微信APPV3支付的相關(guān)資料,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下2024-01-01
SpringBoot獲取配置文件的簡(jiǎn)單實(shí)現(xiàn)方法
這篇文章主要給大家介紹了關(guān)于SpringBoot如何獲取配置文件的簡(jiǎn)單實(shí)現(xiàn)方法,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用Spring Boot具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧2020-05-05
springcloud整合到項(xiàng)目中無法啟動(dòng)報(bào)錯(cuò)Failed to start bean&n
這篇文章主要介紹了springcloud整合到項(xiàng)目中無法啟動(dòng)報(bào)錯(cuò)Failed to start bean 'eurekaAutoServiceRegistration'問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-01-01
SpringBoot之HandlerInterceptor攔截器的使用詳解
這篇文章主要介紹了SpringBoot之HandlerInterceptor攔截器的使用詳解,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-10-10
Java內(nèi)部類的實(shí)現(xiàn)原理與可能的內(nèi)存泄漏說明
這篇文章主要介紹了Java內(nèi)部類的實(shí)現(xiàn)原理與可能的內(nèi)存泄漏說明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2020-10-10
新手小白學(xué)JAVA IDEA下載使用手冊(cè)全集
IDEA的每一個(gè)方面都是為了最大限度地提高開發(fā)人員的工作效率而設(shè)計(jì)的,它的智能編碼輔助和人機(jī)工程學(xué)設(shè)計(jì)會(huì)讓開發(fā)過程變得愉悅且高效,今天給大家分享新手小白學(xué)JAVA IDEA下載使用手冊(cè)全集,對(duì)idea新手使用相關(guān)知識(shí)感興趣的朋友跟隨小編一起學(xué)習(xí)吧2021-05-05
spring boot 加載web容器tomcat流程源碼分析
本文章主要描述spring boot加載web容器 tomcat的部分,為了避免文章知識(shí)點(diǎn)過于分散,其他相關(guān)的如bean的加載,tomcat內(nèi)部流程等不做深入討論,具體內(nèi)容詳情跟隨小編一起看看吧2021-06-06

