SpringBoot中集成Redis

目标

在原有SpringBoot项目中,集成Redis,并实现Dao层,Service层,Controller层。

pom.xml

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

使用Spring Boot的Redis依赖。

application-dev.yaml

spring:redis:host: ${REDIS_HOST:localhost}port: ${REDIS_PORT:6379}database: 0password: ${REDIS_PASSWORD}

RedisConfig.java

import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;/*** @author zyl*/
@Configuration
public class RedisConfig {@Beanpublic RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {RedisTemplate<String, Object> template = new RedisTemplate<>();template.setConnectionFactory(factory);Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Object.class);ObjectMapper om = new ObjectMapper();om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);om.activateDefaultTyping(om.getPolymorphicTypeValidator(), ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.WRAPPER_ARRAY);jackson2JsonRedisSerializer.setObjectMapper(om);StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();// key采用String的序列化方式template.setKeySerializer(stringRedisSerializer);// hash的key也采用jackson的序列化方式template.setHashKeySerializer(jackson2JsonRedisSerializer);// value序列化方式采用jacksontemplate.setValueSerializer(jackson2JsonRedisSerializer);// hash的value序列化方式采用jacksontemplate.setHashValueSerializer(jackson2JsonRedisSerializer);template.afterPropertiesSet();return template;}
}

这里配置使用redis的链接池,以及key,hash key和数据存储使用的序列化方式。

Domain层

City.java

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;import java.io.Serializable;/*** @author zyl*/
@NoArgsConstructor
@AllArgsConstructor
@Data
@Builder
public class City implements Serializable {private Long id;private String name;private String state;private String country;
}

注意:这里要实现Serializable接口,只有这样,我们这里使用的Redis依赖库才能够正常使用。

Dao层

CityDao.java

/*** @author zyl*/
public interface CityDao {void save(City city);City findById(Long id);void delete(Long id);
}

上面是Dao的定义层,下面来看看Dao的实现层:

CityDaoImpl.java

import org.springframework.data.redis.core.BoundHashOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Repository;import javax.annotation.Resource;
import java.util.concurrent.TimeUnit;/*** @author zyl*/
@Repository
public class CityDaoImpl implements CityDao {private static final String HASH_REFERENCE = "City";@Resourceprivate RedisTemplate<String, City> redisTemplate;@Overridepublic void save(City city) {Long id = city.getId();String key = HASH_REFERENCE + "_" + id;BoundHashOperations<String, Long, City> boundHashOperations = redisTemplate.boundHashOps(key);boundHashOperations.putIfAbsent(id, city);boundHashOperations.expire(60, TimeUnit.SECONDS);}@Overridepublic City findById(Long id) {String key = HASH_REFERENCE + "_" +id;BoundHashOperations<String, Long, City> boundHashOperations = redisTemplate.boundHashOps(key);return boundHashOperations.get(id);}@Overridepublic void delete(Long id) {String key = HASH_REFERENCE + "_" +id;BoundHashOperations<String, Long, City> boundHashOperations = redisTemplate.boundHashOps(key);boundHashOperations.delete(id);}
}

注意这里重点是通过BoundHashOperations类来实现Redis相关对象的操作。BoundHashOperations类是操作Redis的重点类。如果使用通过HashOperations类让redis里面的数据过期处理,有点麻烦,故这里使用BoundHashOperations类处理。

VO层

ApiRes.java

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.http.HttpStatus;/*** 通用响应类* @author zyl*/
@NoArgsConstructor
@AllArgsConstructor
@Builder
@Data
public class ApiRes<T> {private int status = HttpStatus.OK.value();private String message;private T data;public static final String SUCCESS_MSG = "操作成功";public static final String ERROR_MSG = "操作成功";/*** 返回成功数据* @author zyl* @return 成功消息*/public static <T> ApiRes<T> success(T data){return ApiRes.success(SUCCESS_MSG, data);}/*** 返回成功消息* @author zyl* @param msg 返回内容* @return 成功消息*/public static <T> ApiRes<T> success(String msg){return ApiRes.success(msg, null);}/*** 返回成功消息* @author zyl* @param msg 返回内容* @param data 数据对象* @return 成功消息*/public static <T> ApiRes<T> success(String msg, T data){return new ApiRes<>(HttpStatus.OK.value(), msg, data);}/*** 返回错误消息* @author zyl*/public static <T> ApiRes<T> error(){return ApiRes.error(ERROR_MSG);}/*** 返回错误消息* @author zyl* @param msg 返回内容* @return 警告消息*/public static <T> ApiRes<T> error(String msg){return ApiRes.error(msg, null);}/*** 返回错误消息* @author zyl* @param msg 返回内容* @param data 数据对象* @return 警告消息*/public static <T> ApiRes<T> error(String msg, T data){return new ApiRes<>(HttpStatus.INTERNAL_SERVER_ERROR.value(), msg, data);}/*** 返回错误消息* @author zyl* @param msg 返回内容* @param code 响应编码* @return 警告消息*/public static <T> ApiRes<T> error(int code, String msg){return new ApiRes<>(code, msg, null);}
}

