SpringBoot2.0 集成Reids,作为数据库或者缓存。并支持CRUD

Redis的优势:

             1、性能极高 – Redis能读的速度是110000次/s,写的速度是81000次/s 。

             2、丰富的数据类型 – Redis支持二进制案例的 Strings, Lists, Hashes, Sets 及 Ordered Sets 数据类型操作。

             3、原子 – Redis的所有操作都是原子性的,意思就是要么成功执行要么失败完全不执行。单个操作是原子性的。多个操作也支持事务,即原子性,通过MULTI和EXEC指令包起来。

             4、丰富的特性 – Redis还支持 publish/subscribe, 通知, key 过期等等特性。

        Redis可作为数据库,可降低数据IO的读操作,减轻IO的压力。可以减少CPU和内存的压力。并且可以修改表结构,特殊对待某一条数据。并且Redis是NoSQL,读取速度快,对于较大数据处理快。

        Redis做缓存,可用于高频次访问的数据;也可用于分布式架构中session共享。


搭建步骤:

    一、采用IDEA搭建Springboot项目,并引入redis所需的依赖。如下

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
    <version>2.0.0.RELEASE</version>
</dependency>

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-redis</artifactId>
</dependency>

    二、配置Redis数据源信息

server.port=1104
server.tomcat.uri-encoding=UTF-8

#################redis基础配置###################
# 数据库设置
spring.redis.database=5
#宿主机IP
spring.redis.host=localhost
#端口号
spring.redis.port=6379
#密码
spring.redis.password=jane@2018
# 连接超时时间 单位 ms(毫秒)
spring.redis.timeout=3000

#################redis线程池设置#################
# 连接池中的最大空闲连接,默认值也是8。
spring.redis.jedis.pool.max-idle=500
#连接池中的最小空闲连接,默认值也是0。
spring.redis.jedis.pool.min-idle=50
# 如果赋值为-1,则表示不限制;如果pool已经分配了maxActive个jedis实例,则此时pool的状态为exhausted(耗尽)。
spring.redis.jedis.pool.max-wait=2000
# 等待可用连接的最大时间,单位毫秒,默认值为-1,表示永不超时。如果超过等待时间,则直接抛出JedisConnectionException
spring.redis.jedis.pool.max-active=1000

    三、编写Redis配置类

    添加一个conf包,放置redis的一些配置类

    1、首先添加RedisConf类,实例化Redis的一系列操作对象,例如HashOperations、SetOperations等,本demo中只使用了HashOperations。但是其他操作对象同样实例,以便后续的扩展

package com.jane.demo.conf.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.core.*;

/**
 * @author jane
 * @version 2018/03/08
 */
@Configuration
public class RedisConf {

    @Autowired
    private StringRedisTemplate redisTemplate;

    /**
     * 实例化 HashOperations 对象,可以使用 Hash 类型操作
     */
    /*@Bean
    public HashOperations<String, String, String> hashOperations() {
        return redisTemplate.opsForHash();
    }*/

    /**
     * 实例化 ValueOperations 对象,可以使用 String 操作
     */
    @Bean
    public ValueOperations<String, String> valueOperations() {
        return redisTemplate.opsForValue();
    }

    /**
     * 实例化 ListOperations 对象,可以使用 List 操作
     * @return
     */
    @Bean
    public ListOperations<String, String> listOperations() {
        return redisTemplate.opsForList();
    }

    /**
     * 实例化 SetOperations 对象,可以使用 Set 操作
     */
    @Bean
    public SetOperations<String, String> setOperations() {
        return redisTemplate.opsForSet();
    }

    /**
     * 实例化 ZSetOperations 对象,可以使用 ZSet 操作
     */
    @Bean
    public ZSetOperations<String, String> zSetOperations() {
        return redisTemplate.opsForZSet();
    }

}

2、分别定义了读和取的Redis库接口

    2.1 Redis写操作库接口IWriteRedisRepository<T>,可用于不同的类型的数据的写入

package com.jane.demo.conf;

/**
 * 缓存写操作
 * @param <T>
 */
public interface IWriteRedisRepository<T> extends IRedisRepository<T> {
    /**
     * 插入缓存,并不过期
     * @param key      * @param t      */
    void put(String key, T t);

    /**
     *插入缓存
     * @param key      * @param t      * @param expire 过期时间,如果为-1,则不设置过期时间
     */
    void put(String key, T t, long expire);

    /**
     * 移除缓存
     * @param key
     */
    void remove(String key);

    /**
     * 清空缓存
     */
    void empty();

}

