需要先搭好SSM開發環境,并安裝好redis,下面是具體的實現步驟:
1、在項目中引入jedis架包:jedis-2.8.2.jar、spring-data-redis-1.6.2.RELEASE.jar和commons-pool-1.6.jar,注意引入的jar版本,過高或過低都有可能引發異常,上面提到這些版本組合親測可用;
2、編寫Redis需要用的2個工具類 RedisUtil.Java和SerializeUtil.java
3、新增一個Cache類mybatisRedisCache,實現 org.apache.ibatis.cache.Cache 接口
4、開啟mybatis對緩存的支持,在本項目中,是修改 mybatis-config.xml文件
5、在相關的 mapper.xml 添加自定義的緩存類MybatisRedisCache
RedisUtil工具類是用以跟Redis數據通信,SerializeUtil為序列化工具類,也是lang包下的工具,主要用于序列化操作,同時提供對象克隆接口。下面是具體代碼:
import?redis.clients.jedis.Jedis; import?redis.clients.jedis.JedisPool; import?redis.clients.jedis.JedisPoolConfig; public?class?RedisUtil?{ ????private?Static?String?ADDR?=?"127.0.0.1"; ????private?static?int?PORT?=?6379; ????private?static?int?MAX_ACTIVE?=?1024; ????private?static?int?MAX_IDLE?=?200; ????private?static?int?MAX_WAIT?=?100000; ????private?static?int?TIMEOUT?=?10000; ????private?static?boolean?TEST_ON_BORROW?=?true; ????private?static?JedisPool?jedisPool?=?null; ????static?{ ????????try{ ????????????JedisPoolConfig?config?=?new?JedisPoolConfig(); ????????????config.setMaxIdle(MAX_IDLE); ????????????config.setMaxWaitMillis(MAX_WAIT); ????????????config.setTestOnBorrow(TEST_ON_BORROW); ????????????jedisPool?=?new?JedisPool(config,ADDR,PORT,TIMEOUT); ????????}catch?(Exception?e)?{ ????????????e.printStackTrace(); ????????} ????} ????public?synchronized?static?Jedis?getJedis(){ ????????try{ ????????????if(jedisPool?!=?null){ ????????????????Jedis?jedis?=?jedisPool.getResource(); ????????????????return?jedis; ????????????}else{ ????????????????return?null; ????????????} ????????}catch?(Exception?e)?{ ????????????e.printStackTrace(); ????????????return?null; ????????} ????} ????public?static?void?returnResource(final?Jedis?jedis){ ????????if(jedis?!=?null){ ????????????jedisPool.returnResource(jedis); ????????} ????} }
import?java.io.ByteArrayInputStream; import?java.io.ByteArrayOutputStream; import?java.io.ObjectInputStream; import?java.io.ObjectOutputStream; public?class?SerializeUtil?{ ????public?static?byte[]?serialize(Object?object)?{ ????????ObjectOutputStream?oos?=?null; ????????ByteArrayOutputStream?baos?=?null; ????????try?{ ????????????//?序列化 ????????????baos?=?new?ByteArrayOutputStream(); ????????????oos?=?new?ObjectOutputStream(baos); ????????????oos.writeObject(object); ????????????byte[]?bytes?=?baos.toByteArray(); ????????????return?bytes; ????????}?catch?(Exception?e)?{ ????????????e.printStackTrace(); ????????} ????????return?null; ????} ????public?static?Object?unserialize(byte[]?bytes)?{ ????????if?(bytes?==?null) ????????????return?null; ????????ByteArrayInputStream?bais?=?null; ????????try?{ ????????????//?反序列化 ????????????bais?=?new?ByteArrayInputStream(bytes); ????????????ObjectInputStream?ois?=?new?ObjectInputStream(bais); ????????????return?ois.readObject(); ????????}?catch?(Exception?e)?{ ????????????e.printStackTrace(); ????????} ????????return?null; ????} } import?java.util.concurrent.locks.ReadWriteLock; import?java.util.concurrent.locks.ReentrantReadWriteLock; import?org.apache.ibatis.cache.Cache; import?org.slf4j.Logger; import?org.slf4j.LoggerFactory; public?class?MybatisRedisCache?implements?Cache?{ ????private?static?Logger?logger?=?LoggerFactory.getLogger(MybatisRedisCache.class);? ????/**?The?ReadWriteLock.?*/? ????private?final?ReadWriteLock?readWriteLock?=?new?ReentrantReadWriteLock(); ????private?String?id; ????public?MybatisRedisCache(final?String?id)?{?? ????????if?(id?==?null)?{ ????????????throw?new?IllegalArgumentException("Cache?instances?require?an?ID"); ????????} ????????logger.debug(">>>>>>>>>>>>>>>>>>>>>>>>MybatisRedisCache:id="+id); ????????this.id?=?id; ????}?? ????public?String?getId()?{ ????????return?this.id; ????} ????public?void?putObject(Object?key,?Object?value)?{ ????????logger.debug(">>>>>>>>>>>>>>>>>>>>>>>>putObject:"+key+"="+value); ????????RedisUtil.getJedis().set(SerializeUtil.serialize(key.toString()),?SerializeUtil.serialize(value)); ????} ????public?Object?getObject(Object?key)?{ ????????Object?value?=?SerializeUtil.unserialize(RedisUtil.getJedis().get(SerializeUtil.serialize(key.toString()))); ????????logger.debug(">>>>>>>>>>>>>>>>>>>>>>>>getObject:"+key+"="+value); ????????return?value; ????} ????public?Object?removeObject(Object?key)?{ ????????return?RedisUtil.getJedis().expire(SerializeUtil.serialize(key.toString()),0); ????} ?public?void?clear()?{ ????????RedisUtil.getJedis().flushDB(); ????} ???public?int?getSize()?{ ????????return?Integer.valueOf(RedisUtil.getJedis().dbSize().toString()); ????} ???public?ReadWriteLock?getReadWriteLock()?{ ????????return?readWriteLock; ????} }
mybatis-config.xml文件,在spring-mybatis.xml文件中選擇全局加載:
<!-- 配置mybatis --> ????<bean> ????????<property></property> ????????<!-- 加載mybatis的全局配置文件 --> ????????<property></property> ????????<!-- mapper掃描 --> ????????<property></property> ???????</bean>
以下是mybatis-config.xml詳細代碼:
<?xml version="1.0" encoding="UTF-8"?>nbsp;configuration?PUBLIC?"-//mybatis.org//DTD?sql?Map?Config?3.0//EN"?? ????"http://mybatis.org/dtd/mybatis-3-config.dtd"> <configuration> ????<settings> ?????????<!-- 全局映射器啟用緩存 --> ????????<setting></setting> ????????<!-- 查詢時,關閉關聯對象即時加載以提高性能 --> ????????<setting></setting> ????????<!-- 對于未知的SQL查詢,允許返回不同的結果集以達到通用的效果 --> ????????<setting></setting> ????????<!-- 允許使用列標簽代替列名 --> ????????<setting></setting> ????????<!-- 不允許使用自定義的主鍵值(比如由程序生成的UUID 32位編碼作為鍵值),數據表的PK生成策略將被覆蓋 --> ????????<setting></setting> ????????<!-- 給予被嵌套的resultMap以字段-屬性的映射支持 FULL,PARTIAL --> ????????<setting></setting> ????????<!-- 對于批量更新操作緩存SQL以提高性能 BATCH,SIMPLE --> ????????<!-- <setting name="defaultExecutorType" value="BATCH" /> --> ????????<!-- 數據庫超過25000秒仍未響應則超時 --> ????????<!-- <setting name="defaultStatementTimeout" value="25000" /> --> ????????<!-- Allows using RowBounds on nested statements --> ????????<setting></setting> ????????<!-- Enables automatic mapping from classic database column names A_COLUMN to camel case classic Java property names aColumn. --> ????????<setting></setting> ????????<!-- MyBatis uses local cache to prevent circular references and speed up repeated nested queries. By default (SESSION) all queries executed during a session are cached. If localCacheScope=STATEMENT local session will be used just for statement execution, no data will be shared between two different calls to the same SqlSession. --> ????????<setting></setting> ????????<!-- Specifies the JDBC type for null values when no specific JDBC type was provided for the parameter. Some drivers require specifying the column JDBC type but others work with generic values like NULL, VARCHAR or OTHER. --> ????????<setting></setting> ????????<!-- Specifies which Object's methods trigger a lazy load --> ????????<setting></setting> ??????????<!-- 打印sql語句 --> ????????<setting></setting>?? </settings></configuration>
最后在需要緩存的映射文件mapper.xml的Namespace加上引用的
<?xml version="1.0" encoding="UTF-8" ?>nbsp;mapper?PUBLIC?"-//mybatis.org//DTD?Mapper?3.0//EN"?"http://mybatis.org/dtd/mybatis-3-mapper.dtd"?> <mapper> ??<cache></cache></mapper>
然后就可以進行測試了,測試時先進行第一次查詢,如果開啟打印sql,將會發現控制臺打印出剛才執行查詢的SQL語句,再進行同樣條件的查詢,這時注意觀察控制臺,如果沒有打印SQL,直接輸出查詢結果,說明是從Redis讀取到數據返回給你,而不是去數據庫中查詢得到的結果。此時配置就成功了。
當然,我們可以開啟Redis客戶端和服務器端,在Redis安裝目錄下找到redis-cli,雙擊打開,輸入keys *回車,將會看到生成的key,Redis就是根據key去獲取所需的value。?
在實際操作的過程中要注意RedisUtil工具類,需要根據自己的情況設置port、ADDR 、如果安裝的Redis設置有密碼,還需加上AUTH,如果沒有設置密碼,這項不要添加在工具類中,哪怕賦空值也不行,
曾經試過這樣: private static String AUTH = ” “;
結果運行的時候報了這個異常: jedis.exceptions.JedisDataException: ERR Client sent AUTH, but no password is set?
意思就是redis服務器沒有設置密碼,但客戶端向其發送了AUTH請求。 此外,要緩存的類需要implements Serializable。 如果懷疑你安裝的Redis有問題,可通過下面的方法進行測試:
??@Test ????public?void?testRedis(){ ?????????//連接本地的?Redis?服務 ????????Jedis?jedis?=?new?Jedis("localhost"); ????????System.out.println("連接成功"); ????????//查看服務是否運行 ????????System.out.println("服務正在運行:?"+jedis.ping()); ????????//設置?redis?字符串數據 ????????jedis.set("success",?"oobom"); ????????//?獲取存儲的數據并輸出 ????????System.out.println("redis?存儲的字符串為:?"+?jedis.get("success")); ????}
更多redis知識請關注redis數據庫教程欄目。