这里定义实现了统一响应VO,下面继续实现定义City的响应VO:

CityRes.java

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;/*** @author zyl*/
@NoArgsConstructor
@AllArgsConstructor
@Data
@Builder
public class CityRes {private Long id;private String name;private String state;private String country;
}

City响应VO定义实现。

Service层

CityService.java

/*** 测试city模板* @author zyl*/
public interface CityService {ApiRes<CityRes> findByState(String state);ApiRes<CityRes> findById(Long id);void delete(Long id);
}

CityServiceImpl.java

import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;import javax.annotation.Resource;/*** @author zyl*/
@Service
public class CityServiceImpl implements CityService {@Resourceprivate CityMapper cityMapper;@Resourceprivate CityDao cityDao;@Overridepublic ApiRes<CityRes> findByState(String state) {City city = cityMapper.findByState(state);if (city == null) {throw new HandleException("没有找到城市数据");}CityRes cityRes = CityRes.builder().build();BeanUtils.copyProperties(city, cityRes);return ApiRes.success(cityRes);}@Overridepublic ApiRes<CityRes> findById(Long id) {// 先查缓存City city = cityDao.findById(id);if (city == null) {// 查数据库city = cityMapper.findById(id);if (city != null) {// 更新缓存cityDao.save(city);}}if (city == null) {throw new HandleException("没有找到城市数据");}CityRes cityRes = CityRes.builder().build();BeanUtils.copyProperties(city, cityRes);return ApiRes.success(cityRes);}@Overridepublic void delete(Long id) {cityMapper.delete(id);cityDao.delete(id);}
}

这里的HandleException类,是自定义异常处理类,这里就不再给出详细实现了。CityMapper类是mybatis的相关定义实现,这不是这里需要关注的,故也不再给出详细实现了。

Controller层

HelloController.java

import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;import javax.annotation.Resource;
import javax.validation.Valid;/*** 测试模板* @author zyl*/
@RefreshScope
@RestController
@RequestMapping("/hello")
public class HelloController {@Resourceprivate CityService cityService;@GetMapping("/city/findById")public ResponseEntity<ApiRes<CityRes>> cityFindById(@RequestParam Long id) {return ResponseEntity.ok(cityService.findById(id));}@GetMapping("/city/delete")public ResponseEntity<ApiRes<String>> cityDelete(@RequestParam Long id) {cityService.delete(id);ApiRes<String> apiRes = ApiRes.success("删除成功");return ResponseEntity.ok(apiRes);}
}

SQL

drop table if exists city;
create table city (id int primary key auto_increment, name varchar(200), state varchar(200), country varchar(200));
insert into city (name, state, country) values ('San Francisco', 'CA', 'US');
insert into city (name, state, country) values ('San Francisco2', 'CA2', 'US2');

测试

这里只看看Redis里面存的数据效果图:

redis存数据效果
看看postman中的响应:
获取数据postman

总结

这里主要使用BoundHashOperations类来处理redis中的对象。为什么不使用HashOperations类?因为不能直接使用HashOperations类对对象进行过期时间设置,而BoundHashOperations类可以这弄。这里值得注意的是,我们只能对Redis里面的整个散列进行过期,不能对散列里面的具体key过期。这一点Redis规范要注意一下。具体如下图:
redis hashs
我们能对1过期,但是不能对2进行过期处理。HashOperations类就是把多个对象存在一个1里面,我们这里为了实现单个对象过期处理,就只能使用BoundHashOperations类,在一个1里面存一个对象,这样实现对一个对象的redis过期。
总的来说,BoundHashOperations类可以自己过期Redis数据,HashOperations类没有直接过期数据方法。

参考:

  • Redis hashes
  • Spring boot redis javadoc
  • Spring Boot Redis CRUD Example

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/202.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

端口映射的作用?如何在路由器上做端口映射

一、端口映射作用 路由器中设置端口映射的主要作用&#xff0c;就是让Internet上的其他用户&#xff0c;可以访问你路由器下面电脑中的数据(软件、文件)。 当家里的电脑使用路由器上网后&#xff0c;在Internet下的其它电脑、手机等网络设备&#xff0c;将无法自接访问你电脑…

多家大厂整理的 1000 道 Java 面试题手册,备战金九银十

Java 面试 金九银十马上要来了&#xff0c;相信很多铁汁这个时候或多或少都有在准备面试的。对于刚入行的或者应届生一般面试前都会刷题或者看面经&#xff0c;这样心里才会有底。但也有人说面试前刷题是很愚蠢的行为&#xff0c;浪费时间效果还不大。但 LZ 认为&#xff0c;存…

步进电机保养小窍门

步进电机本身具有很多优势&#xff0c;在工作中所发挥的功能也对照富强。但是人们也知道任何配备的运行&#xff0c;想要更好发挥作用&#xff0c;都离不开同样平常保养。所以步进电机得同样平凡保养事变很重要&#xff0c;那么要如何正确保养步进电机&#xff0c;下文就往为人…

机器学习-进化算法

进化算法 遗传算法&#xff08;Genetic Algorithm&#xff0c;GA&#xff09;crossovermutation 进化策略&#xff08;Evolutionary Strategies&#xff0c;ES&#xff09;基因编程&#xff08;Genetic Programming&#xff09;Multi-objective Evolutionary Algorithms 遗传算…

Docker 私有仓库

一、私有仓库搭建 拉取私有仓库镜像 docker pull registry 启动私有仓库 docker run -id --nameprivate_registry -p 5000:5000 registry 打开浏览器输入 http://私有仓库服务器IP地址:5000/v2/_catalog 修改 daemon.json 文件 sudo gedit /etc/docker/daemon.json 在…

Flink 源算子之 DataGeneratorSource DataGenerator

目录 1、功能说明 2、API使用说明 3、代码示例 1、功能说明 从Flink1.1开始提供了DataGen连接器&#xff0c;它提供了Source类的实现&#xff08;可并行的源算子&#xff09;&#xff0c;用来生成测试数据&#xff0c;在本地开发或者无法访问外部系统(如kafka)时&#xff0c…

mysql学习

docker创建mysql version: "2" services:mysql:container_name: mysql_simpleimage: mysql:5.7#env_file:#- ../env/mysql.envenvironment:MYSQL_ROOT_PASSWORD: "123456"MYSQL_USER: zhaoMYSQL_PASS: zhaovolumes:# 如果没有data文件夹会自动创建- ./dat…

Docker介绍

目录​​​​​​​ 一、Docker是什么&#xff1f; 二、Docker只能使用Linux吗&#xff1f; 三、为什么要使用Docker&#xff1f; 四、镜像和容器 五、关闭SELINUX 一、Docker是什么&#xff1f; Docker是轻量级的虚拟机产品&#xff0c;我们在使用Docker的时候&#xff…

05 proxy代理、组件间的通信

React全家桶 一、脚手架配置代理(proxy)的方式 CORS: 请求url:http://www.baidu.com 发送url:http://www.jd.com response.setHeader(Access-Control-Allow-Origin,*);通过express快速搭建一个服务 创建一个图书组件 import React, { useEffect } from react import axio…

使用OpenXML库替换docx文档(Word文档)中的特定字段

在批量生成Word文档的应用中&#xff0c;最常见的需求莫过于替换掉文档中的特定字段以生成新的文档。利用OpenXML库可轻松实现这一需求。 不完善版本 首先放出最简单然而有bug的版本&#xff1a; using DocumentFormat.OpenXml.Packaging; using DocumentFormat.OpenXml.Wor…

Spring Boot 中的事务回滚规则

Spring Boot 中的事务回滚规则 在应用程序中&#xff0c;事务管理是一个重要的概念。事务是指一系列的操作&#xff0c;这些操作要么全部成功&#xff0c;要么全部失败。在Spring Boot中&#xff0c;我们可以使用事务管理器来管理事务。在使用事务管理器的时候&#xff0c;一个…

【Oracle】springboot连接Oracle 集成mybatis、druid

目录 项目结构与库表数据pom.xmlapplication.yml实体类Mappercontroller接口测试 基于spring-boot 2.7.11&#xff0c;连接Oracle 11g 仅做一个简单的示例 特别说明&#xff08;不一定正确&#xff0c;还请指正&#xff09;&#xff1a;我Oracle也不熟&#xff0c;但据我观察发…