SSM:是Spring+Struts+Mybatis ,另外还使用了PageHelper
前言:
这里主要是利用redis去做mybatis的二级缓存,mybaits映射文件中所有的select都会刷新已有缓存,如果不存在就会新建缓存,所有的insert,update操作都会更新缓存。(这里需要明白对于注解写的SQL语句不会操作缓存,我的增加方法是注解写的就没有清空缓存,后来改为XML中写就清空缓存了,这个问题没有解决?)
redis的好处也显而易见,可以使系统的数据访问性能更高。本节只是展示了整合方法和效果,后面会补齐redis集群、负载均衡和session共享的文章。
开始整合工作:
0.目录结构:
UserAction .java
import java.sql.SQLException; import java.util.HashMap; import java.util.List; import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import org.apache.struts2.ServletActionContext; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Scope; import org.springframework.stereotype.Controller;
import com.github.pagehelper.PageHelper; import com.opensymphony.xwork2.ActionSupport;
import cn.qlq.bean.User; import cn.qlq.service.UserService;
@Controller @Scope(“prototype”) @SuppressWarnings(“all”) public class UserAction extends ActionSupport { private Map<String, Object> response; @Autowired private UserService userService; private int id; private String name; public String add() { try { userService.addUser(id, name); } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } return “add”; }
</span><span style="color: #0000ff;">public</span><span style="color: #000000;"> String delete() {
</span><span style="color: #0000ff;">return</span> "delete"<span style="color: #000000;">;
}
</span><span style="color: #0000ff;">public</span><span style="color: #000000;"> String update() {
</span><span style="color: #0000ff;">return</span> "update"<span style="color: #000000;">;
}
</span><span style="color: #0000ff;">public</span> String find() <span style="color: #0000ff;">throws</span><span style="color: #000000;"> Exception {
User user </span>= userService.findUserById(1<span style="color: #000000;">);
System.out.println(user);
HttpServletRequest request </span>=<span style="color: #000000;"> ServletActionContext.getRequest();
request.setAttribute(</span>"user"<span style="color: #000000;">, user);
</span><span style="color: #0000ff;">return</span> "find"<span style="color: #000000;">;
}
</span><span style="color: #0000ff;">public</span> String findPage() <span style="color: #0000ff;">throws</span><span style="color: #000000;"> Exception {
response </span>= <span style="color: #0000ff;">new</span><span style="color: #000000;"> HashMap();
</span><span style="color: #008000;">//</span><span style="color: #008000;"> 第三个参数代表排序方式</span>
PageHelper.startPage(2, 2, "id desc"<span style="color: #000000;">);
List</span><User> users =<span style="color: #000000;"> userService.findUsersByPage();
response.put(</span>"users"<span style="color: #000000;">, users);
</span><span style="color: #0000ff;">return</span> "success"<span style="color: #000000;">;
}
</span><span style="color: #0000ff;">public</span><span style="color: #000000;"> Map getResponse() {
</span><span style="color: #0000ff;">return</span><span style="color: #000000;"> response;
}
</span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">void</span><span style="color: #000000;"> setResponse(Map response) {
</span><span style="color: #0000ff;">this</span>.response =<span style="color: #000000;"> response;
}
</span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">int</span><span style="color: #000000;"> getId() {
</span><span style="color: #0000ff;">return</span><span style="color: #000000;"> id;
}
</span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">void</span> setId(<span style="color: #0000ff;">int</span><span style="color: #000000;"> id) {
</span><span style="color: #0000ff;">this</span>.id =<span style="color: #000000;"> id;
}
</span><span style="color: #0000ff;">public</span><span style="color: #000000;"> String getName() {
</span><span style="color: #0000ff;">return</span><span style="color: #000000;"> name;
}
</span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">void</span><span style="color: #000000;"> setName(String name) {
</span><span style="color: #0000ff;">this</span>.name =<span style="color: #000000;"> name;
}
}
1.后台启动Redis-server,用redis-cli.exe能连接上则证明开启成功。我是服务注册的Redis。(参考:http://www.cnblogs.com/qlqwjy/p/8554215.html )
2.开始整合redis缓存:
首先在pom.xml中增加需要的redis jar包
<!-- jedis依赖 -->
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>2.7.1</version>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-redis</artifactId>
<version>1.6.2.RELEASE</version>
</dependency>
pom.xml写好后,还需要新增两个配置文件:redis.properties
redis.host=127.0.0.1
redis.port=6379
redis.pass=123456
redis.maxIdle=200
redis.maxActive=1024
redis.maxWait=10000
redis.testOnBorrow=true
其中字段也都很好理解,再加入配置文件:applicationContext-redis.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://www.springframework.org/schema/beans"
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-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd ">
<!– 连接池基本参数配置,类似数据库连接池 –> <context:property-placeholder location=“classpath:redis.properties” ignore-unresolvable=“true”/>
<span style="color: #0000ff;"><</span><span style="color: #800000;">bean </span><span style="color: #ff0000;">id</span><span style="color: #0000ff;">="poolConfig"</span><span style="color: #ff0000;"> class</span><span style="color: #0000ff;">="redis.clients.jedis.JedisPoolConfig"</span><span style="color: #0000ff;">></span>
<span style="color: #0000ff;"><</span><span style="color: #800000;">property </span><span style="color: #ff0000;">name</span><span style="color: #0000ff;">="maxTotal"</span><span style="color: #ff0000;"> value</span><span style="color: #0000ff;">="${redis.maxActive}"</span><span style="color: #0000ff;">/></span>
<span style="color: #0000ff;"><</span><span style="color: #800000;">property </span><span style="color: #ff0000;">name</span><span style="color: #0000ff;">="maxIdle"</span><span style="color: #ff0000;"> value</span><span style="color: #0000ff;">="${redis.maxIdle}"</span> <span style="color: #0000ff;">/></span>
<span style="color: #0000ff;"><</span><span style="color: #800000;">property </span><span style="color: #ff0000;">name</span><span style="color: #0000ff;">="testOnBorrow"</span><span style="color: #ff0000;"> value</span><span style="color: #0000ff;">="${redis.testOnBorrow}"</span><span style="color: #0000ff;">/></span>
<span style="color: #0000ff;"></</span><span style="color: #800000;">bean</span><span style="color: #0000ff;">></span>
<span style="color: #008000;"><!--</span><span style="color: #008000;"> 连接池配置,类似数据库连接池 </span><span style="color: #008000;">--></span>
<span style="color: #0000ff;"><</span><span style="color: #800000;">bean </span><span style="color: #ff0000;">id</span><span style="color: #0000ff;">="jedisConnectionFactory"</span><span style="color: #ff0000;"> class</span><span style="color: #0000ff;">="org.springframework.data.redis.connection.jedis.JedisConnectionFactory"</span> <span style="color: #0000ff;">></span>
<span style="color: #0000ff;"><</span><span style="color: #800000;">property </span><span style="color: #ff0000;">name</span><span style="color: #0000ff;">="hostName"</span><span style="color: #ff0000;"> value</span><span style="color: #0000ff;">="${redis.host}"</span><span style="color: #0000ff;">></</span><span style="color: #800000;">property</span><span style="color: #0000ff;">></span>
<span style="color: #0000ff;"><</span><span style="color: #800000;">property </span><span style="color: #ff0000;">name</span><span style="color: #0000ff;">="port"</span><span style="color: #ff0000;"> value</span><span style="color: #0000ff;">="${redis.port}"</span><span style="color: #0000ff;">></</span><span style="color: #800000;">property</span><span style="color: #0000ff;">></span>
<span style="color: #008000;"><!--</span><span style="color: #008000;"> <property name="password" value="${redis.pass}"></property> </span><span style="color: #008000;">--></span>
<span style="color: #0000ff;"><</span><span style="color: #800000;">property </span><span style="color: #ff0000;">name</span><span style="color: #0000ff;">="poolConfig"</span><span style="color: #ff0000;"> ref</span><span style="color: #0000ff;">="poolConfig"</span><span style="color: #0000ff;">></</span><span style="color: #800000;">property</span><span style="color: #0000ff;">></span>
<span style="color: #0000ff;"></</span><span style="color: #800000;">bean</span><span style="color: #0000ff;">></span>
<span style="color: #0000ff;"><</span><span style="color: #800000;">bean </span><span style="color: #ff0000;">id</span><span style="color: #0000ff;">="redisCacheTransfer"</span><span style="color: #ff0000;"> class</span><span style="color: #0000ff;">="cn.qlq.jedis.RedisCacheTransfer"</span><span style="color: #0000ff;">></span>
<span style="color: #0000ff;"><</span><span style="color: #800000;">property </span><span style="color: #ff0000;">name</span><span style="color: #0000ff;">="jedisConnectionFactory"</span><span style="color: #ff0000;"> ref</span><span style="color: #0000ff;">="jedisConnectionFactory"</span> <span style="color: #0000ff;">/></span>
<span style="color: #0000ff;"></</span><span style="color: #800000;">bean</span><span style="color: #0000ff;">></span>
</beans>
注意,刚开始我的context标签没有加ignore-unresolvable,报了个错误,解决办法参考:http://www.cnblogs.com/qlqwjy/p/8556017.html
配置文件写好后,就开始java代码的编写:
JedisClusterFactory.java
import java.util.HashSet; import java.util.Properties; import java.util.Set; import java.util.regex.Pattern;
import org.apache.commons.pool2.impl.GenericObjectPoolConfig; import org.springframework.beans.factory.FactoryBean; import org.springframework.beans.factory.InitializingBean; import org.springframework.core.io.Resource;
import redis.clients.jedis.HostAndPort; import redis.clients.jedis.JedisCluster;
public class JedisClusterFactory implements FactoryBean<JedisCluster>, InitializingBean {
</span><span style="color: #0000ff;">private</span><span style="color: #000000;"> Resource addressConfig;
</span><span style="color: #0000ff;">private</span><span style="color: #000000;"> String addressKeyPrefix;
</span><span style="color: #0000ff;">private</span><span style="color: #000000;"> JedisCluster jedisCluster;
</span><span style="color: #0000ff;">private</span><span style="color: #000000;"> Integer timeout;
</span><span style="color: #0000ff;">private</span><span style="color: #000000;"> Integer maxRedirections;
</span><span style="color: #0000ff;">private</span><span style="color: #000000;"> GenericObjectPoolConfig genericObjectPoolConfig;
</span><span style="color: #0000ff;">private</span> Pattern p = Pattern.compile("^.+[:]\\d{1,5}\\s*$"<span style="color: #000000;">);
</span><span style="color: #0000ff;">public</span> JedisCluster getObject() <span style="color: #0000ff;">throws</span><span style="color: #000000;"> Exception {
</span><span style="color: #0000ff;">return</span><span style="color: #000000;"> jedisCluster;
}
</span><span style="color: #0000ff;">public</span> Class<? <span style="color: #0000ff;">extends</span> JedisCluster><span style="color: #000000;"> getObjectType() {
</span><span style="color: #0000ff;">return</span> (<span style="color: #0000ff;">this</span>.jedisCluster != <span style="color: #0000ff;">null</span> ? <span style="color: #0000ff;">this</span>.jedisCluster.getClass() : JedisCluster.<span style="color: #0000ff;">class</span><span style="color: #000000;">);
}
</span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">boolean</span><span style="color: #000000;"> isSingleton() {
</span><span style="color: #0000ff;">return</span> <span style="color: #0000ff;">true</span><span style="color: #000000;">;
}
</span><span style="color: #0000ff;">private</span> Set<HostAndPort> parseHostAndPort() <span style="color: #0000ff;">throws</span><span style="color: #000000;"> Exception {
</span><span style="color: #0000ff;">try</span><span style="color: #000000;"> {
Properties prop </span>= <span style="color: #0000ff;">new</span><span style="color: #000000;"> Properties();
prop.load(</span><span style="color: #0000ff;">this</span><span style="color: #000000;">.addressConfig.getInputStream());
Set</span><HostAndPort> haps = <span style="color: #0000ff;">new</span> HashSet<HostAndPort><span style="color: #000000;">();
</span><span style="color: #0000ff;">for</span><span style="color: #000000;"> (Object key : prop.keySet()) {
</span><span style="color: #0000ff;">if</span> (!<span style="color: #000000;">((String) key).startsWith(addressKeyPrefix)) {
</span><span style="color: #0000ff;">continue</span><span style="color: #000000;">;
}
String val </span>=<span style="color: #000000;"> (String) prop.get(key);
</span><span style="color: #0000ff;">boolean</span> isIpPort =<span style="color: #000000;"> p.matcher(val).matches();
</span><span style="color: #0000ff;">if</span> (!<span style="color: #000000;">isIpPort) {
</span><span style="color: #0000ff;">throw</span> <span style="color: #0000ff;">new</span> IllegalArgumentException("ip 或 port 不合法"<span style="color: #000000;">);
}
String[] ipAndPort </span>= val.split(":"<span style="color: #000000;">);
HostAndPort hap </span>= <span style="color: #0000ff;">new</span> HostAndPort(ipAndPort[0], Integer.parseInt(ipAndPort[1<span style="color: #000000;">]));
haps.add(hap);
}
</span><span style="color: #0000ff;">return</span><span style="color: #000000;"> haps;
} </span><span style="color: #0000ff;">catch</span><span style="color: #000000;"> (IllegalArgumentException ex) {
</span><span style="color: #0000ff;">throw</span><span style="color: #000000;"> ex;
} </span><span style="color: #0000ff;">catch</span><span style="color: #000000;"> (Exception ex) {
</span><span style="color: #0000ff;">throw</span> <span style="color: #0000ff;">new</span> Exception("解析 jedis 配置文件失败"<span style="color: #000000;">, ex);
}
}
</span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">void</span> afterPropertiesSet() <span style="color: #0000ff;">throws</span><span style="color: #000000;"> Exception {
Set</span><HostAndPort> haps = <span style="color: #0000ff;">this</span><span style="color: #000000;">.parseHostAndPort();
jedisCluster </span>= <span style="color: #0000ff;">new</span><span style="color: #000000;"> JedisCluster(haps, timeout, maxRedirections, genericObjectPoolConfig);
}
</span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">void</span><span style="color: #000000;"> setAddressConfig(Resource addressConfig) {
</span><span style="color: #0000ff;">this</span>.addressConfig =<span style="color: #000000;"> addressConfig;
}
</span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">void</span> setTimeout(<span style="color: #0000ff;">int</span><span style="color: #000000;"> timeout) {
</span><span style="color: #0000ff;">this</span>.timeout =<span style="color: #000000;"> timeout;
}
</span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">void</span> setMaxRedirections(<span style="color: #0000ff;">int</span><span style="color: #000000;"> maxRedirections) {
</span><span style="color: #0000ff;">this</span>.maxRedirections =<span style="color: #000000;"> maxRedirections;
}
</span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">void</span><span style="color: #000000;"> setAddressKeyPrefix(String addressKeyPrefix) {
</span><span style="color: #0000ff;">this</span>.addressKeyPrefix =<span style="color: #000000;"> addressKeyPrefix;
}
</span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">void</span><span style="color: #000000;"> setGenericObjectPoolConfig(GenericObjectPoolConfig genericObjectPoolConfig) {
</span><span style="color: #0000ff;">this</span>.genericObjectPoolConfig =<span style="color: #000000;"> genericObjectPoolConfig;
}
}
RedisCache.java
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; import org.springframework.data.redis.connection.jedis.JedisConnection; import org.springframework.data.redis.connection.jedis.JedisConnectionFactory; import org.springframework.data.redis.serializer.JdkSerializationRedisSerializer; import org.springframework.data.redis.serializer.RedisSerializer;
import redis.clients.jedis.exceptions.JedisConnectionException;
public class RedisCache implements Cache { private static final Logger logger = LoggerFactory.getLogger(RedisCache.class);
</span><span style="color: #0000ff;">private</span> <span style="color: #0000ff;">static</span><span style="color: #000000;"> JedisConnectionFactory jedisConnectionFactory;
</span><span style="color: #0000ff;">private</span> <span style="color: #0000ff;">final</span><span style="color: #000000;"> String id;
</span><span style="color: #0000ff;">private</span> <span style="color: #0000ff;">final</span> ReadWriteLock rwl = <span style="color: #0000ff;">new</span><span style="color: #000000;"> ReentrantReadWriteLock();
</span><span style="color: #0000ff;">public</span> RedisCache(<span style="color: #0000ff;">final</span><span style="color: #000000;"> String id) {
</span><span style="color: #0000ff;">if</span> (id == <span style="color: #0000ff;">null</span><span style="color: #000000;">) {
</span><span style="color: #0000ff;">throw</span> <span style="color: #0000ff;">new</span> IllegalArgumentException("Cache instances require an ID"<span style="color: #000000;">);
}
logger.debug(</span>"MybatisRedisCache:id=" +<span style="color: #000000;"> id);
</span><span style="color: #0000ff;">this</span>.id =<span style="color: #000000;"> id;
}
</span><span style="color: #008000;">/**</span><span style="color: #008000;">
* 清空所有缓存
</span><span style="color: #008000;">*/</span>
<span style="color: #0000ff;">public</span> <span style="color: #0000ff;">void</span><span style="color: #000000;"> clear() {
rwl.readLock().lock();
JedisConnection connection </span>= <span style="color: #0000ff;">null</span><span style="color: #000000;">;
</span><span style="color: #0000ff;">try</span><span style="color: #000000;"> {
connection </span>=<span style="color: #000000;"> jedisConnectionFactory.getConnection();
connection.flushDb();
connection.flushAll();
logger.debug(</span>"清除缓存......."<span style="color: #000000;">);
} </span><span style="color: #0000ff;">catch</span><span style="color: #000000;"> (JedisConnectionException e) {
e.printStackTrace();
} </span><span style="color: #0000ff;">finally</span><span style="color: #000000;"> {
</span><span style="color: #0000ff;">if</span> (connection != <span style="color: #0000ff;">null</span><span style="color: #000000;">) {
connection.close();
}
rwl.readLock().unlock();
}
}
</span><span style="color: #0000ff;">public</span><span style="color: #000000;"> String getId() {
</span><span style="color: #0000ff;">return</span> <span style="color: #0000ff;">this</span><span style="color: #000000;">.id;
}
</span><span style="color: #008000;">/**</span><span style="color: #008000;">
* 获取缓存总数量
</span><span style="color: #008000;">*/</span>
<span style="color: #0000ff;">public</span> <span style="color: #0000ff;">int</span><span style="color: #000000;"> getSize() {
</span><span style="color: #0000ff;">int</span> result = 0<span style="color: #000000;">;
JedisConnection connection </span>= <span style="color: #0000ff;">null</span><span style="color: #000000;">;
</span><span style="color: #0000ff;">try</span><span style="color: #000000;"> {
connection </span>=<span style="color: #000000;"> jedisConnectionFactory.getConnection();
result </span>=<span style="color: #000000;"> Integer.valueOf(connection.dbSize().toString());
logger.info(</span>"添加mybaits二级缓存数量:" +<span style="color: #000000;"> result);
} </span><span style="color: #0000ff;">catch</span><span style="color: #000000;"> (JedisConnectionException e) {
e.printStackTrace();
} </span><span style="color: #0000ff;">finally</span><span style="color: #000000;"> {
</span><span style="color: #0000ff;">if</span> (connection != <span style="color: #0000ff;">null</span><span style="color: #000000;">) {
connection.close();
}
}
</span><span style="color: #0000ff;">return</span><span style="color: #000000;"> result;
}
</span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">void</span><span style="color: #000000;"> putObject(Object key, Object value) {
rwl.writeLock().lock();
JedisConnection connection </span>= <span style="color: #0000ff;">null</span><span style="color: #000000;">;
</span><span style="color: #0000ff;">try</span><span style="color: #000000;"> {
connection </span>=<span style="color: #000000;"> jedisConnectionFactory.getConnection();
RedisSerializer</span><Object> serializer = <span style="color: #0000ff;">new</span><span style="color: #000000;"> JdkSerializationRedisSerializer();
connection.set(SerializeUtil.serialize(key), SerializeUtil.serialize(value));
logger.info(</span>"添加mybaits二级缓存key=" + key + ",value=" +<span style="color: #000000;"> value);
} </span><span style="color: #0000ff;">catch</span><span style="color: #000000;"> (JedisConnectionException e) {
e.printStackTrace();
} </span><span style="color: #0000ff;">finally</span><span style="color: #000000;"> {
</span><span style="color: #0000ff;">if</span> (connection != <span style="color: #0000ff;">null</span><span style="color: #000000;">) {
connection.close();
}
rwl.writeLock().unlock();
}
}
</span><span style="color: #0000ff;">public</span><span style="color: #000000;"> Object getObject(Object key) {
</span><span style="color: #008000;">//</span><span style="color: #008000;"> 先从缓存中去取数据,先加上读锁</span>
rwl.readLock().lock(); Object result = null; JedisConnection connection = null; try { connection = jedisConnectionFactory.getConnection(); RedisSerializer<Object> serializer = new JdkSerializationRedisSerializer(); result = serializer.deserialize(connection.get(serializer.serialize(key))); logger.info (“命中mybaits二级缓存,value=” + result);
} </span><span style="color: #0000ff;">catch</span><span style="color: #000000;"> (JedisConnectionException e) {
e.printStackTrace();
} </span><span style="color: #0000ff;">finally</span><span style="color: #000000;"> {
</span><span style="color: #0000ff;">if</span> (connection != <span style="color: #0000ff;">null</span><span style="color: #000000;">) {
connection.close();
}
rwl.readLock().unlock();
}
</span><span style="color: #0000ff;">return</span><span style="color: #000000;"> result;
}
</span><span style="color: #0000ff;">public</span><span style="color: #000000;"> Object removeObject(Object key) {
rwl.writeLock().lock();
JedisConnection connection </span>= <span style="color: #0000ff;">null</span><span style="color: #000000;">;
Object result </span>= <span style="color: #0000ff;">null</span><span style="color: #000000;">;
</span><span style="color: #0000ff;">try</span><span style="color: #000000;"> {
connection </span>=<span style="color: #000000;"> jedisConnectionFactory.getConnection();
RedisSerializer</span><Object> serializer = <span style="color: #0000ff;">new</span><span style="color: #000000;"> JdkSerializationRedisSerializer();
result </span>= connection.expire(serializer.serialize(key), 0<span style="color: #000000;">);
} </span><span style="color: #0000ff;">catch</span><span style="color: #000000;"> (JedisConnectionException e) {
e.printStackTrace();
} </span><span style="color: #0000ff;">finally</span><span style="color: #000000;"> {
</span><span style="color: #0000ff;">if</span> (connection != <span style="color: #0000ff;">null</span><span style="color: #000000;">) {
connection.close();
}
rwl.writeLock().unlock();
}
</span><span style="color: #0000ff;">return</span><span style="color: #000000;"> result;
}
</span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">static</span> <span style="color: #0000ff;">void</span><span style="color: #000000;"> setJedisConnectionFactory(JedisConnectionFactory jedisConnectionFactory) {
RedisCache.jedisConnectionFactory </span>=<span style="color: #000000;"> jedisConnectionFactory;
}
</span><span style="color: #0000ff;">public</span><span style="color: #000000;"> ReadWriteLock getReadWriteLock() {
</span><span style="color: #008000;">//</span><span style="color: #008000;"> TODO Auto-generated method stub</span>
<span style="color: #0000ff;">return</span><span style="color: #000000;"> rwl;
}
}
RedisCacheTransfer.java
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
/**
静态注入中间类 */ public class RedisCacheTransfer { @Autowired public void setJedisConnectionFactory(JedisConnectionFactory jedisConnectionFactory) { RedisCache.setJedisConnectionFactory(jedisConnectionFactory); }
}
SerializeUtil.java
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; }
</span><span style="color: #008000;">/**</span><span style="color: #008000;">
* 反序列化
</span><span style="color: #008000;">*/</span>
<span style="color: #0000ff;">public</span> <span style="color: #0000ff;">static</span> Object unserialize(<span style="color: #0000ff;">byte</span><span style="color: #000000;">[] bytes) {
</span><span style="color: #0000ff;">if</span> (bytes != <span style="color: #0000ff;">null</span><span style="color: #000000;">) {
ByteArrayInputStream bais </span>= <span style="color: #0000ff;">null</span><span style="color: #000000;">;
</span><span style="color: #0000ff;">try</span><span style="color: #000000;"> {
</span><span style="color: #008000;">//</span><span style="color: #008000;"> 反序列化</span>
bais = <span style="color: #0000ff;">new</span><span style="color: #000000;"> ByteArrayInputStream(bytes);
ObjectInputStream ois </span>= <span style="color: #0000ff;">new</span><span style="color: #000000;"> ObjectInputStream(bais);
</span><span style="color: #0000ff;">return</span><span style="color: #000000;"> ois.readObject();
} </span><span style="color: #0000ff;">catch</span><span style="color: #000000;"> (Exception e) {
}
}
</span><span style="color: #0000ff;">return</span> <span style="color: #0000ff;">null</span><span style="color: #000000;">;
}
}
到此,修改就算完成,开始开启二级缓存
3.开启二级缓存:
Mybatis的全局配置文件开启二级缓存(SqlMapConfig.xml)
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<span style="color: #008000;"><!--</span><span style="color: #008000;"> 开启二级缓存 </span><span style="color: #008000;">--></span>
<span style="color: #0000ff;"><</span><span style="color: #800000;">settings</span><span style="color: #0000ff;">></span>
<span style="color: #0000ff;"><</span><span style="color: #800000;">setting </span><span style="color: #ff0000;">name</span><span style="color: #0000ff;">="cacheEnabled"</span><span style="color: #ff0000;"> value</span><span style="color: #0000ff;">="true"</span><span style="color: #0000ff;">/></span>
<span style="color: #0000ff;"></</span><span style="color: #800000;">settings</span><span style="color: #0000ff;">></span>
<span style="color: #008000;"><!--</span><span style="color: #008000;"> 只需要定义个别名,这个应该有</span><span style="color: #008000;">--></span>
<span style="color: #0000ff;"><</span><span style="color: #800000;">typeAliases </span><span style="color: #0000ff;">></span>
<span style="color: #0000ff;"><</span><span style="color: #800000;">package </span><span style="color: #ff0000;">name</span><span style="color: #0000ff;">="cn.qlq.bean"</span><span style="color: #0000ff;">/></span>
<span style="color: #0000ff;"></</span><span style="color: #800000;">typeAliases</span><span style="color: #0000ff;">></span>
</configuration>
Mapper.xml中开启二级缓存并设置缓存类(UserMapper.xml)
<?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">
<!– namespace命名空间,作用就是对sql进行分类化管理,理解sql隔离 注意:使用mapper代理方法开发,namespace有特殊重要的作用 –> <mapper namespace=“cn.qlq.mapper.UserMapper”> <!– 使用Redis二级缓存 –> <cache type=“cn.qlq.jedis.RedisCache”></cache>
<span style="color: #0000ff;"><</span><span style="color: #800000;">select </span><span style="color: #ff0000;">id</span><span style="color: #0000ff;">="findUserById"</span><span style="color: #ff0000;"> parameterType</span><span style="color: #0000ff;">="int"</span><span style="color: #ff0000;"> resultType</span><span style="color: #0000ff;">="cn.qlq.bean.User"</span><span style="color: #0000ff;">></span><span style="color: #000000;">
select
* from user where id = #{id}
</span><span style="color: #0000ff;"></</span><span style="color: #800000;">select</span><span style="color: #0000ff;">></span>
<span style="color: #0000ff;"><</span><span style="color: #800000;">select </span><span style="color: #ff0000;">id</span><span style="color: #0000ff;">="findUsersByPage"</span><span style="color: #ff0000;"> resultType</span><span style="color: #0000ff;">="cn.qlq.bean.User"</span><span style="color: #0000ff;">></span><span style="color: #000000;">
select * from user
</span><span style="color: #0000ff;"></</span><span style="color: #800000;">select</span><span style="color: #0000ff;">></span>
<span style="color: #0000ff;"><</span><span style="color: #800000;">insert </span><span style="color: #ff0000;">id</span><span style="color: #0000ff;">="addUser"</span><span style="color: #0000ff;">></span><span style="color: #000000;">
insert into user values(#{0},#{1})
</span><span style="color: #0000ff;"></</span><span style="color: #800000;">insert</span><span style="color: #0000ff;">></span>
</mapper>
4.测试二级缓存:
127.0.0.1:6379> flushall
OK
127.0.0.1:6379> keys *
(empty list or set)
127.0.0.1:6379>
日志如下:(如下底色是黄的是发出的SQL语句,字体是红色的是缓存的命中率为0之后向redis添加缓存)
13:01:05,064 DEBUG DefaultActionInvocation:76 - Executing action method = findPage
13:01:05,091 DEBUG SqlSessionUtils:109 - Creating a new SqlSession
13:01:05,109 DEBUG SqlSessionUtils:145 - SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@15546ea6] was not registered for synchronization because synchronization is not active
13:01:05,157 DEBUG LoggingCache:55 - Cache Hit Ratio [SQL_CACHE]: 0.0
13:01:05,350 INFO RedisCache:107 - 命中mybaits二级缓存,value=null
13:01:05,364 DEBUG DataSourceUtils:110 - Fetching JDBC Connection from DataSource
13:01:05,365 DEBUG BasicResourcePool:1644 - trace com.mchange.v2.resourcepool.BasicResourcePool@44083847 [managed: 3, unused: 2, excluded: 0] (e.g. com.mchange.v2.c3p0.impl.NewPooledConnection@29072429)
13:01:05,366 DEBUG SpringManagedTransaction:88 - JDBC Connection [com.mchange.v2.c3p0.impl.NewProxyConnection@75adf2b9] will not be managed by Spring
13:01:05,371 DEBUG findUsersByPage_COUNT:132 - ooo Using Connection [com.mchange.v2.c3p0.impl.NewProxyConnection@75adf2b9]
13:01:05,385 DEBUG findUsersByPage_COUNT:132 - ==> Preparing: SELECT count(0) FROM user
13:01:05,447 DEBUG findUsersByPage_COUNT:132 - ==> Parameters:
13:01:05,487 TRACE findUsersByPage_COUNT:138 - <== Columns: count(0)
13:01:05,487 TRACE findUsersByPage_COUNT:138 - <== Row: 7
13:01:05,499 INFO RedisCache:107 - 命中mybaits二级缓存,value=null
13:01:05,500 DEBUG findUsersByPage:132 - ooo Using Connection [com.mchange.v2.c3p0.impl.NewProxyConnection@75adf2b9]
13:01:05,501 DEBUG findUsersByPage:132 - ==> Preparing: SELECT * FROM user order by id desc LIMIT ?, ?
13:01:05,502 DEBUG findUsersByPage:132 - ==> Parameters: 2(Integer), 2(Integer)
13:01:05,503 TRACE findUsersByPage:138 - <== Columns: id, name
13:01:05,504 TRACE findUsersByPage:138 - <== Row: 4, QLQ4
13:01:05,505 TRACE findUsersByPage:138 - <== Row: 3, QLQ3
13:01:05,511 INFO RedisCache:87 - 添加mybaits二级缓存key=-167006705:2220054459:cn.qlq.mapper.UserMapper.findUsersByPage_COUNT:0:2147483647:select * from user,value=[7]
13:01:05,515 INFO RedisCache:87 - 添加mybaits二级缓存key=-165358097:5089576455:cn.qlq.mapper.UserMapper.findUsersByPage:0:2147483647:select * from user:2:2:id desc:2,value=[cn.qlq.bean.User@68e9fd61, cn.qlq.bean.User@39835e11]
13:01:05,515 DEBUG SqlSessionUtils:173 - Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@15546ea6]
13:01:05,516 DEBUG DataSourceUtils:332 - Returning JDBC Connection to DataSource
打开RedisDesktopManager查看缓存记录
命中率计算方法:第一次访问没有命中为0,所以将缓存加进去。
第二次命中缓存,命中率为1/2
第三次命中缓存,命中率为2/3
5.测试清除二级缓存:
经过 测试发现当SQL语句写在注解上面(mybatis使用注解)的时候不会清除缓存,而写在XML中的语句执行后会清除缓存。
1.注解insert,update,delete不会清除缓存
// @Insert("insert into user values(#{0},#{1})")
public int addUser(int id, String name) throws SQLException;
2.Mapper.xml写的SQL语句执行之后会清除缓存
<insert id="addUser">
insert into user values(#{0},#{1})
</insert>
(1)get方式添加一条记录
(2)查看日志:
13:21:37,876 DEBUG addUser:132 - ==> Preparing: insert into user values(?,?)
13:21:37,942 DEBUG addUser:132 - ==> Parameters: 8(Integer), QLQ8(String)
13:21:38,087 DEBUG RedisCache:45 - 清除缓存.......
(3)查看redis是否有数据:
git源码地址:https://github.com/qiao-zhi/Maven_SSM
接下来还会整合redis+Shiro。与Sessionsession共享。
原文地址:(https://www.cnblogs.com/qlqwjy/p/8556130.html)