REDIS学习(4)spring boot redisTemplate 对REDIS的简单封装,以及对引用包的说明,以及对序列化的详细说明
来源:互联网 发布:支持ubuntu的手机 编辑:程序博客网 时间:2024/06/03 21:16
综合1,2,3以及目前,我们所引用的redis包不过是
<dependency><groupId>org.springframework.boot</groupId><!-- 会附带引进jedis-2.7.3的包 --><artifactId>spring-boot-starter-redis</artifactId></dependency>
添加进来后
引用包至少有
spring-boot-starter-redis-1.3.5.RELEASE.jar
spring-data-redis-1.6.4.RELEASE.jar
jedis-2.7.3.jar
三个包
结合前面的第三节,redis都是跟Spring一起做为通用缓存接口使用
这一节使用的redisTemplate更像是一个数据库的操作
@Servicepublic class RedisService {@AutowiredRedisTemplate<?, ?> redisTemplate;/**获得客户端列表 */public List<?> getClients(){return redisTemplate.getClientList();}/**设置有超时时间的KV */public Long set(String key, String value, long seconds) {return redisTemplate.execute(c -> {c.set(key.getBytes(), value.getBytes());c.expire(key.getBytes(), seconds);return 1L;});}/** *存入不会超时的KV */public Long set(String key, String value) {return redisTemplate.execute(c -> {c.set(key.getBytes(), value.getBytes());return 1L;});}/** * redis数据库条数 */public Long dbSize() {return redisTemplate.execute(c -> c.dbSize());}public String ping() {return redisTemplate.execute(c -> c.ping());}/** * 删除所有指定数据库的数据 */public long flushDB() {return redisTemplate.execute(c -> {c.flushDb();return 1L;});}/**判断redis数据库是否有对应的key*/public boolean exist(String key){return redisTemplate.execute(c->c.exists(key.getBytes()));}/**获得redis数据库所有的key*/public Set<String> keys(String pattern){return redisTemplate.execute(c->c.keys(pattern.getBytes()).stream().map(this::getUTF).collect(Collectors.toSet()));}private String getUTF(byte[] data){try {return new String(data, "utf-8");} catch (UnsupportedEncodingException e) {LogCore.BASE.error("parse bytes err:{}", e);return null;}}}
使用:
@SuppressWarnings({ "unchecked", "rawtypes" })public long save(UserInfo usrInfo) {return redisTemplate.execute(c -> {RedisSerializer key_slz = redisTemplate.getKeySerializer();RedisSerializer slz = redisTemplate.getValueSerializer();LogCore.BASE.info("key_slz={},slz={}",key_slz.getClass().getSimpleName(),slz.getClass().getSimpleName());c.set(key_slz.serialize(usrInfo.getClass().getSimpleName() + ":" + usrInfo.no), slz.serialize(usrInfo));return 1L;});}@SuppressWarnings({ "rawtypes", "unchecked" })public UserInfo get(String no) {return (UserInfo) redisTemplate.execute(c -> {RedisSerializer key_slz = redisTemplate.getKeySerializer();RedisSerializer slz = redisTemplate.getValueSerializer();return slz.deserialize(c.get(key_slz.serialize(UserInfo.class.getSimpleName() + ":" + no)));});}
根据上一节内容,我们知道如果没有指定RedisTemplate,spring redis cache会选用javaAPI的序列化方式来将对象序列化,这种序列化方式性能一般,切后面增加字段会造成麻烦,我觉的比较合适的序列化方式有protocol buffer,JSON,带有递归的二进制字节流的方式等。
我们下面详细分析RedisTempalte这个类,StringRedisTemplate是RedisTemplate的唯一子类。
这个类很简单,我们甚至可以仿照此方法定义自己的MyRedisTemplate
[API]
public class StringRedisTemplate extends RedisTemplate<String, String> {public StringRedisTemplate() {RedisSerializer<String> stringSerializer = new StringRedisSerializer();setKeySerializer(stringSerializer);setValueSerializer(stringSerializer);setHashKeySerializer(stringSerializer);setHashValueSerializer(stringSerializer);}public StringRedisTemplate(RedisConnectionFactory connectionFactory) {this();setConnectionFactory(connectionFactory);afterPropertiesSet();}protected RedisConnection preProcessConnection(RedisConnection connection, boolean existingConnection) {return new DefaultStringRedisConnection(connection);}}注意,子类的构造方法总会默认调用父类的无参构造方法。
RedisTemplate默认定义了两个常用的序列化类
private RedisSerializer<?> defaultSerializer = new JdkSerializationRedisSerializer();
以及 private RedisSerializer<String> stringSerializer = new StringRedisSerializer();
我们可以如下注入我们的RedisTemplate,下面的例子将key的序列化方式定义为字符串,将value的序列化使用了jackson
@Configuration@EnableCachingpublic class RedisConfig extends CachingConfigurerSupport {@Beanpublic CacheManager cacheManager(RedisTemplate<?, ?> redisTemplate) {RedisCacheManager manager = new RedisCacheManager(redisTemplate);return manager;}@Beanpublic RedisTemplate<?, ?> redisTemplate(RedisConnectionFactory connectionFactory) {RedisTemplate<String, Object> template = new RedisTemplate<String, Object>();template.setConnectionFactory(connectionFactory);setMySerializer(template);template.afterPropertiesSet();LogCore.BASE.info("template{}" ,ReflectionToStringBuilder.toString(template, ToStringStyle.SHORT_PREFIX_STYLE));return template;}/** * 设置序列化方法 */private void setMySerializer(RedisTemplate template) {Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<Object>(Object.class);ObjectMapper om = new ObjectMapper();om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);jackson2JsonRedisSerializer.setObjectMapper(om);template.setKeySerializer(template.getStringSerializer());template.setValueSerializer(jackson2JsonRedisSerializer);}@Beanpublic KeyGenerator smpkeyGenerator() {return (target, method, params) -> {StringBuilder sb = new StringBuilder();sb.append(target.getClass().getSimpleName()).append(":");//执行方法所在的类sb.append(Stream.of(params).map(String::valueOf).collect(Collectors.joining("_")));return sb.toString();};}}
最后我们看一下Spring data redis定义的序列化接口和默认的JDK序列化的封装,代码比较整洁,我们可以从中学习
[API]
public interface RedisSerializer<T> {byte[] serialize(T t) throws SerializationException;T deserialize(byte[] bytes) throws SerializationException;}[API]
public class JdkSerializationRedisSerializer implements RedisSerializer<Object> {private Converter<Object, byte[]> serializer = new SerializingConverter();private Converter<byte[], Object> deserializer = new DeserializingConverter();public Object deserialize(byte[] bytes) {if (SerializationUtils.isEmpty(bytes)) {return null;}try {return deserializer.convert(bytes);} catch (Exception ex) {throw new SerializationException("Cannot deserialize", ex);}}public byte[] serialize(Object object) {if (object == null) {return SerializationUtils.EMPTY_ARRAY;}try {return serializer.convert(object);} catch (Exception ex) {throw new SerializationException("Cannot serialize", ex);}}}
[API]
public interface Converter<S, T> {T convert(S source);}
[API]
public class SerializingConverter implements Converter<Object, byte[]> {private final Serializer<Object> serializer;public SerializingConverter() {this.serializer = new DefaultSerializer();}public SerializingConverter(Serializer<Object> serializer) {Assert.notNull(serializer, "Serializer must not be null");this.serializer = serializer;}@Overridepublic byte[] convert(Object source) {ByteArrayOutputStream byteStream = new ByteArrayOutputStream(1024);try {this.serializer.serialize(source, byteStream);return byteStream.toByteArray();}catch (Throwable ex) {throw new SerializationFailedException("Failed to serialize object using " +this.serializer.getClass().getSimpleName(), ex);}}}
[API]
public class DeserializingConverter implements Converter<byte[], Object> {private final Deserializer<Object> deserializer;public DeserializingConverter() {this.deserializer = new DefaultDeserializer();}public DeserializingConverter(ClassLoader classLoader) {this.deserializer = new DefaultDeserializer(classLoader);}public DeserializingConverter(Deserializer<Object> deserializer) {Assert.notNull(deserializer, "Deserializer must not be null");this.deserializer = deserializer;}@Overridepublic Object convert(byte[] source) {ByteArrayInputStream byteStream = new ByteArrayInputStream(source);try {return this.deserializer.deserialize(byteStream);}catch (Throwable ex) {throw new SerializationFailedException("Failed to deserialize payload. " +"Is the byte array a result of corresponding serialization for " +this.deserializer.getClass().getSimpleName() + "?", ex);}}}
[API]序列化writeObject
public class DefaultSerializer implements Serializer<Object> {@Overridepublic void serialize(Object object, OutputStream outputStream) throws IOException {if (!(object instanceof Serializable)) {throw new IllegalArgumentException(getClass().getSimpleName() + " requires a Serializable payload " +"but received an object of type [" + object.getClass().getName() + "]");}ObjectOutputStream objectOutputStream = new ObjectOutputStream(outputStream);objectOutputStream.writeObject(object);objectOutputStream.flush();}}
[API]反序列化是用类加载器
public class DefaultDeserializer implements Deserializer<Object> {private final ClassLoader classLoader;public DefaultDeserializer() {this.classLoader = null;}<span style="color:#ff0000;">public DefaultDeserializer(ClassLoader classLoader) {this.classLoader = classLoader;}</span>@Override@SuppressWarnings("resource")public Object deserialize(InputStream inputStream) throws IOException {ObjectInputStream objectInputStream = new ConfigurableObjectInputStream(inputStream, this.classLoader);try {return objectInputStream.readObject();}catch (ClassNotFoundException ex) {throw new NestedIOException("Failed to deserialize object type", ex);}}}
- REDIS学习(4)spring boot redisTemplate 对REDIS的简单封装,以及对引用包的说明,以及对序列化的详细说明
- 对redis中的redis.conf配置文件的详细说明
- spring boot redis RedisTemplate和ValueOperations对 string-value的操作
- redis中的基本数据类型,以及在Spring-Boot对Redis的基本使用
- redis中的基本数据类型,以及在Spring-Boot对Redis的基本使用
- Spring Boot对Redis的整合
- spring 整合 redis,以及spring的RedisTemplate如何使用
- Spring 整合Redis以及Spring的RedisTemplate如何使用
- spring 整合 redis,以及spring的RedisTemplate如何使用
- spring 整合 redis,以及spring的RedisTemplate如何使用
- spring 整合 redis,以及spring的RedisTemplate如何使用
- spring 整合 redis,以及spring的RedisTemplate如何使用
- spring 整合 redis,以及spring的RedisTemplate如何使用
- Redis入门之redis 连接以及 对字符的操作
- Redis入门之redis 连接以及 对字符的操作
- redis学习之java类对redis库操作的简单封装
- spring对redis的操作
- 对TCG的概要分析和对TPM的学习-可信根说明以及RTM(二)
- 设计模式总结之Composite Pattern(组合模式)
- 自定义 Android 对话框 (AlertDialog) 的样式
- XML在Android-iOS上的应用
- Java SWT 文本框 垂直 居中
- 导入*.sql脚本
- REDIS学习(4)spring boot redisTemplate 对REDIS的简单封装,以及对引用包的说明,以及对序列化的详细说明
- Android 自动跳转到系统界面总结
- 函数指针!!
- 【网络】高级I/O多路复用之select、poll和epoll
- 微信公众号测试帐号
- Hats’Worlds(字典树)
- HDOJ 5795 A Simple Nim
- 快速集成android实现listview的字母A-Z排序,界面侧边字母索引
- spring 事务注意事项 -- 事务注解一定写到service最外层