从.Net到Java学习第四篇——spring boot+redis
“学习 java 已经十天,有时也怀念当初.net的经典,让这语言将你我相连,怀念你......”接上一篇,本篇使用到的框架 redis、FastJSON。
环境准备
安装 redis,下图是我本机的 redis 绿色版,你可以网上自行下载安装,如果不知道如何怎么操作,可以移步到我的另一篇文章:ASP.NET Redis 开发
以管理员身份打开 CMD 窗口:
C:\Users\zouqj>e:
E:</span>>cd E:\Redis-x64-3.2.100
E:\Redis-x64-3.2.100>redis-server --service-install redis.windows.conf --loglevel verbose --service-name redis --port 6379
运行之后,记得启动 redis 服务,我这里 redis 没有设置密码。
启动服务命令:net start redis
关于 FastJSON 框架的使用呢可以参考文章:高性能 JSON 框架之 FastJson 的简单使用
修改 pom.xml,添加 redis 的依赖
<!--redis--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-redis</artifactId> <version>1.3.8.RELEASE</version> </dependency> <!--JSON--> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.1.23</version> </dependency>
修改项目配置文件,添加如下配置节点
redis:
database: 0
host: 127.0.0.1
port: 6379
pool:
max-active: 100
max-idle: 10
max-wait: 100000
timeout: 0
最终配置如下:
redis 配置项说明:
# REDIS (RedisProperties) # Redis 数据库索引(默认为 0) spring.redis.database=0 # Redis 服务器地址 spring.redis.host=127.0.0.1 # Redis 服务器连接端口 spring.redis.port=6379 # Redis 服务器连接密码(默认为空) spring.redis.password= # 连接池最大连接数(使用负值表示没有限制) spring.redis.pool.max-active=8 # 连接池最大阻塞等待时间(使用负值表示没有限制) spring.redis.pool.max-wait=-1 # 连接池中的最大空闲连接 spring.redis.pool.max-idle=8 # 连接池中的最小空闲连接 spring.redis.pool.min-idle=0 # 连接超时时间(毫秒) spring.redis.timeout=0
新建一个 redis 的配置类RedisConfig,因为是配置类,所以要在类上面添加注解@Configuration
@EnableAutoConfiguration 注解我们看下它的源码,发现它是一个组合注解
@Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented @Inherited @AutoConfigurationPackage @Import({EnableAutoConfigurationImportSelector.class}) public @interface EnableAutoConfiguration { String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";Class</span><?>[] exclude() <span style="color: rgba(0, 0, 255, 1)">default</span><span style="color: rgba(0, 0, 0, 1)"> {}; String[] excludeName() </span><span style="color: rgba(0, 0, 255, 1)">default</span><span style="color: rgba(0, 0, 0, 1)"> {};
}
@EnableAutoConfiguration注解大致处理流程就是:
1、先去扫描已经被 @Component 所注释的类,当然会先判断有没有 @Condition 相关的注解。
2、然后递归的取扫描该类中的 @ImportResource,@PropertySource,@ComponentScan,@Bean,@Import。一直处理完。
参考:@EnableAutoConfiguration 配置解释
@Configuration @EnableAutoConfiguration public class RedisConfig { @Bean @ConfigurationProperties(prefix = "spring.redis.pool") public JedisPoolConfig getRedisConfig() { JedisPoolConfig config = new JedisPoolConfig(); return config; }@Bean @ConfigurationProperties(prefix </span>= "spring.redis"<span style="color: rgba(0, 0, 0, 1)">) </span><span style="color: rgba(0, 0, 255, 1)">public</span><span style="color: rgba(0, 0, 0, 1)"> JedisConnectionFactory getConnectionFactory() { JedisConnectionFactory factory </span>= <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> JedisConnectionFactory(); factory.setUsePool(</span><span style="color: rgba(0, 0, 255, 1)">true</span><span style="color: rgba(0, 0, 0, 1)">); JedisPoolConfig config </span>=<span style="color: rgba(0, 0, 0, 1)"> getRedisConfig(); factory.setPoolConfig(config); </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> factory; } @Bean </span><span style="color: rgba(0, 0, 255, 1)">public</span> RedisTemplate<?, ?><span style="color: rgba(0, 0, 0, 1)"> getRedisTemplate() { JedisConnectionFactory factory </span>=<span style="color: rgba(0, 0, 0, 1)"> getConnectionFactory(); RedisTemplate</span><?, ?> template = <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> StringRedisTemplate(factory); </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> template; }
}
添加一个 redis 的接口服务RedisService
package com.yujie.service;public interface RedisService {
/**
* set 存数据 * @param key * @param value * @return
*/
boolean set(String key, String value);</span><span style="color: rgba(0, 128, 0, 1)">/**</span><span style="color: rgba(0, 128, 0, 1)"> * get获取数据 * </span><span style="color: rgba(128, 128, 128, 1)">@param</span><span style="color: rgba(0, 128, 0, 1)"> key * </span><span style="color: rgba(128, 128, 128, 1)">@return</span> <span style="color: rgba(0, 128, 0, 1)">*/</span><span style="color: rgba(0, 0, 0, 1)"> String get(String key); </span><span style="color: rgba(0, 128, 0, 1)">/**</span><span style="color: rgba(0, 128, 0, 1)"> * 设置有效天数 * </span><span style="color: rgba(128, 128, 128, 1)">@param</span><span style="color: rgba(0, 128, 0, 1)"> key * </span><span style="color: rgba(128, 128, 128, 1)">@param</span><span style="color: rgba(0, 128, 0, 1)"> expire * </span><span style="color: rgba(128, 128, 128, 1)">@return</span> <span style="color: rgba(0, 128, 0, 1)">*/</span> <span style="color: rgba(0, 0, 255, 1)">boolean</span> expire(String key, <span style="color: rgba(0, 0, 255, 1)">long</span><span style="color: rgba(0, 0, 0, 1)"> expire); </span><span style="color: rgba(0, 128, 0, 1)">/**</span><span style="color: rgba(0, 128, 0, 1)"> * 移除数据 * </span><span style="color: rgba(128, 128, 128, 1)">@param</span><span style="color: rgba(0, 128, 0, 1)"> key * </span><span style="color: rgba(128, 128, 128, 1)">@return</span> <span style="color: rgba(0, 128, 0, 1)">*/</span> <span style="color: rgba(0, 0, 255, 1)">boolean</span><span style="color: rgba(0, 0, 0, 1)"> remove(String key);
}
添加 redis 实现类RedisServiceImpl,注意下面代码中标红了的代码,这里设置 redis 的 key 和 value 以字符串的方式进行存储,如果不配置的话,默认是以 16 进制的形式进行存储,到时候我们读取的时候,就会看着很乱。
@Service("redisService") public class RedisServiceImpl implements RedisService { @Resource private RedisTemplate<String, ?> redisTemplate;@Override </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">boolean</span> set(<span style="color: rgba(0, 0, 255, 1)">final</span> String key, <span style="color: rgba(0, 0, 255, 1)">final</span><span style="color: rgba(0, 0, 0, 1)"> String value) { </span><span style="color: rgba(0, 0, 255, 1)">boolean</span> result = redisTemplate.execute(<span style="color: rgba(0, 0, 255, 1)">new</span> RedisCallback<Boolean><span style="color: rgba(0, 0, 0, 1)">() { @Override </span><span style="color: rgba(0, 0, 255, 1)">public</span> Boolean doInRedis(RedisConnection connection) <span style="color: rgba(0, 0, 255, 1)">throws</span><span style="color: rgba(0, 0, 0, 1)"> DataAccessException { <span style="color: rgba(255, 0, 0, 1)"> RedisSerializer</span></span><span style="color: rgba(255, 0, 0, 1)"><String> serializer =</span><span style="color: rgba(0, 0, 0, 1)"><span style="color: rgba(255, 0, 0, 1)"> redisTemplate.getStringSerializer();</span> connection.set(serializer.serialize(key), serializer.serialize(value)); </span><span style="color: rgba(0, 0, 255, 1)">return</span> <span style="color: rgba(0, 0, 255, 1)">true</span><span style="color: rgba(0, 0, 0, 1)">; } }); </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> result; } @Override </span><span style="color: rgba(0, 0, 255, 1)">public</span> String get(<span style="color: rgba(0, 0, 255, 1)">final</span><span style="color: rgba(0, 0, 0, 1)"> String key) { String result </span>= redisTemplate.execute(<span style="color: rgba(0, 0, 255, 1)">new</span> RedisCallback<String><span style="color: rgba(0, 0, 0, 1)">() { @Override </span><span style="color: rgba(0, 0, 255, 1)">public</span> String doInRedis(RedisConnection connection) <span style="color: rgba(0, 0, 255, 1)">throws</span><span style="color: rgba(0, 0, 0, 1)"> DataAccessException { <span style="color: rgba(255, 0, 0, 1)">RedisSerializer</span></span><span style="color: rgba(255, 0, 0, 1)"><String> serializer = redisTemplate.getStringSerializer(); </span><span style="color: rgba(0, 0, 255, 1)">byte</span>[] value =<span style="color: rgba(0, 0, 0, 1)"> connection.get(serializer.serialize(key)); </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> serializer.deserialize(value); } }); </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> result; } @Override </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">boolean</span> expire(<span style="color: rgba(0, 0, 255, 1)">final</span> String key, <span style="color: rgba(0, 0, 255, 1)">long</span><span style="color: rgba(0, 0, 0, 1)"> expire) { </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> redisTemplate.expire(key, expire, TimeUnit.SECONDS); } @Override </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">boolean</span> remove(<span style="color: rgba(0, 0, 255, 1)">final</span><span style="color: rgba(0, 0, 0, 1)"> String key) { </span><span style="color: rgba(0, 0, 255, 1)">boolean</span> result = redisTemplate.execute(<span style="color: rgba(0, 0, 255, 1)">new</span> RedisCallback<Boolean><span style="color: rgba(0, 0, 0, 1)">() { @Override </span><span style="color: rgba(0, 0, 255, 1)">public</span> Boolean doInRedis(RedisConnection connection) <span style="color: rgba(0, 0, 255, 1)">throws</span><span style="color: rgba(0, 0, 0, 1)"> DataAccessException { RedisSerializer</span><String> serializer =<span style="color: rgba(0, 0, 0, 1)"> redisTemplate.getStringSerializer(); connection.del(key.getBytes()); </span><span style="color: rgba(0, 0, 255, 1)">return</span> <span style="color: rgba(0, 0, 255, 1)">true</span><span style="color: rgba(0, 0, 0, 1)">; } }); </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> result; }
}
由于项目中引入了 spring-boot-starter-test 的依赖,也就是集成了 spring boot 的单元测试框架。给 redis 实现类,添加单元测试,将光标移动到RedisService接口位置处,然后按 Alt+Enter,如下图所示:
全选所有方法
在 model 包中,添加一个实体类Person
public class Person { private String name; private String sex;</span><span style="color: rgba(0, 0, 255, 1)">public</span><span style="color: rgba(0, 0, 0, 1)"> Person() { } </span><span style="color: rgba(0, 0, 255, 1)">public</span><span style="color: rgba(0, 0, 0, 1)"> Person(String name, String sex) { </span><span style="color: rgba(0, 0, 255, 1)">this</span>.name =<span style="color: rgba(0, 0, 0, 1)"> name; </span><span style="color: rgba(0, 0, 255, 1)">this</span>.sex =<span style="color: rgba(0, 0, 0, 1)"> sex; } </span><span style="color: rgba(0, 0, 255, 1)">public</span><span style="color: rgba(0, 0, 0, 1)"> String getName() { </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> name; } </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> setName(String name) { </span><span style="color: rgba(0, 0, 255, 1)">this</span>.name =<span style="color: rgba(0, 0, 0, 1)"> name; } </span><span style="color: rgba(0, 0, 255, 1)">public</span><span style="color: rgba(0, 0, 0, 1)"> String getSex() { </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> sex; } </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> setSex(String sex) { </span><span style="color: rgba(0, 0, 255, 1)">this</span>.sex =<span style="color: rgba(0, 0, 0, 1)"> sex; }
}
接下来,我们再修改一下单元测试
@RunWith(SpringRunner.class) @SpringBootTest public class RedisServiceImplTest { private JSONObject json = new JSONObject(); @Autowired private RedisService redisService;@Test </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span> contextLoads() <span style="color: rgba(0, 0, 255, 1)">throws</span><span style="color: rgba(0, 0, 0, 1)"> Exception { } </span><span style="color: rgba(0, 128, 0, 1)">/**</span><span style="color: rgba(0, 128, 0, 1)"> * 插入字符串 </span><span style="color: rgba(0, 128, 0, 1)">*/</span><span style="color: rgba(0, 0, 0, 1)"> @Test </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> setString() { redisService.set(</span>"redis_string_test", "springboot redis test"<span style="color: rgba(0, 0, 0, 1)">); } </span><span style="color: rgba(0, 128, 0, 1)">/**</span><span style="color: rgba(0, 128, 0, 1)"> * 获取字符串 </span><span style="color: rgba(0, 128, 0, 1)">*/</span><span style="color: rgba(0, 0, 0, 1)"> @Test </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> getString() { String result </span>= redisService.get("redis_string_test"<span style="color: rgba(0, 0, 0, 1)">); System.out.println(result); } </span><span style="color: rgba(0, 128, 0, 1)">/**</span><span style="color: rgba(0, 128, 0, 1)"> * 插入对象 </span><span style="color: rgba(0, 128, 0, 1)">*/</span><span style="color: rgba(0, 0, 0, 1)"> @Test </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> setObject() { Person person </span>= <span style="color: rgba(0, 0, 255, 1)">new</span> Person("person", "male"<span style="color: rgba(0, 0, 0, 1)">); redisService.set(</span>"redis_obj_test"<span style="color: rgba(0, 0, 0, 1)">, json.toJSONString(person)); } </span><span style="color: rgba(0, 128, 0, 1)">/**</span><span style="color: rgba(0, 128, 0, 1)"> * 获取对象 </span><span style="color: rgba(0, 128, 0, 1)">*/</span><span style="color: rgba(0, 0, 0, 1)"> @Test </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> getObject() { String result </span>= redisService.get("redis_obj_test"<span style="color: rgba(0, 0, 0, 1)">); Person person </span>= json.parseObject(result, Person.<span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)">); System.out.println(json.toJSONString(person)); } </span><span style="color: rgba(0, 128, 0, 1)">/**</span><span style="color: rgba(0, 128, 0, 1)"> * 插入对象List </span><span style="color: rgba(0, 128, 0, 1)">*/</span><span style="color: rgba(0, 0, 0, 1)"> @Test </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> setList() { Person person1 </span>= <span style="color: rgba(0, 0, 255, 1)">new</span> Person("person1", "male"<span style="color: rgba(0, 0, 0, 1)">); Person person2 </span>= <span style="color: rgba(0, 0, 255, 1)">new</span> Person("person2", "female"<span style="color: rgba(0, 0, 0, 1)">); Person person3 </span>= <span style="color: rgba(0, 0, 255, 1)">new</span> Person("person3", "male"<span style="color: rgba(0, 0, 0, 1)">); List</span><Person> list = <span style="color: rgba(0, 0, 255, 1)">new</span> ArrayList<><span style="color: rgba(0, 0, 0, 1)">(); list.add(person1); list.add(person2); list.add(person3); redisService.set(</span>"redis_list_test"<span style="color: rgba(0, 0, 0, 1)">, json.toJSONString(list)); } </span><span style="color: rgba(0, 128, 0, 1)">/**</span><span style="color: rgba(0, 128, 0, 1)"> * 获取list </span><span style="color: rgba(0, 128, 0, 1)">*/</span><span style="color: rgba(0, 0, 0, 1)"> @Test </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> getList() { String result </span>= redisService.get("redis_list_test"<span style="color: rgba(0, 0, 0, 1)">); List</span><String> list = json.parseArray(result, String.<span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)">); System.out.println(list); } @Test </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> remove() { redisService.remove(</span>"redis_test"<span style="color: rgba(0, 0, 0, 1)">); }
}
我们发现,在单元测试类上面自动添加了 2 个注解,@SpringBootTest和@RunWith(SpringRunner.class)
@SpringBootTest 注解是 SpringBoot 自 1.4.0 版本开始引入的一个用于测试的注解。
@RunWith 就是一个运行器
@RunWith(SpringRunner.class) 就是指用SpringRunner来运行
运行单元测试:
查看 redis 中的结果,这里用到一个可视化的 redis 管理工具:RedisDesktopManager