从.Net到Java学习第四篇——spring boot+redis

从.Net 到 Java 学习系列目录

“学习 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>&lt;?&gt;[] 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&lt;?, ?&gt;<span style="color: rgba(0, 0, 0, 1)"> getRedisTemplate() {
    JedisConnectionFactory factory </span>=<span style="color: rgba(0, 0, 0, 1)"> getConnectionFactory();
    RedisTemplate</span>&lt;?, ?&gt; 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&lt;Boolean&gt;<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)">&lt;String&gt; 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&lt;String&gt;<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)">&lt;String&gt; 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&lt;Boolean&gt;<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>&lt;String&gt; 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>&lt;Person&gt; list = <span style="color: rgba(0, 0, 255, 1)">new</span> ArrayList&lt;&gt;<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>&lt;String&gt; 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)">);
}

}

View Code

 我们发现,在单元测试类上面自动添加了 2 个注解,@SpringBootTest@RunWith(SpringRunner.class)

@SpringBootTest 注解是 SpringBoot 自 1.4.0 版本开始引入的一个用于测试的注解。

@RunWith 就是一个运行器

@RunWith(SpringRunner.class) 就是指用SpringRunner来运行

运行单元测试:

查看 redis 中的结果,这里用到一个可视化的 redis 管理工具:RedisDesktopManager