Skip to content

Latest commit

 

History

History
2024 lines (1679 loc) · 86.4 KB

File metadata and controls

2024 lines (1679 loc) · 86.4 KB

Spring Boot 2.X 整合集成 Ehcache3 + JSR 107

1 摘要

Ehcache 作为一个广泛使用的 Java 缓存框架,新版本Ehcache 3 对 API 进行了大量重构, Ehcache 3 支持 JSR107 以及非堆内存。本文将介绍 Spring Boot 2.X 简易集成 Ehcache3 + JSR107 。

Ehcache 官方文档: http://www.ehcache.org/documentation/

2 Maven 依赖

../pom.xml
../demo-common/pom.xml
            <!-- Ehcache -->
            <dependency>
                <groupId>org.ehcache</groupId>
                <artifactId>ehcache</artifactId>
                <version>${ehcache3.version}</version>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-cache</artifactId>
                <version>${springboot.version}</version>
            </dependency>
            <dependency>
                <groupId>javax.cache</groupId>
                <artifactId>cache-api</artifactId>
                <version>${javax-cache.version}</version>
            </dependency>

其中对应的版本号为:

<ehcache3.version>3.5.3</ehcache3.version>
<springboot.version>2.0.6.RELEASE</springboot.version>
<javax-cache.version>1.1.0</javax-cache.version>

3 配置 Ehcache 3

3.1 修改yml 配置文件

../demo-web/src/main/resources/application.yml
  # ehcache 3
  cache:
    jcache:
      config: classpath:ehcache3.xml

3.2 创建Ehcache3 的配置文件

../demo-web/src/main/resources/ehcache3.xml
<config
        xmlns='http://www.ehcache.org/v3'
        xmlns:jsr107='http://www.ehcache.org/v3/jsr107'>

    <service>
        <jsr107:defaults>
            <!-- Cache name -->
            <jsr107:cache name="userCache" template="heap-cache"/>
        </jsr107:defaults>
    </service>

    <!-- Cache template -->
    <cache-template name="heap-cache">
        <!-- Cache listener,log cache event,the class is created by yourself -->
        <listeners>
            <listener>
                <class>com.ljq.demo.springboot.common.cache.Ehcache3EventLog</class>
                <event-firing-mode>ASYNCHRONOUS</event-firing-mode>
                <event-ordering-mode>UNORDERED</event-ordering-mode>
                <events-to-fire-on>CREATED</events-to-fire-on>
                <events-to-fire-on>UPDATED</events-to-fire-on>
                <events-to-fire-on>EXPIRED</events-to-fire-on>
                <events-to-fire-on>REMOVED</events-to-fire-on>
                <events-to-fire-on>EVICTED</events-to-fire-on>
            </listener>
        </listeners>
        <resources>
            <heap unit="entries">2000</heap>
            <!-- off-heap,host computer memory,not managed by JVM GC -->
            <offheap unit="MB">100</offheap>
        </resources>
    </cache-template>
</config>

3.3 Ehcache 3 配置类

../demo-common/src/main/java/com/ljq/demo/springboot/common/cache/Ehcache3Config.java
package com.ljq.demo.springboot.common.cache;

import org.springframework.boot.autoconfigure.cache.JCacheManagerCustomizer;
import org.springframework.stereotype.Component;

import javax.cache.CacheManager;
import javax.cache.configuration.MutableConfiguration;
import javax.cache.expiry.Duration;
import javax.cache.expiry.TouchedExpiryPolicy;
import java.util.concurrent.TimeUnit;

/**
 * @Description: Ehcache 3 配置类
 * @Author: junqiang.lu
 * @Date: 2019/3/16
 */
@Component
public class Ehcache3Config implements JCacheManagerCustomizer {

    private static final String CACHE_NAME = "userCache";

    @Override
    public void customize(CacheManager cacheManager) {
        cacheManager.createCache(CACHE_NAME,new MutableConfiguration<>()
                .setExpiryPolicyFactory(TouchedExpiryPolicy.factoryOf(new Duration(TimeUnit.SECONDS, 30)))
                .setStoreByValue(false)
                .setStatisticsEnabled(true)
        );

    }

}

3.4 Ehcache 3 事件监听日志类

../demo-common/src/main/java/com/ljq/demo/springboot/common/cache/Ehcache3EventLog.java
package com.ljq.demo.springboot.common.cache;

import lombok.extern.slf4j.Slf4j;
import org.ehcache.event.CacheEvent;
import org.ehcache.event.CacheEventListener;

/**
 * @Description: Ehcache3 事件日志
 * @Author: junqiang.lu
 * @Date: 2019/3/16
 */
@Slf4j
public class Ehcache3EventLog implements CacheEventListener<Object, Object> {

    @Override
    public void onEvent(CacheEvent<?, ?> event) {
        log.info("Event: {},  Key: {}, old value: {}, new value: ",event.getType(),event.getKey(),
                event.getOldValue(),event.getNewValue());
    }

}

3.4 开启 Ehcache 3 注解

在 SpringBoot 启动类上使用 @EnableCaching 注解

../demo-web/src/main/java/com/ljq/demo/springboot/web/DemoWebApplication.java
package com.ljq.demo.springboot.web;

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.servlet.ServletComponentScan;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
import org.springframework.context.annotation.ComponentScan;

@SpringBootApplication
@EnableEurekaServer
@ComponentScan(basePackages = {"com.ljq.demo"})
@MapperScan("com.ljq.demo.springboot.dao")
@ServletComponentScan
@EnableCaching
public class DemoWebApplication extends SpringBootServletInitializer {

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

    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
        return builder.sources(DemoWebApplication.class);
    }
}

4 Ehcache 3 注解使用

4.1 准备工作

接口参数接收 bean

../demo-model/src/main/java/com/ljq/demo/springboot/vo/ehcache3/NoCacheBean.java
package com.ljq.demo.springboot.vo.ehcache3;

import com.ljq.demo.springboot.BaseBean;
import lombok.Data;

import javax.validation.constraints.Min;
import javax.validation.constraints.NotNull;

/**
 * @Description: 不使用缓存 参数接收bean
 * @Author: junqiang.lu
 * @Date: 2019/3/16
 */
@Data
public class NoCacheBean extends BaseBean {


    private static final long serialVersionUID = 8568564661258311962L;

    /**
     * 用户 id
     */
    @NotNull(message = "用户 id 不能为空")
    @Min(value = 1, message = "用户 id 至少为 1")
    private Long id;

}

../demo-model/src/main/java/com/ljq/demo/springboot/vo/ehcache3/CacheResultBean.java
package com.ljq.demo.springboot.vo.ehcache3;

import com.ljq.demo.springboot.BaseBean;
import lombok.Data;

import javax.validation.constraints.Min;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Pattern;

/**
 * @Description: CacheResult 注解测试 参数接收 bean
 * @Author: junqiang.lu
 * @Date: 2019/3/16
 */
@Data
public class CacheResultBean extends BaseBean {

    private static final long serialVersionUID = -7236570402000051173L;

    /**
     * 当前页
     */
    @NotNull(message = "当前页不能为空")
    @Min(value = 1, message = "当前页至少为 1")
    private Integer currPage;

    /**
     * 每页显示条数
     */
    @NotNull(message = "每页显示条数不能为空")
    @Min(value = 5, message = "每页至少展示 5 条结果")
    private Integer pageLimit;

    /**
     * 排序依据,如依据 "id" 排序
     */
    @NotNull(message = "排序依据不能为空")
    @Pattern(regexp = "^[\\s\\S]{1,30}$", message = "排序依据需要控制在 1-30 个字符以内")
    private String sidx;

    /**
     * 排序规则,升序:asc;降序:desc
     */
    @NotNull(message = "排序规则不能为空")
    @Pattern(regexp = "^[\\s\\S]{1,10}$", message = "排序规则需要控制在 1-10 个字符以内")
    private String order;

}

../demo-model/src/main/java/com/ljq/demo/springboot/vo/ehcache3/CachePutBean.java
package com.ljq.demo.springboot.vo.ehcache3;

import com.ljq.demo.springboot.BaseBean;
import lombok.Data;

import javax.validation.constraints.Min;
import javax.validation.constraints.NotNull;

/**
 * @Description: CachePut 注解测试 参数接收 bean
 * @Author: junqiang.lu
 * @Date: 2019/3/16
 */
@Data
public class CachePutBean extends BaseBean {

    private static final long serialVersionUID = 5556099626135790988L;

    /**
     * 用户 id
     */
    @NotNull(message = "用户 id 不能为空")
    @Min(value = 1, message = "用户 id 至少为 1")
    private Long id;

}

../demo-model/src/main/java/com/ljq/demo/springboot/vo/ehcache3/CacheRemoveBean.java
package com.ljq.demo.springboot.vo.ehcache3;

import com.ljq.demo.springboot.BaseBean;
import lombok.Data;

import javax.validation.constraints.Min;
import javax.validation.constraints.NotNull;

/**
 * @Description: CacheRemove 注解测试 参数接收 bean
 * @Author: junqiang.lu
 * @Date: 2019/3/16
 */
@Data
public class CacheRemoveBean extends BaseBean {

    private static final long serialVersionUID = -2815271308925839053L;

    /**
     * 用户 id
     */
    @NotNull(message = "用户 id 不能为空")
    @Min(value = 1, message = "用户 id 至少为 1")
    private Long id;

}

../demo-model/src/main/java/com/ljq/demo/springboot/vo/ehcache3/CacheRemoveAllBean.java
package com.ljq.demo.springboot.vo.ehcache3;

import com.ljq.demo.springboot.BaseBean;
import lombok.Data;

import javax.validation.constraints.Min;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Pattern;

/**
 * @Description: CacheRemoveAll 注解测试 参数接收 bean
 * @Author: junqiang.lu
 * @Date: 2019/3/16
 */
@Data
public class CacheRemoveAllBean extends BaseBean {

    private static final long serialVersionUID = 7311007086863087333L;

    /**
     * 当前页
     */
    @NotNull(message = "当前页不能为空")
    @Min(value = 1, message = "当前页至少为 1")
    private Integer currPage;

    /**
     * 每页显示条数
     */
    @NotNull(message = "每页显示条数不能为空")
    @Min(value = 5, message = "每页至少展示 5 条结果")
    private Integer pageLimit;

    /**
     * 排序依据,如依据 "id" 排序
     */
    @NotNull(message = "排序依据不能为空")
    @Pattern(regexp = "^[\\s\\S]{1,30}$", message = "排序依据需要控制在 1-30 个字符以内")
    private String sidx;

    /**
     * 排序规则,升序:asc;降序:desc
     */
    @NotNull(message = "排序规则不能为空")
    @Pattern(regexp = "^[\\s\\S]{1,10}$", message = "排序规则需要控制在 1-10 个字符以内")
    private String order;

}

部分工具类

防止 SQL 注入工具类

../demo-common/src/main/java/com/ljq/demo/springboot/common/util/SQLCheckUtil.java
package com.ljq.demo.springboot.common.util;

import java.util.regex.Pattern;

/**
 * @Description: sql 校验工具
 * @Author: junqiang.lu
 * @Date: 2018/11/28
 */
public class SQLCheckUtil {

    /**
     * sql 最大长度
     */
    private static final int MAX_SQL_LENGTH = 1024 * 1024;

    private SQLCheckUtil(){}

    /**
     * 获取安全 sql 语句(防止 sql 注入)
     * 返回为空(null)的情况:
     *     1) sql 语句为空
     *     2) sql 语句中包含可能产生 sql 注入风险的关键词
     *
     * @param sql sql 语句
     * @return null or safe sql
     * @throws Exception 当 sql 语句长度超过 ${MAX_SQL_LENGTH} 字符时抛出异常
     */
    public static String getSafeSQL(String sql) throws Exception {
        if (sql == null || sql.length() <= 0) {
            return null;
        }
        if (sql.length() > MAX_SQL_LENGTH) {
            throw new Exception("Query string is too long,it must be less than 1048576 = 1024*1024.");
        }
        /**
         * 防止 sql 注入
         */
        String sqlRegex = "(?:')|(?:--)|(/\\*(?:.|[\\n\\r])*?\\*/)|"
                                + "(\\b(select|update|union|and|or|delete|insert|trancate|char|"
                                + "into|substr|ascii|declare|exec|count|master|into|drop|execute)\\b)";
        Pattern sqlPattern = Pattern.compile(sqlRegex, Pattern.CASE_INSENSITIVE);
        if (sqlPattern.matcher(sql).find()) {
            return null;
        }
        return sql;
    }

}

