SpringBoot如何引入缓存提高单次查询数据效率

 更新时间:2024年01月27日 10:04:03   作者:张紫娃  
这篇文章主要介绍了SpringBoot如何引入缓存提高单次查询数据效率问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教

SpringBoot引入缓存提高单次查询数据效率

第1步:引入缓存上下文

import com.zhangziwa.practisesvr.model.Student;

import java.util.HashMap;
import java.util.Map;
import java.util.Objects;

import static org.apache.commons.lang3.ObjectUtils.anyNull;

public class StudentContextHolder {
    private static final ThreadLocal<Map<Integer, Student>> studentContextHolder = ThreadLocal.withInitial(HashMap::new);

    public static Student getStudent(Integer id) {
        if (Objects.isNull(id)) {
            return null;
        }
        return studentContextHolder.get().get(id);
    }

    public static void setStudent(Integer id, Student student) {
        if (anyNull(id, student)) {
            return;
        }
        if (getStudent(id) != null) {
            throw new UnsupportedOperationException("Student with id " + id + " already exists.");
        }
        studentContextHolder.get().put(id, student);
    }

    public static void clear() {
        studentContextHolder.remove();
    }
}

第2步:查询先查缓存,查询到值先存缓存

public Student queryById(Integer id) {
    if (Objects.isNull(id)) {
        return null;
    }
    
    // 线程缓存里去
    Student student = StudentContextHolder.getStudent(id);
    if (nonNull(student)) {
        return student;
    }
    
    student = studentsMapper.queryById(id);
    
    // 查询数据库值先存缓存
    StudentContextHolder.setStudent(id, student);
    
    return student;
}

第3步:清理缓存上下文

public class ResponsePostInterceptor implements HandlerInterceptor {

    //在Controller执行之前调用,如果返回false,controller不执行
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.err.println("***ResponsePostInterceptor.preHandle***");
        return true;
    }

    //controller执行之后,且页面渲染之前调用
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.err.println("***ResponsePostInterceptor.postHandle***");
    }

    //页面渲染之后调用,一般用于资源清理操作
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.err.println("***ResponsePostInterceptor.afterCompletion***");
        StudentContextHolder.clear(); //  清除student上下文
    }
}

第4步:验证使用

@GetMapping("{id}")
public ResponseEntity<Student> queryById(@PathVariable("id") Integer id) {
    System.out.println("***StudentController.queryById***");
    
    Student body = studentService.queryById(id);
    System.out.println(body);
    
    System.out.println(studentService.queryById(id));
    
    return ResponseEntity.ok(body);
}

执行日志

[2024-01-26 01:16:16.068_068] [WARN ] [http-nio-8080-exec-2] [LogFilter.java:21] → [LogFilter.doFilter: Start processing request at 2024-01-25T17:16:16.068132700Z - /students/8]
***LogFilter.doFilter.start***
***RequestHeaderCheckFilter.doFilter.start***

***ResponsePostInterceptor.preHandle***
***LogInterceptor.preHandle***
[2024-01-26 01:16:16.094_094] [WARN ] [http-nio-8080-exec-2] [LogInterceptor.java:37] → [LogInterceptor.postHandle: Start processing request at 2024-01-25T17:16:16.094950300Z - /students/8]

***StudentController.queryById***
Creating a new SqlSession
SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@3bfba234] was not registered for synchronization because synchronization is not active
[2024-01-26 01:16:16.128_128] [INFO ] [http-nio-8080-exec-2] [HikariDataSource.java:110] → [practisedb - Starting...]
[2024-01-26 01:16:16.248_248] [INFO ] [http-nio-8080-exec-2] [HikariPool.java:565] → [practisedb - Added connection com.mysql.cj.jdbc.ConnectionImpl@12e4ef1]
[2024-01-26 01:16:16.252_252] [INFO ] [http-nio-8080-exec-2] [HikariDataSource.java:123] → [practisedb - Start completed.]
JDBC Connection [HikariProxyConnection@688850212 wrapping com.mysql.cj.jdbc.ConnectionImpl@12e4ef1] will not be managed by Spring
==>  Preparing: select id, username, password, age, height, gender, class_id, is_delete from students where id = ?
***SqlExecuteInterceptor.intercept***
***SqlReadRowInterceptor.intercept***
==> Parameters: 8(Integer)
<==    Columns: id, username, password, age, height, gender, class_id, is_delete
<==        Row: 8, 汪子韬, lq2fks1eg5, 24, 161.84, 女, 5, 0
<==      Total: 1
Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@3bfba234]
Student(id=8, username=汪子韬, password=lq2fks1eg5, age=24, height=161, gender=女, classId=5, isDelete=false)

