前言
在上一节中,壹哥 带大家学习了Spring Boot中提供的缓存实现方案,尤其是Spring Cache这种实现方案,接下来在本章节中,我将带大家通过代码来具体实现缓存功能。
一. Spring Boot实现默认缓存
1. 创建Web项目
我们按照之前的经验,创建一个SpringBoot的Web程序,具体过程略。
2. 添加依赖包
在pom.xml文件中添加如下核心依赖包。
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-jpa</artifactId></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-cache</artifactId></dependency>
3. 创建application.yml配置文件
创建一个application.yml文件,在这里配置数据库和jpa的信息。
server port8080spring application name cache-demo datasource driver-class-name com.mysql.cj.jdbc.Driver username root password syc url jdbc mysql //localhost 3306/spring-security?useUnicode=true&characterEncoding=utf8&characterSetResults=utf8&useSSL=false&serverTimezone=UTC #cache:#type: generic #由redis进行缓存,一共有10种缓存方案 jpa database mysql show-sql true #开发阶段,打印要执行的sql语句. hibernate ddl-auto update
4. 开启缓存功能
创建一个缓存配置类,主要是在该类上添加@EnableCaching注解,开启缓存功能。
packagecom.yyg.boot.config; importorg.springframework.cache.annotation.EnableCaching; /*** @Author 一一哥Sun* @Date Created in 2020/4/14* @Description Description* EnableCaching启用缓存*/publicclassCacheConfig { }
5. 创建User实体类
接着创建一个User实体类,封装用户信息。
packagecom.yyg.boot.domain; importlombok.Data; importlombok.ToString; importjavax.persistence.*; importjava.io.Serializable; name="user") (publicclassUserimplementsSerializable { //IllegalArgumentException: DefaultSerializer requires a Serializable payload// but received an object of type [com.syc.redis.domain.User]strategy=GenerationType.AUTO) (privateLongid; privateStringusername; privateStringpassword; }
6. 创建User仓库类
我们再创建一个JpaRepository,实现对数据库的CRUD操作。
packagecom.yyg.boot.repository; importcom.yyg.boot.domain.User; importorg.springframework.data.jpa.repository.JpaRepository; publicinterfaceUserRepositoryextendsJpaRepository<User,Long> { }
7. 创建Service服务类
7.1 定义UserService接口
packagecom.yyg.boot.service; importcom.yyg.boot.domain.User; publicinterfaceUserService { UserfindById(Longid); Usersave(Useruser); voiddeleteById(Longid); }
7.2 实现UserServiceImpl类
packagecom.yyg.boot.service.impl; importcom.yyg.boot.domain.User; importcom.yyg.boot.repository.UserRepository; importcom.yyg.boot.service.UserService; importorg.springframework.beans.factory.annotation.Autowired; importorg.springframework.cache.annotation.CacheEvict; importorg.springframework.cache.annotation.CachePut; importorg.springframework.cache.annotation.Cacheable; importorg.springframework.stereotype.Service; publicclassUserServiceImplimplementsUserService { privateUserRepositoryuserRepository; //普通的缓存+数据库查询代码实现逻辑://User user=RedisUtil.get(key);// if(user==null){// user=userDao.findById(id);// //redis的key="product_item_"+id// RedisUtil.set(key,user);// }// return user;/*** 注解@Cacheable:查询的时候才使用该注解!* 注意:在Cacheable注解中支持EL表达式* redis缓存的key=user_1/2/3....* redis的缓存雪崩,缓存穿透,缓存预热,缓存更新...* condition = "#result ne null",条件表达式,当满足某个条件的时候才进行缓存* unless = "#result eq null":当user对象为空的时候,不进行缓存*/value="user", key="#id", unless="#result eq null") (publicUserfindById(Longid) { returnuserRepository.findById(id).orElse(null); } /*** 注解@CachePut:一般用在添加和修改方法中* 既往数据库中添加一个新的对象,于此同时也往redis缓存中添加一个对应的缓存.* 这样可以达到缓存预热的目的.*/value="user", key="#result.id", unless="#result eq null") (publicUsersave(Useruser) { returnuserRepository.save(user); } /*** CacheEvict:一般用在删除方法中*/value="user", key="#id") (publicvoiddeleteById(Longid) { userRepository.deleteById(id); } }
8. 创建Controller接口方法
然后创建一个Controller,定义几个URL接口进行测试。
packagecom.yyg.boot.web; importcom.yyg.boot.domain.User; importcom.yyg.boot.service.UserService; importlombok.extern.slf4j.Slf4j; importorg.springframework.beans.factory.annotation.Autowired; importorg.springframework.http.HttpStatus; importorg.springframework.http.ResponseEntity; importorg.springframework.web.bind.annotation.*; "/user") (publicclassUserController { privateUserServiceuserService; publicUsersaveUser(Useruser) { returnuserService.save(user); } "/{id}") (publicResponseEntity<User>getUserById( ("id") Longid) { Useruser=userService.findById(id); log.warn("user="+user.hashCode()); HttpStatusstatus=user==null?HttpStatus.NOT_FOUND : HttpStatus.OK; returnnewResponseEntity<>(user, status); } "/{id}") (publicStringremoveUser( ("id") Longid) { userService.deleteById(id); return"ok"; } }
9. 创建入口类
最后创建一个项目入口类,启动项目。
packagecom.yyg.boot; importorg.springframework.boot.SpringApplication; importorg.springframework.boot.autoconfigure.SpringBootApplication; publicclassCacheApplication { publicstaticvoidmain(String[] args) { SpringApplication.run(CacheApplication.class, args); } }
10. 项目代码结构
这是完整的项目代码结构,各位可以参考创建。
11. 启动项目进行测试
11.1 测试数据添加
我们首先调用添加接口在Postman中执行,往数据库中添加一条数据。
可以看到数据库中,已经成功的添加了一条数据。
11.2 测试查询功能
然后我们再测试一下查询接口方法。
此时可以看到控制台中,会打印出User对象的hashCode。
11.3 验证缓存效果
我们再多次执行查询接口,发现User对象的hashCode值不变,说明数据都是来自于缓存,而不是每次都重新查询。
结语
至此,我们就利用Spring Cache的注解,在Spring Boot中实现了缓存功能,你会发现这种缓存的实现是很简单的,你学会了吗?
今日小作业:
对学生信息管理系统进行缓存优化。