首页 > 编程语言 > 详细

(37)Spring Boot集成EHCache实现缓存机制【从零开始学Spring Boot】

时间:2016-05-03 02:11:41      阅读:306      评论:0      收藏:0      [点我收藏+]

【本文章是否对你有用以及是否有好的建议,请留言】

写后感:博主写这么一系列文章也不容易啊,请评论支持下。

?

?????? 如果看过我之前(35)的文章这一篇的文章就会很简单,没有什么挑战性了。

?????? 那么我们先说说这一篇文章我们都会学到的技术点:Spring Data JPA,Spring Boot 使用Mysql,Spring MVC,EHCache,Spring Cache等(其中@Cacheable请看上一节的理论知识),具体分如下几个步骤:

1)新建Maven Java Project

2)在pom.xml中加入依赖包

3)编写Spring Boot启动类;

4)配置application.properties;

5)编写缓存配置类以及ehcache.xml配置文件;

6)编写DemoInfo实体类进行测试;

7)编写持久类DemoInfoRepository;

8)编写处理类DemoInfoService;

9)编写DemoInfoController测试类;

10)运行测试;

?

以上就是具体的步骤了,那么接下来我们一起按照这个步骤来进行实现吧。

?

1)新建Maven Java Project

?????? 新建一个工程名为spring-boot-ehcachemaven java project

?

2)在pom.xml中加入依赖包

?????? pom.xml文件中加入相应的依赖包,Spring Boot父节点依赖包;spring boot web支持;缓存依赖spring-context-support;集成ehcache需要的依赖;JPA操作数据库;mysql 数据库驱动,具体pom.xml文件:

<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>com.kfit</groupId>

??? <artifactId>spring-boot-ehcache</artifactId>

??? <version>0.0.1-SNAPSHOT</version>

??? <packaging>jar</packaging>

?

??? <name>spring-boot-ehcache</name>

??? <url>http://maven.apache.org</url>

?

??? <properties>

?????? <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>

?

?????? <!-- 配置JDK编译版本. -->

?????? <java.version>1.8</java.version>

??? </properties>

?

?

??? <!-- spring boot 父节点依赖,

?????? 引入这个之后相关的引入就不需要添加version配置,

?????? ?spring boot会自动选择最合适的版本进行添加。

??? -->

??? <parent>

?????? <groupId>org.springframework.boot</groupId>

?????? <artifactId>spring-boot-starter-parent</artifactId>

?????? <version>1.3.3.RELEASE</version>

??? </parent>

?

??? <dependencies>

?????? <!-- 单元测试. -->

?????? <dependency>

?????????? <groupId>junit</groupId>

?????????? <artifactId>junit</artifactId>

?????????? <scope>test</scope>

?????? </dependency>

?

?????? <!-- spring boot web支持:mvc,aop... -->

?????? <dependency>

?????????? <groupId>org.springframework.boot</groupId>

?????????? <artifactId>spring-boot-starter-web</artifactId>

?????? </dependency>

??????

?????? <!--

?????????? 包含支持UI模版(VelocityFreeMarkerJasperReports),

?????????? 邮件服务,

?????????? 脚本服务(JRuby)

?????????? 缓存CacheEHCache),

?????????? 任务计划Schedulinguartz)。

?????? ?-->

?????? <dependency>

??? ????? <groupId>org.springframework</groupId>

??? ????? <artifactId>spring-context-support</artifactId>

??? ??? </dependency>

?

?????? <!-- 集成ehcache需要的依赖-->

?????? <dependency>

?????????? <groupId>net.sf.ehcache</groupId>

?????????? <artifactId>ehcache</artifactId>

?????? </dependency>

??????

?????? <!-- JPA操作数据库. -->

?????? <dependency>

??? ????? <groupId>org.springframework.boot</groupId>

??? ????? <artifactId>spring-boot-starter-data-jpa</artifactId>

??? ??? </dependency>

??????

?????? <!-- mysql 数据库驱动. -->

?????? <dependency>

??? ????? <groupId>mysql</groupId>

??? ????? <artifactId>mysql-connector-java</artifactId>

??? ??? </dependency>

??? ???

??? ??? <!-- Spring boot单元测试. -->

?????? <dependency>

??????????? <groupId>org.springframework.boot</groupId>

??????????? <artifactId>spring-boot-starter-test</artifactId>

??????????? <scope>test</scope>

??????? </dependency>

??? </dependencies>

</project>

?

?

3)编写Spring Boot启动类(com.kfit.App.java);

package com.kfit;

?

import org.springframework.boot.SpringApplication;

import org.springframework.boot.autoconfigure.SpringBootApplication;

?

/**

?*

?*

?* @SpringBootApplication申明让spring boot自动给程序进行必要的配置,

?*

@SpringBootApplication

等待于:

@Configuration

@EnableAutoConfiguration

@ComponentScan

?*

?* @author Angel(QQ:412887952)

?* @version v.0.1

?*/

@SpringBootApplication

publicclass App {

??? publicstaticvoid main(String[] args) {

?????? SpringApplication.run(App.class, args);

??? }

}

?

?

4)配置application.properties;

?????? application.properties中主要配置数据库连接和JPA的基本配置,具体如下:

Src/main/resouces/application.properties

########################################################

###datasource ,mysql数据库连接配置

########################################################

spring.datasource.url = jdbc:mysql://localhost:3306/test

spring.datasource.username = root

spring.datasource.password = root

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

?

?

?

########################################################

### Java Persistence Api JPA自动建表操作配置

########################################################

# Specify the DBMS

spring.jpa.database = MYSQL

# Show or not log for each sql query

spring.jpa.show-sql = true

# Hibernate ddl auto (create, create-drop, update)

spring.jpa.hibernate.ddl-auto = update

# Naming strategy

spring.jpa.hibernate.naming-strategy = org.hibernate.cfg.ImprovedNamingStrategy

# stripped before adding them to the entity manager)

spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.MySQL5Dialect

?

?

5)编写缓存配置类以及ehcache.xml配置文件:

?????? 这个类主要是注册缓存管理对象EhCacheCacheManager、缓存工厂对象EhCacheManagerFactoryBean,具体代码如下:

EhCacheManagerFactoryBean

package com.kfit.config;

?

import org.springframework.cache.annotation.EnableCaching;

import org.springframework.cache.ehcache.EhCacheCacheManager;

import org.springframework.cache.ehcache.EhCacheManagerFactoryBean;

import org.springframework.context.annotation.Bean;

import org.springframework.context.annotation.Configuration;

import org.springframework.core.io.ClassPathResource;

?

/**

?* 缓存配置.

?* @author Angel(QQ:412887952)

?* @version v.0.1

?*/

@Configuration

@EnableCaching//标注启动缓存.

publicclass CacheConfiguration {

???

??? /**

??? ?*? ehcache 主要的管理器

??? ?* @param bean

??? ?* @return

??? ?*/

??? @Bean

??? public EhCacheCacheManager ehCacheCacheManager(EhCacheManagerFactoryBean bean){

?????? System.out.println("CacheConfiguration.ehCacheCacheManager()");

?????? returnnew EhCacheCacheManager(bean.getObject());

??? }

???

??? /*

??? ?? * shared与否的设置,

??? ?? * Spring分别通过CacheManager.create()

??? ?? * new CacheManager()方式来创建一个ehcache基地.

??? ?? *

??? ?? * 也说是说通过这个来设置cache的基地是这里的Spring独用,还是跟别的(hibernateEhcache共享)

??? ?? *

??? ?? */

??? ? @Bean

??? ? public EhCacheManagerFactoryBean ehCacheManagerFactoryBean(){

??? ??? System.out.println("CacheConfiguration.ehCacheManagerFactoryBean()");

?????? EhCacheManagerFactoryBean cacheManagerFactoryBean = new EhCacheManagerFactoryBean ();

??? ??? cacheManagerFactoryBean.setConfigLocation (new ClassPathResource("conf/ehcache.xml"));

??? ??? cacheManagerFactoryBean.setShared(true);

??? ??? returncacheManagerFactoryBean;

??? ? }

???

}

?

src/main/resouces/conf下编写ehcache.xml配置文件,当然这个文件你可以放在其它目录下:

<?xml version="1.0" encoding="UTF-8"?>

<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

??? xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd"

??? updateCheck="false">

???

???

??? <!--

??? diskStore:为缓存路径,ehcache分为内存和磁盘两级,此属性定义磁盘的缓存位置。参数解释如下:

?????? user.home – 用户主目录

?????? user.dir? 用户当前工作目录

?????? java.io.tmpdir – 默认临时文件路径

??????

??? ?-->

??? <diskStore path="java.io.tmpdir/Tmp_EhCache" />

???

??? <!--

?????? defaultCache默认缓存策略,当ehcache找不到定义的缓存时,则使用这个缓存策略。只能定义一个。

??? ?-->

??? ?

??? ?<!--

?????? name:缓存名称。

?????? maxElementsInMemory:缓存最大数目

?????? maxElementsOnDisk:硬盘最大缓存个数。?

?????? eternal:对象是否永久有效,一但设置了,timeout将不起作用。?

