>>分享流行的Java框架以及开源软件,对孙卫琴的《精通Spring:Java Web开发技术详解》提供技术支持 书籍支持  卫琴直播  品书摘要  在线测试  资源下载  联系我们
发表一个新主题 开启一个新投票 回复文章 您是本文章第 20021 个阅读者 刷新本主题
 * 贴子主题:  Spring Boot集成EHCache实现缓存机制 回复文章 点赞(0)  收藏  
作者:Jacky    发表时间:2020-03-23 23:47:05     消息  查看  搜索  好友  邮件  复制  引用

                                                                                                

Spring Boot集成EHCache实现缓存机制

                        我们先说说这一篇文章我们都会学到的技术点:Spring Data JPA,SpringBoot使用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-ehcache的maven java project。

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

              在pom.xml文件中加入相应的依赖包,SpringBoot父节点依赖包;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.0http://maven.apache.org/xsd/maven-4.0.0.xsd" >

                 < modelVersion >4.0.0 </ modelVersion >

                               < groupId >com.kfit </ groupId >

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

                 < version >0.0.1-SNAPSHOT </ version >

                 < packaging >jar </ packaging >

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

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

                               < properties >

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

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

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

                 </ properties >

                    <!-- springboot  父节点依赖,

                    引入这个之后相关的引入就不需要添加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 ><u>junit</u> </ groupId >

                               < artifactId ><u>junit</u> </ artifactId >

                               < scope >test </ scope >

                        </ dependency >

                                      <!-- springboot web 支持:<u>mvc</u>,<u>aop</u>... -->

                        < dependency >

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

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

                        </ dependency >

                                                   <!--

                           包含支持UI模版(Velocity,FreeMarker,JasperReports),

                           邮件服务,

                           脚本服务(JRuby),

                           缓存Cache(EHCache),

                           任务计划Scheduling(<u>uartz</u>)。

                     -->

                        < dependency >

                       < groupId >org.springframework </ groupId >

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

                     </ dependency >

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

                        < dependency >

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

                               < artifactId ><u>ehcache</u> </ artifactId >

                        </ dependency >

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

                        < dependency >

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

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

                     </ dependency >

                                                   <!-- <u>mysql</u> 数据库驱动. -->

                        < dependency >

                       < groupId ><u>mysql</u> </ groupId >

                       < artifactId ><u>mysql</u>-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;

      importorg.springframework.boot.SpringApplication;

       importorg.springframework.boot.autoconfigure.SpringBootApplication;

     /**

       *

       *

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

       *

       @SpringBootApplication

     等价于:

       @Configuration

       @EnableAutoConfiguration

       @ComponentScan

       *

       *  @author  Angel(QQ:412887952)

       *  @version  v.0.1

       */

      @SpringBootApplication

       public class App {

              public static void 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 sqlquery

      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 tothe entity manager)

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

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

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

      EhCacheManagerFactoryBean:

       package com.kfit.config;

       importorg.springframework.cache.annotation.EnableCaching;

       import org.springframework.cache.ehcache.EhCacheCacheManager;

       importorg.springframework.cache.ehcache.EhCacheManagerFactoryBean;

       importorg.springframework.context.annotation.Bean;

       importorg.springframework.context.annotation.Configuration;

       importorg.springframework.core.io.ClassPathResource;

       /**

       * 缓存配置.

       *  @author  Angel(QQ:412887952)

       *  @version  v.0.1

       */


      @Configuration

      @EnableCaching // 标注启动缓存.

       public class CacheConfiguration {

             /**

              * <u>ehcache</u> 主要的管理器

              *  @param  bean

              *  @return

              */


                 @Bean

              publicEhCacheCacheManager ehCacheCacheManager(EhCacheManagerFactoryBean bean){

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

                     return newEhCacheCacheManager( bean.getObject());

            }

                                     /*

                * 据shared与否的设置,

                * Spring 分别通过CacheManager.create()

                * 或new CacheManager()方式来创建一个<u>ehcache</u>基地.

                *

                * 也说是说通过这个来设置cache的基地是这里的Spring独用,还是跟别的(如<u>hibernate</u>的<u>Ehcache</u>共享)

                *

                */


                   @Bean

                public EhCacheManagerFactoryBean ehCacheManagerFactoryBean(){

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

                   EhCacheManagerFactoryBean cacheManagerFactoryBean =  newEhCacheManagerFactoryBean ();

                     cacheManagerFactoryBean.setConfigLocation (  newClassPathResource( "conf/ehcache.xml"));

                     cacheManagerFactoryBean.setShared(  true);

                  return cacheManagerFactoryBean;

              }

   }

                     在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. Thedefault value is false.

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

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

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

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

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

                    FIFO ,first in firstout,这个是大家最熟的,先进先出。

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

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

             -->

                 < 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

       public class DemoInfo {

                 @Id  @GeneratedValue

              private long id; // 主键.

              private String name; // 名称;

              private String pwd; // 密码;

              private int state;

              public long getId() {

                     return id;

            }

              public void setId(  long id)
{

                     this. id = id;

            }

              public String getName(){

                     return name;

            }

              public void setName(String name) {

                     this. name = name;

            }

              public String getPwd(){

                     return pwd;

            }

              public void setPwd(String pwd) {

                     this. pwd = pwd;

            }

              public int getState() {

                     return state;

            }

              public void setState(  int state)
{

                     this. state = state;

            }

                 @Override

              public StringtoString() {

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

            }

     }

                     (7)编写持久类DemoInfoRepository;

              编写持久类DemoInfoRepository:

    com.kfit.repository.DemoInfoRepository:

       package com.kfit.repository;

       importorg.springframework.data.repository.CrudRepository;

      import com.kfit.bean.DemoInfo;

                    /**

       * 操作数据库.

       *  @author  Angel(QQ:412887952)

       *  @version  v.0.1

       */


       public interfaceDemoInfoRepository  extends CrudRepository<DemoInfo,Long>{

     }

                     (8)编写处理类DemoInfoService;

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

       com.kfit.service.DemoInfoService :

       package com.kfit.service;

       import com.kfit.bean.DemoInfo;

       import javassist.NotFoundException;

       public interface DemoInfoService{

                           void delete(Long id);

                          DemoInfoupdate(DemoInfo updated)  throws NotFoundException;

                          DemoInfofindById(Long  id);

                          DemoInfosave(DemoInfo  demoInfo);

                   }

                   com.kfit.service.impl.DemoInfoServiceImpl:

       package com.kfit.service.impl;

       import javax.annotation.Resource;

       importorg.springframework.cache.annotation.CacheEvict;

       importorg.springframework.cache.annotation.CachePut;

       importorg.springframework.cache.annotation.Cacheable;

       importorg.springframework.stereotype.Service;

       import com.kfit.bean.DemoInfo;

       import com.kfit.repository.DemoInfoRepository;

       import com.kfit.service.DemoInfoService;

       import javassist.NotFoundException;

                    @Service

       public class DemoInfoServiceImpl  implements DemoInfoService{

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

              public static final String  CACHE_KEY
= "'demoInfo'";

                             @Resource

               private DemoInfoRepository demoInfoRepository;

                                     /**

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

             */


              public static final String  DEMO_CACHE_NAME
= "demo";

                                     /**

              * 保存数据.

              *  @param  demoInfo

              */


                 @CacheEvict(value=  DEMO_CACHE_NAME,key=  CACHE_KEY)

                 @Override

              public DemoInfosave(DemoInfo demoInfo){

                     return demoInfoRepository.save( demoInfo);

            }

                                     /**

              * 查询数据.

              *  @param  id

              *  @return

              */


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

                 @Override

              public DemoInfofindById(Long id){

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

                     return demoInfoRepository.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 DemoInfoupdate(DemoInfo updated)  throws NotFoundException{

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

                     if( demoInfo ==  null){

                          
throw  new
NotFoundException( "No find");

                   }

                        demoInfo.setName( updated.getName());

                        demoInfo.setPwd( updated.getPwd());

                     return demoInfo;

            }

                                                         /**

              * 删除数据.

              *  @param  id

              */


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

         @Override

          public void delete(Long id){

                        demoInfoRepository.delete( id);

        }

}

                     (9)编写DemoInfoController测试类;

      编写一个rest进行测试:

      com.kfit.controller.DemoInfoController :

       package com.kfit.controller;

        import javax.annotation.Resource;

       importorg.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

       public class 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]


                                                                                                              