2.2  Redis读操作库接口 IReadRedisRepository<T>

package com.jane.demo.conf;

import java.util.List;
import java.util.Set;

/**
 * 缓存读操作
 *
 * @author jane
 * @version  2018/03/08
 */
public interface IReadRedisRepository<T> extends IRedisRepository<T> {

    /**
     * 获取键值keyValue
     * @param key      * @return
     */
    T get(String key);

    /**
     * 获取所有缓存Value信息
     * @return
     */
    List<T> getAll();

    /**
     * 获取所有键值key
     * @return
     */
    Set<String> getKeys();

    /**
     * 键值key是否存在
     * @param key      * @return
     */
    boolean isKeyExists(String key);

    /**
     * Redis缓存计数器
     * @return
     */
    long count();
}

3、创建一个抽象类AbstractRedisRepository<T>,实现上面的两个Redis的读写操作接口

package com.jane.demo.conf.impl;

import com.alibaba.fastjson.JSON;
import com.jane.demo.conf.IReadRedisRepository;
import com.jane.demo.conf.IWriteRedisRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.HashOperations;
import org.springframework.data.redis.core.StringRedisTemplate;

import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;

/**
 * Redis缓存操作
 *
 * @author jane
 * @version 2018/03/08
 */
public abstract class AbstractRedisRepository<T> implements IReadRedisRepository<T>, IWriteRedisRepository<T> {

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Autowired
    private HashOperations<String, String, String> hashOperations;

    /**
     * 插入缓存,并不过期
     * @param key      * @param t      */
    @Override
    public void put(String key, T t) {
        put(key, t, -1);
    }

    /**
     * 插入缓存
     * @param key      * @param t      * @param expire 过期时间,如果为-1,则不设置过期时间
     */
    @Override
    public void put(String key, T t, long expire) {
        hashOperations.put(getRedisKey(), key, JSON.toJSONString(t));
        if (expire != -1) {
            stringRedisTemplate.expire(getRedisKey(), expire, TimeUnit.SECONDS);
        }
    }

    /**
     * 移除缓存
     * @param key
     */
    @Override
    public void remove(String key) {
        hashOperations.delete(getRedisKey(), key);
    }

    /**
     * 清空缓存
     */
    @Override
    public void empty() {
        Set<String> set = hashOperations.keys(getRedisKey());
        set.forEach(key -> hashOperations.delete(getRedisKey(), key));
    }

    /**
     * 获取缓存Value
     * @param key
     * @return
     */
    @Override
    public T get(String key) {
        return JSON.parseObject(hashOperations.get(getRedisKey(), key), getSerializeClass());
    }

    /**
     * 序列化对象
     * @return
     */
    protected abstract Class<T> getSerializeClass();

    /**
     * 获取所有缓存Value
     * @return
     */
    @Override
    public List<T> getAll() {
        return JSON.parseArray(JSON.toJSONString(hashOperations.values(getRedisKey())), getSerializeClass());
    }

    /**
     * 获取所有缓存的key
     * @return
     */
    @Override
    public Set<String> getKeys() {
        return hashOperations.keys(getRedisKey());
    }

    /**
     * 键值key是否存在
     * @param key      * @return
     */
    @Override
    public boolean isKeyExists(String key) {
        return hashOperations.hasKey(getRedisKey(), key);
    }

    /**
     * 缓存计数器
     * @return
     */
    @Override
    public long count() {
        return hashOperations.size(getRedisKey());
    }

}

4、创建一个RedisKey的类,这个类的作用类似于数据库中表名,比如我添加的是USER_KEY。即用户表

package com.jane.demo.conf;

/**
 * 系统模块名称,类似与表名
 * @author jane
 * @version 2018/03/09
 */
public class RedisKey {
    public final static String USER_KEY = "JANE.DEMO.USER";     //用户(表)
}

四、添加简单的业务逻辑和实体类

    1、添加实体类User

package com.jane.demo.entity;

import lombok.Data;

/**
 * 用户类
 * 登录名唯一作为键值
 * @author jane
 * @version 2018/03/09
 */
@Data
public class User {

    private String name; //用户姓名

    private String phoneNumber; //电话

    private String loginName;   //登录名(唯一)
}

2、添加继承AbstractRedisRepository的UserRedis类,并设置起redisKey和序列化。

package com.jane.demo.redis;

import com.jane.demo.conf.RedisKey;
import com.jane.demo.conf.impl.AbstractRedisRepository;
import com.jane.demo.entity.User;
import org.springframework.stereotype.Component;

/**
 * 用户模块
 * @author jane
 * @version 2018/03/09
 */
