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例子


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM