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

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

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);

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

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

相关文章:
【推荐】 常见的三种撞库方法
【推荐】 == vs === in Javascript

企业项目开发--本地缓存guava cache(2)的更多相关文章

  1. 第七章 企业项目开发--本地缓存guava cache

    1.在实际项目开发中,会使用到很多缓存技术,而且数据库的设计一般也会依赖于有缓存的情况下设计. 常用的缓存分两种:本地缓存和分布式缓存. 常用的本地缓存是guava cache,本章主要介绍guava ...

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

    此文已由作者赵计刚授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. 1.在实际项目开发中,会使用到很多缓存技术,而且数据库的设计一般也会依赖于有缓存的情况下设计. 常用的缓存分 ...

  3. 第八章 企业项目开发--分布式缓存memcached

    注意:本节代码基于<第七章 企业项目开发--本地缓存guava cache> 1.本地缓存的问题 本地缓存速度一开始高于分布式缓存,但是随着其缓存数量的增加,所占内存越来越大,系统运行内存 ...

  4. 企业项目开发--分布式缓存memcached(3)

    此文已由作者赵计刚授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. 3.3.ssmm0-data 结构: 3.3.1.pom.xml  1 <?xml version=& ...

  5. 企业项目开发--分布式缓存Redis

    第九章 企业项目开发--分布式缓存Redis(1) 注意:本章代码将会建立在上一章的代码基础上,上一章链接<第八章 企业项目开发--分布式缓存memcached> 1.为什么用Redis ...

  6. 第九章 企业项目开发--分布式缓存Redis(1)

    注意:本章代码将会建立在上一章的代码基础上,上一章链接<第八章 企业项目开发--分布式缓存memcached> 1.为什么用Redis 1.1.为什么用分布式缓存(或者说本地缓存存在的问题 ...

  7. 第十章 企业项目开发--分布式缓存Redis(2)

    注意:本章代码是在上一章的基础上进行添加修改,上一章链接<第九章 企业项目开发--分布式缓存Redis(1)> 上一章说了ShardedJedisPool的创建过程,以及redis五种数据 ...

  8. 第十一章 企业项目开发--消息队列activemq

    注意:本章代码基于 第十章 企业项目开发--分布式缓存Redis(2) 代码的github地址:https://github.com/zhaojigang/ssmm0 消息队列是分布式系统中实现RPC ...

  9. 第六章 企业项目开发--cookie

    注:本章代码基于<第五章 企业项目开发--mybatis注解与xml并用>的代码,链接如下: http://www.cnblogs.com/java-zhao/p/5120792.html ...

随机推荐

  1. java 内存, 类加载g

    1. java 内存区域 方法区 虚拟机栈 本地方法栈 堆 程序计数器 其中 :  方法区  和 堆 是所有线程共享的 , 其他是线程隔离的 1.  程序计数器 : 可以看做是当前线程所执行的字节码的 ...

  2. tomcat+bean例子

    C:\Program Files\Apache Software Foundation\Tomcat 7.0\webapps\app\WEB-INF\classes\文件夹下 建立beanTestPa ...

  3. python输出格式对齐问题

    采用.format打印输出时,可以定义输出字符串的输出宽度,在 ':' 后传入一个整数, 可以保证该域至少有这么多的宽度. 用于美化表格时很有用. >>> table = {'Goo ...

  4. ajax 简介0

    WEB项目总是发生些新的变化,过去每个人都会抱怨WEB项目功能不如CS程序丰富,相应速度不够快速.但现在由于Ajax的出现有了很大的改观,具有快速的高响应性的用户界面.在传统的Web 应用程序中,当用 ...

  5. 【RabbitMQ】 Java简单的实现RabbitMQ

    准备工作 1.安装RabbitMQ,参考[RabbitMQ] RabbitMQ安装 2.新建Java项目,引入RabbitMQ的Maven依赖 <dependency> <group ...

  6. SHELL脚本取系统当前年月日问题 (去0)

    1. #!/bin/bash tmonth=`date +%m`tyear=`date +%y`tday=`date +%d`day=`expr $tday + 0`month=`expr $tmon ...

  7. mybatis LIKE

    <sql id="selectId"> `ID` AS id, `NAME` AS name, `DESCRIPTION` AS description, `TYPE` ...

  8. Apache hadoop安装配置

    1.网络中继更改问题 命令:   vi /etc/sysconfig/network-scripts/ifcfg-eth0 需要修改的代码 DEVICE=eth0 HWADDR=00:0C:29:11 ...

  9. 好文推荐系列--------(3)GruntJS 在线重载 提升生产率至新境界

    好文原文地址:http://segmentfault.com/a/1190000000354555 本文将首先介绍grunt-markdown插件如何配合HTML模板使用,接着我将介绍如何使用grun ...

  10. 用JAVA实现大文件上传及显示进度信息

    一. 大文件上传基础描述: 各种WEB框架中,对于浏览器上传文件的请求,都有自己的处理对象负责对Http MultiPart协议内容进行解析,并供开发人员调用请求的表单内容. 比如: Spring 框 ...