分页工具类

../demo-common/src/main/java/com/ljq/demo/springboot/common/page/QueryUtil.java
package com.ljq.demo.springboot.common.page;

import com.ljq.demo.springboot.common.util.SQLCheckUtil;
import lombok.Data;

import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;

/**
 * @Description: 分页查询工具(极简版)
 * @Author: junqiang.lu
 * @Date: 2018/11/28
 */
@Data
public class QueryUtil extends HashMap<String, Object> implements Serializable {

    private static final long serialVersionUID = -731879956899505222L;

    /**
     * 默认当前页数
     * 最小当前页数
     */
    private static final int DEFAULT_PAGE = 1;

    /**
     * 默认每页显示条数
     * 最小每页显示条数
     */
    private static final int DEFAULT_LIMIT = 5;
    /**
     * 最大每页显示条数
     */
    private static final int MAX_LIMIT = 100;

    private int currPage = 1;

    private int pageLimit = 5;

    private QueryUtil(){}

    /**
     * 有参构造方法
     *
     * @param queryMap 包含分页查询参数的 map 集合
     *     map 中需要包含的分页参数:
     *         currPage: 当前页数
     *         pageLimit: 每页显示条数
     *         sidx: 排序依据,如按照 "id" 排序,则 map.put("sidx","id")
     *         order: 排序规则,升序(asc)或者降序(desc),如升序排序,则 map.put("order","desc")
     * @throws Exception sql 参数不合法
     */
    public QueryUtil(Map<String, Object> queryMap) throws Exception {

        /**
         * 当前页码参数获取与校验
         */
        String currPageParam = String.valueOf(queryMap.get("currPage"));
        if (currPageParam != null && currPageParam.length() > 0) {
            int currPage = Integer.parseInt(currPageParam);
            this.currPage = currPage < DEFAULT_PAGE ? DEFAULT_PAGE : currPage;
        }
        /**
         * 每页显示条数参数获取与校验
         */
        String pageLimitParam = String.valueOf(queryMap.get("pageLimit"));
        if (pageLimitParam != null && pageLimitParam.length() > 0) {
            int pageLimit = Integer.parseInt(pageLimitParam);
            this.pageLimit = pageLimit < DEFAULT_PAGE ? DEFAULT_LIMIT : pageLimit;
            this.pageLimit = pageLimit > MAX_LIMIT ? MAX_LIMIT : pageLimit;
        }
        this.put("offset", (this.currPage - 1) * this.pageLimit);
        this.put("currPage", this.currPage);
        this.put("pageLimit", this.pageLimit);
        /**
         * 排序规则参数获取(防止 sql 注入)
         */
        this.put("sidx", SQLCheckUtil.getSafeSQL(String.valueOf(queryMap.get("sidx"))));
        this.put("order", SQLCheckUtil.getSafeSQL(String.valueOf(queryMap.get("order"))));
    }

}
../demo-common/src/main/java/com/ljq/demo/springboot/common/page/PageUtil.java
package com.ljq.demo.springboot.common.page;

import lombok.Data;

import java.io.Serializable;
import java.util.List;

/**
 * @Description: 分页工具(极简版)
 * @Author: junqiang.lu
 * @Date: 2018/11/28
 */
@Data
public class PageUtil<T> implements Serializable {

    private static final long serialVersionUID = -1989898212258749371L;

    /**
     * 默认总记录条数
     * 总记录条数最小值
     */
    private static final int DEFAULT_TOTAL_COUNT = 0;
    /**
     * 默认当前页数
     * 当前页数最小值
     */
    private static final int DEFAULT_CURR_PAGE = 1;
    /**
     * 默认每页记录数
     * 每页最小记录数
     */
    private static final int DEFAULT_PAGE_LIMIT = 5;

    /**
     * 总记录条数
     */
    private int totalCount;
    /**
     * 每页记录数
     */
    private int pageLimit;
    /**
     * 总页数
     */
    private int totalPage;
    /**
     * 当前页数
     */
    private int currPage;
    /**
     * 列表数据
     */
    private List<T> list;


    private PageUtil(){}

    /**
     * 有参构造方法
     *
     * @param list 列表数据
     * @param totalCount 总记录条数
     * @param pageLimit 每页记录数
     * @param currPage 当前页数
     */
    public PageUtil(List<T> list, int totalCount, int pageLimit, int currPage){
        if (totalCount < DEFAULT_TOTAL_COUNT) {
            totalCount = DEFAULT_TOTAL_COUNT;
        }
        this.totalCount = totalCount;

        if (pageLimit < DEFAULT_PAGE_LIMIT) {
            pageLimit = DEFAULT_PAGE_LIMIT;
        }
        this.pageLimit = pageLimit;

        if (currPage < DEFAULT_CURR_PAGE) {
            currPage = DEFAULT_CURR_PAGE;
        }
        this.currPage = currPage;

        int remainder = totalCount % pageLimit;
        if (remainder > 0) {
            this.totalPage = (totalCount / pageLimit + 1);
        } else {
            this.totalPage = (totalCount / pageLimit);
        }

        this.list = list;
    }

}

Map 转换工具类

../demo-common/src/main/java/com/ljq/demo/springboot/common/util/MapUtil.java
package com.ljq.demo.springboot.common.util;

import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.cglib.beans.BeanMap;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @Description: java bean 与 map 互相转换工具类
 * @Author: junqiang.lu
 * @Date: 2018/5/14
 */
public class MapUtil {

    private MapUtil(){}


    /**
     * 将 java 对象装换为map
     * @param bean
     * @return
     */
    public static <T> Map<String, Object> beanToMap(T bean) {
        Map<String, Object> map = new HashMap();
        if (bean != null) {
            BeanMap beanMap = BeanMap.create(bean);
            for (Object key : beanMap.keySet()) {
                map.put(key+"", beanMap.get(key));
            }
        }
        return map;
    }

    /**
     * 将map装换为javabean对象
     * @param map
     * @param bean
     * @return
     */
    public static <T> T mapToBean(Map<String, Object> map,T bean) {
        BeanMap beanMap = BeanMap.create(bean);
        beanMap.putAll(map);
        return bean;
    }

    /**
     * 将List<T>转换为List<Map<String, Object>>
     * @param objList
     * @return
     */
    public static <T> List<Map<String, Object>> objectsToMaps(List<T> objList) throws Exception{
        List<Map<String, Object>> list = new ArrayList();
        if (objList != null && objList.size() > 0) {
            Map<String, Object> map = null;
            T bean = null;
            for (int i = 0,size = objList.size(); i < size; i++) {
                bean = objList.get(i);
                map = beanToMap(bean);
                list.add(map);
            }
        }
        return list;
    }

    /**
     * 将List<Map<String,Object>>转换为List<T>
     * @param maps
     * @param clazz
     * @return
     * @throws InstantiationException
     * @throws IllegalAccessException
     */
    public static <T> List<T> mapsToObjects(List<Map<String, Object>> maps,Class<T> clazz)
            throws InstantiationException, IllegalAccessException {
        List<T> list = new ArrayList();
        if (maps != null && maps.size() > 0) {
            Map<String, Object> map = null;
            T bean = null;
            for (int i = 0,size = maps.size(); i < size; i++) {
                map = maps.get(i);
                bean = clazz.newInstance();
                mapToBean(map, bean);
                list.add(bean);
            }
        }
        return list;
    }

    /**
     * 将 object 对象转换为 Map<String, Object>
     *
     * @param object object 对象
     * @return map
     * @throws IOException
     */
    public static Map<String, Object> objectToMap(Object object) throws IOException {
        ObjectMapper mapper = new ObjectMapper();
        String params = mapper.writeValueAsString(object);
        Map<String, Object> resultMap = mapper.readValue(params, new TypeReference<Map<String,Object>>(){});
        return resultMap;
    }

    /**
     * 判断 map 对象是否为空
     * 当 map != null 且 map 中有值时,返回 true,否则返回 false
     *
     * @param map map 对象
     * @return map 对象为空的判断结果
     */
    public static boolean isEmpty(Map map){
        if(map == null || map.isEmpty()){
            return true;
        }
        return false;
    }

}

4.2 重点在这里(Service 层)

../demo-service/src/main/java/com/ljq/demo/springboot/service/Ehcache3Service.java
package com.ljq.demo.springboot.service;

import com.ljq.demo.springboot.common.api.ApiResult;
import com.ljq.demo.springboot.vo.ehcache3.*;

/**
 * @Description: Ehcache3 Demo 业务
 * @Author: junqiang.lu
 * @Date: 2019/3/16
 */
public interface Ehcache3Service {

    /**
     * 不使用缓存
     *
     * @param noCacheBean
     * @return
     * @throws Exception
     */
    ApiResult noCache(NoCacheBean noCacheBean) throws Exception;

    /**
     * 使用 @CacheResult 注解
     *
     * @param cacheResultBean
     * @return
     * @throws Exception
     */
    ApiResult cacheResult(CacheResultBean cacheResultBean) throws Exception;

    /**
     * 使用 @CachePut 注解
     *
     * @param cachePutBean
     * @param apiResult 用户储存缓存数据
     * @return
     * @throws Exception
     */
    void cachePut(CachePutBean cachePutBean, ApiResult apiResult) throws Exception;

    /**
     * 校验 @CachePut 注解
     *
     * @param cachePutBean
     * @return
     * @throws Exception
     */
    ApiResult cachePutValidate(CachePutBean cachePutBean) throws Exception;

    /**
     * 使用 @CacheRemove 注解
     *
     * @param cacheRemoveBean
     * @return
     * @throws Exception
     */
    ApiResult cacheRemove(CacheRemoveBean cacheRemoveBean) throws Exception;

    /**
     * 校验 @CacheRemove 注解
     *
     * @param cacheRemoveBean
     * @return
     * @throws Exception
     */
    ApiResult cacheRemoveValidate(CacheRemoveBean cacheRemoveBean) throws Exception;

    /**
     * 使用 @CacheRemoveAll 注解
     *
     * @param cacheRemoveAllBean
     * @return
     * @throws Exception
     */
    ApiResult cacheRemoveAll(CacheRemoveAllBean cacheRemoveAllBean) throws Exception;

    /**
     * 校验 @CacheRemoveAll 注解
     *
     * @param cacheRemoveAllBean
     * @return
     * @throws Exception
     */
    ApiResult cacheRemoveAllValidate(CacheRemoveAllBean cacheRemoveAllBean) throws Exception;

}

Service 实现类

../demo-service/src/main/java/com/ljq/demo/springboot/service/impl/Ehcache3ServiceImpl.java
package com.ljq.demo.springboot.service.impl;

import com.ljq.demo.springboot.common.api.ApiResult;
import com.ljq.demo.springboot.common.api.ResponseCode;
import com.ljq.demo.springboot.common.exception.ParamsCheckException;
import com.ljq.demo.springboot.common.page.PageUtil;
import com.ljq.demo.springboot.common.page.QueryUtil;
import com.ljq.demo.springboot.common.util.MapUtil;
import com.ljq.demo.springboot.dao.user.UserDao;
import com.ljq.demo.springboot.entity.UserDO;
import com.ljq.demo.springboot.service.Ehcache3Service;
import com.ljq.demo.springboot.vo.ehcache3.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.cache.annotation.*;
import java.util.List;
import java.util.Map;

/**
 * @Description: Ehcache3 Demo 业务具体实现类
 * @Author: junqiang.lu
 * @Date: 2019/3/16
 */
@Service("ehcache3Service")
@Transactional(rollbackFor = Exception.class)
@CacheDefaults(cacheName = "userCache")
@Slf4j
public class Ehcache3ServiceImpl implements Ehcache3Service {

