美文网首页
企业项目开发--本地缓存guava cache(2)

企业项目开发--本地缓存guava cache(2)

作者: yijian2595 | 来源:发表于2018-12-18 17:10 被阅读3次

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

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

    AdminCacheKey:

    package com.xxx.vo.userManagement;
    
    /**
     * guava cache的key
     */
    public class AdminCacheKey {
        private String username;
        private String password;
        private int start;
        private int limit;
    
        public AdminCacheKey() {
        }
    
        public AdminCacheKey(String username, String password, int start, int limit) {
            this.username = username;
            this.password = password;
            this.start = start;
            this.limit = limit;
        }
    
        public String getUsername() {
            return username;
        }
    
        public void setUsername(String username) {
            this.username = username;
        }
    
        public String getPassword() {
            return password;
        }
    
        public void setPassword(String password) {
            this.password = password;
        }
    
        public int getStart() {
            return start;
        }
    
        public void setStart(int start) {
            this.start = start;
        }
    
        public int getLimit() {
            return limit;
        }
    
        public void setLimit(int limit) {
            this.limit = limit;
        }
    
        @Override
        public int hashCode() {
            final int prime = 31;
            int result = 1;
            result = prime * result + limit;
            result = prime * result
                    + ((password == null) ? 0 : password.hashCode());
            result = prime * result + start;
            result = prime * result
                    + ((username == null) ? 0 : username.hashCode());
            return result;
        }
    
        @Override
        public boolean equals(Object obj) {
            if (this == obj)
                return true;
            if (obj == null)
                return false;
            if (getClass() != obj.getClass())
                return false;
            AdminCacheKey other = (AdminCacheKey) obj;
            if (limit != other.limit)
                return false;
            if (password == null) {
                if (other.password != null)
                    return false;
            } else if (!password.equals(other.password))
                return false;
            if (start != other.start)
                return false;
            if (username == null) {
                if (other.username != null)
                    return false;
            } else if (!username.equals(other.username))
                return false;
            return true;
        }
    }

    该类是封装了多个查询条件的一个VO类。

    2.2、ssmm0-userManagement

    AdminController:

    package com.xxx.web.admin;
    
    import java.util.List;
    
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import javax.servlet.http.HttpSession;
    
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RequestParam;
    import org.springframework.web.bind.annotation.ResponseBody;
    import org.springframework.web.servlet.ModelAndView;
    
    import com.xxx.model.userManagement.Admin;
    import com.xxx.service.userManagement.AdminService;
    import com.xxx.util.admin.AdminCookieUtil;
    
    /**
     * adminController
     */
    @Controller
    @RequestMapping("/admin")
    public class AdminController {
        
        @Autowired
        private AdminService adminService;
        
        /**
         * 管理员注册
         */
        @ResponseBody
        @RequestMapping("/register")
        public boolean register(@RequestParam("username") String username,
                                @RequestParam("password") String password){
            Admin admin = new Admin();
            admin.setUsername(username);
            admin.setPassword(password);
            
            boolean isRegisterSuccess = adminService.register(admin);
            
            return isRegisterSuccess;
        }
        
        /**
         * 管理员登录
         */
        @RequestMapping("/login")
        public ModelAndView login(@RequestParam("username") String username,
                                  @RequestParam("password") String password,
                                  HttpServletResponse response,
                                  HttpSession session){
            
            
            Admin admin = adminService.login(username, password);
            
            ModelAndView modelAndView = new ModelAndView();
            if(admin == null){
                modelAndView.addObject("message", "用户不存在或者密码错误!请重新输入");
                modelAndView.setViewName("error");
            }else{
                modelAndView.addObject("admin", admin);
                modelAndView.setViewName("userinfo");
                /*
                 * 这为什么不直接传一个username,而传了一个admin,
                 * 是因为在实际开发中,你传过去的信息可能不只是username,还有用户手机号、地址等等
                 */
                //使用cookie
                AdminCookieUtil.addLoginCookie(admin, response);
                //使用session
                //session.setAttribute("adminSession", admin);
            }
            
            return modelAndView;
        }
        
        /*****************************mybatis xml方式解决的问题*******************************/
        /**
         * 根据username或password查找List<Admin>
         */
        @ResponseBody
        @RequestMapping("/findAdmin")
        public List<Admin> findAdmin(@RequestParam(value="username",required=false) String username,
                                        @RequestParam(value="password",required=false) String password,
                                        @RequestParam("start") int start,
                                        @RequestParam("limit") int limit,
                                        HttpServletRequest request,
                                        HttpSession session){
            Admin admin = AdminCookieUtil.getLoginCookie(request);
            //Admin admin = (Admin) session.getAttribute("adminSession");
            
            if(admin == null){//未登录
                return null;
            }
            System.out.println(admin.toJson());
            List<Admin> adminList = adminService.findAdmin(username, password, start, limit);
            return adminList;
        }
        
        /**
         * 插入一个用户并返回主键
         * 注意:get请求也会自动装配(即将前台传入的username和password传入admin)
         */
        @ResponseBody
        @RequestMapping("/insert")
        public Admin insertAdminWithBackId(Admin admin){
            return adminService.insertAdminWithBackId(admin);
        }
        /*************************guava cache******************************/
        /**
         * 根据username查找List<Admin>
         */
        @ResponseBody
        @RequestMapping("/findAdminByUsername")
        public List<Admin> findAdminByUserName(@RequestParam(value="username") String username){
            
            List<Admin> adminList = adminService.findByUsername(username);
            return adminList;
        }
        
        @ResponseBody
        @RequestMapping("/findAdminList")
        public List<Admin> findAdminList(@RequestParam(value="username") String username,
                                             @RequestParam(value="password",required=false) String password,
                                             @RequestParam("start") int start,
                                             @RequestParam("limit") int limit){
            
            List<Admin> adminList = adminService.findAdminList(username, password, start, limit);
            return adminList;
        }
    }

    将使用到的两个方法:

    • public List<Admin> findAdminByUserName(String username)

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

    3、测试

    • 单元测试:使用springJunit去测就行

    • 整体测试:代码写好之后,注意对代码去做测试的方法,先运行相应的controller的方法,然后对查询出来的部分数据在数据库中直接进行修改,再运行之前的controller对应的方法。出现两种结果:

      • 第二次运行与第一次结果相同:缓存成功

      • 第二次运行与第一次结果不同:缓存不成功

     

    4、总结:

    • 常用的几个API:

      • get(Object key):首先获取value-->若获取不到,先缓存-->再从缓存中去取(以上三步是原子操作),使用该方法优先于使用put

      • getIfPresent(Object key):获取value,若获取不到,返回null;若获取的到,返回value

      • put(Object key, Object value):显示的添加缓存key-value

    • guava cache的get(Object key)的value不能为null(这个可以去看源代码的注释),看下边的代码例子:

          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 {
                          //1、下边这样null的话,不抛异常
                          /*List<Admin> admins = adminDao.getUserByName(username);
                          if(admins==null){
                              return null; 
                          }
                          return admins;*/
                          //2、但是如果这里查询出来的结果为null的话,也没关系
                          //return adminDao.getUserByName(username);
                          //3、如果这里直接返回null,就会出现com.google.common.cache.CacheLoader$InvalidCacheLoadException
                          return null;
                      }
                  });

      注意:该代码中的三种null情况,只有第三种会抛出异常。前两种不为空的原因是因为,即使admins没有元素,admins也不会是null,而是[],这应该是mybatis的功劳?!这个是个问题,以后在读mybatis源码的时候,会仔细研究!!!但是实际使用中,我们判断一个list是否为空,会使用CollectionUtil.isNotEmpty(list)类似于下边这样,就会抛出异常了。

          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 {
                          //1、下边这样null的话,不抛异常
                          List<Admin> admins = adminDao.getUserByName(username);
                          //System.out.println(admins);//如果admins为空,不会返回null,而是返回[]
                          if(CollectionUtils.isEmpty(admins)){
                              System.out.println(admins+"-->");
                              return null; 
                          }
                          return admins;
                          //2、但是如果这里查询出来的结果为null的话,也没关系
                          //return adminDao.getUserByName(username);
                          //3、如果这里直接返回null,就会出现com.google.common.cache.CacheLoader$InvalidCacheLoadException
                          //return null;
                      }
                  });

      但是,为了在guava cache的使用中不抛出异常,我们这里直接使用下边这句就好了,由mybatis将[]返回就好了。

      return adminDao.getUserByName(username);

    免费领取验证码、内容安全、短信发送、直播点播体验包及云服务器等套餐

    更多网易技术、产品、运营经验分享请点击

    相关文章:
    【推荐】 BigData – Join中竟然也有谓词下推!?
    【推荐】 大数据算法:排位问题
    【推荐】 微服务化之无状态化与容器化

    相关文章

      网友评论

          本文标题:企业项目开发--本地缓存guava cache(2)

          本文链接:https://www.haomeiwen.com/subject/mhblkqtx.html