1. 程式人生 > 實用技巧 >Linux伺服器基本操作

Linux伺服器基本操作

Springboot整合redis

redis設定:

  • 修改redis伺服器的配置檔案
vim /usr/local/redis/bin/redis.conf

bind 0.0.0.0 
protected-mode no
  • 重新啟動redis
systemctl restart redis.service   #重新啟動服務

注意:伺服器的話需要設定安全組開放埠

1.匯入依賴

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

2.全域性配置檔案中配置redis資訊

# 應用名稱
spring:
  application:
    name: springboot-redis01
  redis:
    host: 47.93.190.68
    port: 6379
    database: 0
    jedis:
      #redis連線池資訊
      pool:
        max-active: 8
        min-idle: 0
        max-idle: 8
        max-wait: -1

server:
  servlet:
    context-path: /redis01

通過以上配置後springboot就為我們提供了RedisTemplate和StringRedisTemplate(對key,value形式的都是string操作)

相關操作

StringRedisTemplate

對string型別的操作方式:

//操作string
stringRedisTemplate.opsForValue().set("string01","string");
System.out.println(stringRedisTemplate.opsForValue().get("string01"));
//操作hash型別
stringRedisTemplate.opsForHash().put("hash-user","username","name");
stringRedisTemplate.opsForHash().put("hash-user","userage","age");
//操作list
stringRedisTemplate.opsForList().rightPushAll("list","l1","l2");
//操作set
stringRedisTemplate.opsForSet().add("set01", "daaa");
//操作zset
stringRedisTemplate.opsForZSet().add("zset01", "zset", 1);
  • 繫結一個鍵(k)進行操作:通常是對一個key進行多次的操作時使用。

//沒有key就會新增key
BoundValueOperations<String, String> boundValueOps = stringRedisTemplate.boundValueOps("name");
//追加的方式
boundValueOps.append("hahaha");
boundValueOps.append("hahaha");
System.out.println(boundValueOps.get());

//重新賦值
boundValueOps.set("hanwei hello");
System.out.println(boundValueOps.get());

注意: 一旦繫結key之後後續根據返回物件的操作都是基於這個key的操作

redisTemplate

  • 一般操作是將物件儲存在redis中。
@Test
    public void testRedisTemplate(){
        //通過這種方式是獲取不到stringRedisTemplate方式設定的值的
        System.out.println(redisTemplate.opsForValue().get("name"));//null

        //設定key的序列化方式為string
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        //以下是設定value的序列化
        Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Object.class);

        //jackson
        ObjectMapper objectMapper = new ObjectMapper();
        //轉換json格式的時候將原始型別保留,這樣在反序列化的時候就能知道對應的型別資訊
        objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);

        //修改儲存在redis中的日期格式
        objectMapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd"));
        jackson2JsonRedisSerializer.setObjectMapper(objectMapper);
        redisTemplate.setValueSerializer(jackson2JsonRedisSerializer);


        User user = new User();
        user.setId(22).setName("hanhan").setBir(new Date());
        redisTemplate.opsForValue().set("user",user);
        System.out.println(redisTemplate.opsForValue().get("user").toString());

        //hash型別的是(key,(key,val)),所以需要單獨設定序列化方式
        redisTemplate.setHashKeySerializer(new StringRedisSerializer());
        redisTemplate.setHashValueSerializer(jackson2JsonRedisSerializer);
        redisTemplate.opsForHash().put("user1","user",user);
        System.out.println(redisTemplate.opsForHash().get("user1", "user"));
    }

注意redistemplate預設使用的是jdk的序列化,儲存到redis中會是下面的情況:image-20201215184546111,所以我們將key的序列化改為string型別的,將value改為json序列化。

mybatis中使用redis

mybatis自身快取存在問題,本地快取local cache

​ 1.本地快取儲存在當前執行的jvm記憶體中,如果快取資料過多會佔用一定jvm記憶體,導致應用執行快取。

​ 2.不能在分散式系統中做到快取共享。

重寫mybatis cache 使用redis作分散式快取

如果使用mybatis的二級快取只需要在mapper檔案中新增,二級快取的作用範圍是每個maper。

自定義redis快取作為mybatis的快取

  • 匯入依賴
<dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <!--  springboot-redis-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
        </dependency>

<!--        mybatis-->
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>2.1.1</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.1.21</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
    </dependencies>

注意:mybatis的xml檔案如果再java檔案下的話,一定要加resources將xml釋出

  • 自定義RedisCache類
package com.han.cache;