    @Autowired
    private UserDao userDao;


    /**
     * 不使用缓存
     *
     * @param noCacheBean
     * @return
     * @throws Exception
     */
    @Override
    public ApiResult noCache(NoCacheBean noCacheBean) throws Exception {
        /**
         * 获取请求参数
         */
        UserDO userParams = new UserDO();
        BeanUtils.copyProperties(noCacheBean, userParams);

        UserDO userDB = userDao.queryObject(userParams);
        if (userDB == null || userDB.getId() == 0) {
            return ApiResult.failure(ResponseCode.ACCOUNT_NOT_EXIST.getMsg());
        }

        return ApiResult.success(userDB);
    }

    /**
     * 使用 @CacheResult 注解
     *
     * @param cacheResultBean
     * @return
     * @throws Exception
     */
    @CacheResult
    @Override
    public ApiResult cacheResult(CacheResultBean cacheResultBean) throws Exception {
        /**
         * 获取参数
         */
        Map<String, Object> map = MapUtil.beanToMap(cacheResultBean);
        QueryUtil queryUtil = new QueryUtil(map);
        // 列表查询
        List<UserDO> userDBList = userDao.queryList(queryUtil);
        if (userDBList == null || userDBList.isEmpty()) {
            return ApiResult.success(new PageUtil(null, 0, queryUtil.getPageLimit(), queryUtil.getCurrPage()));
        }

        int total = userDao.queryCount(queryUtil);
        // 分页处理
        PageUtil pageUtil = new PageUtil(userDBList, total, queryUtil.getPageLimit(), queryUtil.getCurrPage());

        return ApiResult.success(pageUtil);
    }

    /**
     * 使用 @CachePut 以及 @CacheValue 注解
     *
     * @param cachePutBean
     * @param apiResult 用户储存缓存数据
     * @return
     * @throws Exception
     */
    @CachePut(cacheName = "userCache")
    @Override
    public void cachePut(@CacheKey CachePutBean cachePutBean, @CacheValue ApiResult apiResult) throws Exception {
        if (cachePutBean != null && apiResult != null) {
            return;
        }
        throw new ParamsCheckException(ResponseCode.PARAM_ERROR.getMsg());
    }

    /**
     * 校验 @CachePut 注解
     *
     * @param cachePutBean
     * @return
     * @throws Exception
     */
    @CacheResult
    @Override
    public ApiResult cachePutValidate(CachePutBean cachePutBean) throws Exception {
        /**
         * 获取请求参数
         */
        UserDO userParams = new UserDO();
        BeanUtils.copyProperties(cachePutBean, userParams);

        UserDO userDB = userDao.queryObject(userParams);
        if (userDB == null || userDB.getId() == 0) {
            return ApiResult.failure(ResponseCode.ACCOUNT_NOT_EXIST.getMsg());
        }

        return ApiResult.success(userDB);
    }

    /**
     * 使用 @CacheRemove 注解
     *
     * @param cacheRemoveBean
     * @return
     * @throws Exception
     */
    @CacheRemove(cacheName = "userCache")
    @Override
    public ApiResult cacheRemove(CacheRemoveBean cacheRemoveBean) throws Exception {
        /**
         * 获取请求参数
         */
        UserDO userParams = new UserDO();
        BeanUtils.copyProperties(cacheRemoveBean, userParams);

        UserDO userDB = userDao.queryObject(userParams);
        if (userDB == null || userDB.getId() == 0) {
            return ApiResult.failure(ResponseCode.ACCOUNT_NOT_EXIST.getMsg());
        }

        return ApiResult.success(userDB);
    }

    /**
     * 校验 @CacheRemove 注解
     *
     * @param cacheRemoveBean
     * @return
     * @throws Exception
     */
    @CacheResult
    @Override
    public ApiResult cacheRemoveValidate(CacheRemoveBean cacheRemoveBean) throws Exception {
        /**
         * 获取请求参数
         */
        UserDO userParams = new UserDO();
        BeanUtils.copyProperties(cacheRemoveBean, userParams);

        UserDO userDB = userDao.queryObject(userParams);
        if (userDB == null || userDB.getId() == 0) {
            return ApiResult.failure(ResponseCode.ACCOUNT_NOT_EXIST.getMsg());
        }

        return ApiResult.success(userDB);
    }

    /**
     * 使用 @CacheRemoveAll 注解
     *
     * @param cacheRemoveAllBean
     * @return
     * @throws Exception
     */
    @CacheRemoveAll(cacheName = "userCache")
    @Override
    public ApiResult cacheRemoveAll(CacheRemoveAllBean cacheRemoveAllBean) throws Exception {
        /**
         * 获取参数
         */
        Map<String, Object> map = MapUtil.beanToMap(cacheRemoveAllBean);
        QueryUtil queryUtil = new QueryUtil(map);
        // 列表查询
        List<UserDO> userDBList = userDao.queryList(queryUtil);
        if (userDBList == null || userDBList.isEmpty()) {
            return ApiResult.success(new PageUtil(null, 0, queryUtil.getPageLimit(), queryUtil.getCurrPage()));
        }

        int total = userDao.queryCount(queryUtil);
        // 分页处理
        PageUtil pageUtil = new PageUtil(userDBList, total, queryUtil.getPageLimit(), queryUtil.getCurrPage());

        return ApiResult.success(pageUtil);
    }

    /**
     * 校验 @CacheRemoveAll 注解
     *
     * @param cacheRemoveAllBean
     * @return
     * @throws Exception
     */
    @CacheResult
    @Override
    public ApiResult cacheRemoveAllValidate(CacheRemoveAllBean cacheRemoveAllBean) throws Exception {
        /**
         * 获取参数
         */
        Map<String, Object> map = MapUtil.beanToMap(cacheRemoveAllBean);
        QueryUtil queryUtil = new QueryUtil(map);
        // 列表查询
        List<UserDO> userDBList = userDao.queryList(queryUtil);
        if (userDBList == null || userDBList.isEmpty()) {
            return ApiResult.success(new PageUtil(null, 0, queryUtil.getPageLimit(), queryUtil.getCurrPage()));
        }

        int total = userDao.queryCount(queryUtil);
        // 分页处理
        PageUtil pageUtil = new PageUtil(userDBList, total, queryUtil.getPageLimit(), queryUtil.getCurrPage());

        return ApiResult.success(pageUtil);
    }

}

4.3 数据持久层 mapper 文件

../demo-dao/src/main/resources/mapper/usermapper.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.ljq.demo.springboot.dao.user.UserDao">

    <!-- 用户查询结果 userResultMap-->
    <resultMap id="userMap" type="com.ljq.demo.springboot.entity.UserDO">
        <result property="id" column="id"/>
        <result property="userName" column="user_name"/>
        <result property="userPasscode" column="user_passcode"/>
        <result property="userEmail" column="user_email"/>
        <result property="userInsertTime" column="user_insert_time"/>
        <result property="userUpdateTime" column="user_update_time"/>
        <result property="userStatus" column="user_status"/>
        <result property="userVersion" column="user_version"/>
        <result property="userDel" column="user_del"/>
    </resultMap>

    <!-- 用户表基础字段 -->
    <sql id="user_base_field">
        `id`,
        `user_name`,
        `user_passcode`,
        `user_email`,
        `user_insert_time`,
        `user_update_time`,
        `user_status`,
        `user_version`,
        `user_del`
	</sql>

    <!-- 查询用户列表 -->
    <select id="queryList" parameterType="java.util.Map" resultMap="userMap">
        select u.id, u.user_name, u.user_passcode, u.user_email, u.user_insert_time, u.user_update_time, u.user_status,
            u.user_version, u.user_del
        from `user` u
        where u.user_del = 0
        <choose>
            <when test="sidx != null and sidx.trim() != ''">
                order by ${sidx} ${order}
            </when>
            <otherwise>
                order by id desc
            </otherwise>
        </choose>
        <if test="offset != null and pageLimit != null">
            limit #{offset}, #{pageLimit}
        </if>
    </select>

    <!-- 统计用户列表查询条数 -->
    <select id="queryCount" parameterType="java.util.Map" resultType="int" >
        select count(*) counts
        from `user`
        where `user_del` = 0
        <choose>
            <when test="sidx != null and sidx.trim() != ''">
                order by ${sidx} ${order}
            </when>
            <otherwise>
                order by id desc
            </otherwise>
        </choose>
    </select>

    <!-- 帐号注册校验 S -->
    <select id="signUpCheck" parameterType="com.ljq.demo.springboot.entity.UserDO" resultType="int">
        select count(*) counts
        from `user`
        where `user_del` = 0
        <if test="userName != null and '' != userName">
            and `user_name` = #{userName}
        </if>
    </select>
    <!-- 帐号注册校验 E -->

    <!-- 查询用户详情 S -->
    <select id="queryObject" parameterType="com.ljq.demo.springboot.entity.UserDO" resultMap="userMap">
        select
            <include refid="user_base_field" />
        from `user` u
        where `user_del` = 0
        <if test="id != null and id &gt; 0">
            and `id` = #{id}
        </if>
    </select>
    <!-- 查询用户详情 E -->

</mapper>

4.4 Controller 层

../demo-web/src/main/java/com/ljq/demo/springboot/web/controller/Ehcache3Controller.java
package com.ljq.demo.springboot.web.controller;

import com.ljq.demo.springboot.common.api.ApiResult;
import com.ljq.demo.springboot.common.api.ResponseCode;
import com.ljq.demo.springboot.common.exception.ParamsCheckException;
import com.ljq.demo.springboot.service.Ehcache3Service;
import com.ljq.demo.springboot.vo.ehcache3.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

/**
 * @Description: Ehcache 3 示例控制中心
 * @Author: junqiang.lu
 * @Date: 2019/3/21
 */
@RestController
@RequestMapping(value = "api/ehcache3")
@Slf4j
public class Ehcache3Controller {

    @Autowired
    private Ehcache3Service ehcache3Service;

    /**
     * 不使用缓存
     *
     * @param noCacheBean
     * @return
     */
    @RequestMapping(value = "noCache", method = RequestMethod.POST)
    public ApiResult noCache(@RequestBody NoCacheBean noCacheBean) {

        ApiResult apiResult = null;
        try {
            apiResult = ehcache3Service.noCache(noCacheBean);
        } catch (Exception e) {
            if (ParamsCheckException.class.isAssignableFrom(e.getClass())){
                log.error("参数错误");
                return apiResult.failure(ResponseCode.PARAM_ERROR.getCode(), e.getMessage());
            }
            log.error("未知异常",e);
            return apiResult.failure(ResponseCode.UNKNOWN_ERROR.getMsg());
        }

        return apiResult;
    }

    /**
     * 使用 @CacheResult 注解
     *
     * @param cacheResultBean
     * @return
     */
    @RequestMapping(value = "cacheResult", method = RequestMethod.POST)
    public ApiResult cacheResult(@RequestBody CacheResultBean cacheResultBean) {

        ApiResult apiResult = null;
        try {
            apiResult = ehcache3Service.cacheResult(cacheResultBean);
        } catch (Exception e) {
            if (ParamsCheckException.class.isAssignableFrom(e.getClass())){
                log.error("参数错误");
                return apiResult.failure(ResponseCode.PARAM_ERROR.getCode(), e.getMessage());
            }
            log.error("未知异常",e);
            return apiResult.failure(ResponseCode.UNKNOWN_ERROR.getMsg());
        }

        return apiResult;
    }

    /**
     * 使用 @CachePut 注解
     *
     * @param cacheResultBean
     * @return
     */
    @RequestMapping(value = "cachePut", method = RequestMethod.POST)
    public ApiResult cachePut(@RequestBody CachePutBean cacheResultBean) {

        ApiResult apiResult = null;
        try {
            ehcache3Service.cachePut(cacheResultBean, apiResult.success());
        } catch (Exception e) {
            if (ParamsCheckException.class.isAssignableFrom(e.getClass())){
                log.error("参数错误");
                return apiResult.failure(ResponseCode.PARAM_ERROR.getCode(), e.getMessage());
            }
            log.error("未知异常",e);
            return apiResult.failure(ResponseCode.UNKNOWN_ERROR.getMsg());
        }

        return apiResult.success();
    }

