第四课 项目中使用redis

2018-08-27  本文已影响1人  Arroganter

二、项目中使用redis

2.1、使用jedis操作redis测试

进行测试之前需要引入依赖

<dependency>
  <groupId>redis.clients</groupId>
  <artifactId>jedis</artifactId>
  <version>2.9.0</version>
</dependency>

测试:

@Test
    public void testJedis() throws Exception{
        //创建一个连接jedis对象,参数:host,port
        Jedis jedis = new Jedis("192.168.25.128", 6379);
        //直接使用jedis来操作redis,所有jedis的命令都对应一个方法
        jedis.set("test123", "my first jedis test");
        String s = jedis.get("test123");
        System.out.println(s);
        //关闭连接
        jedis.close();
    }
    输出结果:my first jedis test
    去客户端查看:
    192.168.25.128:6379> get test123
    "my first jedis test"

这里只测试了String类型,Jedis提供了与redis操作对应的方法来操作redis。
操作hash类型主要有:hset(…),hget(…),hdel(…),hexist(…)
key命令:persist(key),expire(key,seconds)
具体的根据提示来选择自己需要的。

测试,从连接池获取jedis:

    @Test//连接
    public void testJedisPool() throws Exception{
        JedisPool jedisPool = new  JedisPool("192.168.25.128", 6379);
        //从连接池获得一个连接,就是一个jedis对象
        Jedis jedis = jedisPool.getResource();
        //操作redis
        String s = jedis.get("test123");
        System.out.println(s);
        //关闭连接,每次使用完毕后关闭连接,连接池回收资源
        jedis.close();
        //关闭连接池
        jedisPool.close();
    }

这个就跟从数据库连接池获取连接道理是一样的,需要连接的时候从连接池中取获取一个连接就行,使用完后就放回连接池,而不用重新去创建一个连接,这项技术能大大提高操作redis的性能。

2.2、使用JedisClient操作redis

测试的时候我们发现,每次都要自己创建关闭连接,频繁使用的话会显得很繁琐。所以我们可以一开始就定义好对应方法来帮我们关闭连接。使用的时候调用自己的方法即可。

接口如下:

public interface JedisClient {
    String set(String key, String value);
    String get(String key);
    Boolean exists(String key);
    Long expire(String key, int seconds);
    Long ttl(String key);
    Long incr(String key);
    Long hset(String key, String field, String value);
    String hget(String key, String field);
    Long hdel(String key, String... field);
    Boolean hexists(String key, String field);
    List<String> hvals(String key);
    Long del(String key);
}

这里定义的方法主要是针对String类型,Hash类型,key命令。
比如String类型,Hash类型的存储、获取、删除、是否存在指定key,设置过期时间,自增,自间,有效时间等。

实现类如下:

public class JedisClientPool implements JedisClient {

    private JedisPool jedisPool;

    public JedisPool getJedisPool() {
        return jedisPool;
    }
    public void setJedisPool(JedisPool jedisPool) {
        this.jedisPool = jedisPool;
    }
    public String set(String key, String value) {
        Jedis jedis = jedisPool.getResource();
        String result = jedis.set(key, value);
        jedis.close();
        return result;
    }
    public String get(String key) {
        Jedis jedis = jedisPool.getResource();
        String result = jedis.get(key);
        jedis.close();
        return result;
    }
    public Boolean exists(String key) {
        Jedis jedis = jedisPool.getResource();
        Boolean result = jedis.exists(key);
        jedis.close();
        return result;
    }
    public Long expire(String key, int seconds) {
        Jedis jedis = jedisPool.getResource();
        Long result = jedis.expire(key, seconds);
        jedis.close();
        return result;
    }
    public Long ttl(String key) {
        Jedis jedis = jedisPool.getResource();
        Long result = jedis.ttl(key);
        jedis.close();
        return result;
    }

    public Long incr(String key) {
        Jedis jedis = jedisPool.getResource();
        Long result = jedis.incr(key);
        jedis.close();
        return result;
    }
    public Long hset(String key, String field, String value) {
        Jedis jedis = jedisPool.getResource();
        Long result = jedis.hset(key, field, value);
        jedis.close();
        return result;
    }
    public String hget(String key, String field) {
        Jedis jedis = jedisPool.getResource();
        String result = jedis.hget(key, field);
        jedis.close();
        return result;
    }
    public Long hdel(String key, String... field) {
        Jedis jedis = jedisPool.getResource();
        Long result = jedis.hdel(key, field);
        jedis.close();
        return result;
    }
    public Boolean hexists(String key, String field) {
        Jedis jedis = jedisPool.getResource();
        Boolean result = jedis.hexists(key, field);
        jedis.close();
        return result;
    }
    public List<String> hvals(String key) {
        Jedis jedis = jedisPool.getResource();
        List<String> result = jedis.hvals(key);
        jedis.close();
        return result;
    }
    public Long del(String key) {
        Jedis jedis = jedisPool.getResource();
        Long result = jedis.del(key);
        jedis.close();
        return result;
    }
}

