zoukankan      html  css  js  c++  java
  • 企业项目开发--本地缓存guava cache(1)

    此文已由作者赵计刚授权网易云社区发布。

    欢迎访问网易云社区,了解更多网易技术产品运营经验。


    1、在实际项目开发中,会使用到很多缓存技术,而且数据库的设计一般也会依赖于有缓存的情况下设计。

    • 常用的缓存分两种:本地缓存和分布式缓存。

    • 常用的本地缓存是guava cache,本章主要介绍guava cache在项目中的使用。

    关于常用缓存以及每种缓存常用场景的介绍,之后可以去查看我记录的"Java缓存相关"系列博客。链接如下:

    第一章 常用的缓存技术

     

    2、实际使用

    本项目的代码基于第六章的代码进行构建,这里只列出修改过的代码:



    2.1、ssmm0-data

    pom.xml:

            <!-- guava cache -->
            <dependency>
                <groupId>com.google.guava</groupId>
                <artifactId>guava</artifactId>
                <version>14.0.1</version>
            </dependency>

    在pom.xml中引入了guava cache14.0.1的依赖包。

    AdminMapper:

    package com.xxx.mapper.userManagement;
    
    import java.util.List;
    
    import org.apache.ibatis.annotations.Insert;
    import org.apache.ibatis.annotations.Param;
    import org.apache.ibatis.annotations.Result;
    import org.apache.ibatis.annotations.Results;
    import org.apache.ibatis.annotations.Select;
    
    import com.xxx.model.userManagement.Admin;
    
    /**
     * 管理员Mapper
     */
    public interface AdminMapper {
        
        /**************注解**************/
        @Insert("INSERT INTO userinfo(username, password) VALUES(#{username},#{password})")
        public int insertAdmin(Admin admin);
    
        @Select("SELECT * FROM userinfo WHERE username = #{username} AND password = #{password}")
        @Results(value = { 
                @Result(id = true, column = "id", property = "id"),
                @Result(column = "username", property = "username"),
                @Result(column = "password", property = "password") })
        public Admin selectAdmin(@Param("username") String username,
                                 @Param("password") String password);
        
        /***************xml**************/
        /**
         * 条件不定式查询
         * 我们这里使用@Param指定参数,这样的话,在AdminMapper.xml中就不用再使用parameterType属性了;否则得写parameterType属性
         */
        public List<Admin> getAdminByConditions(@Param("username")String username,
                                                @Param("password")String password, 
                                                @Param("start")int start, 
                                                @Param("limit")int limit);
        
        /**
         * 返回主键
         */
        public int insertAdminWithBackId(Admin admin);
        
        /****************guava cache*****************/
        @Select("SELECT * FROM userinfo WHERE username = #{username}")
        @Results(value = { 
                @Result(id = true, column = "id", property = "id"),
                @Result(column = "username", property = "username"),
                @Result(column = "password", property = "password") })
        public List<Admin> getUserByName(@Param("username") String username);
    }

    将使用到的两个方法:

    • public List<Admin> getUserByName(String username)

    • public List<Admin> getAdminByConditions(String username, String password, int start, int limit)

    AdminDao:

    package com.xxx.dao.userManagement;
    
    import java.util.List;
    
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Repository;
    
    import com.xxx.mapper.userManagement.AdminMapper;
    import com.xxx.model.userManagement.Admin;
    
    /**
     * 管理员DAO
     */
    @Repository
    public class AdminDao {
        @Autowired
        private AdminMapper adminMapper;
        /***************注解*****************/
        public boolean register(Admin admin){
            return adminMapper.insertAdmin(admin)==1?true:false;
        }
        
        public Admin login(String username ,String password){
            return adminMapper.selectAdmin(username, password);
        }
        /****************xml******************/
        public List<Admin> findAdmin(String username, String password, int start, int limit){
            return adminMapper.getAdminByConditions(username, password, start, limit);
        }
        
        public int insertAdminWithBackId(Admin admin){
            return adminMapper.insertAdminWithBackId(admin);
        }
        /******************guava cache********************/
        public List<Admin> getUserByName(String username){
            return adminMapper.getUserByName(username);
        }
    }

    将使用到的两个方法:

    • public List<Admin> getUserByName(String username)

    • public List<Admin> findAdmin(String username, String password, int start, int limit)

    AdminService:

    package com.xxx.service.userManagement;
    
    import java.util.List;
    import java.util.concurrent.ExecutionException;
    import java.util.concurrent.TimeUnit;
    
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Service;
    
    import com.google.common.cache.CacheBuilder;
    import com.google.common.cache.CacheLoader;
    import com.google.common.cache.LoadingCache;
    import com.xxx.dao.userManagement.AdminDao;
    import com.xxx.model.userManagement.Admin;
    import com.xxx.vo.userManagement.AdminCacheKey;
    
    /**
     * 管理员service
     */
    @Service
    public class AdminService {
        @Autowired
        private AdminDao adminDao;
    
        public boolean register(Admin admin) {
            return adminDao.register(admin);
        }
    
        public Admin login(String username, String password) {
            return adminDao.login(username, password);
        }
    
        /*********** 以下方法是为了测试mybatis中使用xml **********/
        public List<Admin> findAdmin(String username, 
                                     String password, 
                                     int start,
                                     int limit) {
            return adminDao.findAdmin(username, password, start, limit);
        }
    
        public Admin insertAdminWithBackId(Admin admin) {
            int record = adminDao.insertAdminWithBackId(admin);
            if (record == 1) {
                return admin;// 这时的admin已经被赋予主键了
            }
            return null;
        }
    
        /************************ guava cache *************************/
        /************单条件的查询,key为String***********/
        public List<Admin> findByUsername(String username) {
            List<Admin> adminList = null;
            try {
                adminList = adminListCache.get(username);
            } catch (ExecutionException e) {
                e.printStackTrace();
            }
            return adminList;
        }
    
        LoadingCache<String, List<Admin>> adminListCache = CacheBuilder.newBuilder()
                .expireAfterWrite(20, TimeUnit.MINUTES)// 缓存20分钟
                .maximumSize(1000)// 最多缓存1000个对象
                .build(new CacheLoader<String, List<Admin>>() {
                    public List<Admin> load(String username) throws Exception {
                        return adminDao.getUserByName(username);
                    }
                });
    
        /************多条件的查询,key为Object(封装了多个条件的VO类)***********/
        public List<Admin> findAdminList(String username, 
                                         String password,
                                         int start, 
                                         int limit) {
            /*
             * 注意:
             * 如果以一个新建的对象做为key的话,因为每次都是新建一个对象,所以这样的话,实际上每次访问key都是不同的,即每次访问都是重新进行缓存;
             * 但是实际上,我们想要根据对象的属性来判断对象是否相等,只需要根据这些属性重写对象的hashCode与equals方法即可,
             * 所以重写了AdminCacheKey类的hashCode和equals方法,这样,每次访问的话,就会以每个条件是否相等来判断对象(即key)是否相等了,这一块儿的缓存就会起作用了
             */
            AdminCacheKey cacheKey = new AdminCacheKey(username, 
                                                       password, 
                                                       start,
                                                       limit);
            List<Admin> adminList = null;
            try {
                System.out.println(cacheKey);
                adminList = adminsCache.get(cacheKey);
            } catch (ExecutionException e) {
                e.printStackTrace();
            }
            return adminList;
        }
    
        LoadingCache<AdminCacheKey, List<Admin>> adminsCache = CacheBuilder.newBuilder()
                .expireAfterWrite(60, TimeUnit.MINUTES) // 缓存项在给定时间内(60min)没有被写访问(创建或覆盖),则回收
                .maximumSize(100) // 最多缓存100项
                .build(new CacheLoader<AdminCacheKey, List<Admin>>() {
                    public List<Admin> load(AdminCacheKey key) throws Exception {
                        return adminDao.findAdmin(key.getUsername(),
                                                  key.getPassword(), 
                                                  key.getStart(), 
                                                  key.getLimit());
                    }
                });
    
    }

    将使用到的两个方法:

    • public List<Admin> findByUsername(String username)

    • public List<Admin> findAdminList(String username, String password, int start, int limit)

    这一块儿是整个guava cache使用的部分。这里边写出了两种guava cache使用的方式:

    • 单查询条件:key为String或Object都可以

    • 多查询条件:key为Object,该Object封装了多个查询条件,并通过这些查询条件重写了该Object的hashcode()和equals()

    这一部分中guava cache的使用方式,就是实际开发中最常用的方法。




    相关文章:
    【推荐】 感动到流泪!数据分析师的福音:跨视图粒度计算

  • 相关阅读:
    Java实现 LeetCode 792 自定义字符串排序(暴力)
    Java实现 LeetCode 792 自定义字符串排序(暴力)
    asp.net session对象的持久化
    Java实现 LeetCode 791 自定义字符串排序(桶排序)
    Java实现 LeetCode 791 自定义字符串排序(桶排序)
    Java实现 LeetCode 791 自定义字符串排序(桶排序)
    Java实现 LeetCode 790 多米诺和托米诺平铺(递推)
    Java实现 LeetCode 790 多米诺和托米诺平铺(递推)
    Java实现 LeetCode 790 多米诺和托米诺平铺(递推)
    小白也能看懂的约瑟夫环问题
  • 原文地址:https://www.cnblogs.com/zyfd/p/10138173.html
Copyright © 2011-2022 走看看