SpringBoot如何引入緩存提高單次查詢數(shù)據(jù)效率
SpringBoot引入緩存提高單次查詢數(shù)據(jù)效率
第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);
// 查詢數(shù)據(jù)庫值先存緩存
StudentContextHolder.setStudent(id, student);
return student;
}
第3步:清理緩存上下文
public class ResponsePostInterceptor implements HandlerInterceptor {
//在Controller執(zhí)行之前調(diào)用,如果返回false,controller不執(zhí)行
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.err.println("***ResponsePostInterceptor.preHandle***");
return true;
}
//controller執(zhí)行之后,且頁面渲染之前調(diào)用
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.err.println("***ResponsePostInterceptor.postHandle***");
}
//頁面渲染之后調(diào)用,一般用于資源清理操作
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.err.println("***ResponsePostInterceptor.afterCompletion***");
StudentContextHolder.clear(); // 清除student上下文
}
}
第4步:驗(yàn)證使用
@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);
}
執(zhí)行日志
[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***
總結(jié)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
Springboot項(xiàng)目啟動(dòng)失敗提示找不到dao類的解決
Spring Boot啟動(dòng)失敗,因ProductServiceImpl未正確注入ProductDao,原因:Dao未注冊(cè)為Bean,解決:在啟動(dòng)類添加@MapperScan掃描Dao包,或單個(gè)Dao加@Mapper注解,推薦前者以批量注入2025-08-08
簡(jiǎn)單了解Java關(guān)鍵字throw和throws的區(qū)別
這篇文章主要介紹了簡(jiǎn)單了解Java關(guān)鍵字throw和throws的區(qū)別,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-11-11
java中將一個(gè)實(shí)體類復(fù)制到另一個(gè)實(shí)體類的3種方法示例
這篇文章主要給大家介紹了關(guān)于java中將一個(gè)實(shí)體類復(fù)制到另一個(gè)實(shí)體類的3種方法,所謂實(shí)體類就是一個(gè)擁有Set和Get方法的類,文中通過實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下2023-07-07
SpringBoot中登錄驗(yàn)證碼的4種實(shí)現(xiàn)方案
這篇文章主要介紹了在SpringBoot應(yīng)用中實(shí)現(xiàn)四種登錄驗(yàn)證碼的技術(shù)方案,包括圖形驗(yàn)證碼、短信驗(yàn)證碼、郵箱驗(yàn)證碼和滑動(dòng)拼圖驗(yàn)證碼,需要的可以參考下2025-04-04
Java集合定義與用法實(shí)例總結(jié)【Set、List與Map】
這篇文章主要介紹了Java集合定義與用法,結(jié)合實(shí)例形式總結(jié)分析了Java集合中Set、List和Map相關(guān)概念、功能、用法及操作注意事項(xiàng),需要的朋友可以參考下2018-08-08
Java源碼難點(diǎn)突破Lambda表達(dá)式執(zhí)行原理
這篇文章主要為大家介紹了Java難點(diǎn)突破Lambda表達(dá)式執(zhí)行原理分析及示例的實(shí)現(xiàn)源碼,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步2022-03-03
SpringBoot中實(shí)現(xiàn)定時(shí)任務(wù)的4種方式詳解
這篇文章主要介紹了SpringBoot中實(shí)現(xiàn)定時(shí)任務(wù)的4種方式詳解,在Springboot中定時(shí)任務(wù)是一項(xiàng)經(jīng)常能用到的功能,實(shí)現(xiàn)定時(shí)任務(wù)的方式有很多,今天來介紹常用的幾種,需要的朋友可以參考下2023-11-11

