Java中常用缓存Cache机制的实现

一、什么是缓存?

  缓存,就是将程序或系统经常要调用的对象存在内存中,以便其使用时可以快速调用,不必再去创建新的重复的实例。这样做可以减少系统开销,提高系统效率。

二、缓存的实现方式:

  实现方式1:

  内存缓存,也就是实现一个类中静态Map,对这个Map进行常规的增删查.。

import org.springframework.stereotype.Component;
import www.mxh.com.usercache.entity.UserInfo;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;

/**
 * 基于hashMap实现的缓存管理
 */
@Component
public class UserCacheManager {

    /**
     * 用户信息缓存
     */
    private static HashMap<String, UserInfo> userList = new HashMap<>();

    /**
     * 保存时间
     */
    private static int liveTime = 60;

    /**
     * 添加用户信息缓存
     * @param sessionId
     * @param userInfo
     * @return
     */
    public static boolean addCache(String sessionId,UserInfo userInfo){
        userList.put(sessionId,userInfo);
        return true;
    }

    /**
     * 删除用户缓存信息
     * @param sessionId
     * @return
     */
    public static boolean delCache(String sessionId){
        userList.remove(sessionId);
        return true;
    }

    /**
     * 获取用户缓存信息
     * @param sessionId
     * @return
     */
    public static UserInfo getCache(String sessionId){
        return userList.get(sessionId);
    }

    /**
     * 清除过期的用户缓存信息
     */
    public static void clearData(){
        Calendar nowTime = Calendar.getInstance();
        nowTime.add(Calendar.MINUTE,-liveTime);
        Date time = nowTime.getTime();
        for(String key : userList.keySet()){
            UserInfo userInfo = userList.get(key);
            if(userInfo.getLogin_time() == null || time.after(userInfo.getLogin_time())){
                userList.remove(key);
            }
        }
    }

}

     实现方式2(使用spring支持的cache):

  实现步骤: 

  第一步: 导入spring-boot-starter-cache模块

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-cache</artifactId>
</dependency>

       第二步: @EnableCaching开启缓存

@SpringBootApplication
@EnableCaching
public class Springboot07CacheApplication {

   public static void main(String[] args) {
      SpringApplication.run(Springboot07CacheApplication.class, args);
   }
}

       第三步: 使用缓存注解

     UserInfoCacheController

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import www.mxh.com.usercache.dao.LoginMapper;
import www.mxh.com.usercache.entity.UserInfo;
import www.mxh.com.usercache.service.Impl.LoginServiceImpl;

@Scope("prototype")
@Controller
public class UserInfoCacheController {

    @Autowired(required = true)
    private LoginMapper loginMapper;

    @Autowired
    private LoginServiceImpl loginService;

    @ResponseBody
    @RequestMapping(value = "/user/cache/login",method = RequestMethod.GET)
    public void userLoginByCache(String username,String password){
        UserInfo userInfo = loginService.UserLoginByCache(username, password);
        System.out.println(userInfo);
    }

    /**
     * 通过username删除单个用户缓存信息
     * @param username
     */
    @CacheEvict(value="userInfo",key="#username")
    @ResponseBody
    @RequestMapping(value = "/user/cache/delete",method = RequestMethod.GET)
    public void deleteUserInfoCache(String username) {
        System.out.println("清除用户信息缓存");
    }

    /*@Cacheable(value="userInfo",key="#username")
    @ResponseBody
    @RequestMapping(value = "/user/cache/select",method = RequestMethod.GET)
    public UserInfo selectUserInfoCache(String username) {
        System.out.println("清除用户信息缓存");
    }*/

    /**
     * 通过username修改单个用户缓存信息
     * @param username
     * @param password
     * @param age
     * @param sex
     * @param user_id
     * @return
     */
    @CachePut(value="userInfo",key = "#username")
    @ResponseBody
    @RequestMapping(value = "/user/cache/update",method = RequestMethod.GET)
    public UserInfo updateUserInfoCache(@RequestParam(required = false) String username,
                                        @RequestParam(required = false) String password,
                                        @RequestParam(required = false) Integer age,
                                        @RequestParam(required = false) String sex,
                                        @RequestParam(required = false) Long user_id) {
        UserInfo userInfo = loginMapper.updateUserInfoById(username, password, age, sex, user_id);
        System.out.println("1.更新用户缓存信息: " + userInfo);
        if(null == userInfo){
            userInfo = loginMapper.selectUserByUsernameAndPassword(username,password);
        }
        System.out.println("2.更新用户缓存信息: " + userInfo);
        return userInfo;
    }

}

  

 LoginServiceImpl
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import www.mxh.com.usercache.dao.LoginMapper;
import www.mxh.com.usercache.entity.UserInfo;
import www.mxh.com.usercache.service.LoginService;
import www.mxh.com.usercache.util.UserCacheManager;

