【推荐】2019 Java 开发者跳槽指南.pdf(吐血整理) >>>
在spring中集成lettuce需要引入三个依赖,spring-data-redis、lettuce和commons-pool2,引入时需要注意版本的关系,该文配置是在springframework5.1.8RELEASE 版本上配置的,其他版本的请自行修改上面三个依赖的版本号!
pom配置
....
<org.springframework.version>5.1.8.RELEASE</org.springframework.version>
<lettuce>5.1.6.RELEASE</lettuce>
<spring.data.redis>2.1.9.RELEASE</spring.data.redis>
<org.apache.commons.pool2>2.8.0</org.apache.commons.pool2>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-redis</artifactId>
<version>${spring.data.redis}</version>
</dependency>
<dependency>
<groupId>io.lettuce</groupId>
<artifactId>lettuce-core</artifactId>
<version>${lettuce}</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
<version>${org.apache.commons.pool2}</version>
</dependency>
....
application.properties
# Redis
#redis数据库索引(默认为0)
redis.database=0
#redis服务器IP地址
redis.host=127.0.0.1
#redis端口号
redis.port=6379
#redis密码,默认为空
redis.password=123456
#连接redis超时时间(毫秒)
redis.time-out=5000
# 建立连接最大等待时间,默认1ms,超出该时间会抛异常。设为-1表示无限等待,直到分配成功。
redis.lettuce.pool.max-wait=1
# 最大连连接数,默认为8,负值表示没有限制
redis.lettuce.pool.max-active=8
# 最大空闲连接数,默认8。负值表示没有限制
redis.lettuce.pool.max-idle=8
# 最小空闲连接数,默认0。
redis.lettuce.pool.min-idle=0
# 设置关闭连接的超时时间
redis.lettuce.shutdown-timeout=100
redis配置类
import com.alibaba.fastjson.support.spring.GenericFastJsonRedisSerializer;
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
import org.springframework.beans.factory.annotation.Value;
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.RedisPassword;
import org.springframework.data.redis.connection.RedisStandaloneConfiguration;
import org.springframework.data.redis.connection.lettuce.LettuceClientConfiguration;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
import org.springframework.data.redis.connection.lettuce.LettucePoolingClientConfiguration;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import java.time.Duration;
@Configuration
public class RedisConfiguration {
@Value("${redis.database}")
private int dbIndex;
@Value("${redis.host}")
private String hostname;
@Value("${redis.port}")
private int port;
@Value("${redis.password}")
private String password;
@Value("${redis.time-out}")
private int timeOut;
@Value("${redis.lettuce.pool.max-active}")
private int maxTotal;
@Value("${redis.lettuce.pool.max-idle}")
private int maxIdle;
@Value("${redis.lettuce.pool.min-idle}")
private int minIdle;
@Value("${redis.lettuce.pool.max-wait}")
private int maxWait;
@Value("${redis.lettuce.shutdown-timeout}")
private int shutdownTimeOut;
/**
* 配置连接池参数
*
* @return GenericObjectPool
*/
@Bean
public GenericObjectPoolConfig getRedisConfig() {
GenericObjectPoolConfig genericObjectPoolConfig = new GenericObjectPoolConfig();
genericObjectPoolConfig.setMaxIdle(maxIdle);
genericObjectPoolConfig.setMaxTotal(maxTotal);
genericObjectPoolConfig.setMinIdle(minIdle);
genericObjectPoolConfig.setMaxWaitMillis(maxWait);
return genericObjectPoolConfig;
}
/**
* 生成连接池
*
* @param poolConfig 连接池配置
* @return LettuceClientConfiguration
*/
@Bean
public LettuceClientConfiguration getDefaultLettucePool(GenericObjectPoolConfig poolConfig) {
return LettucePoolingClientConfiguration.builder().shutdownTimeout(Duration.ofMillis(shutdownTimeOut))
.commandTimeout(Duration.ofMillis(timeOut))
.poolConfig(poolConfig).build();
}
/**
* 单节点redis配置
*
* @return RedisStandaloneConfiguration
*/
@Bean
public RedisStandaloneConfiguration getRedisStandaloneConfiguration() {
RedisStandaloneConfiguration configuration = new RedisStandaloneConfiguration(hostname, port);
configuration.setPassword(RedisPassword.of(password));
return configuration;
}
/**
* lettuce 连接工厂配置
*
* @return LettuceConnectionFactory implement RedisConnectionFactory
*/
@Bean
public LettuceConnectionFactory getLettuceConnectionFactory(RedisStandaloneConfiguration configuration,
LettuceClientConfiguration clientConfig) {
LettuceConnectionFactory factory = new LettuceConnectionFactory(configuration, clientConfig);
//校验连接是否有效
factory.setValidateConnection(true);
//选择数据库
factory.setDatabase(dbIndex);
factory.afterPropertiesSet();
return factory;
}
/**
* 自定义 redisTemplate (方法名一定要叫 redisTemplate 因为 @Bean 是根据方法名配置这个bean的name的)
* 默认的 RedisTemplate<K,V> 为泛型,使用时不太方便,自定义为 <String, Object>
* 默认序列化方式为 JdkSerializationRedisSerializer 序列化后的内容不方便阅读,改为序列化成 fastjson
*
*/
@Bean(name = "redisTemplate")
public RedisTemplate<String, Object> getRedisTemplate(RedisConnectionFactory factory) {
RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
// 将 key 序列化成字符串
redisTemplate.setKeySerializer(new StringRedisSerializer());
// 将 value 序列化成 json
redisTemplate.setValueSerializer(new GenericFastJsonRedisSerializer());
// 将 hash 的 key 序列化成字符串
redisTemplate.setHashKeySerializer(new StringRedisSerializer());
// 将 hash 的 value 序列化成 json
redisTemplate.setHashValueSerializer(new GenericFastJsonRedisSerializer());
//事务支持
//redisTemplate.setEnableTransactionSupport(true);
redisTemplate.setConnectionFactory(factory);
return redisTemplate;
}
}
在项目中可以直接自动注入使用,需要注意的是:这个StringRedisTemplate 跟RedisTemplate 两者的数据是不共通的;也就是说StringRedisTemplate只能管理StringRedisTemplate里面的数据,RedisTemplate只能管理RedisTemplate中的数据。当你的redis数据库里面本来存的是字符串数据或者你要存储字符串数据的时候就必须要用StringRedisTemplate,虽然RedisTemplate能存储字符串,但是存储到库中就变成带双引号的字符串了,在做字符串相关操作的时候就会返回错误的结果,比如redisTemplate.opsForHash().lengthOfValue(H key, HK hashKey)(获取字段对应值的长度)这个方法返回的字符串长度就包括两个引号!
如果你的数据是复杂的对象类型,而取出的时候又不想做任何的数据转换,直接从Redis里面取出一个对象,那么使用RedisTemplate是更好的选择。
@Autowired
private RedisTemplate<String, Object> redisTemplate;
@Autowired
private StringRedisTemplate redisTemplate;
对于RedisTemplate 的使用请参考https://docs.spring.io/spring-data/redis/docs/2.2.3.RELEASE/reference/html/#redis:template
在做测试时pom里引入了其他的版本的netty,导致报错!这是由于lettuce是底层是基于Netty框架的,所以导致netty版本冲突!
org.springframework.data.redis.connection.PoolException: Could not get a resource from the pool; nested exception is io.lettuce.core.RedisConnectionException: Unable to connect to 127.0.0.1:6379
at org.springframework.data.redis.connection.lettuce.LettucePoolingConnectionProvider.getConnection(LettucePoolingConnectionProvider.java:86)
at org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory$SharedConnection.getNativeConnection(LettuceConnectionFactory.java:1104)
at org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory$SharedConnection.getConnection(LettuceConnectionFactory.java:1085)
at org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory.getSharedConnection(LettuceConnectionFactory.java:866)
at org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory.getConnection(LettuceConnectionFactory.java:341)
at org.springframework.data.redis.core.RedisConnectionUtils.doGetConnection(RedisConnectionUtils.java:132)
at org.springframework.data.redis.core.RedisConnectionUtils.getConnection(RedisConnectionUtils.java:95)
at org.springframework.data.redis.core.RedisConnectionUtils.getConnection(RedisConnectionUtils.java:82)
at org.springframework.data.redis.core.RedisTemplate.execute(RedisTemplate.java:211)
at org.springframework.data.redis.core.RedisTemplate.execute(RedisTemplate.java:184)
at org.springframework.data.redis.core.RedisTemplate.delete(RedisTemplate.java:727)
at com.fh.frame.redis.BaseRedisOperator.del(BaseRedisOperator.java:62)
at com.fh.controller.information.configwxappaccount.ConfigWxAppAccountController.clearCache(ConfigWxAppAccountController.java:277)
at com.fh.controller.information.configwxappaccount.ConfigWxAppAccountController.editData(ConfigWxAppAccountController.java:107)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:190)
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:138)
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:104)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:892)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:797)
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1039)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:942)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1005)
at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:908)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:661)
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:882)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:742)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.apache.shiro.web.servlet.ProxiedFilterChain.doFilter(ProxiedFilterChain.java:61)
at org.apache.shiro.web.servlet.AdviceFilter.executeChain(AdviceFilter.java:108)
at org.apache.shiro.web.servlet.AdviceFilter.doFilterInternal(AdviceFilter.java:137)
at org.apache.shiro.web.servlet.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:125)
at org.apache.shiro.web.servlet.ProxiedFilterChain.doFilter(ProxiedFilterChain.java:66)
at org.apache.shiro.web.servlet.AbstractShiroFilter.executeChain(AbstractShiroFilter.java:449)
at org.apache.shiro.web.servlet.AbstractShiroFilter$1.call(AbstractShiroFilter.java:365)
at org.apache.shiro.subject.support.SubjectCallable.doCall(SubjectCallable.java:90)
at org.apache.shiro.subject.support.SubjectCallable.call(SubjectCallable.java:83)
at org.apache.shiro.subject.support.DelegatingSubject.execute(DelegatingSubject.java:383)
at org.apache.shiro.web.servlet.AbstractShiroFilter.doFilterInternal(AbstractShiroFilter.java:362)
at org.apache.shiro.web.servlet.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:125)
at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:357)
at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:270)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at com.alibaba.druid.support.http.WebStatFilter.doFilter(WebStatFilter.java:123)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:200)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:109)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:198)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:493)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:140)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:81)
at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:650)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:342)
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:800)
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66)
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:806)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1498)
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Thread.java:745)
Caused by: io.lettuce.core.RedisConnectionException: Unable to connect to 127.0.0.1:6379
at io.lettuce.core.RedisConnectionException.create(RedisConnectionException.java:78)
at io.lettuce.core.RedisConnectionException.create(RedisConnectionException.java:56)
at io.lettuce.core.AbstractRedisClient.getConnection(AbstractRedisClient.java:235)
at io.lettuce.core.RedisClient.connect(RedisClient.java:204)
at org.springframework.data.redis.connection.lettuce.StandaloneConnectionProvider.lambda$getConnection$1(StandaloneConnectionProvider.java:113)
at java.util.Optional.orElseGet(Optional.java:267)
at org.springframework.data.redis.connection.lettuce.StandaloneConnectionProvider.getConnection(StandaloneConnectionProvider.java:113)
at org.springframework.data.redis.connection.lettuce.LettucePoolingConnectionProvider.lambda$null$0(LettucePoolingConnectionProvider.java:74)
at io.lettuce.core.support.ConnectionPoolSupport$RedisPooledObjectFactory.create(ConnectionPoolSupport.java:209)
at io.lettuce.core.support.ConnectionPoolSupport$RedisPooledObjectFactory.create(ConnectionPoolSupport.java:199)
at org.apache.commons.pool2.BasePooledObjectFactory.makeObject(BasePooledObjectFactory.java:58)
at org.apache.commons.pool2.impl.GenericObjectPool.create(GenericObjectPool.java:899)
at org.apache.commons.pool2.impl.GenericObjectPool.borrowObject(GenericObjectPool.java:429)
at org.apache.commons.pool2.impl.GenericObjectPool.borrowObject(GenericObjectPool.java:354)
at io.lettuce.core.support.ConnectionPoolSupport$1.borrowObject(ConnectionPoolSupport.java:122)
at io.lettuce.core.support.ConnectionPoolSupport$1.borrowObject(ConnectionPoolSupport.java:117)
at org.springframework.data.redis.connection.lettuce.LettucePoolingConnectionProvider.getConnection(LettucePoolingConnectionProvider.java:80)
... 75 more
Caused by: io.netty.channel.ChannelPipelineException: io.lettuce.core.PlainChannelInitializer.handlerAdded() has thrown an exception; removed.
at io.netty.channel.DefaultChannelPipeline.callHandlerAdded0(DefaultChannelPipeline.java:625)
at io.netty.channel.DefaultChannelPipeline.access$100(DefaultChannelPipeline.java:46)
at io.netty.channel.DefaultChannelPipeline$PendingHandlerAddedTask.execute(DefaultChannelPipeline.java:1461)
at io.netty.channel.DefaultChannelPipeline.callHandlerAddedForAllHandlers(DefaultChannelPipeline.java:1126)
at io.netty.channel.DefaultChannelPipeline.invokeHandlerAddedIfNeeded(DefaultChannelPipeline.java:651)
at io.netty.channel.AbstractChannel$AbstractUnsafe.register0(AbstractChannel.java:514)
at io.netty.channel.AbstractChannel$AbstractUnsafe.access$200(AbstractChannel.java:427)
at io.netty.channel.AbstractChannel$AbstractUnsafe$1.run(AbstractChannel.java:486)
at io.netty.util.concurrent.AbstractEventExecutor.safeExecute$$$capture(AbstractEventExecutor.java:163)
at io.netty.util.concurrent.AbstractEventExecutor.safeExecute(AbstractEventExecutor.java)
at io.netty.util.concurrent.SingleThreadEventExecutor.runAllTasks(SingleThreadEventExecutor.java:404)
at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:495)
at io.netty.util.concurrent.SingleThreadEventExecutor$5.run(SingleThreadEventExecutor.java:905)
at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
... 1 more
Caused by: java.lang.NoSuchMethodError: io.netty.buffer.ByteBufUtil.hexDump([BII)Ljava/lang/String;
at io.netty.channel.DefaultChannelId.asShortText(DefaultChannelId.java:210)
at io.netty.channel.AbstractChannel.toString(AbstractChannel.java:410)
at java.lang.String.valueOf(String.java:2994)
at java.lang.StringBuilder.append(StringBuilder.java:131)
at io.netty.channel.ChannelInitializer.exceptionCaught(ChannelInitializer.java:97)
at io.netty.channel.ChannelInitializer.initChannel(ChannelInitializer.java:133)
at io.netty.channel.ChannelInitializer.handlerAdded(ChannelInitializer.java:112)
at io.netty.channel.AbstractChannelHandlerContext.callHandlerAdded(AbstractChannelHandlerContext.java:989)
at io.netty.channel.DefaultChannelPipeline.callHandlerAdded0(DefaultChannelPipeline.java:610)
... 14 more
来源:oschina
链接:https://my.oschina.net/1181360/blog/3148278