• 企业项目开发--本地缓存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的使用方式,就是实际开发中最常用的方法。




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

  • 相关阅读:
    畅销书排行榜
    阿里云大数据产品体系
    天然气收费管理系统的研究与实现随笔
    Web端实现RTC视频特效的解决方案
    从0搭建在线聊天室,只需4步!
    技术干货 | JavaScript 之事件循环(Event Loop)
    C++20 四大特性之一:Module 特性详解
    Android Flutter 多实例实践
    网易云信线上万人连麦技术大揭秘
    Python + Pytest 自动化框架的用例依赖实操
  • 原文地址:https://www.cnblogs.com/zyfd/p/10138173.html
Copyright © 2020-2023  润新知