SpringBoot 集成Ehcache实现缓存

EhCache 是一个纯Java的进程内缓存框架,具有快速、精干等特点,是Hibernate中默认的CacheProvider。

Ehcache是一种广泛使用的开源Java分布式缓存。主要面向通用缓存,Java EE和轻量级容器。它具有内存和磁盘存储,缓存加载器,缓存扩展,缓存异常处理程序,一个gzip缓存servlet过滤器,支持REST和SOAP api等特点。

本文档主要通过案例介绍一下,如何在SpringBoot中集中Ehcache,使用Ehcache。

使用的SpringBoot版本为1.5.9.RELEASE,Ehcache版本2.10.4,还使用MyBatis用于数据存取,并集成了mybatis-plus用于简化数据存取。

首先需要通过IDEA创建一个Maven项目。

一、代码

    创建数据表,使用数据库为MySql

CREATE TABLE `tasklog` (
  `id` varchar(32) NOT NULL DEFAULT '' COMMENT '主键',
  `taskId` varchar(32) DEFAULT NULL COMMENT '任务ID',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

    pom.xml

        把项目的pom.xml修改为以下内容

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>

	<groupId>org.lvgang</groupId>
	<artifactId>springboot-ehcache</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<packaging>jar</packaging>

	<name>springboot-ehcache</name>
	<description>Demo project for Spring Boot</description>

	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>1.5.9.RELEASE</version>
		<relativePath/> <!-- lookup parent from repository -->
	</parent>

	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
		<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
		<java.version>1.8</java.version>
	</properties>

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

		<!-- spring-boot mybatis依赖-->
		<dependency>
			<groupId>org.mybatis.spring.boot</groupId>
			<artifactId>mybatis-spring-boot-starter</artifactId>
			<version>1.3.1</version>
		</dependency>

		<!-- mysql 数据库驱动. -->
		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
		</dependency>

		<!-- mybatis-plus begin -->
		<dependency>
			<groupId>com.baomidou</groupId>
			<artifactId>mybatisplus-spring-boot-starter</artifactId>
			<version>1.0.5</version>
		</dependency>
		<dependency>
			<groupId>com.baomidou</groupId>
			<artifactId>mybatis-plus</artifactId>
			<version>2.1.8</version>
		</dependency>

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

		<!-- Spring boot EhCache-->
		<dependency>
			<groupId>net.sf.ehcache</groupId>
			<artifactId>ehcache</artifactId>
		</dependency>

		<!-- Spring boot单元测试. -->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>

	</dependencies>

	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>

</project>

    application.properties

########################################################
###datasource
########################################################
spring.datasource.url = jdbc:mysql://xxx.xxx.xxx.xxx:3306/taskdb
spring.datasource.username = root
spring.datasource.password = xxxxxxx
spring.datasource.driverClassName = com.mysql.jdbc.Driver
spring.datasource.max-active=20
spring.datasource.max-idle=8
spring.datasource.min-idle=8
spring.datasource.initial-size=10

########################################################
###mybatis-plus
########################################################
mybatis-plus.mapper-locations=classpath:org/lvgang/springbootehcache/mapper/*Mapper.xml

########################################################
###log
########################################################
logging.level.org.lvgang.springbootehcache.mapper=debug

    编写Bean

package org.lvgang.springbootehcache.bean;

import java.io.Serializable;

public class Tasklog implements Serializable{

    public String id;
    public String taskId;

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getTaskId() {
        return taskId;
    }

    public void setTaskId(String taskId) {
        this.taskId = taskId;
    }

    @Override
    public String toString() {
        return "Tasklog{" +
                "id='" + id + '\'' +
                ", taskId='" + taskId + '\'' +
                '}';
    }
}

    编写Mapper

package org.lvgang.springbootehcache.mapper;

import com.baomidou.mybatisplus.mapper.BaseMapper;
import org.lvgang.springbootehcache.bean.Tasklog;

public interface TaskLogMapper extends BaseMapper<Tasklog> {

}

        mapper继承了mybatisplus用于简化数据存储编码

    编写Service

package org.lvgang.springbootehcache.service;

import net.sf.ehcache.Cache;
import net.sf.ehcache.Element;
import org.lvgang.springbootehcache.bean.Tasklog;
import org.lvgang.springbootehcache.mapper.TaskLogMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.stereotype.Service;

import java.util.Map;

/**
 * 测试服务层
 */
@Service
public class TaskLogService {

    @Autowired  private TaskLogMapper taskLogMapper;
    @Autowired  private net.sf.ehcache.CacheManager cacheManager;

    /**
     * 缓存的key
     */
    public static final String CACHE_KEY   = "taskLog";

    /**
     * 添加tasklog
     * @param tasklog
     * @return
     */
    @CachePut(value = CACHE_KEY, key = "#tasklog.id")
    public Tasklog create(Tasklog tasklog){
        System.out.println("CREATE");
        System.err.println (tasklog);
        taskLogMapper.insert(tasklog);
        return tasklog;
    }

    /**
     * 根据ID获取Tasklog
     * @param id
     * @return
     */
    @Cacheable(value = CACHE_KEY, key = "#id")
    public Tasklog findById(String id){
        System.out.println("FINDBYID");
        System.out.println("ID:"+id);
        return taskLogMapper.selectById(id);
    }

    /**
     * 根据ID更新Tasklog
     * @param tasklog
     * @return
     */
    @CachePut(value = CACHE_KEY, key = "#tasklog.id")
    public Tasklog update(Tasklog tasklog){
        System.out.println("UPDATE");
        System.out.println (tasklog);
        taskLogMapper.updateById(tasklog);
        return tasklog;
    }

    /**
     * 根据ID删除Tasklog
     * @param id
     */
    @CacheEvict(value = CACHE_KEY, key = "#id")
    public void delete(String id){
        System.out.println("DELETE");
        System.out.println("ID:"+id);
        taskLogMapper.deleteById(id);
    }


    public void getCache(){
        System.out.println("GETCACHE");
        Cache cache = cacheManager.getCache(CACHE_KEY);
        Map<Object,Element> elements = cache.getAll(cache.getKeys());
        if(elements!=null){
            for (Map.Entry<Object, Element> entry : elements.entrySet()) {
                System.out.println("key= " + entry.getValue().getObjectKey());
                System.out.println("value= " + entry.getValue().getObjectValue());
            }
        }
    }

//    @Cacheable、@CachePut、@CacheEvict 注释介绍
//    @Cacheable 的作用 主要针对方法配置,能够根据方法的请求参数对其结果进行缓存
//    @CachePut 的作用 主要针对方法配置,能够根据方法的请求参数对其结果进行缓存,和 @Cacheable 不同的是,它每次都会触发真实方法的调用
//    @CachEvict 的作用 主要针对方法配置,能够根据一定的条件对缓存进行清空
}

    编写Controller

package org.lvgang.springbootehcache.controller;

import org.lvgang.springbootehcache.bean.Tasklog;
import org.lvgang.springbootehcache.service.TaskLogService;
import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.UUID;


/**
 * 测试控制层
 */
@RestController
@RequestMapping("/taskLog")
public class TaskLogController {

    @Autowired
    private TaskLogService taskLogService;

    /**
     * 根据ID查询
     * @return
     */
    @RequestMapping("/get")
    public Tasklog getById(String id) {
        return taskLogService.findById(id);
    }

    /**
     * 添加数据
     * @return
     */
    @RequestMapping("/add")
    public String add() {
        Tasklog bean = new Tasklog();
        bean.setId(UUID.randomUUID().toString().replace("-", ""));
        bean.setTaskId(bean.getId());
        taskLogService.create(bean);
        return "插入成功";
    }

    /**
     * 更新数据
     * @return
     */
    @RequestMapping("/update")
    public String update(String id) {
        Tasklog bean = new Tasklog();
        bean.setId(id);
        bean.setTaskId(UUID.randomUUID().toString().replace("-", ""));

        bean = taskLogService.update(bean);
        if (bean != null) {
            return "更新成功";
        } else {
            return "更新失败";
        }
    }

    /**
     * 删除数据
     * @return
     */
    @RequestMapping("/romove")
    public String romove(String id) {
        taskLogService.delete(id);
        return "删除成功";
    }

    /**
     * 控制台输出缓存
     * @param id
     */
    @RequestMapping("/getCache")
    public void getCache(String id) {
        taskLogService.getCache();
    }
}

    SpringBoot Ehcache配置类

package org.lvgang.springbootehcache;

import net.sf.ehcache.config.CacheConfiguration;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.CachingConfigurer;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.ehcache.EhCacheCacheManager;
import org.springframework.cache.interceptor.CacheErrorHandler;
import org.springframework.cache.interceptor.CacheResolver;
import org.springframework.cache.interceptor.KeyGenerator;
import org.springframework.cache.interceptor.SimpleKeyGenerator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;


/**
 * EhCache配置文件,可以替代ehcache.xml 文件
 */

@Configuration
@EnableCaching
public class EhCacheConfiguration implements CachingConfigurer {

    @Bean(destroyMethod="shutdown")
    public net.sf.ehcache.CacheManager ehCacheManager() {
        CacheConfiguration cacheConfiguration = new CacheConfiguration();
        cacheConfiguration.setName("taskLog");
        cacheConfiguration.setMemoryStoreEvictionPolicy("LRU");
        cacheConfiguration.setMaxEntriesLocalHeap(1000);
        net.sf.ehcache.config.Configuration config = new net.sf.ehcache.config.Configuration();
        //可以创建多个cacheConfiguration,都添加到Config中
        config.addCache(cacheConfiguration);
        return net.sf.ehcache.CacheManager.newInstance(config);
    }

    @Bean
    @Override
    public CacheManager cacheManager() {
        return new EhCacheCacheManager(ehCacheManager());
    }

    @Bean
    @Override
    public KeyGenerator keyGenerator() {
        return new SimpleKeyGenerator();
    }

    @Override
    public CacheResolver cacheResolver() { return null; }

    @Override
    public CacheErrorHandler errorHandler() {
        return null;
    }

}

    SpringBoot 启动类

package org.lvgang.springbootehcache;

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication // 等价于@Configuration,@EnableAutoConfiguration和@ComponentScan
@MapperScan("org.lvgang.springbootehcache.mapper")  //mybatis mapper搜索路径
public class SpringbootEhcacheApplication {
	public static void main(String[] args) {
		SpringApplication.run(SpringbootEhcacheApplication.class, args);
	}
}

二、测试

    在执行以下测试时,必须先需要在数据库表中增加一条ID为9f829afb589542ffb4b7bff33345af2f的数据。

    查询

        在浏览器按顺序执行以下URL:   

        http://localhost:8080/taskLog/get?id=9f829afb589542ffb4b7bff33345af2f

        http://localhost:8080/taskLog/get?id=9f829afb589542ffb4b7bff33345af2f

        http://localhost:8080/taskLog/getCache

        控制台输出:

FINDBYID
ID:9f829afb589542ffb4b7bff33345af2f
2018-01-17 23:20:30.493 DEBUG 6164 --- [nio-8080-exec-1] o.l.s.mapper.TaskLogMapper.selectById    : ==>  Preparing: SELECT id,taskId FROM tasklog WHERE id=? 
2018-01-17 23:20:30.528 DEBUG 6164 --- [nio-8080-exec-1] o.l.s.mapper.TaskLogMapper.selectById    : ==> Parameters: 9f829afb589542ffb4b7bff33345af2f(String)
2018-01-17 23:20:30.605 DEBUG 6164 --- [nio-8080-exec-1] o.l.s.mapper.TaskLogMapper.selectById    : <==      Total: 1
GETCACHE
key= 9f829afb589542ffb4b7bff33345af2f
value= Tasklog{id='9f829afb589542ffb4b7bff33345af2f', taskId='9f829afb589542ffb4b7bff33345af2f'}

    添加

        在浏览器按顺序执行以下URL:   

        http://localhost:8080/taskLog/add

        http://localhost:8080/taskLog/getCache

        控制台输出:

CREATE
Tasklog{id='e91f0a90531d4512a7665a52ca6cbbab', taskId='e91f0a90531d4512a7665a52ca6cbbab'}
2018-01-17 23:23:46.986 DEBUG 9808 --- [nio-8080-exec-3] o.l.s.mapper.TaskLogMapper.insert        : ==>  Preparing: INSERT INTO tasklog ( id, taskId ) VALUES ( ?, ? ) 
2018-01-17 23:23:47.030 DEBUG 9808 --- [nio-8080-exec-3] o.l.s.mapper.TaskLogMapper.insert        : ==> Parameters: e91f0a90531d4512a7665a52ca6cbbab(String), e91f0a90531d4512a7665a52ca6cbbab(String)
2018-01-17 23:23:47.143 DEBUG 9808 --- [nio-8080-exec-3] o.l.s.mapper.TaskLogMapper.insert        : <==    Updates: 1
GETCACHE
key= e91f0a90531d4512a7665a52ca6cbbab
value= Tasklog{id='e91f0a90531d4512a7665a52ca6cbbab', taskId='e91f0a90531d4512a7665a52ca6cbbab'}

    修改

        在浏览器按顺序执行以下URL:   

        http://localhost:8080/taskLog/update?id=9f829afb589542ffb4b7bff33345af2f

        http://localhost:8080/taskLog/getCache

        控制台输出:

UPDATE
Tasklog{id='9f829afb589542ffb4b7bff33345af2f', taskId='c34c6e2ba06c46a3b267269dc871a0aa'}
2018-01-17 23:25:28.644 DEBUG 3856 --- [nio-8080-exec-1] o.l.s.mapper.TaskLogMapper.updateById    : ==>  Preparing: UPDATE tasklog SET taskId=? WHERE id=? 
2018-01-17 23:25:28.675 DEBUG 3856 --- [nio-8080-exec-1] o.l.s.mapper.TaskLogMapper.updateById    : ==> Parameters: c34c6e2ba06c46a3b267269dc871a0aa(String), 9f829afb589542ffb4b7bff33345af2f(String)
2018-01-17 23:25:28.784 DEBUG 3856 --- [nio-8080-exec-1] o.l.s.mapper.TaskLogMapper.updateById    : <==    Updates: 1
GETCACHE
key= 9f829afb589542ffb4b7bff33345af2f
value= Tasklog{id='9f829afb589542ffb4b7bff33345af2f', taskId='c34c6e2ba06c46a3b267269dc871a0aa'}

    删除

        http://localhost:8080/taskLog/get?id=9f829afb589542ffb4b7bff33345af2f

        http://localhost:8080/taskLog/getCache

        http://localhost:8080/taskLog/remove?id=9f829afb589542ffb4b7bff33345af2f

        http://localhost:8080/taskLog/getCache

        控制台输出:

FINDBYID
ID:9f829afb589542ffb4b7bff33345af2f
2018-01-17 23:27:39.535 DEBUG 9896 --- [nio-8080-exec-1] o.l.s.mapper.TaskLogMapper.selectById    : ==>  Preparing: SELECT id,taskId FROM tasklog WHERE id=? 
2018-01-17 23:27:39.565 DEBUG 9896 --- [nio-8080-exec-1] o.l.s.mapper.TaskLogMapper.selectById    : ==> Parameters: 9f829afb589542ffb4b7bff33345af2f(String)
2018-01-17 23:27:39.633 DEBUG 9896 --- [nio-8080-exec-1] o.l.s.mapper.TaskLogMapper.selectById    : <==      Total: 1
GETCACHE
key= 9f829afb589542ffb4b7bff33345af2f
value= Tasklog{id='9f829afb589542ffb4b7bff33345af2f', taskId='c34c6e2ba06c46a3b267269dc871a0aa'}
DELETE
ID:9f829afb589542ffb4b7bff33345af2f
2018-01-17 23:28:09.138 DEBUG 9896 --- [nio-8080-exec-5] o.l.s.mapper.TaskLogMapper.deleteById    : ==>  Preparing: DELETE FROM tasklog WHERE id=? 
2018-01-17 23:28:09.138 DEBUG 9896 --- [nio-8080-exec-5] o.l.s.mapper.TaskLogMapper.deleteById    : ==> Parameters: 9f829afb589542ffb4b7bff33345af2f(String)
2018-01-17 23:28:09.247 DEBUG 9896 --- [nio-8080-exec-5] o.l.s.mapper.TaskLogMapper.deleteById    : <==    Updates: 1
GETCACHE

三、修改为ehcache.xml配置文件

    上面的例子使用了Java类配置ehcache,下面介绍如何更改为ehcache.xml配置文件

    创建ehcache.xml配置文件

        在resources文件夹中,创建ehcache.xml配置文件

<?xml version="1.0" encoding="UTF-8"?>
<ehcache>
    <diskStore path="java.io.tmpdir"/>
    <!--
       name:缓存名称。
       maxElementsInMemory:缓存最大个数。
       eternal:对象是否永久有效,一但设置了,timeout将不起作用。
       timeToIdleSeconds:设置对象在失效前的允许闲置时间(单位:秒)。仅当eternal=false对象不是永久有效时使用,可选属性,默认值是0,也就是可闲置时间无穷大。
       timeToLiveSeconds:设置对象在失效前允许存活时间(单位:秒)。最大时间介于创建时间和失效时间之间。仅当eternal=false对象不是永久有效时使用,默认是0.,也就是对象存活时间无穷大。
       overflowToDisk:当内存中对象数量达到maxElementsInMemory时,Ehcache将会对象写到磁盘中。
       diskSpoolBufferSizeMB:这个参数设置DiskStore(磁盘缓存)的缓存区大小。默认是30MB。每个Cache都应该有自己的一个缓冲区。
       maxElementsOnDisk:硬盘最大缓存个数。
       diskPersistent:是否缓存虚拟机重启期数据 Whether the disk store persists between restarts of the Virtual Machine. The default value is false.
       diskExpiryThreadIntervalSeconds:磁盘失效线程运行时间间隔,默认是120秒。
       memoryStoreEvictionPolicy:当达到maxElementsInMemory限制时,Ehcache将会根据指定的策略去清理内存。默认策略是LRU(最近最少使用)。你可以设置为FIFO(先进先出)或是LFU(较少使用)。
       clearOnFlush:内存数量最大时是否清除。
    -->
    <defaultCache
            maxElementsInMemory="10000"
            eternal="false"
            timeToIdleSeconds="120"
            timeToLiveSeconds="120"
            overflowToDisk="true"
            maxElementsOnDisk="10000000"
            diskPersistent="false"
            diskExpiryThreadIntervalSeconds="120"
            memoryStoreEvictionPolicy="LRU"
    />
    <cache name="taskLog" maxElementsInMemory="1000"/>
</ehcache>

    配置ehcache配置文件位置

    在application.properties增加以下内容,可以让springboot可以找到配置文件 

########################################################
###ehcache
########################################################
spring.cache.ehcache.config=classpath:ehcache.xml

    删除EhCacheConfiguration 

    把org.lvgang.springbootehcache包中的EhCacheConfiguration删除,因为使用了ehcache.xml配置文件,就不需要Java的EhCache配置文件

    在SpringBoot的启动声明缓存启动

package org.lvgang.springbootehcache;

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication // 等价于@Configuration,@EnableAutoConfiguration和@ComponentScan
@MapperScan("org.lvgang.springbootehcache.mapper")  //mybatis mapper搜索路径
@EnableCaching   //缓存启动
public class SpringbootEhcacheApplication {
	public static void main(String[] args) {
		SpringApplication.run(SpringbootEhcacheApplication.class, args);
	}
}

    通过四步可以实现由Java的EhCache配置文件更改为ehcache.xml配置文件在SpringBoot集中EhCache。

转载于:https://my.oschina.net/sdlvzg/blog/1594834

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值