当前位置: 首页 > news >正文

【AI学习笔记】用AI生成spring boot + redis

环境: WIN11 家庭版 | IDEA2023 | JDK17 | MAVEN3.6+ | redis for windows

1.“我:请帮我生成一个spring boot 项目”

2.deepseek:

打开 IDEA,点击 New Project
选择 Spring Initializr
Name: 项目名称(如 demo-project)
Location: 项目保存路径
Language: Java
Type: Maven 或 Gradle
Group: 包名(如 com.example)
Artifact: 项目标识(如 demo)
Package name: 自动生成(如 com.example.demo)
JDK: 选择 JDK 17
Java: 17
选择依赖(根据需求选择):
Spring Web - Web 开发
Spring Boot DevTools - 开发工具
Lombok - 简化代码
Spring Data JPA - 数据库操作
MySQL Driver - MySQL 数据库
Thymeleaf - 模板引擎
点击 Create 完成项目创建**项目结构:**demo-project/
├── src/
│   ├── main/
│   │   ├── java/
│   │   │   └── com/example/demo/
│   │   │       ├── DemoApplication.java
│   │   │       ├── controller/
│   │   │       ├── service/
│   │   │       └── repository/
│   │   └── resources/
│   │       ├── application.properties
│   │       ├── static/
│   │       └── templates/
├── pom.xml
└── README.md
package com.example.demo.controller;import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;@RestController
public class HelloController {@GetMapping("/hello")public String hello() {return "Hello, Spring Boot with JDK 17!";}@GetMapping("/info")public String info() {return "项目运行在 JDK " + System.getProperty("java.version");}
}

配置application.properties/application.yml

properties
# 服务器配置
server.port=8080
server.servlet.context-path=/# 应用配置
spring.application.name=demo-project# 日志配置
logging.level.com.example.demo=DEBUG

运行项目
打开 DemoApplication.java

点击 main 方法旁边的运行按钮

或使用快捷键:Ctrl+Shift+F10

测试应用
在浏览器中访问:

http://localhost:8080/hello

http://localhost:8080/info

3.“在上述项目中添加redis”

4.deepseek:

添加 Redis 依赖

<dependencies><!-- Spring Boot Data Redis --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency><!-- Redis 连接池 --><dependency><groupId>org.apache.commons</groupId><artifactId>commons-pool2</artifactId></dependency><!-- JSON 序列化支持 --><dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-databind</artifactId></dependency>
</dependencies>

配置 redis - application.properties

# redis 基本配置
spring.redis.host=localhost
spring.redis.port=6379
spring.redis.password=
spring.redis.database=0# 连接池配置
spring.redis.lettuce.pool.max-active=8
spring.redis.lettuce.pool.max-idle=8
spring.redis.lettuce.pool.min-idle=0
spring.redis.lettuce.pool.max-wait=-1ms# 连接超时
spring.redis.timeout=2000ms

新增redis配置类
创建 Redis 配置类来自定义序列化方式

package com.example.demo.config;import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;@Configuration
public class RedisConfig {@Beanpublic RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory connectionFactory) {RedisTemplate<String, Object> template = new RedisTemplate<>();template.setConnectionFactory(connectionFactory);// 设置 key 的序列化器template.setKeySerializer(new StringRedisSerializer());template.setHashKeySerializer(new StringRedisSerializer());// 设置 value 的序列化器template.setValueSerializer(new GenericJackson2JsonRedisSerializer());template.setHashValueSerializer(new GenericJackson2JsonRedisSerializer());template.afterPropertiesSet();return template;}
}

创建redis服务类

package com.example.demo.service;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;import java.util.concurrent.TimeUnit;@Service
public class RedisService {@Autowiredprivate RedisTemplate<String, Object> redisTemplate;/*** 设置缓存*/public void set(String key, Object value) {redisTemplate.opsForValue().set(key, value);}/*** 设置缓存带过期时间*/public void set(String key, Object value, long timeout, TimeUnit unit) {redisTemplate.opsForValue().set(key, value, timeout, unit);}/*** 获取缓存*/public Object get(String key) {return redisTemplate.opsForValue().get(key);}/*** 删除缓存*/public Boolean delete(String key) {return redisTemplate.delete(key);}/*** 判断 key 是否存在*/public Boolean hasKey(String key) {return redisTemplate.hasKey(key);}/*** 设置过期时间*/public Boolean expire(String key, long timeout, TimeUnit unit) {return redisTemplate.expire(key, timeout, unit);}/*** 获取过期时间*/public Long getExpire(String key) {return redisTemplate.getExpire(key, TimeUnit.SECONDS);}
}