/*定义缓存名称*/ @CacheConfig(cacheNames
= "userInfo") @Service public class LoginServiceImpl implements LoginService { @Autowired(required = true) private LoginMapper loginMapper;    
/*将查询到的数据放入缓存,下次调用该方法会先去缓存中查询数据*/  @Cacheable(value
= "userInfo", key = "#username") @Override public UserInfo UserLoginByCache(String username, String password) { UserInfo userInfo = loginMapper.selectUserByUsernameAndPasswordWithCache(username, password); System.out.println("用户缓存信息: " + userInfo); return userInfo; } }

  

 LoginMapper
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import org.springframework.stereotype.Repository;
import www.mxh.com.usercache.entity.UserInfo;

/**
 * 登陆dao层操作接口
 */
@Repository
public interface LoginMapper{

    @Select("select * from user_info where username=#{username} and password=#{password}")
    UserInfo selectUserByUsernameAndPassword(@Param("username") String username,
                                             @Param("password") String password);

    @Select("select * from user_info where username=#{username} and password=#{password}")
    UserInfo selectUserByUsernameAndPasswordWithCache(@Param("username") String username,
                                                      @Param("password") String password);

    @Select("update user_info set username=#{username},password=#{password},age=#{age},sex=#{sex} where user_id=#{user_id}")
    UserInfo updateUserInfoById(@Param("username") String username,
                                @Param("password") String password,
                                @Param("age") int age,
                                @Param("sex") String sex,
                                @Param("user_id") long user_id);

    /*@Select("insert into user_info (username,password,age,sex,user_id) values(#{username},#{password},#{age},#{sex},#{user_id})")
    UserInfo saveUserInfo(@Param("username") String username,
                          @Param("password") String password,
                          @Param("age") int age,
                          @Param("sex") String sex,
                          @Param("user_id") long user_id);*/

}

UserInfo(实体类)
import java.io.Serializable;
import java.util.Date;

public class UserInfo implements Serializable {

    private static final long serialVersionUID = 1L;

    private Long user_id;

    private String username;

    private String password;

    private String sex;

    private Integer age;

    private Date login_time;

    public Long getUser_id() {
        return user_id;
    }

    public void setUser_id(Long user_id) {
        this.user_id = user_id;
    }

    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 String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public Date getLogin_time() {
        return login_time;
    }

    public void setLogin_time(Date login_time) {
        this.login_time = login_time;
    }

    @Override
    public String toString() {
        return "UserInfo{" +
                "user_id=" + user_id +
                ", username='" + username + '\'' +
                ", password='" + password + '\'' +
                ", sex='" + sex + '\'' +
                ", age=" + age +
                ", login_time=" + login_time +
                '}';
    }
}

  application.properties

server.port=8009
spring.datasource.url=jdbc:mysql://localhost:3306/bank?useUnicode=true&characterEncoding=utf8
spring.darasource.username=root
spring.datasource.password=root
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
# 目标缓存管理器
#spring.cache.type=SIMPLE
spring.cache.type=ehcache
spring.cache.ehcache.config=classpath:ehcache.xml
# 打印sql语句
logging.level.www.mxh.com.usercache.dao=debug

ehcache.xml
<ehcache>

    <!--
        磁盘存储:将缓存中暂时不使用的对象,转移到硬盘,类似于Windows系统的虚拟内存
        path:指定在硬盘上存储对象的路径
        path可以配置的目录有:
            user.home(用户的家目录)
            user.dir(用户当前的工作目录)
            java.io.tmpdir(默认的临时目录)
            ehcache.disk.store.dir(ehcache的配置目录)
            绝对路径(如:d:\\ehcache)
        查看路径方法:String tmpDir = System.getProperty("java.io.tmpdir");
     -->
    <diskStore path="java.io.tmpdir" />

    <!--
        defaultCache:默认的缓存配置信息,如果不加特殊说明,则所有对象按照此配置项处理
        maxElementsInMemory:设置了缓存的上限,最多存储多少个记录对象
        eternal:代表对象是否永不过期 (指定true则下面两项配置需为0无限期)
        timeToIdleSeconds:最大的发呆时间 /秒
        timeToLiveSeconds:最大的存活时间 /秒
        overflowToDisk:是否允许对象被写入到磁盘
        说明:下列配置自缓存建立起600秒(10分钟)有效 。
        在有效的600秒(10分钟)内,如果连续120秒(2分钟)未访问缓存,则缓存失效。
        就算有访问,也只会存活600秒。
     -->
    <defaultCache maxElementsInMemory="10000" eternal="false"
                  timeToIdleSeconds="600" timeToLiveSeconds="600" overflowToDisk="true" />

    <!--类中的缓存空间须在该文件中配置-->
    <cache name="userInfo" maxElementsInMemory="10000" eternal="false"
           timeToIdleSeconds="120" timeToLiveSeconds="600" overflowToDisk="true" />

</ehcache>
具体代码详见博客文件中的user_cache例子

猜你喜欢

转载自www.cnblogs.com/mxh-java/p/10822333.html
今日推荐