本文基于Springboot2.0努释,使用mysql數(shù)據(jù)庫(kù),通過(guò)jpa實(shí)現(xiàn)orm咬摇,再用redis實(shí)現(xiàn)數(shù)據(jù)庫(kù)的緩存伐蒂。
目錄
1、項(xiàng)目結(jié)構(gòu)
2肛鹏、環(huán)境配置
3逸邦、代碼
4、測(cè)試
5在扰、參考文章
1缕减、項(xiàng)目結(jié)構(gòu)
項(xiàng)目結(jié)構(gòu)
2、環(huán)境配置
1)pom.xml
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<!-- 引入Redis緩存 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
</dependencies>
2)application.yml
注意:
- 創(chuàng)建mysql數(shù)據(jù)庫(kù)名稱(chēng)為 jpa_redis
- redis 端口芒珠、
- mysql 數(shù)據(jù)庫(kù)賬號(hào)密碼
server:
port: 8081
# context-path: /
spring:
redis:
host: localhost
port: 6379
datasource:
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://localhost:3306/jpa_redis
username: root
password: abc
jpa:
hibernate:
ddl-auto: update
show-sql: true
3桥狡、代碼
1)SpringBootRedisApplication
注意添加 @EnableCaching
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cache.annotation.EnableCaching;
@SpringBootApplication
@EnableCaching
public class SpringBootRedisApplication
{
public static void main(String[] args)
{
SpringApplication.run(SpringBootRedisApplication.class, args);
}
}
2)RedisConfig
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.interceptor.KeyGenerator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.cache.RedisCacheWriter;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializationContext;
import java.lang.reflect.Method;
import java.time.Duration;
/**
* Redis 緩存配置類(lèi)
*/
@Configuration
@EnableCaching
public class RedisConfig extends CachingConfigurerSupport
{
/**
* 緩存對(duì)象集合中,緩存是以 key-value 形式保存的皱卓。
* 當(dāng)不指定緩存的 key 時(shí)裹芝,SpringBoot 會(huì)使用 SimpleKeyGenerator 生成 key。
*/
// @Bean
public KeyGenerator wiselyKeyGenerator()
{
// key前綴娜汁,用于區(qū)分不同項(xiàng)目的緩存嫂易,建議每個(gè)項(xiàng)目單獨(dú)設(shè)置
final String PRE_KEY = "test";
final char sp = ':';
return new KeyGenerator()
{
@Override
public Object generate(Object target, Method method, Object... params)
{
StringBuilder sb = new StringBuilder();
sb.append(PRE_KEY);
sb.append(sp);
sb.append(target.getClass().getSimpleName());
sb.append(sp);
sb.append(method.getName());
for (Object obj : params)
{
sb.append(sp);
sb.append(obj.toString());
}
return sb.toString();
}
};
}
@Bean
public CacheManager cacheManager(RedisConnectionFactory factory)
{
// 更改值的序列化方式,否則在Redis可視化軟件中會(huì)顯示亂碼掐禁。默認(rèn)為JdkSerializationRedisSerializer
RedisSerializationContext.SerializationPair<Object> pair = RedisSerializationContext.SerializationPair
.fromSerializer(new GenericJackson2JsonRedisSerializer());
RedisCacheConfiguration defaultCacheConfig = RedisCacheConfiguration
.defaultCacheConfig()
.serializeValuesWith(pair) // 設(shè)置序列化方式
.entryTtl(Duration.ofHours(1)); // 設(shè)置過(guò)期時(shí)間
return RedisCacheManager
.builder(RedisCacheWriter.nonLockingRedisCacheWriter(factory))
.cacheDefaults(defaultCacheConfig).build();
}
}
3)實(shí)體類(lèi)User
注意實(shí)現(xiàn) Serializable 接口
import java.io.Serializable;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Table;
/**
* 用戶(hù)實(shí)體
*/
@Entity
@Table(name = "user")
public class User implements Serializable {
private static final long serialVersionUID = 1l;
@Id
@GeneratedValue
private Integer id;
@Column(length = 20)
private String userName;
@Column(length = 20)
private String password;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
4)UserDao
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import com.cun.entity.User;
/**
* 用戶(hù) dao 接口
*/
public interface UserDao extends JpaRepository<User, Integer>, JpaSpecificationExecutor<User>
{
}
5)UserService
import java.util.List;
import com.cun.entity.User;
public interface UserService
{
List<User> getAllUsers();
User findById(Integer pId);
void clearAllUserCache();
void clear(Integer pId);
}
6)UserServiceImpl
cacheNames
與 value
作用一樣
import java.util.List;
import java.util.Optional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import com.cun.dao.UserDao;
import com.cun.entity.User;
import com.cun.service.UserService;
@Service
@CacheConfig(cacheNames = "userService")
public class UserServiceImpl implements UserService
{
@Autowired
private UserDao userDao;
/**
* cacheNames 與 value 定義一樣怜械,設(shè)置了 value 的值,則類(lèi)的 cacheNames 配置無(wú)效傅事。<br>
* 使用 keyGenerator 缕允,注意是否在config文件中定義好。
* @see com.cun.service.UserService#getAllUsers()
*/
@Override
@Cacheable(value = "getAllUsers")
// @Cacheable(value = "getAllUsers", keyGenerator = "wiselyKeyGenerator")
public List<User> getAllUsers()
{
return userDao.findAll();
}
/**
* 執(zhí)行該函數(shù)時(shí)蹭越,將清除以 userService 的緩存障本,【cacheNames = "userService"】<br>
* 也可指定清除的key 【@CacheEvict(value="abc")】
*/
@CacheEvict(value = "getAllUsers")
public void clearAllUserCache()
{
}
/**
* key ="#p0" 表示以第1個(gè)參數(shù)作為 key
*/
@Override
@Cacheable(value="user", key ="#p0")
public User findById(Integer pId)
{
Optional<User> _User = userDao.findById(pId);
return Optional.ofNullable(_User).get().orElse(null);
}
@CacheEvict(value="user", key ="#p0")
public void clear(Integer pId)
{
}
}
7)UserController
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import com.cun.entity.User;
import com.cun.service.UserService;
/**
* 參考 https://blog.csdn.net/larger5/article/details/79696562
*/
@RestController
public class UserController
{
@Autowired
private UserService userService;
// http://localhost:8081/all
@GetMapping("/all")
public List<User> getAllUsers()
{
System.out.println("只有第一次才會(huì)打印sql語(yǔ)句");
return userService.getAllUsers();
}
// http://localhost:8081/findById?id=1
@GetMapping("/findById")
public User findById(@RequestParam(name = "id")Integer pId)
{
return userService.findById(pId);
}
// http://localhost:8081/clear
@GetMapping("/clear")
public void clear()
{
userService.clearAllUserCache();
}
// http://localhost:8081/clearOne?id=1
@GetMapping("/clearOne")
public void clear(@RequestParam(name = "id")Integer pId)
{
userService.clear(pId);
}
}
4、測(cè)試
啟動(dòng)服務(wù)后般又,可以看到 jpa 框架自動(dòng)生成 user 表
user表
1)添加測(cè)試數(shù)據(jù)
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.*;
import com.cun.SpringBootRedisApplication;
import com.cun.dao.UserDao;
import com.cun.entity.User;
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes=SpringBootRedisApplication.class)
public class AddTester {
@Autowired
private UserDao userDao;
@Test
public void test()
{
User _User = new User();
_User.setPassword("123");
_User.setUserName("老王");
userDao.save(_User);
User _User2 = new User();
_User2.setPassword("456");
_User2.setUserName("小李");
userDao.save(_User2);
}
}
2)緩存測(cè)試
訪(fǎng)問(wèn) http://localhost:8081/all 彼绷,可看到緩存數(shù)據(jù)
image.png
訪(fǎng)問(wèn) http://localhost:8081/findById?id=1,可看到緩存數(shù)據(jù)
image.png
則調(diào)用 http://localhost:8081/clear 后茴迁,getAllUsers 的緩存將被清除寄悯;
則調(diào)用 http://localhost:8081/clearOne?id=1 后,user::1 的緩存將被清除堕义。