import com.han.util.ApplicationContextUtils;
import org.apache.ibatis.cache.Cache;
import org.springframework.context.ApplicationContext;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.StringRedisSerializer;

import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

/**
 * @author M.han
 * @title: RedisCache
 * @projectName springboot-redis
 * @description: TODO
 * @date 2020/12/1520:18
 */
public class RedisCache implements Cache {
    private String id;

    public RedisCache(String id) {
        System.out.println("當前加入快取的id==》" + id);
        this.id = id;
    }

    @Override
    public String getId() {
        return id;
    }

    /***
     * 放入快取
     * @param key
     * @param val
     */
    @Override
    public void putObject(Object key, Object val) {
        System.out.println("KEY:" + key);
        System.out.println("val:" + val);
        //獲取物件
        RedisTemplate redisTemplate = (RedisTemplate) ApplicationContextUtils.getBean("redisTemplate");

        redisTemplate.setKeySerializer(new StringRedisSerializer());
        //儲存在Redis中,注意上面對key使用了string序列化,所以傳入的key是string型別的
        redisTemplate.opsForValue().set(key.toString(), val);
    }

    /***
     * 從快取中獲取
     * @param key
     * @return
     */
    @Override
    public Object getObject(Object key) {
        System.out.println("從快取中讀取了=》" + key);
        //獲取物件
        RedisTemplate redisTemplate = (RedisTemplate) ApplicationContextUtils.getBean("redisTemplate");
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        return redisTemplate.opsForValue().get(key.toString());
    }

    /***
     *  刪除快取中的資料
     */
    @Override
    public Object removeObject(Object o) {
        return null;
    }

    /***
     * 清空快取
     */
    @Override
    public void clear() {

    }

    /***
     * 快取的命中概率
     * @return
     */
    @Override
    public int getSize() {
        return 0;
    }

    /***
     * 讀寫鎖,可以為空,寫寫互斥,讀寫互斥,讀讀共享
     * @return
     */
    @Override
    public ReadWriteLock getReadWriteLock() {
        return new ReentrantReadWriteLock();
    }
}

  • 因為快取類是mybatis使用而沒有交給spring容器託管(因為在mybatis執行這個的時候要傳入id),但是在RedisCache類中需要注入RedisTemplate,所以自定義一個獲取spring工廠中的bean的工具類。
package com.han.util;

import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;

/**
 * @author M.han
 * @title: ApplicationUtils
 * @projectName springboot-redis
 * @description: 獲取spring中的bean
 * @date 2020/12/15 20:26
 */
@Component
public class ApplicationContextUtils implements ApplicationContextAware {
    private static ApplicationContext applicationContext;
    /***
     *
     * @param applicationContext 已經建立好的工廠物件
     * @throws BeansException
     */
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        ApplicationContextUtils.applicationContext = applicationContext;
    }
    //下面是自定義獲取bean

    /***
     *根據id來獲取bean
     */
    public static Object getBean(String id){
        return applicationContext.getBean(id);
    }

    /***
     * 通過型別獲取bean
     * @param clazz
     * @return
     */
    public static Object getBean(Class clazz){
        return applicationContext.getBean(clazz);
    }

    /***
     * 根據id和型別同時獲取bean
     * @param id
     * @param clazz
     * @return
     */
    public static Object getBean(String id,Class clazz){
        return applicationContext.getBean(id,clazz);
    }
}

  • mapper.xml檔案中指定redis快取
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.han.dao.UserMapper">
    <!--使用自定義的redis快取實現-->
    <cache type="com.han.cache.RedisCache"/>

    <select id="findAll" resultType="com.han.pojo.User">
        select id,username,password from user
    </select>
</mapper>

  • yaml檔案配置資訊
# 應用名稱
spring:
  application:
    name: springboot-redis01
  redis:
    host:  
    port:  
    database: 0
    jedis:
      #redis連線池資訊
      pool:
        max-active: 8
        min-idle: 0
        max-idle: 8
        max-wait: -1
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://--------/db?characterEncoding=utf-8&serverTimezone=GMT%2B8
    username: root
    password: 

server:
  servlet:
    context-path: /redis01
mybatis:
  mapper-locations: classpath*:com/han/dao/*.xml
  type-aliases-package: com.han.pojo
logging:
  level:
    root: info
    com.han.dao: debug

注意啟動檔案上新增MapperScan註解掃描。

通過以上配置,只要redis快取中有該資料,mybatis就不會執行查詢,而是從快取中取資料。