Springboot中整合了Redis(Springboot2.0 spring-boot-starter-data-redis)可直接使用RedisTemplate进行数据操作。出于学习的目的,加深对Redis配置及其数据操作的理解,本项目采用redis原生API(引入redis.clients--Jedis)进行有关redis操作的实现。采用Redis缓存物联网信号[二进制bit字符串]对应的协议解析表,实现信号接入后,经网关筛选及分类写入kafka对应的topic,经过storm进行解析(引入协议解析表进行原信号解析)。
- 原始信号简化为字符串------->>>如:01AB02ABBA等,其中两位字符代表一个属性,如前两位表示设备类别,其后依次为设备通道号、设备编号、温度信号及报警信号。
- 分析信号,采用redis中hash类型存储为最佳方案。
- 键名为信号的各个属性(如设备编号、温度信号等),sub-key为原始信号字符(如01、AB等--2个字符一组),value为原始信号字符对应的协议解析值(如01-->第一类设备(烟感),AB-->1#设备,02-->02channal,AB-->存在超温风险,BA-->报警风险)。
分析好目标及数据存储方式之后,开始编码。项目整体使用Springboot框架,引入Jedis进行数据存储操作。
一、POM文件
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.0.RELEASE</version>
</parent>
<properties>
<java.version>1.8</java.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<!-- Json -->
<!-- <dependency> -->
<!-- <groupId>com.alibaba</groupId> -->
<!-- <artifactId>fastjson</artifactId> -->
<!-- <version>1.2.9</version> -->
<!-- </dependency> -->
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
</dependency>
</dependencies>
二、配置文件application.properties(只进行log配置,使用springboot logback)及redis.properties
logging.file=protocol-redis.log
#Redis服务器(IP)
spring.redis.host=
#Redis服务端口号
spring.redis.port=
#Redis服务密码
spring.redis.password=
#Redis服务器连接超时的时间(0代表不超时)
spring.redis.timeout=0
#在borrow一个jedis实例时,是否提前进行validate操作;如果为true,则得到的jedis实例均是可用的
spring.redis.testOnBorrow=true
#控制一个pool最多有多少个状态为idle(空闲的)的jedis实例,默认值也是8
spring.redis.maxIdle=8
#连接超时时是否阻塞,false时报异常,ture阻塞直到超时, 默认true
spring.redis.blockWhenExhausted=true
#等待可用连接的最大时间,单位毫秒,默认值为-1,表示永不超时。如果超过等待时间,则直接抛出JedisConnectionException
spring.redis.maxWaitMillis=-1
#最大空连接数
spring.redis.maxTotal=200
三、Redis配置类,RedisConfig,写入配置参数,返回连接池实例
package com.protocol.redis;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;
@Configuration
@EnableAutoConfiguration
@PropertySource("classpath:redisConfig/redis.properties")
public class RedisConfig {
@Value("${spring.redis.host}")
private String host;
@Value("${spring.redis.port}")
private int port;
@Value("${spring.redis.password}")
private String passwd;
@Value("${spring.redis.timeout}")
private int timeout;
@Value("${spring.redis.blockWhenExhausted}")
private boolean blockWhenExhausted;
@Value("${spring.redis.maxIdle}")
private int maxIdle;
@Value("${spring.redis.maxWaitMillis}")
private int maxWaitMillis;
@Value("${spring.redis.maxTotal}")
private int maxTotal;
@Value("${spring.redis.testOnBorrow}")
private boolean testOnBorrow;
private JedisPool jedisPool;
@Bean
public JedisPoolConfig getRedisConfig() {
JedisPoolConfig config=new JedisPoolConfig();
return config;
}
@Bean
public JedisPool getJedisPool() {
JedisPoolConfig config=getRedisConfig();
config.setMaxIdle(maxIdle);
config.setMaxTotal(maxTotal);
config.setBlockWhenExhausted(blockWhenExhausted);
config.setTestOnBorrow(testOnBorrow);
config.setMaxWaitMillis(maxWaitMillis);
JedisPool jedisPool=new JedisPool(config,host,port,timeout,passwd);
return jedisPool;
}
}
四、编写redis数据操作的redisService接口及其实现类redisServiceImpl(本例中只使用hash操作)
service接口类:定义数据操作的redis 连接池资源获取方法、释放资源、写入数据(setInfo)及查询数据get方法。
package com.protocol.redis;
import java.util.Map;
import redis.clients.jedis.Jedis;
public interface RedisService {
public redis.clients.jedis.Jedis getResource();
public void returnResource(Jedis jedis);
public void setInfo(String key, Map<String, String> value);
public Map<String, String> get(String key);
}
serviceImplements类,用于实现service类定义的方法:
package com.protocol.redis;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import redis.clients.jedis.JedisPool;
@Service
public class RedisServiceImpl implements RedisService{
@Autowired
private JedisPool jedisPool;
public redis.clients.jedis.Jedis getResource() {
//获取Jedis连接池资源
return jedisPool.getResource();
}
@SuppressWarnings("deprecation")
public void returnResource(redis.clients.jedis.Jedis jedis) {
if(jedis!=null) {
//释放jedisPool资源
jedisPool.returnResource(jedis);
}
}
/**
*实现数据写入的setInfo方法
*/
public void setInfo(String key, Map<String, String> value) {
redis.clients.jedis.Jedis jedis=null;
try {
//获取jedis实例连接
jedis=getResource();
//选择使用的数据库(0-15,如不指定默认为0)
jedis.select(15);
//使用hmset方法(key,value(hashmap<key,value>))
jedis.hmset(key, value);
}catch (Exception e) {
e.printStackTrace();// TODO: handle exception
}finally {
returnResource(jedis);
}
}
/**
*实现数据查询的get方法
*/
public Map<String, String> get(String key){
redis.clients.jedis.Jedis jedis=null;
Map<String, String> result=null;
try {
jedis=getResource();
jedis.select(15);
//通过key返回其所有的subkey及value
jedis.hgetAll(key);
result=jedis.hgetAll(key);
}catch (Exception e) {
e.printStackTrace();// TODO: handle exception
}finally {
returnResource(jedis);
}
return result;
}
}
五、数据操作示例的类RunCreatA.class(本例中数据写在代码里了,也可通过定义controller,采用restful API的方式实现数据交互,此类继承runnable,通过springboot application管理运行),分别写入信号字符对应的字段及其值。
package com.protocol.setprotocol;
import java.util.HashMap;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.stereotype.Component;
import com.protocol.redis.RedisService;
@Component
public class RunCreateA implements ApplicationRunner{
@Autowired
private RedisService redisService;
public void setType() {
String keyType="ProtocolA:Type";
Map<String, String> type=new HashMap<>();
type.put("01", "SmokeSensor");
type.put("02", "TemperatureSensor");
redisService.setInfo(keyType, type);
System.out.println("#######--Done With Write--#########");
redisService.get(keyType);
System.out.println("------------"+redisService.get(keyType)+"---------");
}
public void setNo() {
String keyNo="ProtocolA:No";
Map<String, String> No=new HashMap<>();
No.put("AA", "1# equipment");
No.put("AB", "2# equipment");
No.put("AC", "5# equipment");
redisService.setInfo(keyNo, No);
redisService.get(keyNo);
System.out.println("------------"+redisService.get(keyNo)+"---------");
}
public void setChannal() {
String keyChannal="ProtocolA:Channal";
Map<String, String> channal=new HashMap<>();
channal.put("01", "channal:1");
channal.put("02", "channal:2");
redisService.setInfo(keyChannal, channal);
redisService.get(keyChannal);
System.out.println("------------"+redisService.get(keyChannal)+"---------");
}
public void setTem() {
String keyTem="ProtocolA:Temperature";
Map<String, String> temperature=new HashMap<>();
temperature.put("AA", "Normal");
temperature.put("AB", "Risk:normal, little high");
temperature.put("BA", "Big Risk,too high");
temperature.put("BB", "Fire!");
redisService.setInfo(keyTem, temperature);
redisService.get(keyTem);
System.out.println("------------"+redisService.get(keyTem)+"---------");
}
public void setAlarm() {
String keyAlarm="ProtocolA:Alarm";
Map<String, String> alarm=new HashMap<>();
alarm.put("AA", "Normal");
alarm.put("BA", "Risk");
alarm.put("BB", "FireAlarm!");
redisService.setInfo(keyAlarm, alarm);
redisService.get(keyAlarm);
System.out.println("------------"+redisService.get(keyAlarm)+"---------");
}
public void run(ApplicationArguments args) throws Exception{
setType();
setNo();
setChannal();
setTem();
setAlarm();
System.out.println("start write!");
}
}
六、运行结果:
在redisclient软件中查看
本例代码已上传至github:https://github.com/Anonym91/Springboot-Redis