?????? overflowToDisk:是否保存到磁盘,当系统当机时

?????? timeToIdleSeconds:设置对象在失效前的允许闲置时间(单位:秒)。仅当eternal=false对象不是永久有效时使用,可选属性,默认值是0,也就是可闲置时间无穷大。

?????? timeToLiveSeconds:设置对象在失效前允许存活时间(单位:秒)。最大时间介于创建时间和失效时间之间。仅当eternal=false对象不是永久有效时使用,默认是0.,也就是对象存活时间无穷大。

?????? diskPersistent:是否缓存虚拟机重启期数据 Whether the disk store persists between restarts of the Virtual Machine. The default value is false.?

?????? diskSpoolBufferSizeMB:这个参数设置DiskStore(磁盘缓存)的缓存区大小。默认是30MB。每个Cache都应该有自己的一个缓冲区。?

?????? diskExpiryThreadIntervalSeconds:磁盘失效线程运行时间间隔,默认是120秒。

?????? memoryStoreEvictionPolicy:当达到maxElementsInMemory限制时,Ehcache将会根据指定的策略去清理内存。默认策略是LRU(最近最少使用)。你可以设置为FIFO(先进先出)或是LFU(较少使用)。?

??????? clearOnFlush:内存数量最大时是否清除。

???????? memoryStoreEvictionPolicy:可选策略有:LRU(最近最少使用,默认策略)、FIFO(先进先出)、LFU(最少访问次数)。

???????? ?? FIFOfirst in first out,这个是大家最熟的,先进先出。

???????? ?? LFU Less Frequently Used,就是上面例子中使用的策略,直白一点就是讲一直以来最少被使用的。如上面所讲,缓存的元素有一个hit属性,hit值最小的将会被清出缓存。

???????? ?? LRULeast Recently Used,最近最少使用的,缓存的元素有一个时间戳,当缓存容量满了,而又需要腾出地方来缓存新的元素的时候,那么现有缓存元素中时间戳离当前时间最远的元素将被清出缓存。

??? -->

??? <defaultCache

?????? eternal="false"

?????? maxElementsInMemory="1000"

?????? overflowToDisk="false"

?????? diskPersistent="false"

?????? timeToIdleSeconds="0"

?????? timeToLiveSeconds="600"

?????? memoryStoreEvictionPolicy="LRU" />

?

??? <cache

?????? name="demo"??

?????? eternal="false"

?????? maxElementsInMemory="100"

?????? overflowToDisk="false"

?????? diskPersistent="false"

?????? timeToIdleSeconds="0"

?????? timeToLiveSeconds="300"

?????? memoryStoreEvictionPolicy="LRU" />

??????

</ehcache>

?

6)编写DemoInfo实体类进行测试;

com.kfit.bean下编写DemoInfo实体类进行缓存测试:

package com.kfit.bean;

?

import javax.persistence.Entity;

import javax.persistence.GeneratedValue;

import javax.persistence.Id;

?

/**

?* 测试实体类.

?* @author Angel(QQ:412887952)

?* @version v.0.1

?*/

@Entity

publicclass DemoInfo {

??? @Id@GeneratedValue

??? privatelongid;//主键.

??? private String name;//名称;

??? private String pwd;//密码;

??? privateintstate;

??? publiclong getId() {

?????? returnid;

??? }

??? publicvoid setId(longid) {

?????? this.id = id;

??? }

??? public String getName() {

?????? returnname;

??? }

??? publicvoid setName(String name) {

?????? this.name = name;

??? }

??? public String getPwd() {

?????? returnpwd;

??? }

??? publicvoid setPwd(String pwd) {

?????? this.pwd = pwd;

??? }

??? publicint getState() {

?????? returnstate;

??? }

??? publicvoid setState(intstate) {

?????? this.state = state;

??? }

??? @Override

??? public String toString() {

?????? return"DemoInfo [id=" + id + ", name=" + name + ", pwd=" + pwd + ", state=" + state + "]";

??? }

}

?

7)编写持久类DemoInfoRepository;

?????? 编写持久类DemoInfoRepository

com.kfit.repository.DemoInfoRepository

package com.kfit.repository;

?

import org.springframework.data.repository.CrudRepository;

?

import com.kfit.bean.DemoInfo;

?

/**

?* 操作数据库.

?* @author Angel(QQ:412887952)

?* @version v.0.1

?*/

publicinterface DemoInfoRepository extends CrudRepository<DemoInfo,Long>{

?

}

?

8)编写处理类DemoInfoService;

?????? 编写增删改查的方法,在这几个方法中都使用注解缓存,进行缓存的创建以及删除,修改等操作:

?com.kfit.service.DemoInfoService

package com.kfit.service;

?

import com.kfit.bean.DemoInfo;

?

import javassist.NotFoundException;

?

publicinterface DemoInfoService {

?

??? void delete(Long id);

?

??? DemoInfo update(DemoInfo updated) throws NotFoundException;

?

??? DemoInfo findById(Long id);

?

??? DemoInfo save(DemoInfo demoInfo);

?

}

?

com.kfit.service.impl.DemoInfoServiceImpl

package com.kfit.service.impl;

?

import javax.annotation.Resource;

?

import org.springframework.cache.annotation.CacheEvict;

import org.springframework.cache.annotation.CachePut;

import org.springframework.cache.annotation.Cacheable;

import org.springframework.stereotype.Service;

?

import com.kfit.bean.DemoInfo;

import com.kfit.repository.DemoInfoRepository;

import com.kfit.service.DemoInfoService;

?

import javassist.NotFoundException;

?

@Service

publicclass DemoInfoServiceImpl implements DemoInfoService {

???

??? //这里的单引号不能少,否则会报错,被识别是一个对象;

??? publicstaticfinal String CACHE_KEY = "‘demoInfo‘";

??

??? ?@Resource

??? ?private DemoInfoRepository demoInfoRepository;

???

??? /**

??? ?* value属性表示使用哪个缓存策略,缓存策略在ehcache.xml

??? */

??? publicstaticfinal String DEMO_CACHE_NAME = "demo";

???

??? /**

??? ?* 保存数据.

??? ?* @param demoInfo

??? ?*/

??? @CacheEvict(value=DEMO_CACHE_NAME,key=CACHE_KEY)

??? @Override

??? public DemoInfo save(DemoInfo demoInfo){

?????? returndemoInfoRepository.save(demoInfo);

??? }

???

??? /**

??? ?* 查询数据.

??? ?* @param id

??? ?* @return

??? ?*/

??? @Cacheable(value=DEMO_CACHE_NAME,key="‘demoInfo_‘+#id")

??? @Override

??? public DemoInfo findById(Long id){

?????? System.err.println("没有走缓存!"+id);

?????? returndemoInfoRepository.findOne(id);

??? }

???

??? /**

??? ?* http://www.mincoder.com/article/2096.shtml:

??? ?*

??? ?* 修改数据.

??? ?*

??? ?* 在支持Spring Cache的环境下,对于使用@Cacheable标注的方法,Spring在每次执行前都会检查Cache中是否存在相同key的缓存元素,如果存在就不再执行该方法,而是直接从缓存中获取结果进行返回,否则才会执行并将返回结果存入指定的缓存中。@CachePut也可以声明一个方法支持缓存功能。与@Cacheable不同的是使用@CachePut标注的方法在执行前不会去检查缓存中是否存在之前执行过的结果,而是每次都会执行该方法,并将执行结果以键值对的形式存入指定的缓存中。

?

?????? @CachePut也可以标注在类上和方法上。使用@CachePut时我们可以指定的属性跟@Cacheable是一样的。

??? ?*

??? ?* @param updated

??? ?* @return

??? ?*

??? ?* @throws NotFoundException

??? ?*/

??? @CachePut(value = DEMO_CACHE_NAME,key = "‘demoInfo_‘+#updated.getId()")

??? //@CacheEvict(value = DEMO_CACHE_NAME,key = "‘demoInfo_‘+#updated.getId()")//这是清除缓存.

??? @Override

??? public DemoInfo update(DemoInfo updated) throws NotFoundException{

?????? DemoInfo demoInfo = demoInfoRepository.findOne(updated.getId());

?????? if(demoInfo == null){

?????????? thrownew NotFoundException("No find");

?????? }

?????? demoInfo.setName(updated.getName());

?????? demoInfo.setPwd(updated.getPwd());

?????? returndemoInfo;

??? }

???

???

??? /**

??? ?* 删除数据.

??? ?* @param id

??? ?*/

??? @CacheEvict(value = DEMO_CACHE_NAME,key = "‘demoInfo_‘+#id")//这是清除缓存.

??? @Override

??? publicvoid delete(Long id){

?????? demoInfoRepository.delete(id);

??? }

??? ??

???

}

?

9)编写DemoInfoController测试类;

编写一个rest进行测试:

com.kfit.controller.DemoInfoController

package com.kfit.controller;

?

import javax.annotation.Resource;

?

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

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

?

import com.kfit.bean.DemoInfo;

import com.kfit.service.DemoInfoService;

?

import javassist.NotFoundException;

?

@RestController