    /**
     * 校验 @CachePut 注解
     *
     * @param cachePutBean
     * @return
     */
    @RequestMapping(value = "cachePutValidate", method = RequestMethod.POST)
    public ApiResult cachePutValidate(@RequestBody CachePutBean cachePutBean) {

        ApiResult apiResult = null;
        try {
            apiResult = ehcache3Service.cachePutValidate(cachePutBean);
        } catch (Exception e) {
            if (ParamsCheckException.class.isAssignableFrom(e.getClass())){
                log.error("参数错误");
                return apiResult.failure(ResponseCode.PARAM_ERROR.getCode(), e.getMessage());
            }
            log.error("未知异常",e);
            return apiResult.failure(ResponseCode.UNKNOWN_ERROR.getMsg());
        }

        return apiResult;
    }

    /**
     * 使用 @CacheRemove 注解
     *
     * @param cacheRemoveBean
     * @return
     */
    @RequestMapping(value = "cacheRemove", method = RequestMethod.POST)
    public ApiResult cacheRemove(@RequestBody CacheRemoveBean cacheRemoveBean) {

        ApiResult apiResult = null;
        try {
            apiResult = ehcache3Service.cacheRemove(cacheRemoveBean);
        } catch (Exception e) {
            if (ParamsCheckException.class.isAssignableFrom(e.getClass())){
                log.error("参数错误");
                return apiResult.failure(ResponseCode.PARAM_ERROR.getCode(), e.getMessage());
            }
            log.error("未知异常",e);
            return apiResult.failure(ResponseCode.UNKNOWN_ERROR.getMsg());
        }

        return apiResult;
    }

    /**
     * 校验 @CacheRemove 注解
     *
     * @param cacheRemoveBean
     * @return
     */
    @RequestMapping(value = "cacheRemoveValidate", method = RequestMethod.POST)
    public ApiResult cacheRemoveValidate(@RequestBody CacheRemoveBean cacheRemoveBean) {

        ApiResult apiResult = null;
        try {
            apiResult = ehcache3Service.cacheRemoveValidate(cacheRemoveBean);
        } catch (Exception e) {
            if (ParamsCheckException.class.isAssignableFrom(e.getClass())){
                log.error("参数错误");
                return apiResult.failure(ResponseCode.PARAM_ERROR.getCode(), e.getMessage());
            }
            log.error("未知异常",e);
            return apiResult.failure(ResponseCode.UNKNOWN_ERROR.getMsg());
        }

        return apiResult;
    }

    /**
     * 使用 @CacheRemoveAll 注解
     *
     * @param cacheRemoveAllBean
     * @return
     */
    @RequestMapping(value = "cacheRemoveAll", method = RequestMethod.POST)
    public ApiResult cacheRemoveAll(@RequestBody CacheRemoveAllBean cacheRemoveAllBean) {

        ApiResult apiResult = null;
        try {
            apiResult = ehcache3Service.cacheRemoveAll(cacheRemoveAllBean);
        } catch (Exception e) {
            if (ParamsCheckException.class.isAssignableFrom(e.getClass())){
                log.error("参数错误");
                return apiResult.failure(ResponseCode.PARAM_ERROR.getCode(), e.getMessage());
            }
            log.error("未知异常",e);
            return apiResult.failure(ResponseCode.UNKNOWN_ERROR.getMsg());
        }

        return apiResult;
    }

    /**
     * 校验 @CacheRemoveAll 注解
     *
     * @param cacheRemoveAllBean
     * @return
     */
    @RequestMapping(value = "cacheRemoveAllValidate", method = RequestMethod.POST)
    public ApiResult cacheRemoveAllValidate(@RequestBody CacheRemoveAllBean cacheRemoveAllBean) {

        ApiResult apiResult = null;
        try {
            apiResult = ehcache3Service.cacheRemoveAllValidate(cacheRemoveAllBean);
        } catch (Exception e) {
            if (ParamsCheckException.class.isAssignableFrom(e.getClass())){
                log.error("参数错误");
                return apiResult.failure(ResponseCode.PARAM_ERROR.getCode(), e.getMessage());
            }
            log.error("未知异常",e);
            return apiResult.failure(ResponseCode.UNKNOWN_ERROR.getMsg());
        }

        return apiResult;
    }

}

5 Ehcache 3 使用测试

测试工具: Postman

1 不使用缓存

请求参数:

POST /api/ehcache3/noCache
Content-Type: application/json
cache-control: no-cache
Postman-Token: a3d969a0-f7b0-43c3-b388-5c821804b6af
User-Agent: PostmanRuntime/7.6.1
Accept: */*
Host: 127.0.0.1:8088
accept-encoding: gzip, deflate
content-length: 13
{ "id" : 1 }

后台日志:

2019-03-24 14:42:05:837 [http-nio-8088-exec-2] INFO  com.ljq.demo.springboot.web.acpect.LogAspect(LogAspect.java 66) -[AOP-LOG-START]
	requestMark: 306c25b8-273f-464f-bdd8-834ec90026e1
	requestIP: 127.0.0.1
	contentType:application/json
	requestUrl: http://127.0.0.1:8088/api/ehcache3/noCache
	requestMethod: POST
	requestParams: {"language":null,"id":1}
	targetClassAndMethod: com.ljq.demo.springboot.web.controller.Ehcache3Controller#noCache
2019-03-24 14:42:05:855 [http-nio-8088-exec-2] DEBUG c.ljq.demo.springboot.dao.user.UserDao.queryObject(BaseJdbcLogger.java 159) -==>  Preparing: select `id`, `user_name`, `user_passcode`, `user_email`, `user_insert_time`, `user_update_time`, `user_status`, `user_version`, `user_del` from `user` u where `user_del` = 0 and `id` = ? 
2019-03-24 14:42:05:855 [http-nio-8088-exec-2] DEBUG c.ljq.demo.springboot.dao.user.UserDao.queryObject(BaseJdbcLogger.java 159) -==> Parameters: 1(Long)
2019-03-24 14:42:05:857 [http-nio-8088-exec-2] DEBUG c.ljq.demo.springboot.dao.user.UserDao.queryObject(BaseJdbcLogger.java 159) -<==      Total: 1
2019-03-24 14:42:05:860 [http-nio-8088-exec-2] INFO  com.ljq.demo.springboot.web.acpect.LogAspect(LogAspect.java 74) -[AOP-LOG-END]
	ApiResult(code=1000, msg=成功, data=UserDO(id=1, userName=tom, userPasscode=ed0de7252acf2980e677bacab01bde25, userEmail=tom@example.com, userInsertTime=2019-03-13 17:25:44, userUpdateTime=2019-03-13 17:25:44, userStatus=1, userVersion=1, userDel=0))

测试结果: 不使用缓存,每次请求都需要查询数据库

5.2 使用 @CacheResult 注解

@CacheResult 注解说明: 该注解使用的对象是方法、参数。首次请求时会将该注解的方法/参数 结果保存至缓存,再缓存失效之前,如果缓存的 Key 不变(使用@CacheKey 注解的参数,即请求参数),再次调用该方法,将会直接返回缓存中的数据,而不在执行该方法体,从而可以起到缓解数据库压力的作用

测试方法: 使用相同的请求参数在短时间内(缓存失效之前)连续请求,两次请求的返回结果是相同的,对比两次请求的日志

请求参数:

POST /api/ehcache3/cacheResult
Content-Type: application/json
cache-control: no-cache
Postman-Token: dd97c7f1-277a-47e1-8032-6bbe2c6fa8fe
User-Agent: PostmanRuntime/7.6.1
Accept: */*
Host: 127.0.0.1:8088
accept-encoding: gzip, deflate
content-length: 73
{ "currPage" : 1, "pageLimit" : 5, "sidx" : "id", "order" : "desc" }

第一次请求日志:

2019-03-24 14:50:29:919 [http-nio-8088-exec-5] INFO  com.ljq.demo.springboot.web.acpect.LogAspect(LogAspect.java 66) -[AOP-LOG-START]
	requestMark: 2ec4e7e6-de6d-40b0-874b-adfea89bade1
	requestIP: 127.0.0.1
	contentType:application/json
	requestUrl: http://127.0.0.1:8088/api/ehcache3/cacheResult
	requestMethod: POST
	requestParams: {"language":null,"currPage":1,"pageLimit":5,"sidx":"id","order":"desc"}
	targetClassAndMethod: com.ljq.demo.springboot.web.controller.Ehcache3Controller#cacheResult
2019-03-24 14:50:29:974 [http-nio-8088-exec-5] DEBUG com.ljq.demo.springboot.dao.user.UserDao.queryList(BaseJdbcLogger.java 159) -==>  Preparing: select u.id, u.user_name, u.user_passcode, u.user_email, u.user_insert_time, u.user_update_time, u.user_status, u.user_version, u.user_del from `user` u where u.user_del = 0 order by id desc limit ?, ? 
2019-03-24 14:50:29:976 [http-nio-8088-exec-5] DEBUG com.ljq.demo.springboot.dao.user.UserDao.queryList(BaseJdbcLogger.java 159) -==> Parameters: 0(Integer), 5(Integer)
2019-03-24 14:50:29:983 [http-nio-8088-exec-5] DEBUG com.ljq.demo.springboot.dao.user.UserDao.queryList(BaseJdbcLogger.java 159) -<==      Total: 5
2019-03-24 14:50:29:984 [http-nio-8088-exec-5] DEBUG c.ljq.demo.springboot.dao.user.UserDao.queryCount(BaseJdbcLogger.java 159) -==>  Preparing: select count(*) counts from `user` where `user_del` = 0 order by id desc 
2019-03-24 14:50:29:984 [http-nio-8088-exec-5] DEBUG c.ljq.demo.springboot.dao.user.UserDao.queryCount(BaseJdbcLogger.java 159) -==> Parameters: 
2019-03-24 14:50:29:989 [http-nio-8088-exec-5] DEBUG c.ljq.demo.springboot.dao.user.UserDao.queryCount(BaseJdbcLogger.java 159) -<==      Total: 1
2019-03-24 14:50:30:005 [Ehcache [_default_]-0] INFO  c.l.demo.springboot.common.cache.Ehcache3EventLog(Ehcache3EventLog.java 17) -Event: CREATED,  Key: CacheResultBean(currPage=1, pageLimit=5, sidx=id, order=desc), old value: null, new value: 
2019-03-24 14:50:30:005 [http-nio-8088-exec-5] INFO  com.ljq.demo.springboot.web.acpect.LogAspect(LogAspect.java 74) -[AOP-LOG-END]
	ApiResult(code=1000, msg=成功, data=PageUtil(totalCount=5, pageLimit=5, totalPage=1, currPage=1, list=[UserDO(id=5, userName=liming, userPasscode=ed0de7252acf2980e677bacab01bde25, userEmail=liming@example.com, userInsertTime=2019-03-13 17:25:44, userUpdateTime=2019-03-13 17:25:44, userStatus=1, userVersion=1, userDel=0), UserDO(id=4, userName=lily, userPasscode=ed0de7252acf2980e677bacab01bde25, userEmail=lily@example.com, userInsertTime=2019-03-13 17:25:44, userUpdateTime=2019-03-13 17:25:44, userStatus=1, userVersion=1, userDel=0), UserDO(id=3, userName=jack, userPasscode=ed0de7252acf2980e677bacab01bde25, userEmail=jack@example.com, userInsertTime=2019-03-13 17:25:44, userUpdateTime=2019-03-13 17:25:44, userStatus=1, userVersion=1, userDel=0), UserDO(id=2, userName=bob, userPasscode=ed0de7252acf2980e677bacab01bde25, userEmail=bob@example.com, userInsertTime=2019-03-13 17:25:44, userUpdateTime=2019-03-13 17:25:44, userStatus=1, userVersion=1, userDel=0), UserDO(id=1, userName=tom, userPasscode=ed0de7252acf2980e677bacab01bde25, userEmail=tom@example.com, userInsertTime=2019-03-13 17:25:44, userUpdateTime=2019-03-13 17:25:44, userStatus=1, userVersion=1, userDel=0)]))