----------------------------
原文链接:https://blog.csdn.net/linxingliang/article/details/52263773

程序猿的技术大观园:www.javathinker.net



[这个贴子最后由 flybird 在 2020-03-28 12:26:18 重新编辑]
  Java面向对象编程-->泛型
  JavaWeb开发-->JSP技术详解(Ⅰ)
  JSP与Hibernate开发-->映射对象标识符
  Java网络编程-->对象的序列化与反序列化
  精通Spring-->CSS过渡和动画
  Vue3开发-->Vue简介
  SpringCloud Feign的分析
  Spring MVC SSE服务器端推送
  springmvc处理异步请求的示例
  Spring MVC的@ExceptionHandler注解的用法
  @Resource注解的用法
  通过Spring JDBC API访问数据库
  @SessionAttributes的用法
  深入Redis客户端(redis客户端属性、redis缓冲区、关闭redis客...
  微服务架构的基础框架选择:Spring Cloud还是Dubbo?
  阿里面试官问我:如何用Redis设计秒杀系统?我的回答让他比起...
  Spring配置日志
  反向代理、负载均衡!优秀的 Nginx 是如何做到的?
  Spring MVC:切面的应用
  Spring Boot整合WebSocket及Spring Security实例
  Spring AOP的本质
  更多...
 IPIP: 已设置保密
楼主      
1页 1条记录 当前第1
发表一个新主题 开启一个新投票 回复文章


中文版权所有: JavaThinker技术网站 Copyright 2016-2026 沪ICP备16029593号-2
荟萃Java程序员智慧的结晶,分享交流Java前沿技术。  联系我们
如有技术文章涉及侵权,请与本站管理员联系。