觉得对你有益的小伙伴记得点个赞+关注
后续完整内容持续更新中
希望一起交流的欢迎发邮件至javalyhn@163.com
学Redis,光看理论未免太枯燥了。因此先来一个小实战热热身。 该实战用到了Swagger,一个很简单的工具,不会没关系,看完下面的实战就会用了,要是想更加深入的理解,欢迎期待我来更新。
1 Springboot+Mybatis+redis缓存实战
1.1 创建Moudle
1.2 改pom
<dependencies>
<!--SpringBoot通用依赖模块-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!--swagger2-->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.9.2</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.9.2</version>
</dependency>
<!--SpringBoot与Redis整合依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!-- jedis -->
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>3.1.0</version>
</dependency>
<!--Mysql数据库驱动-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>${mysql.version}</version>
</dependency>
<!--SpringBoot集成druid连接池-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.1.10</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>${druid.version}</version>
</dependency>
<!--mybatis和springboot整合-->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>${mybatis.spring.boot.version}</version>
</dependency>
<!-- 添加springboot对amqp的支持 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
<version>1.10</version>
</dependency>
<!--通用基础配置junit/devtools/test/log4j/lombok/hutool-->
<!--hutool-->
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.2.3</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${junit.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>${log4j.version}</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
<optional>true</optional>
</dependency>
<!--persistence-->
<dependency>
<groupId>javax.persistence</groupId>
<artifactId>persistence-api</artifactId>
<version>1.0.2</version>
</dependency>
<!--通用Mapper-->
<dependency>
<groupId>tk.mybatis</groupId>
<artifactId>mapper</artifactId>
<version>${mapper.version}</version>
</dependency>
</dependencies>
1.3 写yml(properties)
server.port=5555
spring.application.name=redis
# ========================logging 日志相关的配置=====================
#系统默认,全局root配置的日志形式,可以注释掉
logging.level.root=warn
#开发人员自己设置的包结构,对那个package进行什么级别的日志监控
logging.level.com.lyhn.redis=info
#开发人员自定义日志路径和日志名称
logging.file.name=D:/mylogs2/logs/redis.log
#%d{HH:mm:ss.SSS}――日志输出时间
#%thread――输出日志的进程名字,这在Web应用以及异步任务处理中很有用
#%-5level――日志级别,并且使用5个字符靠左对齐
#%logger- ――日志输出者的名字
#%msg――日志消息
#%n――平台的换行符
#logging.pattern.console=%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger- %msg%n
logging.pattern.console=%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger- %msg%n
logging.pattern.file=%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger- %msg%n
# ========================alibaba.druid相关配置=====================
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/db2022?useUnicode=true&characterEncoding=utf-8&useSSL=false
spring.datasource.username=root
spring.datasource.password=123456
spring.datasource.druid.test-while-idle=false
# ========================redis相关配置=====================
# Redis数据库索引(默认为0)
spring.redis.database=0
# Redis服务器地址
spring.redis.host=
# Redis服务器连接端口
spring.redis.port=
# Redis服务器连接密码(默认为空)
spring.redis.password=
# 连接池最大连接数(使用负值表示没有限制) 默认 8
spring.redis.lettuce.pool.max-active=8
# 连接池最大阻塞等待时间(使用负值表示没有限制) 默认 -1,记得加入单位ms,不然idea报红色
spring.redis.lettuce.pool.max-wait=-1ms
# 连接池中的最大空闲连接 默认 8
spring.redis.lettuce.pool.max-idle=8
# 连接池中的最小空闲连接 默认 0
spring.redis.lettuce.pool.min-idle=0
# ========================mybatis相关配置===================
mybatis.mapper-locations=classpath:mapper/*.xml
mybatis.type-aliases-package=com.lyhn.redis.entities
# ========================swagger=====================
spring.swagger2.enabled=true
1.4 主启动
@SpringBootApplication
@MapperScan("com.lyhn.redis_practice.mapper") //import tk.mybatis.spring.annotation.MapperScan;
public class RedisPracticeApplication {
public static void main(String[] args) {
SpringApplication.run(RedisPracticeApplication.class, args);
}
}
1.5 业务类
RedisConfig
@Configuration
public class RedisConfig
{
/**
* @param lettuceConnectionFactory
* @return
*
* redis序列化的工具配置类,下面这个请一定开启配置
* 127.0.0.1:6379> keys *
* 1) "ord:102" 序列化过
* 2) "\xac\xed\x00\x05t\x00\aord:102" 野生,没有序列化过
*/
@Bean
public RedisTemplate<String,Serializable> redisTemplate(LettuceConnectionFactory lettuceConnectionFactory)
{
RedisTemplate<String,Serializable> redisTemplate = new RedisTemplate<>();
redisTemplate.setConnectionFactory(lettuceConnectionFactory);
//设置key序列化方式string
redisTemplate.setKeySerializer(new StringRedisSerializer());
//设置value的序列化方式json
redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer());
redisTemplate.setHashKeySerializer(new StringRedisSerializer());
redisTemplate.setHashValueSerializer(new GenericJackson2JsonRedisSerializer());
redisTemplate.afterPropertiesSet();
return redisTemplate;
}
}
编写这个配置类的原因是为了解决Redis序列化的问题
如果我们不进行序列化
正确情况
SwaggerConfig
@Configuration
@EnableSwagger2
public class SwaggerConfig {
@Value("${spring.swagger2.enabled}")
private Boolean enabled;
@Bean
public Docket createRestApi() {
return new Docket(DocumentationType.SWAGGER_2)
.apiInfo(apiInfo())
.enable(enabled)
.select()
.apis(RequestHandlerSelectors.basePackage("com.lyhn.redis_practice")) //你自己的package
.paths(PathSelectors.any())
.build();
}
public ApiInfo apiInfo() {
return new ApiInfoBuilder()
.title("springboot利用swagger2构建api接口文档 "+"\t"+new SimpleDateFormat("yyyy-MM-dd").format(new Date()))
.description("lyhn的高级篇redis")
.version("1.0")
.build();
}
}
1.6 干活
- 检查数据库表t_user是否ok
- TK Mapper拷贝来的User juejin.cn/post/719060…
@Table(name = "t_user")
public class User {
@GeneratedValue(generator = "JDBC")
@Id
private Integer id;
/**
* 用户名
*/
private String username;
/**
* 密码
*/
private String password;
/**
* 性别 0=女 1=男
*/
private Byte sex;
/**
* 删除标志,默认0不删除,1删除
*/
private Byte deleted;
/**
* 更新时间
*/
@Column(name = "update_time")
private Date updateTime;
/**
* 创建时间
*/
@Column(name = "create_time")
private Date createTime;
/**
* @return id
*/
public Integer getId() {
return id;
}
/**
* @param id
*/
public void setId(Integer id) {
this.id = id;
}
/**
* 获取用户名
*
* @return username - 用户名
*/
public String getUsername() {
return username;
}
/**
* 设置用户名
*
* @param username 用户名
*/
public void setUsername(String username) {
this.username = username;
}
/**
* 获取密码
*
* @return password - 密码
*/
public String getPassword() {
return password;
}
/**
* 设置密码
*
* @param password 密码
*/
public void setPassword(String password) {
this.password = password;
}
/**
* 获取性别 0=女 1=男
*
* @return sex - 性别 0=女 1=男
*/
public Byte getSex() {
return sex;
}
/**
* 设置性别 0=女 1=男
*
* @param sex 性别 0=女 1=男
*/
public void setSex(Byte sex) {
this.sex = sex;
}
/**
* 获取删除标志,默认0不删除,1删除
*
* @return deleted - 删除标志,默认0不删除,1删除
*/
public Byte getDeleted() {
return deleted;
}
/**
* 设置删除标志,默认0不删除,1删除
*
* @param deleted 删除标志,默认0不删除,1删除
*/
public void setDeleted(Byte deleted) {
this.deleted = deleted;
}
/**
* 获取更新时间
*
* @return update_time - 更新时间
*/
public Date getUpdateTime() {
return updateTime;
}
/**
* 设置更新时间
*
* @param updateTime 更新时间
*/
public void setUpdateTime(Date updateTime) {
this.updateTime = updateTime;
}
/**
* 获取创建时间
*
* @return create_time - 创建时间
*/
public Date getCreateTime() {
return createTime;
}
/**
* 设置创建时间
*
* @param createTime 创建时间
*/
public void setCreateTime(Date createTime) {
this.createTime = createTime;
}
}
- Swagger和前台DTO配置UserDTO(DTO:data tranfer object 数据传输对象)
@NoArgsConstructor
@AllArgsConstructor
@Data
@ApiModel(value = "用户信息")
public class UserDTO implements Serializable
{
@ApiModelProperty(value = "用户ID")
private Integer id;
@ApiModelProperty(value = "用户名")
private String username;
@ApiModelProperty(value = "密码")
private String password;
@ApiModelProperty(value = "性别 0=女 1=男 ")
private Byte sex;
@ApiModelProperty(value = "删除标志,默认0不删除,1删除")
private Byte deleted;
@ApiModelProperty(value = "更新时间")
private Date updateTime;
@ApiModelProperty(value = "创建时间")
private Date createTime;
/**
* @return id
*/
public Integer getId() {
return id;
}
/**
* @param id
*/
public void setId(Integer id) {
this.id = id;
}
/**
* 获取用户名
*
* @return username - 用户名
*/
public String getUsername() {
return username;
}
/**
* 设置用户名
*
* @param username 用户名
*/
public void setUsername(String username) {
this.username = username;
}
/**
* 获取密码
*
* @return password - 密码
*/
public String getPassword() {
return password;
}
/**
* 设置密码
*
* @param password 密码
*/
public void setPassword(String password) {
this.password = password;
}
/**
* 获取性别 0=女 1=男
*
* @return sex - 性别 0=女 1=男
*/
public Byte getSex() {
return sex;
}
/**
* 设置性别 0=女 1=男
*
* @param sex 性别 0=女 1=男
*/
public void setSex(Byte sex) {
this.sex = sex;
}
/**
* 获取删除标志,默认0不删除,1删除
*
* @return deleted - 删除标志,默认0不删除,1删除
*/
public Byte getDeleted() {
return deleted;
}
/**
* 设置删除标志,默认0不删除,1删除
*
* @param deleted 删除标志,默认0不删除,1删除
*/
public void setDeleted(Byte deleted) {
this.deleted = deleted;
}
/**
* 获取更新时间
*
* @return update_time - 更新时间
*/
public Date getUpdateTime() {
return updateTime;
}
/**
* 设置更新时间
*
* @param updateTime 更新时间
*/
public void setUpdateTime(Date updateTime) {
this.updateTime = updateTime;
}
/**
* 获取创建时间
*
* @return create_time - 创建时间
*/
public Date getCreateTime() {
return createTime;
}
/**
* 设置创建时间
*
* @param createTime 创建时间
*/
public void setCreateTime(Date createTime) {
this.createTime = createTime;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", username='" + username + '\'' +
", password='" + password + '\'' +
", sex=" + sex +
'}';
}
}
- mapper接口
public interface UserMapper extends Mapper<User> {
}
- mapperSQL文件
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.atguigu.redis.mapper.UserMapper">
<resultMap id="BaseResultMap" type="com.atguigu.redis.entities.User">
<!--
WARNING - @mbg.generated
-->
<id column="id" jdbcType="INTEGER" property="id" />
<result column="username" jdbcType="VARCHAR" property="username" />
<result column="password" jdbcType="VARCHAR" property="password" />
<result column="sex" jdbcType="TINYINT" property="sex" />
<result column="deleted" jdbcType="TINYINT" property="deleted" />
<result column="update_time" jdbcType="TIMESTAMP" property="updateTime" />
<result column="create_time" jdbcType="TIMESTAMP" property="createTime" />
</resultMap>
</mapper>
- service类
@Slf4j
@Service
public class UserService {
public static final String CACHE_KEY_USER = "user:";
@Resource
private RedisTemplate redisTemplate;
@Resource
private UserMapper userMapper;
public void addUser(User user){
log.info("插入的user:{}",user);
int i = userMapper.insertSelective(user);//insertSelective只会插入不为null的数据
log.info("插入后的user:{}",user);
log.info("==========");
System.out.println();
if(i > 0) {
//到数据库里面,重新取出来再放进缓存 (mysql与redis要保持数据一致性 防止网络抖动等原因 要使得数据插入数据库一定成功)
user = userMapper.selectByPrimaryKey(user.getId());
//缓存key
String key = CACHE_KEY_USER + user.getId();
//往mysql里面插入成功后再从mysql查询出来,再插入redis
redisTemplate.opsForValue().set(key,user);
}
}
public void deleteUser(Integer id) {
//1 先直接删除数据库
int i = userMapper.deleteByPrimaryKey(id);
if(i > 0) {
//2 再修改缓存
String key = CACHE_KEY_USER + id;
redisTemplate.delete(key);
}
}
public void updateUser(User user) {
//1 先直接修改数据库
int i = userMapper.updateByPrimaryKeySelective(user);
if(i > 0) {
//2 再修改缓存
//缓存key
String key = CACHE_KEY_USER + user.getId();
user = userMapper.selectByPrimaryKey(user.getId());
//修改也是用set命令,重新设置,Redis没有update操作,都是重新设置新值
redisTemplate.opsForValue().set(key,user);
}
}
/**
* 先去redis里面找数据 ,找到就直接返回,找不到再去查询mysql
* @param userId
* @return
*/
public User findUserById(Integer userId){
User user = null;
//缓存key
String key=CACHE_KEY_USER+userId;
//1 查询redis
user = (User) redisTemplate.opsForValue().get(key);
//2 redis无,进一步查询mysql
if(user==null)
{
//3 从mysql查出来user
user=this.userMapper.selectByPrimaryKey(userId);
// mysql有,redis无
if (user != null) {
//4 把mysql捞到的数据写入redis,方便下次查询能redis命中。
redisTemplate.opsForValue().set(key,user);
}
}
return user;
}
}
- controller
@RestController
@Slf4j
@Api(description = "用户User接口")
public class UserController {
@Resource
private UserService userService;
@ApiOperation("数据库初始化五条数据")
@PostMapping(value = "user/add")
public void addUser() {
for (int i = 0; i < 5; i++) {
User user = new User();
user.setUsername("lyhn" + i);
user.setPassword(IdUtil.simpleUUID().substring(0,6));
user.setSex((byte) new Random().nextInt(2));
userService.addUser(user);
}
}
@ApiOperation("删除某条数据")
@RequestMapping(value = "/user/del/{id}", method = RequestMethod.POST)
public void deleteUser(@PathVariable Integer id) {
userService.deleteUser(id);
}
@ApiOperation("修改某条数据")
@RequestMapping(value = "/user/update", method = RequestMethod.POST)
public void updateUser(@RequestBody User userDTO) {
User user = new User();
BeanUtils.copyProperties(userDTO, user);
userService.updateUser(user);
}
@ApiOperation("单个用户查询,按userid查用户信息")
@RequestMapping(value = "/user/{id}", method = RequestMethod.GET)
public User findUserById(@PathVariable int id) {
return this.userService.findUserById(id);
}
}
- 启动测试Swagger是否OK
http://localhost:你的微服务端口/swagger-ui.html#/
演示一下查询操作(注意此事没有任何数据)
演示一下插入操作
查看Redis数据
剩下的可以小伙伴们自己写完了去看,很简单的
那么这个实战我们就做完了,后面还有很多案例,这个很简单,只是个开胃菜,欢迎期待下次更新!!!!