第二次请求日志:

2019-03-24 14:50:31:169 [http-nio-8088-exec-6] INFO  com.ljq.demo.springboot.web.acpect.LogAspect(LogAspect.java 66) -[AOP-LOG-START]
	requestMark: 85b05cc6-7f8c-42a5-8199-992c2f69c250
	requestIP: 127.0.0.1
	contentType:application/json
	requestUrl: http://127.0.0.1:8088/api/ehcache3/cacheResult
	requestMethod: POST
	requestParams: {"language":null,"currPage":1,"pageLimit":5,"sidx":"id","order":"desc"}
	targetClassAndMethod: com.ljq.demo.springboot.web.controller.Ehcache3Controller#cacheResult
2019-03-24 14:50:31:182 [http-nio-8088-exec-6] INFO  com.ljq.demo.springboot.web.acpect.LogAspect(LogAspect.java 74) -[AOP-LOG-END]
	ApiResult(code=1000, msg=成功, data=PageUtil(totalCount=5, pageLimit=5, totalPage=1, currPage=1, list=[UserDO(id=5, userName=liming, userPasscode=ed0de7252acf2980e677bacab01bde25, userEmail=liming@example.com, userInsertTime=2019-03-13 17:25:44, userUpdateTime=2019-03-13 17:25:44, userStatus=1, userVersion=1, userDel=0), UserDO(id=4, userName=lily, userPasscode=ed0de7252acf2980e677bacab01bde25, userEmail=lily@example.com, userInsertTime=2019-03-13 17:25:44, userUpdateTime=2019-03-13 17:25:44, userStatus=1, userVersion=1, userDel=0), UserDO(id=3, userName=jack, userPasscode=ed0de7252acf2980e677bacab01bde25, userEmail=jack@example.com, userInsertTime=2019-03-13 17:25:44, userUpdateTime=2019-03-13 17:25:44, userStatus=1, userVersion=1, userDel=0), UserDO(id=2, userName=bob, userPasscode=ed0de7252acf2980e677bacab01bde25, userEmail=bob@example.com, userInsertTime=2019-03-13 17:25:44, userUpdateTime=2019-03-13 17:25:44, userStatus=1, userVersion=1, userDel=0), UserDO(id=1, userName=tom, userPasscode=ed0de7252acf2980e677bacab01bde25, userEmail=tom@example.com, userInsertTime=2019-03-13 17:25:44, userUpdateTime=2019-03-13 17:25:44, userStatus=1, userVersion=1, userDel=0)]))
2019-03-24 14:51:16:088 [Eureka-PeerNodesUpdater] DEBUG com.netflix.discovery.endpoint.EndpointUtils(EndpointUtils.java 198) -The availability zone for the given region us-east-1 are [defaultZone]
2019-03-24 14:51:16:088 [Eureka-PeerNodesUpdater] WARN  com.netflix.eureka.cluster.PeerEurekaNodes(PeerEurekaNodes.java 156) -The replica size seems to be empty. Check the route 53 DNS Registry

测试结果: 使用 @CacheResult 注解之后,在首次请求时需要从数据库中查询,并将返回结果储存至缓存,在缓存失效之前,如果请求参数不变,则返回缓存中的数据;如果请求参数改变,也会重新到数据库查询

5.3 使用 @CachePut 注解

@CachePut 注解说明: 该注解使用的对象是方法,通常与 @CacheValue, @CacheKey 组合使用。@CachePut 的作用是创建或更新缓存,如果是先前没有该缓存,则会创建缓存;如果是已经存在该缓存,则更新这一缓存

测试方法:先使用 @CacheResult 注解的方法请求一次,此时会将查询结果保存至缓存;然后再使用 @CachePut 注解的方法请求一次,此时对比日志,观察是否有更新缓存;最后再来使用 @CacheResult 注解的方法请求一次

(测试方法二: 先使用 @CachePut 注解的方法请求一次,此时会创建一个缓存;然后使用 @CacheResult 注解的方法请求一次,对比两次请求的日志以得出结论)

第一次请求,请求使用 @CacheResult 注解的方法,请求参数:

POST /api/ehcache3/cacheResult
Content-Type: application/json
cache-control: no-cache
Postman-Token: b6408231-3840-4e64-ba0f-9681580e74e7
User-Agent: PostmanRuntime/7.6.1
Accept: */*
Host: 127.0.0.1:8088
accept-encoding: gzip, deflate
content-length: 73
{ "currPage" : 1, "pageLimit" : 5, "sidx" : "id", "order" : "desc" }

第一次请求日志:

2019-03-24 19:51:10:570 [http-nio-8088-exec-1] INFO  com.ljq.demo.springboot.web.acpect.LogAspect(LogAspect.java 66) -[AOP-LOG-START]
	requestMark: 5ee6f971-dee6-474f-b5a1-1c23711476a9
	requestIP: 127.0.0.1
	contentType:application/json
	requestUrl: http://127.0.0.1:8088/api/ehcache3/cachePutValidate
	requestMethod: POST
	requestParams: {"language":null,"id":1}
	targetClassAndMethod: com.ljq.demo.springboot.web.controller.Ehcache3Controller#cachePutValidate
2019-03-24 19:51:10:741 [http-nio-8088-exec-1] DEBUG c.ljq.demo.springboot.dao.user.UserDao.queryObject(BaseJdbcLogger.java 159) -==>  Preparing: select `id`, `user_name`, `user_passcode`, `user_email`, `user_insert_time`, `user_update_time`, `user_status`, `user_version`, `user_del` from `user` u where `user_del` = 0 and `id` = ? 
2019-03-24 19:51:10:759 [http-nio-8088-exec-1] DEBUG c.ljq.demo.springboot.dao.user.UserDao.queryObject(BaseJdbcLogger.java 159) -==> Parameters: 1(Long)
2019-03-24 19:51:10:783 [http-nio-8088-exec-1] DEBUG c.ljq.demo.springboot.dao.user.UserDao.queryObject(BaseJdbcLogger.java 159) -<==      Total: 1
2019-03-24 19:51:10:798 [Ehcache [_default_]-0] INFO  c.l.demo.springboot.common.cache.Ehcache3EventLog(Ehcache3EventLog.java 17) -Event: CREATED,  Key: CachePutBean(id=1), old value: null, new value: 
2019-03-24 19:51:10:798 [http-nio-8088-exec-1] INFO  com.ljq.demo.springboot.web.acpect.LogAspect(LogAspect.java 74) -[AOP-LOG-END]
	ApiResult(code=1000, msg=成功, data=UserDO(id=1, userName=tom, userPasscode=ed0de7252acf2980e677bacab01bde25, userEmail=tom@example.com, userInsertTime=2019-03-13 17:25:44, userUpdateTime=2019-03-13 17:25:44, userStatus=1, userVersion=1, userDel=0))

第二次请求,请求使用 @CachePut 注解的方法,请求参数:

POST /api/ehcache3/cachePut
Content-Type: application/json
cache-control: no-cache
Postman-Token: 512c182c-356e-462c-91a8-989b6b5a20c0
User-Agent: PostmanRuntime/7.6.1
Accept: */*
Host: 127.0.0.1:8088
accept-encoding: gzip, deflate
content-length: 13
{ "id" : 1 }

第二次请求日志:

2019-03-24 19:51:15:295 [http-nio-8088-exec-2] INFO  com.ljq.demo.springboot.web.acpect.LogAspect(LogAspect.java 66) -[AOP-LOG-START]
	requestMark: 4d83a80f-d6ce-4cf6-848e-04f39ed50b8c
	requestIP: 127.0.0.1
	contentType:application/json
	requestUrl: http://127.0.0.1:8088/api/ehcache3/cachePut
	requestMethod: POST
	requestParams: {"language":null,"id":1}
	targetClassAndMethod: com.ljq.demo.springboot.web.controller.Ehcache3Controller#cachePut
2019-03-24 19:51:15:318 [Ehcache [_default_]-0] INFO  c.l.demo.springboot.common.cache.Ehcache3EventLog(Ehcache3EventLog.java 17) -Event: UPDATED,  Key: CachePutBean(id=1), old value: ApiResult(code=1000, msg=成功, data=UserDO(id=1, userName=tom, userPasscode=ed0de7252acf2980e677bacab01bde25, userEmail=tom@example.com, userInsertTime=2019-03-13 17:25:44, userUpdateTime=2019-03-13 17:25:44, userStatus=1, userVersion=1, userDel=0)), new value: 
2019-03-24 19:51:15:318 [http-nio-8088-exec-2] INFO  com.ljq.demo.springboot.web.acpect.LogAspect(LogAspect.java 74) -[AOP-LOG-END]
	ApiResult(code=1000, msg=成功, data=null)

第三次请求,请求使用 @CacheResult 注解的方法,请求参数与第一次相同

第三次请求日志:

2019-03-24 19:51:20:072 [http-nio-8088-exec-6] INFO  com.ljq.demo.springboot.web.acpect.LogAspect(LogAspect.java 66) -[AOP-LOG-START]
	requestMark: 4fb1e21d-d9a7-4981-b508-7d214cbfae05
	requestIP: 127.0.0.1
	contentType:application/json
	requestUrl: http://127.0.0.1:8088/api/ehcache3/cachePutValidate
	requestMethod: POST
	requestParams: {"language":null,"id":1}
	targetClassAndMethod: com.ljq.demo.springboot.web.controller.Ehcache3Controller#cachePutValidate
2019-03-24 19:51:20:076 [http-nio-8088-exec-6] INFO  com.ljq.demo.springboot.web.acpect.LogAspect(LogAspect.java 74) -[AOP-LOG-END]
	ApiResult(code=1000, msg=成功, data=null)

测试结果: 使用 @CachePut 注解,如果缓存已经存在会更新缓存

(如果缓存不存在,则会创建缓存)

5.4 使用 @CacheRemove 注解

@CAcheRemove 注解说明: 该注解的使用对象为方法。使用该注解可删除指定的缓存库中指定的缓存

测试方法: 第一步请求使用 @CacheResult 注解的方法以创建一条缓存;第二步,请求使用 @CacheRemove 注解的方法删除该缓存;第三步再次请求使用 @CacheResult 注解的方法校验缓存是否被删除。三次请求必须在缓存的有效时间内完成

第一次请求,请求使用 @CacheResult 注解的方法,请求参数:

POST /api/ehcache3/cacheRemoveValidate
Content-Type: application/json
cache-control: no-cache
Postman-Token: b062ace8-4795-4c54-ac8b-206cee4b873f
User-Agent: PostmanRuntime/7.6.1
Accept: */*
Host: 127.0.0.1:8088
accept-encoding: gzip, deflate
content-length: 13
{ "id" : 1 }

第一次请求后台日志:

2019-03-24 20:08:31:434 [http-nio-8088-exec-8] INFO  com.ljq.demo.springboot.web.acpect.LogAspect(LogAspect.java 66) -[AOP-LOG-START]
	requestMark: 44dc87f7-ef1d-47b2-94ef-45646370fc7c
	requestIP: 127.0.0.1
	contentType:application/json
	requestUrl: http://127.0.0.1:8088/api/ehcache3/cacheRemoveValidate
	requestMethod: POST
	requestParams: {"language":null,"id":1}
	targetClassAndMethod: com.ljq.demo.springboot.web.controller.Ehcache3Controller#cacheRemoveValidate
2019-03-24 20:08:31:466 [http-nio-8088-exec-8] DEBUG c.ljq.demo.springboot.dao.user.UserDao.queryObject(BaseJdbcLogger.java 159) -==>  Preparing: select `id`, `user_name`, `user_passcode`, `user_email`, `user_insert_time`, `user_update_time`, `user_status`, `user_version`, `user_del` from `user` u where `user_del` = 0 and `id` = ? 
2019-03-24 20:08:31:467 [http-nio-8088-exec-8] DEBUG c.ljq.demo.springboot.dao.user.UserDao.queryObject(BaseJdbcLogger.java 159) -==> Parameters: 1(Long)
2019-03-24 20:08:31:468 [http-nio-8088-exec-8] DEBUG c.ljq.demo.springboot.dao.user.UserDao.queryObject(BaseJdbcLogger.java 159) -<==      Total: 1
2019-03-24 20:08:31:471 [http-nio-8088-exec-8] INFO  com.ljq.demo.springboot.web.acpect.LogAspect(LogAspect.java 74) -[AOP-LOG-END]
	ApiResult(code=1000, msg=成功, data=UserDO(id=1, userName=tom, userPasscode=ed0de7252acf2980e677bacab01bde25, userEmail=tom@example.com, userInsertTime=2019-03-13 17:25:44, userUpdateTime=2019-03-13 17:25:44, userStatus=1, userVersion=1, userDel=0))
2019-03-24 20:08:31:471 [Ehcache [_default_]-2] INFO  c.l.demo.springboot.common.cache.Ehcache3EventLog(Ehcache3EventLog.java 17) -Event: CREATED,  Key: CacheRemoveBean(id=1), old value: null, new value: 

第二次请求,请求使用 @CacheRemove 注解的方法,请求参数:

POST /api/ehcache3/cacheRemove
Content-Type: application/json
cache-control: no-cache
Postman-Token: 5e258d67-c718-42bb-9bb7-cdacdbf79ffb
User-Agent: PostmanRuntime/7.6.1
Accept: */*
Host: 127.0.0.1:8088
accept-encoding: gzip, deflate
content-length: 13
{ "id" : 1 }