publicclass DemoInfoController {

?

??? @Resource

??? private DemoInfoService demoInfoService;

???

??? @RequestMapping("/test")

??? public String test(){

??????

?????? //存入两条数据.

??? ??? DemoInfo demoInfo = new DemoInfo();

??? ??? demoInfo.setName("张三");

??? ??? demoInfo.setPwd("123456");

??? ??? DemoInfo demoInfo2 = demoInfoService.save(demoInfo);

??????

??? ??? //不走缓存.

??? ??? System.out.println(demoInfoService.findById(demoInfo2.getId()));

??? ??? //走缓存.

??? ??? System.out.println(demoInfoService.findById(demoInfo2.getId()));

??? ???

??? ???

??? ??? demoInfo = new DemoInfo();

??? ??? demoInfo.setName("李四");

??? ??? demoInfo.setPwd("123456");

??? ??? DemoInfo demoInfo3 = demoInfoService.save(demoInfo);

??? ???

??? ??? //不走缓存.

??? ??? System.out.println(demoInfoService.findById(demoInfo3.getId()));

??? ??? //走缓存.

??? ??? System.out.println(demoInfoService.findById(demoInfo3.getId()));

??? ???

??? ??? System.out.println("============修改数据=====================");

??? ??? //修改数据.

??? ??? DemoInfo updated = new DemoInfo();

??? ??? updated.setName("李四-updated");

??? ??? updated.setPwd("123456");

??? ??? updated.setId(demoInfo3.getId());

??? ??? try {

?????????? System.out.println(demoInfoService.update(updated));

?????? } catch (NotFoundException e) {

?????????? e.printStackTrace();

?????? }

??? ???

??? ??? //不走缓存.

??? ??? System.out.println(demoInfoService.findById(updated.getId()));

??? ???

?????? return"ok";

??? }

???

???

}

?

10)运行测试;

运行App.java进行测试,访问:http://127.0.0.1:8080/test 进行测试,主要是观察控制台的打印信息。

Hibernate: insert into demo_info (name, pwd, state) values (?, ?, ?)

没有走缓存!52

DemoInfo [id=52, name=张三, pwd=123456, state=0]

DemoInfo [id=52, name=张三, pwd=123456, state=0]

Hibernate: insert into demo_info (name, pwd, state) values (?, ?, ?)

没有走缓存!53

DemoInfo [id=53, name=李四, pwd=123456, state=0]

DemoInfo [id=53, name=李四, pwd=123456, state=0]

============修改数据=====================

DemoInfo [id=53, name=李四-updated, pwd=123456, state=0]

DemoInfo [id=53, name=李四-updated, pwd=123456, state=0]

C:\Users\ADMINI~1.ANG\AppData\Local\Temp\

Hibernate: insert into demo_info (name, pwd, state) values (?, ?, ?)

没有走缓存!54

DemoInfo [id=54, name=张三, pwd=123456, state=0]

DemoInfo [id=54, name=张三, pwd=123456, state=0]

Hibernate: insert into demo_info (name, pwd, state) values (?, ?, ?)

没有走缓存!55

DemoInfo [id=55, name=李四, pwd=123456, state=0]

DemoInfo [id=55, name=李四, pwd=123456, state=0]

============修改数据=====================

DemoInfo [id=55, name=李四-updated, pwd=123456, state=0]

DemoInfo [id=55, name=李四-updated, pwd=123456, state=0]

?

?????? 好了本篇文章就写到这里吧,打烊休息了,实在是动不了!

?

?

Spring Boot 系列博客】

?

0)前言【从零开始学Spring Boot :

http://412887952-qq-com.iteye.com/blog/2291496

?

1spring boot起步之Hello World【从零开始学Spring Boot:

http://412887952-qq-com.iteye.com/blog/2291500

2Spring Boot返回json数据【从零开始学Spring Boot

http://412887952-qq-com.iteye.com/blog/2291508

(15)Spring Boot使用Druid和监控配置【从零开始学Spring Boot】

http://412887952-qq-com.iteye.com/blog/2292362

16Spring Boot使用Druid(编程注入)【从零开始学Spring Boot

http://412887952-qq-com.iteye.com/blogs/2292376

17Spring Boot普通类调用bean【从零开始学Spring Boot】:

http://412887952-qq-com.iteye.com/blog/2292388

......

(35)Spring Boot集成Redis实现缓存机制【从零开始学Spring Boot】

http://412887952-qq-com.iteye.com/blog/2294942

?

更多查看博客:http://412887952-qq-com.iteye.com/

?

(37)Spring Boot集成EHCache实现缓存机制【从零开始学Spring Boot】

原文:http://412887952-qq-com.iteye.com/blog/2294952

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!