创建redis测试方法

package com.example.demo.controller;import com.example.demo.service.RedisService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;@RestController
@RequestMapping("/redis")
public class RedisController {@Autowiredprivate RedisService redisService;/*** 设置缓存*/@PostMapping("/set")public String set(@RequestParam String key, @RequestParam String value) {redisService.set(key, value);return "设置成功: " + key + " = " + value;}/*** 设置带过期时间的缓存*/@PostMapping("/setWithExpire")public String setWithExpire(@RequestParam String key, @RequestParam String value,@RequestParam long timeout) {redisService.set(key, value, timeout, TimeUnit.SECONDS);return "设置成功: " + key + " = " + value + ", 过期时间: " + timeout + "秒";}/*** 获取缓存*/@GetMapping("/get/{key}")public Object get(@PathVariable String key) {Object value = redisService.get(key);if (value == null) {return "键不存在: " + key;}return value;}/*** 删除缓存*/@DeleteMapping("/delete/{key}")public String delete(@PathVariable String key) {Boolean result = redisService.delete(key);return result ? "删除成功: " + key : "删除失败,键不存在: " + key;}/*** 检查键是否存在*/@GetMapping("/hasKey/{key}")public String hasKey(@PathVariable String key) {Boolean exists = redisService.hasKey(key);return exists ? "键存在: " + key : "键不存在: " + key;}/*** 获取系统信息*/@GetMapping("/info")public Map<String, Object> getRedisInfo() {Map<String, Object> info = new HashMap<>();info.put("javaVersion", System.getProperty("java.version"));info.put("redisStatus", "已连接");// 测试 Redis 连接try {redisService.set("test_connection", "success", 10, TimeUnit.SECONDS);info.put("redisTest", "连接正常");} catch (Exception e) {info.put("redisTest", "连接失败: " + e.getMessage());}return info;}
}

创建用户对象

package com.example.demo.model;import java.io.Serializable;
import java.time.LocalDateTime;public class User implements Serializable {private Long id;private String username;private String email;private LocalDateTime createTime;// 构造方法public User() {}public User(Long id, String username, String email) {this.id = id;this.username = username;this.email = email;this.createTime = LocalDateTime.now();}// Getter 和 Setterpublic Long getId() { return id; }public void setId(Long id) { this.id = id; }public String getUsername() { return username; }public void setUsername(String username) { this.username = username; }public String getEmail() { return email; }public void setEmail(String email) { this.email = email; }public LocalDateTime getCreateTime() { return createTime; }public void setCreateTime(LocalDateTime createTime) { this.createTime = createTime; }@Overridepublic String toString() {return "User{" +"id=" + id +", username='" + username + '\'' +", email='" + email + '\'' +", createTime=" + createTime +'}';}
}

redis缓存示例

package com.example.demo.service;import com.example.demo.model.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;import java.util.concurrent.TimeUnit;@Service
public class UserCacheService {@Autowiredprivate RedisService redisService;private static final String USER_KEY_PREFIX = "user:";private static final long USER_CACHE_TIMEOUT = 30; // 30分钟/*** 缓存用户信息*/public void cacheUser(User user) {String key = USER_KEY_PREFIX + user.getId();redisService.set(key, user, USER_CACHE_TIMEOUT, TimeUnit.MINUTES);}/*** 从缓存获取用户信息*/public User getCachedUser(Long userId) {String key = USER_KEY_PREFIX + userId;Object obj = redisService.get(key);if (obj instanceof User) {return (User) obj;}return null;}/*** 删除用户缓存*/public void removeUserFromCache(Long userId) {String key = USER_KEY_PREFIX + userId;redisService.delete(key);}
}

测试用户缓存

package com.example.demo.controller;import com.example.demo.model.User;
import com.example.demo.service.UserCacheService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;@RestController
@RequestMapping("/user")
public class UserController {@Autowiredprivate UserCacheService userCacheService;/*** 缓存用户信息*/@PostMapping("/cache")public String cacheUser(@RequestParam Long id, @RequestParam String username,@RequestParam String email) {User user = new User(id, username, email);userCacheService.cacheUser(user);return "用户缓存成功: " + user;}/*** 获取缓存用户*/@GetMapping("/cache/{id}")public Object getCachedUser(@PathVariable Long id) {User user = userCacheService.getCachedUser(id);if (user == null) {return "用户未在缓存中找到: " + id;}return user;}/*** 删除缓存用户*/@DeleteMapping("/cache/{id}")public String removeCachedUser(@PathVariable Long id) {userCacheService.removeUserFromCache(id);return "用户缓存已删除: " + id;}
}

备注:windows家庭版无法使用docker部署redis,请使用windows专业版、教育版等。

综上,一个简单的springboot + redis框架已经完成,亲测可用,后续将继续扩展集群、分布式,日志、权限等模块

在此记录相关知识点:

spring 两大特点 : IOC/控制反转和依赖注入

ioc个人简单理解:
以前想用对象,我需要 A a = new A;
IOC:先将对象通过配置注解的方式标记,需要使用时,直接使用对象,不需要new,
官方说法是,可以解耦,自我理解为:我先声明我有这个玩意,哪里要用,直接拿来用即可,无需一遍遍的new。

AOP 面向切面,这个理解简单一些,我可以再固定的位置定义切入点,定义后,我可以操作切入点前后执行方法

可以定义before(方法前)、After(方法后)、After-returning(方法执行成功后) After-throwing(方法执行异常后)、Around(环绕)

Around特殊点,可以设置前后执行方法,一般处理事务常用,处理前开启事务,处理后提交事务。

redis 雪崩,击穿,穿透 ,主要是前两者 是key失效,或者redis服务挂了导致请求直接注入数据库,给数据库干蒙蔽。

后者是请求了一个未知key ,要么把null写进redis,要么使用布隆过滤器,原理是预加载,把已知的Key全部缓存进去,如果不存在,直接返回空。

个人理解为,主机启动前先加载缓存数据至redis。

前两者解决方案:雪崩的,设置差异化过期时间,也就是设置失效时间时,给个随机码,每个key不一致,这种情况下,可以避免同时且大量失效。

也可以部署redis集群+哨兵、熔断、服务降级、兜底返回等这个太长了以后写。

击穿的,参照微博热点时间,同一时间大量请求指向一个key,好巧不巧,key失效了,结果就是数据库炸了,现象就是,用户点着没反应,要么报错

这个解决方案查了一下,热点事件一般会轮换设置长期生效,当一个事件不再是热点,则设置短期,当一个事件登上热点,触发设置长期。

另一个就是互斥锁,redis的setnx命令 或 redission(分布式锁)

当发现key失效后,请求key设置setnx成功(lock:key1),并给一个超时时间(5s),然后去查数据库,重新设置缓存,然后删除lock

这个过程中,其他请求发现key失效后,先尝试lock,但因为互斥,所以lock失败,这个时候对方会重新发起请求,或者直接给一个失败结果,主要是保证不会击穿redis,直接将大量请求放到数据库。

http://www.dtcms.com/a/479462.html

相关文章:

  • 如何用rp做网站seo推广系统
  • 易书网上书城网站建设方案江山网站制作
  • 【工业场景】用YOLOv8实现抽烟识别
  • 易语言怎么制作网站哪些网站做的海报比较高大上
  • TCP协议详解
  • 如何进行一个网站建设网站开发赚不赚钱
  • 【c++】:Lambda 表达式介绍和使用
  • 四川建设厅网站施工员证查询网站建设找盛誉网络
  • 了解网站开发 后台流程详情页尺寸
  • 2025年10月13日
  • 使用Reindex迁移Elasticsearch集群数据详解(上)
  • 网站设计 优帮云北京做网站公司电话
  • 上海高端网站制作公司专业网站设计建设服务
  • 大模型-CLIP 双编码器架构如何优化图文关联
  • [Qlib] `Model` | `fit` `predict`
  • 线程池Executors
  • 莆田企业网站建设网站建设的会计核算
  • Redis集群架构详解:如何实现高可用和高性能
  • 凤岗网站建设电商系统架构图
  • 知乎 上海做网站的公司自己做一个网站需要多少钱
  • 广州网站开发怎么做如何利用网站来提升企业形象
  • ESD防护设计宝典(八):能量的阀门——电源分配网络(PDN)设计
  • 怎么建设网站规划网站开场动画怎么做
  • 帝国cms怎么做网站地图竞价推广代运营公司
  • C语言--VSCode开发环境配置
  • 企业网站建设智恒网络山东网站营销seo哪家好
  • 12380网站建设打算手机网站建设liedns
  • 为什么做营销型网站网站的经营推广
  • 公章在线制作网站沈阳建设工程质量安全
  • vtkImageThreshold 图像阈值处理指南:从基础到实战优化