第二次请求后台日志:

2019-03-24 20:08:41:922 [http-nio-8088-exec-3] INFO  com.ljq.demo.springboot.web.acpect.LogAspect(LogAspect.java 66) -[AOP-LOG-START]
	requestMark: 9795f1c5-f5c6-4991-b644-1a39e56f3aa4
	requestIP: 127.0.0.1
	contentType:application/json
	requestUrl: http://127.0.0.1:8088/api/ehcache3/cacheRemove
	requestMethod: POST
	requestParams: {"language":null,"id":1}
	targetClassAndMethod: com.ljq.demo.springboot.web.controller.Ehcache3Controller#cacheRemove
2019-03-24 20:08:41:937 [http-nio-8088-exec-3] DEBUG c.ljq.demo.springboot.dao.user.UserDao.queryObject(BaseJdbcLogger.java 159) -==>  Preparing: select `id`, `user_name`, `user_passcode`, `user_email`, `user_insert_time`, `user_update_time`, `user_status`, `user_version`, `user_del` from `user` u where `user_del` = 0 and `id` = ? 
2019-03-24 20:08:41:938 [http-nio-8088-exec-3] DEBUG c.ljq.demo.springboot.dao.user.UserDao.queryObject(BaseJdbcLogger.java 159) -==> Parameters: 1(Long)
2019-03-24 20:08:41:940 [http-nio-8088-exec-3] DEBUG c.ljq.demo.springboot.dao.user.UserDao.queryObject(BaseJdbcLogger.java 159) -<==      Total: 1
2019-03-24 20:08:41:945 [Ehcache [_default_]-2] INFO  c.l.demo.springboot.common.cache.Ehcache3EventLog(Ehcache3EventLog.java 17) -Event: REMOVED,  Key: CacheRemoveBean(id=1), old value: ApiResult(code=1000, msg=成功, data=UserDO(id=1, userName=tom, userPasscode=ed0de7252acf2980e677bacab01bde25, userEmail=tom@example.com, userInsertTime=2019-03-13 17:25:44, userUpdateTime=2019-03-13 17:25:44, userStatus=1, userVersion=1, userDel=0)), new value: 
2019-03-24 20:08:41:945 [http-nio-8088-exec-3] INFO  com.ljq.demo.springboot.web.acpect.LogAspect(LogAspect.java 74) -[AOP-LOG-END]
	ApiResult(code=1000, msg=成功, data=UserDO(id=1, userName=tom, userPasscode=ed0de7252acf2980e677bacab01bde25, userEmail=tom@example.com, userInsertTime=2019-03-13 17:25:44, userUpdateTime=2019-03-13 17:25:44, userStatus=1, userVersion=1, userDel=0))

第三次请求,请求使用 @CacheResult 注解的方法,请求参数:

POST /api/ehcache3/cacheRemoveValidate
Content-Type: application/json
cache-control: no-cache
Postman-Token: 2e28f160-d920-4451-9c97-b59bab402039
User-Agent: PostmanRuntime/7.6.1
Accept: */*
Host: 127.0.0.1:8088
accept-encoding: gzip, deflate
content-length: 13
{ "id" : 1 }

第三次请求后台日志:

2019-03-24 20:08:53:101 [http-nio-8088-exec-9] INFO  com.ljq.demo.springboot.web.acpect.LogAspect(LogAspect.java 66) -[AOP-LOG-START]
	requestMark: c1b1cae5-d28f-4917-88b1-bc48e355f686
	requestIP: 127.0.0.1
	contentType:application/json
	requestUrl: http://127.0.0.1:8088/api/ehcache3/cacheRemoveValidate
	requestMethod: POST
	requestParams: {"language":null,"id":1}
	targetClassAndMethod: com.ljq.demo.springboot.web.controller.Ehcache3Controller#cacheRemoveValidate
2019-03-24 20:08:53:113 [http-nio-8088-exec-9] DEBUG c.ljq.demo.springboot.dao.user.UserDao.queryObject(BaseJdbcLogger.java 159) -==>  Preparing: select `id`, `user_name`, `user_passcode`, `user_email`, `user_insert_time`, `user_update_time`, `user_status`, `user_version`, `user_del` from `user` u where `user_del` = 0 and `id` = ? 
2019-03-24 20:08:53:114 [http-nio-8088-exec-9] DEBUG c.ljq.demo.springboot.dao.user.UserDao.queryObject(BaseJdbcLogger.java 159) -==> Parameters: 1(Long)
2019-03-24 20:08:53:116 [http-nio-8088-exec-9] DEBUG c.ljq.demo.springboot.dao.user.UserDao.queryObject(BaseJdbcLogger.java 159) -<==      Total: 1
2019-03-24 20:08:53:120 [Ehcache [_default_]-2] INFO  c.l.demo.springboot.common.cache.Ehcache3EventLog(Ehcache3EventLog.java 17) -Event: CREATED,  Key: CacheRemoveBean(id=1), old value: null, new value: 
2019-03-24 20:08:53:120 [http-nio-8088-exec-9] INFO  com.ljq.demo.springboot.web.acpect.LogAspect(LogAspect.java 74) -[AOP-LOG-END]
	ApiResult(code=1000, msg=成功, data=UserDO(id=1, userName=tom, userPasscode=ed0de7252acf2980e677bacab01bde25, userEmail=tom@example.com, userInsertTime=2019-03-13 17:25:44, userUpdateTime=2019-03-13 17:25:44, userStatus=1, userVersion=1, userDel=0))

测试结果: 使用 @CacheRemove 注解的方法会删除指定缓存库中指定的缓存

5.5使用 @CacheRemoveAll 注解

@CacheRemoveAll 注解说明: 该注解使用对象为方法。使用该注解可以删除指定缓存库中的所有缓存

测试方法: 第一步,请求多个使用 @CacheResult 注解的方法,创建多个缓存;第二步,请求使用 @CAcheRemoveAll 注解的方法,删除所有缓存;第三步,再次请求多个使用 @CacheResult 注解的方法,查看请求日志,确认缓存是否被清空。以上请求必须在缓存失效时间内全部请求完成

第一次请求,请求两个使用 @CacheResult 注解的方法,请求参数为:

请求 1 参数

POST /api/ehcache3/cacheResult
Content-Type: application/json
cache-control: no-cache
Postman-Token: 2f3b25e7-0879-4fa6-be37-5d76a4bfb00a
User-Agent: PostmanRuntime/7.6.1
Accept: */*
Host: 127.0.0.1:8088
accept-encoding: gzip, deflate
content-length: 73
{ "currPage" : 1, "pageLimit" : 5, "sidx" : "id", "order" : "desc" }

请求 2 参数:

POST /api/ehcache3/cacheRemoveAllValidate
Content-Type: application/json
cache-control: no-cache
Postman-Token: 4fbea407-0291-4c63-9def-842b631bc4b6
User-Agent: PostmanRuntime/7.6.1
Accept: */*
Host: 127.0.0.1:8088
accept-encoding: gzip, deflate
content-length: 73
{ "currPage" : 1, "pageLimit" : 5, "sidx" : "id", "order" : "desc" }

第一次请求日志:

2019-03-24 20:26:40:207 [http-nio-8088-exec-7] INFO  com.ljq.demo.springboot.web.acpect.LogAspect(LogAspect.java 66) -[AOP-LOG-START]
	requestMark: 14e2302c-e08d-4766-bc3a-a822cb260752
	requestIP: 127.0.0.1
	contentType:application/json
	requestUrl: http://127.0.0.1:8088/api/ehcache3/cacheResult
	requestMethod: POST
	requestParams: {"language":null,"currPage":1,"pageLimit":5,"sidx":"id","order":"desc"}
	targetClassAndMethod: com.ljq.demo.springboot.web.controller.Ehcache3Controller#cacheResult
2019-03-24 20:26:40:223 [http-nio-8088-exec-7] DEBUG com.ljq.demo.springboot.dao.user.UserDao.queryList(BaseJdbcLogger.java 159) -==>  Preparing: select u.id, u.user_name, u.user_passcode, u.user_email, u.user_insert_time, u.user_update_time, u.user_status, u.user_version, u.user_del from `user` u where u.user_del = 0 order by id desc limit ?, ? 
2019-03-24 20:26:40:225 [http-nio-8088-exec-7] DEBUG com.ljq.demo.springboot.dao.user.UserDao.queryList(BaseJdbcLogger.java 159) -==> Parameters: 0(Integer), 5(Integer)
2019-03-24 20:26:40:232 [http-nio-8088-exec-7] DEBUG com.ljq.demo.springboot.dao.user.UserDao.queryList(BaseJdbcLogger.java 159) -<==      Total: 5
2019-03-24 20:26:40:233 [http-nio-8088-exec-7] DEBUG c.ljq.demo.springboot.dao.user.UserDao.queryCount(BaseJdbcLogger.java 159) -==>  Preparing: select count(*) counts from `user` where `user_del` = 0 order by id desc 
2019-03-24 20:26:40:234 [http-nio-8088-exec-7] DEBUG c.ljq.demo.springboot.dao.user.UserDao.queryCount(BaseJdbcLogger.java 159) -==> Parameters: 
2019-03-24 20:26:40:235 [http-nio-8088-exec-7] DEBUG c.ljq.demo.springboot.dao.user.UserDao.queryCount(BaseJdbcLogger.java 159) -<==      Total: 1
2019-03-24 20:26:40:236 [Ehcache [_default_]-3] INFO  c.l.demo.springboot.common.cache.Ehcache3EventLog(Ehcache3EventLog.java 17) -Event: CREATED,  Key: CacheResultBean(currPage=1, pageLimit=5, sidx=id, order=desc), old value: null, new value: 
2019-03-24 20:26:40:236 [http-nio-8088-exec-7] INFO  com.ljq.demo.springboot.web.acpect.LogAspect(LogAspect.java 74) -[AOP-LOG-END]
	ApiResult(code=1000, msg=成功, data=PageUtil(totalCount=5, pageLimit=5, totalPage=1, currPage=1, list=[UserDO(id=5, userName=liming, userPasscode=ed0de7252acf2980e677bacab01bde25, userEmail=liming@example.com, userInsertTime=2019-03-13 17:25:44, userUpdateTime=2019-03-13 17:25:44, userStatus=1, userVersion=1, userDel=0), UserDO(id=4, userName=lily, userPasscode=ed0de7252acf2980e677bacab01bde25, userEmail=lily@example.com, userInsertTime=2019-03-13 17:25:44, userUpdateTime=2019-03-13 17:25:44, userStatus=1, userVersion=1, userDel=0), UserDO(id=3, userName=jack, userPasscode=ed0de7252acf2980e677bacab01bde25, userEmail=jack@example.com, userInsertTime=2019-03-13 17:25:44, userUpdateTime=2019-03-13 17:25:44, userStatus=1, userVersion=1, userDel=0), UserDO(id=2, userName=bob, userPasscode=ed0de7252acf2980e677bacab01bde25, userEmail=bob@example.com, userInsertTime=2019-03-13 17:25:44, userUpdateTime=2019-03-13 17:25:44, userStatus=1, userVersion=1, userDel=0), UserDO(id=1, userName=tom, userPasscode=ed0de7252acf2980e677bacab01bde25, userEmail=tom@example.com, userInsertTime=2019-03-13 17:25:44, userUpdateTime=2019-03-13 17:25:44, userStatus=1, userVersion=1, userDel=0)]))
2019-03-24 20:26:42:837 [http-nio-8088-exec-8] INFO  com.ljq.demo.springboot.web.acpect.LogAspect(LogAspect.java 66) -[AOP-LOG-START]
	requestMark: 46aa821e-9723-40ec-aad2-27a857a1bca0
	requestIP: 127.0.0.1
	contentType:application/json
	requestUrl: http://127.0.0.1:8088/api/ehcache3/cacheRemoveAllValidate
	requestMethod: POST
	requestParams: {"language":null,"currPage":1,"pageLimit":5,"sidx":"id","order":"desc"}
	targetClassAndMethod: com.ljq.demo.springboot.web.controller.Ehcache3Controller#cacheRemoveAllValidate
2019-03-24 20:26:42:849 [http-nio-8088-exec-8] DEBUG com.ljq.demo.springboot.dao.user.UserDao.queryList(BaseJdbcLogger.java 159) -==>  Preparing: select u.id, u.user_name, u.user_passcode, u.user_email, u.user_insert_time, u.user_update_time, u.user_status, u.user_version, u.user_del from `user` u where u.user_del = 0 order by id desc limit ?, ? 
2019-03-24 20:26:42:850 [http-nio-8088-exec-8] DEBUG com.ljq.demo.springboot.dao.user.UserDao.queryList(BaseJdbcLogger.java 159) -==> Parameters: 0(Integer), 5(Integer)
2019-03-24 20:26:42:853 [http-nio-8088-exec-8] DEBUG com.ljq.demo.springboot.dao.user.UserDao.queryList(BaseJdbcLogger.java 159) -<==      Total: 5
2019-03-24 20:26:42:854 [http-nio-8088-exec-8] DEBUG c.ljq.demo.springboot.dao.user.UserDao.queryCount(BaseJdbcLogger.java 159) -==>  Preparing: select count(*) counts from `user` where `user_del` = 0 order by id desc 
2019-03-24 20:26:42:854 [http-nio-8088-exec-8] DEBUG c.ljq.demo.springboot.dao.user.UserDao.queryCount(BaseJdbcLogger.java 159) -==> Parameters: 
2019-03-24 20:26:42:856 [http-nio-8088-exec-8] DEBUG c.ljq.demo.springboot.dao.user.UserDao.queryCount(BaseJdbcLogger.java 159) -<==      Total: 1
2019-03-24 20:26:42:863 [Ehcache [_default_]-3] INFO  c.l.demo.springboot.common.cache.Ehcache3EventLog(Ehcache3EventLog.java 17) -Event: CREATED,  Key: CacheRemoveAllBean(currPage=1, pageLimit=5, sidx=id, order=desc), old value: null, new value: 
2019-03-24 20:26:42:863 [http-nio-8088-exec-8] INFO  com.ljq.demo.springboot.web.acpect.LogAspect(LogAspect.java 74) -[AOP-LOG-END]
	ApiResult(code=1000, msg=成功, data=PageUtil(totalCount=5, pageLimit=5, totalPage=1, currPage=1, list=[UserDO(id=5, userName=liming, userPasscode=ed0de7252acf2980e677bacab01bde25, userEmail=liming@example.com, userInsertTime=2019-03-13 17:25:44, userUpdateTime=2019-03-13 17:25:44, userStatus=1, userVersion=1, userDel=0), UserDO(id=4, userName=lily, userPasscode=ed0de7252acf2980e677bacab01bde25, userEmail=lily@example.com, userInsertTime=2019-03-13 17:25:44, userUpdateTime=2019-03-13 17:25:44, userStatus=1, userVersion=1, userDel=0), UserDO(id=3, userName=jack, userPasscode=ed0de7252acf2980e677bacab01bde25, userEmail=jack@example.com, userInsertTime=2019-03-13 17:25:44, userUpdateTime=2019-03-13 17:25:44, userStatus=1, userVersion=1, userDel=0), UserDO(id=2, userName=bob, userPasscode=ed0de7252acf2980e677bacab01bde25, userEmail=bob@example.com, userInsertTime=2019-03-13 17:25:44, userUpdateTime=2019-03-13 17:25:44, userStatus=1, userVersion=1, userDel=0), UserDO(id=1, userName=tom, userPasscode=ed0de7252acf2980e677bacab01bde25, userEmail=tom@example.com, userInsertTime=2019-03-13 17:25:44, userUpdateTime=2019-03-13 17:25:44, userStatus=1, userVersion=1, userDel=0)]))

第二次请求,请求使用 @CacheRemoveAll 注解的方法,请求参数为:

POST /api/ehcache3/cacheRemoveAll
Content-Type: application/json
cache-control: no-cache
Postman-Token: 67084de2-a509-4d66-9a24-86811267f80f
User-Agent: PostmanRuntime/7.6.1
Accept: */*
Host: 127.0.0.1:8088
accept-encoding: gzip, deflate
content-length: 73
{ "currPage" : 1, "pageLimit" : 5, "sidx" : "id", "order" : "desc" }

第二次请求日志:

2019-03-24 20:26:45:948 [http-nio-8088-exec-3] INFO  com.ljq.demo.springboot.web.acpect.LogAspect(LogAspect.java 66) -[AOP-LOG-START]
	requestMark: 2ddf3f38-b5ae-43b6-ab9c-63ec4982b6cf
	requestIP: 127.0.0.1
	contentType:application/json
	requestUrl: http://127.0.0.1:8088/api/ehcache3/cacheRemoveAll
	requestMethod: POST
	requestParams: {"language":null,"currPage":1,"pageLimit":5,"sidx":"id","order":"desc"}
	targetClassAndMethod: com.ljq.demo.springboot.web.controller.Ehcache3Controller#cacheRemoveAll
2019-03-24 20:26:45:963 [http-nio-8088-exec-3] DEBUG com.ljq.demo.springboot.dao.user.UserDao.queryList(BaseJdbcLogger.java 159) -==>  Preparing: select u.id, u.user_name, u.user_passcode, u.user_email, u.user_insert_time, u.user_update_time, u.user_status, u.user_version, u.user_del from `user` u where u.user_del = 0 order by id desc limit ?, ? 
2019-03-24 20:26:45:964 [http-nio-8088-exec-3] DEBUG com.ljq.demo.springboot.dao.user.UserDao.queryList(BaseJdbcLogger.java 159) -==> Parameters: 0(Integer), 5(Integer)
2019-03-24 20:26:45:967 [http-nio-8088-exec-3] DEBUG com.ljq.demo.springboot.dao.user.UserDao.queryList(BaseJdbcLogger.java 159) -<==      Total: 5
2019-03-24 20:26:45:970 [http-nio-8088-exec-3] DEBUG c.ljq.demo.springboot.dao.user.UserDao.queryCount(BaseJdbcLogger.java 159) -==>  Preparing: select count(*) counts from `user` where `user_del` = 0 order by id desc 
2019-03-24 20:26:45:970 [http-nio-8088-exec-3] DEBUG c.ljq.demo.springboot.dao.user.UserDao.queryCount(BaseJdbcLogger.java 159) -==> Parameters: 
2019-03-24 20:26:45:971 [http-nio-8088-exec-3] DEBUG c.ljq.demo.springboot.dao.user.UserDao.queryCount(BaseJdbcLogger.java 159) -<==      Total: 1
2019-03-24 20:26:45:973 [Ehcache [_default_]-3] INFO  c.l.demo.springboot.common.cache.Ehcache3EventLog(Ehcache3EventLog.java 17) -Event: REMOVED,  Key: CacheResultBean(currPage=1, pageLimit=5, sidx=id, order=desc), old value: ApiResult(code=1000, msg=成功, data=PageUtil(totalCount=5, pageLimit=5, totalPage=1, currPage=1, list=[UserDO(id=5, userName=liming, userPasscode=ed0de7252acf2980e677bacab01bde25, userEmail=liming@example.com, userInsertTime=2019-03-13 17:25:44, userUpdateTime=2019-03-13 17:25:44, userStatus=1, userVersion=1, userDel=0), UserDO(id=4, userName=lily, userPasscode=ed0de7252acf2980e677bacab01bde25, userEmail=lily@example.com, userInsertTime=2019-03-13 17:25:44, userUpdateTime=2019-03-13 17:25:44, userStatus=1, userVersion=1, userDel=0), UserDO(id=3, userName=jack, userPasscode=ed0de7252acf2980e677bacab01bde25, userEmail=jack@example.com, userInsertTime=2019-03-13 17:25:44, userUpdateTime=2019-03-13 17:25:44, userStatus=1, userVersion=1, userDel=0), UserDO(id=2, userName=bob, userPasscode=ed0de7252acf2980e677bacab01bde25, userEmail=bob@example.com, userInsertTime=2019-03-13 17:25:44, userUpdateTime=2019-03-13 17:25:44, userStatus=1, userVersion=1, userDel=0), UserDO(id=1, userName=tom, userPasscode=ed0de7252acf2980e677bacab01bde25, userEmail=tom@example.com, userInsertTime=2019-03-13 17:25:44, userUpdateTime=2019-03-13 17:25:44, userStatus=1, userVersion=1, userDel=0)])), new value: 
2019-03-24 20:26:45:973 [Ehcache [_default_]-3] INFO  c.l.demo.springboot.common.cache.Ehcache3EventLog(Ehcache3EventLog.java 17) -Event: REMOVED,  Key: CacheRemoveAllBean(currPage=1, pageLimit=5, sidx=id, order=desc), old value: ApiResult(code=1000, msg=成功, data=PageUtil(totalCount=5, pageLimit=5, totalPage=1, currPage=1, list=[UserDO(id=5, userName=liming, userPasscode=ed0de7252acf2980e677bacab01bde25, userEmail=liming@example.com, userInsertTime=2019-03-13 17:25:44, userUpdateTime=2019-03-13 17:25:44, userStatus=1, userVersion=1, userDel=0), UserDO(id=4, userName=lily, userPasscode=ed0de7252acf2980e677bacab01bde25, userEmail=lily@example.com, userInsertTime=2019-03-13 17:25:44, userUpdateTime=2019-03-13 17:25:44, userStatus=1, userVersion=1, userDel=0), UserDO(id=3, userName=jack, userPasscode=ed0de7252acf2980e677bacab01bde25, userEmail=jack@example.com, userInsertTime=2019-03-13 17:25:44, userUpdateTime=2019-03-13 17:25:44, userStatus=1, userVersion=1, userDel=0), UserDO(id=2, userName=bob, userPasscode=ed0de7252acf2980e677bacab01bde25, userEmail=bob@example.com, userInsertTime=2019-03-13 17:25:44, userUpdateTime=2019-03-13 17:25:44, userStatus=1, userVersion=1, userDel=0), UserDO(id=1, userName=tom, userPasscode=ed0de7252acf2980e677bacab01bde25, userEmail=tom@example.com, userInsertTime=2019-03-13 17:25:44, userUpdateTime=2019-03-13 17:25:44, userStatus=1, userVersion=1, userDel=0)])), new value: 
2019-03-24 20:26:45:973 [http-nio-8088-exec-3] INFO  com.ljq.demo.springboot.web.acpect.LogAspect(LogAspect.java 74) -[AOP-LOG-END]
	ApiResult(code=1000, msg=成功, data=PageUtil(totalCount=5, pageLimit=5, totalPage=1, currPage=1, list=[UserDO(id=5, userName=liming, userPasscode=ed0de7252acf2980e677bacab01bde25, userEmail=liming@example.com, userInsertTime=2019-03-13 17:25:44, userUpdateTime=2019-03-13 17:25:44, userStatus=1, userVersion=1, userDel=0), UserDO(id=4, userName=lily, userPasscode=ed0de7252acf2980e677bacab01bde25, userEmail=lily@example.com, userInsertTime=2019-03-13 17:25:44, userUpdateTime=2019-03-13 17:25:44, userStatus=1, userVersion=1, userDel=0), UserDO(id=3, userName=jack, userPasscode=ed0de7252acf2980e677bacab01bde25, userEmail=jack@example.com, userInsertTime=2019-03-13 17:25:44, userUpdateTime=2019-03-13 17:25:44, userStatus=1, userVersion=1, userDel=0), UserDO(id=2, userName=bob, userPasscode=ed0de7252acf2980e677bacab01bde25, userEmail=bob@example.com, userInsertTime=2019-03-13 17:25:44, userUpdateTime=2019-03-13 17:25:44, userStatus=1, userVersion=1, userDel=0), UserDO(id=1, userName=tom, userPasscode=ed0de7252acf2980e677bacab01bde25, userEmail=tom@example.com, userInsertTime=2019-03-13 17:25:44, userUpdateTime=2019-03-13 17:25:44, userStatus=1, userVersion=1, userDel=0)]))

