缓存是一种介于数据永久存储介质与数据应用之间的数据临时存储介质
目的:使用缓存可以有效减少低俗数据读取过程的此数(例如磁盘IO),提高系统性能(如果当前缓存中没有本次要查询的数据,则进行查询,否则就从缓存中获取,就不用再访问数据库,同时也减少了数据库的压力)
缓存不仅可以用于提高永久性存储介质的数据读取效率,还可以提供临时的数据存储空间
springboot提供了缓存技术
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-cache</artifactId>
- </dependency>
- #第二种方法:Druid专用配置 推荐
- spring:
- datasource:
- druid:
- driver-class-name: com.mysql.cj.jdbc.Driver
- url: jdbc:mysql://localhost:3306/user_db?serverTimezone=GMT
- username: root
- password: admin
-
- #开启MP运行日志
- mybatis-plus:
- configuration:
- # 标准输出 打印到控制台上 以后我们就不用sout输出了, 这个东西会帮我们输出
- log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
-
-
- @SpringBootApplication
- @EnableCaching // 这个注解的作用是开启缓存功能
- public class Springboot19CacheApplication {
-
- public static void main(String[] args) {
- SpringApplication.run(Springboot19CacheApplication.class, args);
- }
-
- }
- @RestController
- @RequestMapping("/books")
- public class BookController {
- @Autowired
- private BookService bookService;
-
- @GetMapping("{id}")
- public Book get(@PathVariable Integer id){
- return bookService.getById(id);
- }
-
- @PostMapping
- public boolean save (@RequestBody Book book){
- return bookService.save(book);
- }
-
- @PutMapping
- public boolean updata(@RequestBody Book book){
- return bookService.update(book);
- }
-
- @DeleteMapping("{id}")
- public boolean delete(@RequestBody Integer id){
- return bookService.delete(id);
- }
-
- @GetMapping
- public List<Book> getAll(){
- return bookService.getAll();
- }
- }
- @Mapper //通过这个实现数据库的操作 里面有数据库中各种各样的操作
- public interface BookDao extends BaseMapper<Book> {//指定泛型才能知道操作谁
-
- }
- @Data //get+set+toString+hashcode+equals 但是没有构造方法
- @TableName(value = "t_book")
- public class Book {
- // 这里的属性名 要和数据库表中的属性名一致,要不然最终的查询结果是null
- // 将数据库中的结果对此变量名进行注入
- @TableId(value="id",type = IdType.AUTO) //代表自增算法
- @TableField(value = "id")
- private int id;
-
- @TableField(value = "bookName")
- private String bookName;
-
- @TableField(value = "statue")
- private String statue;
-
- @TableField(value="type")
- private String type;
-
- public Book() {
- }
-
- public Book(int id, String bookName, String statue, String type) {
- this.id = id;
- this.bookName = bookName;
- this.statue = statue;
- this.type = type;
- }
- }
- public interface BookService extends IService<Book> {
- public Book getById(Integer id);
- public boolean save(Book book);
- public boolean update(Book book);
- public boolean delete(Integer id);
- public List<Book> getAll();
- }
对getById方法设置缓存机制
就下面这个图而言,如果这个cacheSpace空间中有key的这个操作,那就从CacheSpace中找出来,如果没有的话,再执行方法体中的内容,从而达到了缓存的操作
- @Service
- public class BookServiceImpl extends ServiceImpl<BookDao, Book> implements BookService {
-
- @Autowired
- private BookDao bookDao;
-
- @Override
- @Cacheable(value = "catchSpace",key = "#id")
- //是否是课缓存的,其中要指定两个参数,value 就是放的位置,随便定义;下次找用id找,所以key=id
- // 运行之后,我们就会把查询之后的数据放到上面这个“id”里面,作为key
- public Book getById(Integer id){
- return bookDao.selectById(id);
- }
-
- @Override
- public boolean save(Book book) {
- return bookDao.insert(book) >0;
- }
-
- @Override
- public boolean update(Book book) {
- return bookDao.updateById(book) >0;
- }
-
- @Override
- public boolean delete(Integer id) {
- return bookDao.deleteById(id) >0;
- }
-
- @Override
- public List<Book> getAll() {
- return bookDao.selectList(null);
- }
- }
运行下面这个程序
- @SpringBootApplication
- @EnableCaching // 这个注解的作用是开启缓存功能
- public class Springboot19CacheApplication {
-
- public static void main(String[] args) {
- SpringApplication.run(Springboot19CacheApplication.class, args);
- }
-
- }
接下来在postman中执行下面的语句两次
但是我们发现在idea中只有一条运行结果,所以我们缓存成功
controller.SMSCodeController
- @RestController
-
- @RequestMapping("/sms")
- public class SMSCodeController {
-
- @Autowired
- private SMSCodeService service;
-
- // 通过接受到的电话,得到code码
- @GetMapping
- public String getCode(String tele){
- String code = service.sendCodeToSMS(tele);
- return code;
- }
-
- // 检验一下code码是否正确
- // 把电话号码和验证码都给我们,然后验证是否正确
- @PostMapping
- public boolean checkCode( SMSCode smsCode){//SMSCode类型属性中包含tele和code
- return service.checkCode(smsCode);
- }
-
-
- }
domain.SMSCode
- @Data
- public class SMSCode {
- private String tele; //手机号码
- private String code; //手机验证码
- }
service.serviceImpl.SMSCodeServiceImpl
-
- @Service
- public class SMSCodeServiceImpl implements SMSCodeService {
- @Autowired
- private CodeUtils codeUtils;
-
- @Override
- // 开启缓存功能
- // @Cacheable(value = "cacheSpace" , key = "#tele") 这个语句在这里其实并不适用,因为我们一般的验证码都是一分钟以内,如果再次获取验证码,就不是这个了
- // value = "smsCode" 缓存空间
- @CachePut(value="smsCode",key="#tele") //这个注解可以做到往缓存中放入return的code值,把指定的返回值放到指定的key的位置
- public String sendCodeToSMS(String tele) {
- String code= codeUtils.generator(tele);
- return code;
- }
-
- @Override
- public boolean checkCode(SMSCode smsCode) {
- // 取出内存中的验证码与传递过来的验证码进行对比,如果相同,返回true
- String code = smsCode.getCode();
- String cacheCode =codeUtils.get(smsCode.getTele()); //这是缓存中的验证码,因为tele是key,所以在此处要传入一个tele
- return code.equals(cacheCode);
- }
- }
service.SMSCodeService
-
- public interface SMSCodeService {
- public String sendCodeToSMS(String tele);
- public boolean checkCode(SMSCode smsCode);
-
- }
utils.CodeUtils
- @Component
- public class CodeUtils {
-
- private String[] patch = {"00000","0000","000","00","0",""}; //利用数据结构的优化,进行补零
-
-
- public String generator(String tele){
- int hash = tele.hashCode(); //这个得到的tele的哈希值和我们即将要生成的验证码有很必要的关系
- int encryption = 20206666;
- // 第一次加密
- long result = hash ^ encryption;
- // 第二次加密
- long nowTime = System.currentTimeMillis();
- result = result^nowTime;
- // 取某result的某些位数作为 验证码
- long code = result%1000000; //六个余数
- code = code<0 ? -code :code; //将验证码的复数排除
- // 如果我们生成的code前面几位是零的话,就会省略了前面的零,但是省略的之后,就不足六位了,我们现在要对不足六位的数据进行补零
- String codeStr = code+"";
- int len = codeStr.length();
- return patch[len-1]+codeStr;
- }
-
- @Cacheable(value = "smsCode" , key = "#tele") //key在这里就是电话号码,类似将电话号码作为key
- public String get(String tele){
- // 如果缓存中有对应数据,那我们就利用key获取到了
- // 如果缓存中没有对应的数据,那我们就返回null,也非常的合理
- return null;
- }
- }
postman获取验证码:
postman对验证码进行验证
maven坐标
- <dependency>
- <groupId>net.sf.ehcache</groupId>
- <artifactId>ehcache</artifactId>
- </dependency>
配置文件的配置
- #第二种方法:Druid专用配置 推荐
- spring:
- datasource:
- druid:
- driver-class-name: com.mysql.cj.jdbc.Driver
- url: jdbc:mysql://localhost:3306/user_db?serverTimezone=GMT
- username: root
- password: admin
- cache:
- type: ehcache
-
- #开启MP运行日志
- mybatis-plus:
- configuration:
- # 标准输出 打印到控制台上 以后我们就不用sout输出了, 这个东西会帮我们输出
- log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
下面的这个配置要和上面的左边进行配对,如果有这个配置,但是没有坐标,一样会出现错误
以及还有下面的ehcache.xml配置文件
上面的这组配置,是配置的默认的缓存的地方,但是从我们的代码来看,我们显然不是存放在默认的地方,而是“smsCode”缓存空间中,则我们还需要添加一组配置(不同的数据,缓存不一样,所以可以设置多个缓存策略)
其中,下面的 “name”就是我们指定缓存空间