@Component
public class UserRedis extends AbstractRedisRepository<User> {
    @Override
    public String getRedisKey() {
        return RedisKey.USER_KEY;
    }

    @Override
    protected Class<User> getSerializeClass() {
        return User.class;
    }
}

3、添加UserService,简单定义user的CRUD。

package com.jane.demo.service;

import com.jane.demo.entity.User;
import com.jane.demo.redis.UserRedis;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

/**
 * @author jane
 * @version 2018/03/09
 */
@Service
public class UserService {

    @Autowired
    private UserRedis userRedis;

    /**
     * 保存用户(登录名唯一,作为键值)
     * @param user 用户信息
     */
    public void saveUser(User user){
        userRedis.put(user.getLoginName(), user);
    }

    /**
     * 根据登录名获取用户信息
     * @param loginName 登录名
     * @return 用户信息
     */
    public User getUser(String loginName){
       return userRedis.get(loginName);
    }

    /**
     * 判断当前登录名称是否存在
     * @param loginName 登录名
     * @return 存在返回true,否则false
     */
    public boolean isExsist(String loginName){
        return userRedis.isKeyExists(loginName);
    }

    /**
     * 获取所有用户信息
     * @return 用户集
     */
    public List<User> findAll(){
       return userRedis.getAll();
    }
}

4、添加UserController控制层,用于用户的简单交互。

package com.jane.demo.controller;

import com.jane.demo.entity.User;
import com.jane.demo.model.JsonModel;
import com.jane.demo.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

/**
 * 用户控制层
 * @author jane
 * @version 2018/03/09
 */
@RestController
@RequestMapping("/user")
public class UserController {

    @Autowired
    private UserService userService;

    @RequestMapping(value = "/test", method = RequestMethod.GET)
    public JsonModel test(){
        return new JsonModel(200, "测试成功");
    }

    @RequestMapping(value = "/create", method = RequestMethod.POST)
    public JsonModel create(User user){
        if (!userService.isExsist(user.getLoginName())){
            userService.saveUser(user);
            return new JsonModel(200,"成功添加!");
        }else {
            return new JsonModel(304,"已存在,无法添加!");
        }
    }
    @RequestMapping(value = "/getOne", method = RequestMethod.GET)
    public JsonModel get(String loginName){
        return new JsonModel(200, userService.getUser(loginName),"成功");
    }
}

五、采用junit中的MockMvc测试控制层

package com.jane.demo.controller;

import com.alibaba.fastjson.JSONObject;
import com.jane.demo.entity.User;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.http.MediaType;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.MvcResult;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext;

import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;

/**
 * 用户控制层测试
 *
 * @author jane
 * @version 2018/03/11
 */
@RunWith(SpringRunner.class)
@SpringBootTest
public class UserControllerTest {
    /** 模拟MVC对象*/
    private MockMvc mockMvc;

    /**注入Web应用上下文*/
    @Autowired
    private WebApplicationContext webApplicationContext;

    @Before
    public void setup(){
        this.mockMvc = MockMvcBuilders.webAppContextSetup(this.webApplicationContext).build();
    }

    /**
     * 测试用户的添加
     * @throws Exception
     */
    @Test
    @Ignore
    public void testCreate()throws Exception{
        User user = new User();
        user.setName("JunitTest");
        user.setPhoneNumber("1234531");
        user.setLoginName("junit");

        MvcResult result = mockMvc.perform(post("/user/create?name=JunitTest&phoneNumber=1234531&loginName=junit").contentType(MediaType.APPLICATION_JSON)
                .content(JSONObject.toJSONString(user)))
                    .andExpect(status().isOk())
                    .andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8))
                    .andReturn();
        System.out.println(result.getResponse().getContentAsString());
    }

    /**
     * 测试web项目是否部署成功
     * @throws Exception
     */
    @Test
    @Ignore
    public void testWeb()throws Exception {
        String result = mockMvc.perform(get("/user/test").contentType(MediaType.APPLICATION_JSON))
                .andExpect(status().isOk())
                    .andReturn().getResponse().getContentAsString();
        System.out.println("-------返回的JSON:" + result);

    }

    /**
     * 测试getOne
     * @throws Exception
     */
    @Test
    public void testGetOne()throws Exception {
        MvcResult result = mockMvc.perform(get("/user/getOne").contentType(MediaType.APPLICATION_JSON)
                .param("loginName","jane"))
                    .andExpect(status().isOk())
                    .andReturn();
        System.out.println(result.getResponse().getContentAsString());
    }
}

项目源代码地址:redis_springboot


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章