本地缓存,就是使用应用内使用本地内存将数据暂缓存储,一般数据库的查询如果不怎么改动,可以用本地缓存暂存。
远程缓存,比如redis,就是第三方缓存服务器,不是在当前应用的,需要用过tcp请求去获得的缓存。
Springboot的官方文档中列出了9种:
本地缓存常用的是Ehcache,很早就出现了,用的很广泛,是一个纯Java的进程内缓存框架,具有快速、精干等特点,是Hibernate中默认的CacheProvider.
Caffeine是使用Java8对Guava缓存的重写版本,有人称它为缓存之王,虽然我不知道为啥这么称呼它。我没做过性能测试哦。
本文假设你已经引入spring-boot-starter-web。已经是个SpringBoot项目了,如果不会搭建,可以打开这篇文章看一看《SpringBoot入门建站全系列(一)项目建立》。
**如果大家正在寻找一个java的学习环境,或者在开发中遇到困难,可以<a
href="https://jq.qq.com/?_wv=1027&k=52sgH1J"
target="_blank">
加入我们的java学习圈,点击即可加入
</a>
,共同学习,节约学习时间,减少很多在学习中遇到的难题。**
缓存的注解包含:
@Cacheable:加入缓存,使用前查询缓存。
@CacheEvict:清除缓存
@CachePut:每次都执行方法,并直接存入数据到缓存,使用前不查询缓存
@Caching:可以让我们在一个方法或者类上同时指定多个Spring Cache相关的注解。其拥有三个属性:cacheable、put和evict,分别用于指定@Cacheable、@CachePut和@CacheEvict。
缓存的key是有讲究的,Springboot里面没讲,Spring占用了一大篇幅去说它,这里就不多说了,官方文档在这儿:
https://docs.spring.io/spring/docs/5.1.8.RELEASE/spring-framework-reference/integration.html#cache。
这里要访问数据库进行缓存,所以要依赖数据库相关jar包,同时要依赖ehcache。
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-dbcp2</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
<dependency>
<groupId>net.sf.ehcache</groupId>
<artifactId>ehcache</artifactId>
</dependency>
在application.properties 中需要添加下面的配置:
spring.cache.ehcache.config=classpath:ehcache.xml
spring.datasource.type=org.apache.commons.dbcp2.BasicDataSource
spring.datasource.dbcp2.max-wait-millis=60000
spring.datasource.dbcp2.min-idle=20
spring.datasource.dbcp2.initial-size=2
spring.datasource.dbcp2.validation-query=SELECT 1
spring.datasource.dbcp2.connection-properties=characterEncoding=utf8
spring.datasource.dbcp2.validation-query=SELECT 1
spring.datasource.dbcp2.test-while-idle=true
spring.datasource.dbcp2.test-on-borrow=true
spring.datasource.dbcp2.test-on-return=false
spring.datasource.driverClassName = com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/boot?useUnicode=true&characterEncoding=utf8&serverTimezone=UTC
spring.datasource.username=cff
spring.datasource.password=123456
mybatis.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
这里的spring.cache.ehcache.config指定了ehcache的配置文件位置。
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">
<!-- 磁盘缓存位置 -->
<diskStore path="java.io.tmpdir/ehcache"/>
<!-- 默认缓存 -->
<defaultCache
maxEntriesLocalHeap="10000"
eternal="false"
timeToIdleSeconds="120"
timeToLiveSeconds="120"
maxEntriesLocalDisk="10000000"
diskExpiryThreadIntervalSeconds="120"
memoryStoreEvictionPolicy="LRU"/>
<!-- userCache缓存 -->
<cache name="userCache"
maxElementsInMemory="1000"
eternal="false"
timeToIdleSeconds="0"
timeToLiveSeconds="1000"
overflowToDisk="false"
memoryStoreEvictionPolicy="LRU"/>
</ehcache>
这里配置了一个defaultCache和一个userCache。不多说了,顾名思义的配置。
需要使用@EnableCaching
开启注解。使用@Cacheable注解需要缓存的service。
EhcacheService:
package com.cff.springbootwork.ehcache.service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.stereotype.Service;
import com.cff.springbootwork.mybatis.domain.UserInfo;
import com.cff.springbootwork.mybatis.service.UserInfoService;
@Service
@EnableCaching
public class EhcacheService {
@Autowired
UserInfoService userInfoService;
@Cacheable(value = "userCache", key = "#root.targetClass.simpleName+'-'+#root.methodName+'-'+#userName")
public UserInfo getUserInfoByUserName(String userName) {
return userInfoService.getUserInfoByUserName(userName);
}
public UserInfoService getUserInfoService() {
return userInfoService;
}
public void setUserInfoService(UserInfoService userInfoService) {
this.userInfoService = userInfoService;
}
}
package com.cff.springbootwork.ehcache.web;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import com.cff.springbootwork.ehcache.service.EhcacheService;
import com.cff.springbootwork.mybatis.domain.UserInfo;
@RestController
@RequestMapping("/ehcache")
public class EhcacheRest {
@Autowired
private EhcacheService ehcacheService;
@RequestMapping(value = "/test/{name}", method = { RequestMethod.GET })
public UserInfo test(@PathVariable("name") String name) {
return ehcacheService.getUserInfoByUserName(name);
}
}
Caffeine配置起来相对简单点,没有xml这样的配置。
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-dbcp2</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
<dependency>
<groupId>com.github.ben-manes.caffeine</groupId>
<artifactId>caffeine</artifactId>
</dependency>
在application.properties 中需要添加下面的配置:
spring.cache.type=caffeine
spring.cache.cache-names=userCache
spring.datasource.type=org.apache.commons.dbcp2.BasicDataSource
spring.datasource.dbcp2.max-wait-millis=60000
spring.datasource.dbcp2.min-idle=20
spring.datasource.dbcp2.initial-size=2
spring.datasource.dbcp2.validation-query=SELECT 1
spring.datasource.dbcp2.connection-properties=characterEncoding=utf8
spring.datasource.dbcp2.validation-query=SELECT 1
spring.datasource.dbcp2.test-while-idle=true
spring.datasource.dbcp2.test-on-borrow=true
spring.datasource.dbcp2.test-on-return=false
spring.datasource.driverClassName = com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/boot?useUnicode=true&characterEncoding=utf8&serverTimezone=UTC
spring.datasource.username=cff
spring.datasource.password=123456
mybatis.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
这里的spring.cache.type指定了cache是用caffeine,spring.cache.cache-names=userCache是建立了一个名字为userCache的cache。
需要使用@EnableCaching
开启注解。使用@Cacheable注解需要缓存的service。
CaffeineService :
package com.cff.springbootwork.caffeine.service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.stereotype.Service;
import com.cff.springbootwork.mybatis.domain.UserInfo;
import com.cff.springbootwork.mybatis.service.UserInfoService;
@Service
@EnableCaching
public class CaffeineService {
@Autowired
UserInfoService userInfoService;
@Cacheable(value = "userCache", key = "#root.targetClass.simpleName+'-'+#root.methodName+'-'+#userName")
public UserInfo getUserInfoByUserName(String userName) {
return userInfoService.getUserInfoByUserName(userName);
}
public UserInfoService getUserInfoService() {
return userInfoService;
}
public void setUserInfoService(UserInfoService userInfoService) {
this.userInfoService = userInfoService;
}
}
CaffeineRest :
package com.cff.springbootwork.caffeine.web;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import com.cff.springbootwork.caffeine.service.CaffeineService;
import com.cff.springbootwork.mybatis.domain.UserInfo;
@RestController
@RequestMapping("/caffeine")
public class CaffeineRest {
@Autowired
private CaffeineService caffeineService;
@RequestMapping(value = "/test/{name}", method = { RequestMethod.GET })
public UserInfo test(@PathVariable("name") String name) {
return caffeineService.getUserInfoByUserName(name);
}
}
UserInfoService:
package com.cff.springbootwork.mybatis.service;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.cff.springbootwork.mybatis.dao.UserInfoDao;
import com.cff.springbootwork.mybatis.domain.UserInfo;
@Service
public class UserInfoService {
@Autowired
UserInfoDao userInfoDao;
public UserInfo getUserInfoByUserName(String userName){
return userInfoDao.findByUserName(userName);
}
}
UserInfoDao :
package com.cff.springbootwork.mybatis.dao;
import java.util.List;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import org.apache.ibatis.annotations.Update;
import com.cff.springbootwork.mybatis.domain.UserInfo;
@Mapper
public interface UserInfoDao {
@Select({
"<script>",
"SELECT ",
"user_name as userName,passwd,name,mobile,valid, user_type as userType",
"FROM user_info",
"WHERE user_name = #{userName,jdbcType=VARCHAR}",
"</script>"})
UserInfo findByUserName(@Param("userName") String userName);
}
UserInfo :
package com.cff.springbootwork.mybatis.domain;
public class UserInfo {
private String userName;
private String passwd;
private String name;
private String mobile;
private Integer valid;
private String userType;
public UserInfo() {
}
public UserInfo(UserInfo src) {
this.userName = src.userName;
this.passwd = src.passwd;
this.name = src.name;
this.mobile = src.mobile;
this.valid = src.valid;
}
public UserInfo(String userName, String passwd, String name, String mobile, Integer valid) {
super();
this.userName = userName;
this.passwd = passwd;
this.name = name;
this.mobile = mobile;
this.valid = valid;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getUserName() {
return userName;
}
public void setPasswd(String passwd) {
this.passwd = passwd;
}
public String getPasswd() {
return passwd;
}
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setMobile(String mobile) {
this.mobile = mobile;
}
public String getMobile() {
return mobile;
}
public void setValid(Integer valid) {
this.valid = valid;
}
public Integer getValid() {
return valid;
}
public String getUserType() {
return userType;
}
public void setUserType(String userType) {
this.userType = userType;
}
public String getIdentifyTable(){
return "user_info";
}
}