第三次请求,重发第一次请求,参数不变

第三次请求日志:

2019-03-24 20:26:48:544 [http-nio-8088-exec-9] INFO  com.ljq.demo.springboot.web.acpect.LogAspect(LogAspect.java 66) -[AOP-LOG-START]
	requestMark: 28d1b5ea-6af2-40a9-bf8e-49f38b4db7d4
	requestIP: 127.0.0.1
	contentType:application/json
	requestUrl: http://127.0.0.1:8088/api/ehcache3/cacheResult
	requestMethod: POST
	requestParams: {"language":null,"currPage":1,"pageLimit":5,"sidx":"id","order":"desc"}
	targetClassAndMethod: com.ljq.demo.springboot.web.controller.Ehcache3Controller#cacheResult
2019-03-24 20:26:48:561 [http-nio-8088-exec-9] DEBUG com.ljq.demo.springboot.dao.user.UserDao.queryList(BaseJdbcLogger.java 159) -==>  Preparing: select u.id, u.user_name, u.user_passcode, u.user_email, u.user_insert_time, u.user_update_time, u.user_status, u.user_version, u.user_del from `user` u where u.user_del = 0 order by id desc limit ?, ? 
2019-03-24 20:26:48:563 [http-nio-8088-exec-9] DEBUG com.ljq.demo.springboot.dao.user.UserDao.queryList(BaseJdbcLogger.java 159) -==> Parameters: 0(Integer), 5(Integer)
2019-03-24 20:26:48:565 [http-nio-8088-exec-9] DEBUG com.ljq.demo.springboot.dao.user.UserDao.queryList(BaseJdbcLogger.java 159) -<==      Total: 5
2019-03-24 20:26:48:567 [http-nio-8088-exec-9] DEBUG c.ljq.demo.springboot.dao.user.UserDao.queryCount(BaseJdbcLogger.java 159) -==>  Preparing: select count(*) counts from `user` where `user_del` = 0 order by id desc 
2019-03-24 20:26:48:567 [http-nio-8088-exec-9] DEBUG c.ljq.demo.springboot.dao.user.UserDao.queryCount(BaseJdbcLogger.java 159) -==> Parameters: 
2019-03-24 20:26:48:570 [http-nio-8088-exec-9] DEBUG c.ljq.demo.springboot.dao.user.UserDao.queryCount(BaseJdbcLogger.java 159) -<==      Total: 1
2019-03-24 20:26:48:575 [Ehcache [_default_]-3] INFO  c.l.demo.springboot.common.cache.Ehcache3EventLog(Ehcache3EventLog.java 17) -Event: CREATED,  Key: CacheResultBean(currPage=1, pageLimit=5, sidx=id, order=desc), old value: null, new value: 
2019-03-24 20:26:48:575 [http-nio-8088-exec-9] INFO  com.ljq.demo.springboot.web.acpect.LogAspect(LogAspect.java 74) -[AOP-LOG-END]
	ApiResult(code=1000, msg=成功, data=PageUtil(totalCount=5, pageLimit=5, totalPage=1, currPage=1, list=[UserDO(id=5, userName=liming, userPasscode=ed0de7252acf2980e677bacab01bde25, userEmail=liming@example.com, userInsertTime=2019-03-13 17:25:44, userUpdateTime=2019-03-13 17:25:44, userStatus=1, userVersion=1, userDel=0), UserDO(id=4, userName=lily, userPasscode=ed0de7252acf2980e677bacab01bde25, userEmail=lily@example.com, userInsertTime=2019-03-13 17:25:44, userUpdateTime=2019-03-13 17:25:44, userStatus=1, userVersion=1, userDel=0), UserDO(id=3, userName=jack, userPasscode=ed0de7252acf2980e677bacab01bde25, userEmail=jack@example.com, userInsertTime=2019-03-13 17:25:44, userUpdateTime=2019-03-13 17:25:44, userStatus=1, userVersion=1, userDel=0), UserDO(id=2, userName=bob, userPasscode=ed0de7252acf2980e677bacab01bde25, userEmail=bob@example.com, userInsertTime=2019-03-13 17:25:44, userUpdateTime=2019-03-13 17:25:44, userStatus=1, userVersion=1, userDel=0), UserDO(id=1, userName=tom, userPasscode=ed0de7252acf2980e677bacab01bde25, userEmail=tom@example.com, userInsertTime=2019-03-13 17:25:44, userUpdateTime=2019-03-13 17:25:44, userStatus=1, userVersion=1, userDel=0)]))
2019-03-24 20:26:50:885 [http-nio-8088-exec-10] INFO  com.ljq.demo.springboot.web.acpect.LogAspect(LogAspect.java 66) -[AOP-LOG-START]
	requestMark: e81334d2-077c-4b7a-8aa0-816b160b0ec1
	requestIP: 127.0.0.1
	contentType:application/json
	requestUrl: http://127.0.0.1:8088/api/ehcache3/cacheRemoveAllValidate
	requestMethod: POST
	requestParams: {"language":null,"currPage":1,"pageLimit":5,"sidx":"id","order":"desc"}
	targetClassAndMethod: com.ljq.demo.springboot.web.controller.Ehcache3Controller#cacheRemoveAllValidate
2019-03-24 20:26:50:897 [http-nio-8088-exec-10] DEBUG com.ljq.demo.springboot.dao.user.UserDao.queryList(BaseJdbcLogger.java 159) -==>  Preparing: select u.id, u.user_name, u.user_passcode, u.user_email, u.user_insert_time, u.user_update_time, u.user_status, u.user_version, u.user_del from `user` u where u.user_del = 0 order by id desc limit ?, ? 
2019-03-24 20:26:50:898 [http-nio-8088-exec-10] DEBUG com.ljq.demo.springboot.dao.user.UserDao.queryList(BaseJdbcLogger.java 159) -==> Parameters: 0(Integer), 5(Integer)
2019-03-24 20:26:50:899 [http-nio-8088-exec-10] DEBUG com.ljq.demo.springboot.dao.user.UserDao.queryList(BaseJdbcLogger.java 159) -<==      Total: 5
2019-03-24 20:26:50:900 [http-nio-8088-exec-10] DEBUG c.ljq.demo.springboot.dao.user.UserDao.queryCount(BaseJdbcLogger.java 159) -==>  Preparing: select count(*) counts from `user` where `user_del` = 0 order by id desc 
2019-03-24 20:26:50:900 [http-nio-8088-exec-10] DEBUG c.ljq.demo.springboot.dao.user.UserDao.queryCount(BaseJdbcLogger.java 159) -==> Parameters: 
2019-03-24 20:26:50:906 [http-nio-8088-exec-10] DEBUG c.ljq.demo.springboot.dao.user.UserDao.queryCount(BaseJdbcLogger.java 159) -<==      Total: 1
2019-03-24 20:26:50:909 [Ehcache [_default_]-3] INFO  c.l.demo.springboot.common.cache.Ehcache3EventLog(Ehcache3EventLog.java 17) -Event: CREATED,  Key: CacheRemoveAllBean(currPage=1, pageLimit=5, sidx=id, order=desc), old value: null, new value: 
2019-03-24 20:26:50:909 [http-nio-8088-exec-10] INFO  com.ljq.demo.springboot.web.acpect.LogAspect(LogAspect.java 74) -[AOP-LOG-END]
	ApiResult(code=1000, msg=成功, data=PageUtil(totalCount=5, pageLimit=5, totalPage=1, currPage=1, list=[UserDO(id=5, userName=liming, userPasscode=ed0de7252acf2980e677bacab01bde25, userEmail=liming@example.com, userInsertTime=2019-03-13 17:25:44, userUpdateTime=2019-03-13 17:25:44, userStatus=1, userVersion=1, userDel=0), UserDO(id=4, userName=lily, userPasscode=ed0de7252acf2980e677bacab01bde25, userEmail=lily@example.com, userInsertTime=2019-03-13 17:25:44, userUpdateTime=2019-03-13 17:25:44, userStatus=1, userVersion=1, userDel=0), UserDO(id=3, userName=jack, userPasscode=ed0de7252acf2980e677bacab01bde25, userEmail=jack@example.com, userInsertTime=2019-03-13 17:25:44, userUpdateTime=2019-03-13 17:25:44, userStatus=1, userVersion=1, userDel=0), UserDO(id=2, userName=bob, userPasscode=ed0de7252acf2980e677bacab01bde25, userEmail=bob@example.com, userInsertTime=2019-03-13 17:25:44, userUpdateTime=2019-03-13 17:25:44, userStatus=1, userVersion=1, userDel=0), UserDO(id=1, userName=tom, userPasscode=ed0de7252acf2980e677bacab01bde25, userEmail=tom@example.com, userInsertTime=2019-03-13 17:25:44, userUpdateTime=2019-03-13 17:25:44, userStatus=1, userVersion=1, userDel=0)]))

测试结果: 使用 @CacheRemoveAll 注解将会把指定的缓存库中所有的缓存删除

6 注意事项

  • 使用 @CacheResult,@CacheRemove 注解时,方法的参数只有一个时,默认该参数使用了 @CacheKey 注解
  • @CacheKey 注解用于指定缓存的 Key; @CacheValue 注解用于指定缓存的 Value;这两个注解需要与其他注解搭配使用
  • @CachePut 注解必须要与 @CacheValue 注解搭配使用;可以不与 @CacheKey 搭配使用;如果不使用 @CacheKey ,当方法的参数只有一个时,则这个参数也充当缓存的 key(相当于使用 @CacheKey 注解),当方法有多个参数时,则没有使用 @CacheValue 注解的参数充当缓存的 key(相当于使用 @CacheKey 注解)

7 参考资料推荐

Ehcache 3, JSR-107 and Spring 4.2

Ehcache 3.0 发布,修补了 API 并支持非堆存储

Java Code Examples for javax.cache.annotation.CachePut

缓存那些事--美团技术团队

Cache Abstraction: JCache (JSR-107) Annotations Support

Java Caching(缓存)-策略和JCache API

Spring Boot整合ehcache3.0 缓存

JAVA中使用springBoot和Ehcache3.X无xml配置和xml配置

关于ehcache缓存中eternal及timeToLiveSeconds和timeToIdleSeconds的说明

8 本次提交记录

commit b1f78237dd7a169d2e1a3c9ee1f6abf024e333e1 (HEAD -> dev, origin/master, origin/dev, origin/HEAD, master)
Author: ljq <flying9001@gmail.com>
Date:   Fri Mar 22 11:20:34 2019 +0800

    springBoot 2.X 整合集成 Ehcache 3 jsr107 缓存

版本回退命令

git reset --soft b1f78237dd7a169d2e1a3c9ee1f6abf024e333e1