Student(id=8, username=汪子韬, password=lq2fks1eg5, age=24, height=161, gender=女, classId=5, isDelete=false)

***ResponsePostAdvice.supports***
***ResponsePostAdvice.beforeBodyWrite***

***LogInterceptor.postHandle***
***ResponsePostInterceptor.postHandle***
***LogInterceptor.afterCompletion***
[2024-01-26 01:16:16.394_394] [WARN ] [http-nio-8080-exec-2] [LogInterceptor.java:57] → [LogInterceptor.postHandle: Finished processing request at 2024-01-25T17:16:16.393566400Z - /students/8 in 299 ms. Status code: 200]
[2024-01-26 01:16:16.413_413] [INFO ] [http-nio-8080-exec-2] [logUtils.java:70] → [{"traceId":"9287f21b215b49e19ed7fd94c9aed4e6","endDate":"2024-01-26T01:16:16.3972818+08:00[Asia/Shanghai]","cost":299,"remoteHost":"0:0:0:0:0:0:0:1","remoteAddr":"0:0:0:0:0:0:0:1","remotePort":12742,"method":"GET","requestURI":"/students/8","status":200,"requestContentLength":-1,"sqlCount":1,"sqlCost":31,"sqlSearchedRowCount":1,"currentThreadTime":109,"currentThreadUserTime":78,"currentThreadAllocatedBytes":20845224}]
[2024-01-26 01:16:16.419_419] [WARN ] [http-nio-8080-exec-2] [LogFilter.java:30] → [LogFilter.doFilter: Finished processing request at 2024-01-25T17:16:16.419516700Z - /students/8 in 351 ms. Status code: 200]
***ResponsePostInterceptor.afterCompletion***

***RequestHeaderCheckFilter.doFilter.end***
***LogFilter.doFilter.end***

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • Java异常处理 如何跟踪异常的传播路径

    Java异常处理 如何跟踪异常的传播路径

    这篇文章主要介绍了Java异常处理 如何跟踪异常的传播路径,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2019-07-07
  • Springboot项目启动失败提示找不到dao类的解决

    Springboot项目启动失败提示找不到dao类的解决

    Spring Boot启动失败,因ProductServiceImpl未正确注入ProductDao,原因:Dao未注册为Bean,解决:在启动类添加@MapperScan扫描Dao包,或单个Dao加@Mapper注解,推荐前者以批量注入
    2025-08-08
  • 简单了解Java关键字throw和throws的区别

    简单了解Java关键字throw和throws的区别

    这篇文章主要介绍了简单了解Java关键字throw和throws的区别,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2019-11-11
  • 解决idea找不到或无法加载主类的错误处理

    解决idea找不到或无法加载主类的错误处理

    这篇文章主要介绍了解决idea找不到或无法加载主类的错误处理,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-04-04
  • java中将一个实体类复制到另一个实体类的3种方法示例

    java中将一个实体类复制到另一个实体类的3种方法示例

    这篇文章主要给大家介绍了关于java中将一个实体类复制到另一个实体类的3种方法,所谓实体类就是一个拥有Set和Get方法的类,文中通过实例代码介绍的非常详细,需要的朋友可以参考下
    2023-07-07
  • SpringBoot中登录验证码的4种实现方案

    SpringBoot中登录验证码的4种实现方案

    这篇文章主要介绍了在SpringBoot应用中实现四种登录验证码的技术方案,包括图形验证码、短信验证码、邮箱验证码和滑动拼图验证码,需要的可以参考下
    2025-04-04
  • Java集合定义与用法实例总结【Set、List与Map】

    Java集合定义与用法实例总结【Set、List与Map】

    这篇文章主要介绍了Java集合定义与用法,结合实例形式总结分析了Java集合中Set、List和Map相关概念、功能、用法及操作注意事项,需要的朋友可以参考下
    2018-08-08
  • springboot日期格式化及时差问题分析

    springboot日期格式化及时差问题分析

    这篇文章主要介绍了springboot日期格式化,时差问题,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2022-12-12
  • Java源码难点突破Lambda表达式执行原理

    Java源码难点突破Lambda表达式执行原理

    这篇文章主要为大家介绍了Java难点突破Lambda表达式执行原理分析及示例的实现源码,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步
    2022-03-03
  • SpringBoot中实现定时任务的4种方式详解

    SpringBoot中实现定时任务的4种方式详解

    这篇文章主要介绍了SpringBoot中实现定时任务的4种方式详解,在Springboot中定时任务是一项经常能用到的功能,实现定时任务的方式有很多,今天来介绍常用的几种,需要的朋友可以参考下
    2023-11-11

最新评论