1.概述
在本文中,我们将通过Spring Data Redis库回顾如何将Redis与Spring Boot结合使用的基础知识。
我们将构建一个应用程序,演示如何通过Web界面执行CRUD操作Redis 。 Github上提供了该项目的完整源代码。
2.什么是Redis?
Redis是一个开源的内存中键值数据存储 ,用作数据库,缓存和消息代理。 在实现方面,键值存储代表NoSQL空间中最大和最旧的成员之一。 Redis支持带范围查询的数据结构,例如字符串,哈希,列表,集合和排序集合。
通过为数据存储提供抽象, Spring Data Redis框架使编写使用Redis键值存储的Spring应用程序变得容易。
3.设置Redis服务器
该服务器可从http://redis.io/download免费获得。
如果您使用的是Mac,则可以通过自制软件安装它:
brew install redis
然后启动服务器:
mikes-MacBook-Air:~ mike$ redis-server
10699:C 23 Nov 08:35:58.306 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
10699:C 23 Nov 08:35:58.307 # Redis version=4.0.2, bits=64, commit=00000000, modified=0, pid=10699, just started
10699:C 23 Nov 08:35:58.307 # Warning: no config file specified, using the default config. In order to specify a config file use redis-server /path/to/redis.conf
10699:M 23 Nov 08:35:58.309 * Increased maximum number of open files to 10032 (it was originally set to 256)._._ _.-``__ ''-._ _.-`` `. `_. ''-._ Redis 4.0.2 (00000000/0) 64 bit.-`` .-```. ```\/ _.,_ ''-._ ( ' , .-` | `, ) Running in standalone mode|`-._`-...-` __...-.``-._|'` _.-'| Port: 6379| `-._ `._ / _.-' | PID: 10699`-._ `-._ `-./ _.-' _.-' |`-._`-._ `-.__.-' _.-'_.-'| | `-._`-._ _.-'_.-' | http://redis.io `-._ `-._`-.__.-'_.-' _.-' |`-._`-._ `-.__.-' _.-'_.-'| | `-._`-._ _.-'_.-' | `-._ `-._`-.__.-'_.-' _.-' `-._ `-.__.-' _.-' `-._ _.-' `-.__.-' 10699:M 23 Nov 08:35:58.312 # Server initialized
10699:M 23 Nov 08:35:58.312 * Ready to accept connections
4. Maven依赖
让我们在pom.xml中声明我们要构建的示例应用程序所必需的依赖项:
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-thymeleaf</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency>
5. Redis配置
我们需要将我们的应用程序与Redis服务器连接。 为了建立这种连接,我们使用Redis客户端实现Jedis 。
5.1配置
让我们从配置bean定义开始:
@BeanJedisConnectionFactory jedisConnectionFactory() {return new JedisConnectionFactory();}@Beanpublic RedisTemplate<String, Object> redisTemplate() {final RedisTemplate<String, Object> template = new RedisTemplate<String, Object>();template.setConnectionFactory(jedisConnectionFactory());template.setValueSerializer(new GenericToStringSerializer<Object>(Object.class));return template;}
JedisConnectionFactory被制成一个bean,因此我们可以创建一个RedisTemplate来查询数据。
5.2消息发布者
遵循SOLID的原理 ,我们创建一个MessagePublisher接口:
public interface MessagePublisher {void publish(final String message);
}
我们实现了MessagePublisher接口,以使用高级RedisTemplate发布消息,因为RedisTemplate允许将任意对象作为消息传递:
@Service
public class MessagePublisherImpl implements MessagePublisher {@Autowiredprivate RedisTemplate<String, Object> redisTemplate;@Autowiredprivate ChannelTopic topic;public MessagePublisherImpl() {}public MessagePublisherImpl(final RedisTemplate<String, Object> redisTemplate, final ChannelTopic topic) {this.redisTemplate = redisTemplate;this.topic = topic;}public void publish(final String message) {redisTemplate.convertAndSend(topic.getTopic(), message);}}
我们还将其定义为RedisConfig中的bean:
@BeanMessagePublisher redisPublisher() {return new MessagePublisherImpl(redisTemplate(), topic());}
讯息侦听器
为了订阅消息,我们需要实现MessageListener接口:每次收到新消息时,都会调用回调,并通过名为onMessage的方法执行用户代码。 该接口可访问消息,已通过其接收消息的通道以及订阅使用的与该通道匹配的任何模式。
因此,我们创建一个服务类来实现MessageSubscriber :
@Service
public class MessageSubscriber implements MessageListener {public static List<String> messageList = new ArrayList<String>();public void onMessage(final Message message, final byte[] pattern) {messageList.add(message.toString());System.out.println("Message received: " + new String(message.getBody()));}}
我们向RedisConfig添加一个bean定义:
@BeanMessageListenerAdapter messageListener() {return new MessageListenerAdapter(new MessageSubscriber());}
6. Redis存储库
现在我们已经配置了应用程序以与Redis服务器交互,我们将准备应用程序以获取示例数据。
6.1模型
在此示例中,我们定义了具有两个字段的Movie模型:
private String id;
private String name;
//standard getters and setters
6.2储存库界面
与其他Spring Data项目不同, Spring Data Redis确实提供了在其他Spring Data接口之上构建的任何功能 。 对于拥有其他Spring Data项目经验的我们来说这很奇怪。
通常,不需要使用Spring Data项目编写存储库接口的实现。 我们只需要与界面进行交互即可。 Spring Data JPA提供了许多存储库接口,可以扩展它们以获得诸如CRUD操作,派生查询和分页之类的功能。
因此,不幸的是, 我们需要编写我们自己的接口 ,然后定义方法:
public interface RedisRepository {Map<Object, Object> findAllMovies();void add(Movie movie);void delete(String id);Movie findMovie(String id);}
6.3资料库的实施
我们的实现类使用我们的配置类RedisConfig定义的redisTemplate。
我们使用Spring Data Redis提供的HashOperations模板:
@Repository
public class RedisRepositoryImpl implements RedisRepository {private static final String KEY = "Movie";private RedisTemplate<String, Object> redisTemplate;private HashOperations hashOperations;@Autowiredpublic RedisRepositoryImpl(RedisTemplate<String, Object> redisTemplate){this.redisTemplate = redisTemplate;}@PostConstructprivate void init(){hashOperations = redisTemplate.opsForHash();}public void add(final Movie movie) {hashOperations.put(KEY, movie.getId(), movie.getName());}public void delete(final String id) {hashOperations.delete(KEY, id);}public Movie findMovie(final String id){return (Movie) hashOperations.get(KEY, id);}public Map<Object, Object> findAllMovies(){return hashOperations.entries(KEY);}}
让我们记下init()方法。 在此方法中,我们使用名为opsForHash()的函数,该函数返回对绑定到给定键的哈希值执行的操作。 然后,我们将init()中定义的hashOps用于所有CRUD操作。
7. Web界面
在本节中,我们将回顾向Web界面添加Redis CRUD操作功能。
7.1添加电影
我们希望能够在我们的网页中添加电影。 关键是电影ID ,值是实际对象。 但是,我们稍后将解决此问题,因此仅将电影名称显示为值。
因此,让我们将表单添加到HTML文档中,并分配适当的名称和ID:
<form id="addForm">
<div class="form-group"><label for="keyInput">Movie ID (key)</label><input name="keyInput" id="keyInput" class="form-control"/></div>
<div class="form-group"><label for="valueInput">Movie Name (field of Movie object value)</label><input name="valueInput" id="valueInput" class="form-control"/></div><button class="btn btn-default" id="addButton">Add</button></form>
现在,我们使用JavaScript来保存表单提交中的值:
$(document).ready(function() {var keyInput = $('#keyInput'),valueInput = $('#valueInput');refreshTable();$('#addForm').on('submit', function(event) {var data = {key: keyInput.val(),value: valueInput.val()};$.post('/add', data, function() {refreshTable();keyInput.val('');valueInput.val('');keyInput.focus();});event.preventDefault();});keyInput.focus();
});
我们为POST请求分配@RequestMapping值,请求键和值,创建一个Movie对象,并将其保存到存储库中:
@RequestMapping(value = "/add", method = RequestMethod.POST)public ResponseEntity<String> add(@RequestParam String key,@RequestParam String value) {Movie movie = new Movie(key, value);redisRepository.add(movie);return new ResponseEntity<>(HttpStatus.OK);}
7.2查看内容
添加Movie对象后,我们刷新表以显示更新的表。 在7.1节JavaScript代码块中,我们调用了一个称为refreshTable()JavaScript函数。 此函数执行GET请求以检索存储库中的当前数据:
function refreshTable() {$.get('/values', function(data) {var attr,mainTable = $('#mainTable tbody');mainTable.empty();for (attr in data) {if (data.hasOwnProperty(attr)) {mainTable.append(row(attr, data[attr]));}}});
}
GET请求由名为findAll()的方法处理,该方法检索存储在存储库中的所有Movie对象,然后将数据类型从Map <Object,Object>转换为Map <String,String> :
@RequestMapping("/values")public @ResponseBody Map<String, String> findAll() {Map<Object, Object> aa = redisRepository.findAllMovies();Map<String, String> map = new HashMap<String, String>();for(Map.Entry<Object, Object> entry : aa.entrySet()){String key = (String) entry.getKey();map.put(key, aa.get(key).toString());}return map;}
7.3删除电影
我们编写Javascript来执行POST请求 / delete ,刷新表,并将键盘焦点设置为按键输入:
function deleteKey(key) {$.post('/delete', {key: key}, function() {refreshTable();$('#keyInput').focus();});
}
我们请求密钥,并根据此密钥删除redisRepository中的对象:
@RequestMapping(value = "/delete", method = RequestMethod.POST)public ResponseEntity<String> delete(@RequestParam String key) {redisRepository.delete(key);return new ResponseEntity<>(HttpStatus.OK);}
8.演示
在这里,我们添加了两部电影:
在这里,我们删除了一部电影:
9.结论
在本教程中,我们介绍了Spring Data Redis,以及将其连接到Web应用程序以执行CRUD操作的一种方法。
示例应用程序的源代码在Github上 。
翻译自: https://www.javacodegeeks.com/2017/11/intro-redis-spring-boot.html