其实这些方法主要还是调用了jedis的方法,主要是帮我们创建、关闭了连接然后进行封装,从而在项目中使用可以简化操作。

2.3、从Spring容器中获取JedisClient

在案例中,JedisClient是与Spring整合的。不然每次都要自己创建JedisClient对象,使用Spring那么就不用我们自己创建对象了。

JedisClient与spring整合:applicationContext-redis.xml

<!-- 连接-->
    <bean class="cn.e3mall.jedis.JedisClientPool">
        <property name="jedisPool" ref="jedisPool"/>
    </bean>
    配置jedis连接池
    <bean id="jedisPool" class="redis.clients.jedis.JedisPool">
        <constructor-arg name="host" value="192.168.25.128"/>
        <constructor-arg name="port" value="6379"/>
    </bean>

这样初始化Spring容器的时候就会创建JedisClient了

测试:

public void testJedisClient() throws Exception{
        ApplicationContext ac = new ClassPathXmlApplicationContext("classpath:spring/applicationContext-redis.xml");
        //从容器中拿到JedisClient对象
        JedisClient jc = ac.getBean(JedisClient.class);
        jc.set("mytest", "jedisClient");
        String s = jc.get("mytest");
        System.out.println(s);  
    }
输出:jedisClient

到这里就可以大胆的在项目中使用JedisClient来操作redis了。

2.4、实现redis在文章案例中进行缓存

2.4.1、在文章详情中使用redis
点击某篇文章会进入到文章详情页。这里也使用了redis,比如某篇文章很热门,那么单位时间的浏览量就会很高,对于这种情况我们可以将文章信息添加到redis中。

点击文章的时候会根据文章id去redis中查询是否存在该文章信息,有的话直接响应,如果没有那么就去查数据库,查出来的数据存到redis中再做响应。

但文章信息不能一直在redis中存放,文章过多的话非常耗费redis的存储空间,所以需要设置一下过期时间,如果这段时间该文章没人访问的话就应该将该文章信息从redis中清除来释放空间,如果有人访问的话那么就重新设置回原来的过期时间。

@Service
public class ArticleService implements IArticleService {

    @Autowired
    ArticleMapper articleMapper;

    @Autowired
    CommentMapper commentMapper;
    @Autowired
    private SolrServer solrServer;

    @Autowired
    private JedisClient jedisClient;
    @Value("${REDIS_ITEM_PRE}")
    private String REDIS_ITEM_PRE;
    @Value("${ITEM_CACHE_EXPIRE}")
    private Integer ITEM_CACHE_EXPIRE;


  
    @Override
    public Article getArticleByID(int aid) {
        jedisClient.del(REDIS_ITEM_PRE+":"+aid+":BASE");

        try {
            String string = jedisClient.get(REDIS_ITEM_PRE+":"+aid+":BASE");

            if(string !=null && !string.isEmpty()){
                Article tbItem = JSON.parseObject(string,new TypeReference<Article>() {});
                return tbItem;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        Article article = articleMapper.getArticleByID(aid);

        if(article != null){
            //把结果添加到缓存
            try {
                jedisClient.set(REDIS_ITEM_PRE+":"+aid+":BASE", JSON.toJSONString(article));
                //设置过期时间
                jedisClient.expire(REDIS_ITEM_PRE+":"+aid+":BASE", ITEM_CACHE_EXPIRE);
            } catch (Exception e) {
                e.printStackTrace();
            }
            return article;
        }else{
            return null;
        }

    }
}

applicationContext-redis.xml

<?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:mvc="http://www.springframework.org/schema/mvc"
       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-4.0.xsd
        http://www.springframework.org/schema/mvc
        http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context-4.0.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop-4.0.xsd
        http://www.springframework.org/schema/tx
        http://www.springframework.org/schema/tx/spring-tx-4.0.xsd ">


        <!--<bean class="com.neusoft.util.JedisClientPool">-->
                <!--<property name="jedisPool" ref="jedisPool"/>-->
        <!--</bean>-->

        <bean id="jedisPool" class="redis.clients.jedis.JedisPool">
                <constructor-arg name="host" value="192.168.47.141"/>
                <constructor-arg name="port" value="6379"/>
        </bean>
        <context:property-placeholder location="classpath:app.properties"/>

</beans>

这里使用的是String类型,写成 前缀:d:后缀,这种形式在桌面版redis客户端中文件目录会有层次结构。

Redis实现缓存同步
考虑这么个问题,如果在后台我们修改或删除了文章信息,这就存在信息不同步问题了。这里解决的办法是,每次修改或删除了文章,那么就需要清空redis中的信息。当下次访问首页的时候会去数据库中查询最新的内容信息,存放到redis中,从而实现了缓存同步,代码如下。

jedisClient.del(REDIS_ITEM_PRE+":"+aid+":BASE");

上一篇下一篇

猜你喜欢

热点阅读