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


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