1.概述
在本文中,我们将通过Spring Data Redis库回顾如何在Spring Boot中使用Redis 。
我们将构建一个应用程序,演示如何通过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定义开始:
@Bean
JedisConnectionFactory jedisConnectionFactory() {
return new JedisConnectionFactory();
}
@Bean
public 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 {
@Autowired
private RedisTemplate<String, Object> redisTemplate;
@Autowired
private 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:
@Bean
MessagePublisher 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定义:
@Bean
MessageListenerAdapter 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;
@Autowired
public RedisRepositoryImpl(RedisTemplate<String, Object> redisTemplate){
this.redisTemplate = redisTemplate;
}
@PostConstruct
private 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