4
2
0
2

SpringBoot环境搭建

1、内容

  • 数据库访问:mybatis + mybatis-plus
  • Druid数据源
  • mybatis-plus 代码生成器
  • 统一返回 R 类
  • 接口文档:swagger
  • 数据库:MySQL
  • NoSql:Redis

2、整合Druid 数据源

1、导入pom依赖

<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>druid-spring-boot-starter</artifactId>
    <version>1.2.6</version>
</dependency>

2、配置applocation-dev.yml文件

spring:
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://ip地址:端口/数据库名称?useUnicode=true&characterEncoding=utf8&autoReconnect=true&allowMultiQueries=true&useSSL=false&serverTimezone=GMT%2b8
    username: 用户名
    password: 密码
    # Druid
    druid:
      # 初始化大小,最小,最大
      initial-size: 5
      max-active: 100
      min-idle: 1
      # 配置获取连接等待超时的时间
      max-wait: 60000
      # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位毫秒
      time-between-eviction-runs-millis: 60000
      # 配置一个连接在池中最小生存时间
      min-evictable-idle-time-millis: 300000
      # 用来检测连接是否有效的sql 必须是一个查询语句 注意没有此语句以下三个属性不会生效
      validation-query: SELECT 1 FROM DUAL
      # 归还连接时会执行validationQuery检测连接是否有效,开启会降低性能,默认为true
      test-on-return: false
      # 申请连接时会执行validationQuery检测连接是否有效,开启会降低性能,默认为true
      test-on-borrow: true
      # 申请连接的时候检测,如果空闲时间大于timeBetweenEvictionRunsMillis,执行validationQuery检测连接是否有效。
      test-while-idle: true
      # 配置监控统计拦截的 Filter,去掉后监控界面 SQL 无法统计,wall 用于防火墙
      filters: stat,wall
      # 通过 connection-properties 属性打开 mergeSql 功能;慢 SQL 记录
      connection-properties: druid.stat.mergeSql\=true;druid.stat.slowSqlMillis\=5000
      # 配置 DruidStatFilter
      web-stat-filter:
        enabled: true
        url-pattern: /*
        exclusions: .js,*.gif,*.jpg,*.bmp,*.png,*.css,*.ico,/druid/*
      # 配置 DruidStatViewServlet
      stat-view-servlet:
        url-pattern: /druid/*
        # IP 白名单,没有配置或者为空,则允许所有访问
        #allow: 127.0.0.1
        # IP 黑名单,若白名单也存在,则优先使用
        #deny: 192.168.31.253
        # 禁用 HTML 中 Reset All 按钮
        reset-enable: true
        # 登录用户名/密码
        login-username: root
        login-password: root
        # 注意 此处必须开启,否则无法访问druid监控面板
        enabled: true
      use-global-data-source-stat: true

3、访问监控面板

http://localhost:端口号/项目名称/druid/login.html

输入配置文件中设置的:login-username 和 login-password

3、整合Mybatis-plus

1、导入 pom 依赖

<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-boot-starter</artifactId>
    <version>3.4.3.4</version>
</dependency>
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>fastjson</artifactId>
    <version>1.2.47</version>
</dependency>

2、编辑 application-dev.yml 文件

mybatis-plus:
  configuration:
    map-underscore-to-camel-case: true
    auto-mapping-behavior: full
  mapper-locations: classpath:mapper/*.xml
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
  global-config:
    # 逻辑删除配置
    db-config:
      # 删除前
      logic-not-delete-value: 1
      # 删除后
      logic-delete-value: 0

3、编写 Mybatis-plus 配置类 添加 @MapperScan

/**
 * @Description 配置分页插件
 * @Author Admin
 * @Date 2021/9/29 18:59
 * @Version 1.0
 */
@Configuration
@MapperScan("com.codertl.springbootbuild.mapper")
public class MybatisPlusConfig {

    /**
     * 分页插件
     */
    // 最新版
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
        return interceptor;
    }
}

4、分页插件使用示例

@GetMapping("/getStuAll")
@ApiOperation("查询全部学生")
public Result<Page> getStuAll(Page<Student> page) {
    Page<Student> studentPage = studentService.page(page);
    return BaseResponseUtils.success(studentPage);
}

4、Mybatis-plus 自动代码生成

1、导入 pom 依赖

<!-- mybatis-plus-generator 代码生成器 -->
<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-generator</artifactId>
    <version>3.4.1</version>
</dependency>
<!-- 模板引擎 -->
<dependency>
    <groupId>org.freemarker</groupId>
    <artifactId>freemarker</artifactId>
    <version>2.3.28</version>
</dependency>

2、自动生成代码

package com.codertl.springbootbuild.config;


import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.core.toolkit.StringPool;
import com.baomidou.mybatisplus.generator.AutoGenerator;
import com.baomidou.mybatisplus.generator.InjectionConfig;
import com.baomidou.mybatisplus.generator.config.*;
import com.baomidou.mybatisplus.generator.config.po.TableInfo;
import com.baomidou.mybatisplus.generator.config.rules.DateType;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
import com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine;
import org.junit.Test;
import org.springframework.boot.test.context.SpringBootTest;

import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

/**
 * <p>
 * 快速生成
 * </p>
 *
 */
@SpringBootTest
public class FastAutoGeneratorTest {



    /**
     * 执行 run
     */
    @Test
    public  void autoGeneratorTest() throws SQLException {
        // 实例化代码生成器
        AutoGenerator mpg = new AutoGenerator();

        // 1.全局配置
        GlobalConfig gc = new GlobalConfig();
        // user.dir获取到你当前工程的 src 目录路径
        String projectPath = System.getProperty("user.dir");
        gc.setOutputDir(projectPath + "/src/main/java");
        gc.setAuthor("codertl");
        gc.setOpen(false);// 生成后是否打开资源管理器
        gc.setServiceName("%sService");// 去掉Service接口的首字母
        gc.setIdType(IdType.ASSIGN_ID);// 主键策略
        gc.setDateType(DateType.ONLY_DATE);// 定义生成的实体类中日期类型
        gc.setSwagger2(true); // 开启Swagger2模式

        mpg.setGlobalConfig(gc);

        // 2.配置数据源
        DataSourceConfig dsc = new DataSourceConfig();
        //todo 修改数据库连接相关信息
        dsc.setUrl("jdbc:mysql://ip地址:端口/数据库名称?useUnicode=true&characterEncoding=utf8&autoReconnect=true&allowMultiQueries=true&useSSL=false");
        dsc.setDriverName("com.mysql.cj.jdbc.Driver");
        dsc.setUsername("root");
        dsc.setPassword("密码");
        dsc.setDbType(DbType.MYSQL);
        mpg.setDataSource(dsc);

        // 3.包配置
        PackageConfig pc = new PackageConfig();
        //todo 修改模块名称
        //pc.setModuleName("student"); // 设置模块名称
        pc.setParent("com.codertl.springbootbuild");
        //pc.setController("controller");
        //pc.setEntity("entity");
        //pc.setService("service");
        //pc.setMapper("mapper");
        mpg.setPackageInfo(pc);

        // 自定义配置
        InjectionConfig cfg = new InjectionConfig() {
            @Override
            public void initMap() {
                // to do nothing
            }
        };

        // 如果模板引擎是 freemarker
        String templatePath = "/templates/mapper.xml.ftl";
        // 如果模板引擎是 velocity
        // String templatePath = "/templates/mapper.xml.vm";

        // 自定义输出配置
        List<FileOutConfig> focList = new ArrayList<>();
        // 自定义配置会被优先输出
        focList.add(new FileOutConfig(templatePath) {
            @Override
            public String outputFile(TableInfo tableInfo) {
                // 自定义输出文件名 , 如果你 Entity 设置了前后缀、此处注意 xml 的名称会跟着发生变化!!
                return projectPath + "/src/main/resources/mapper/" +  tableInfo.getEntityName() + "Mapper" + StringPool.DOT_XML;
            }
        });
        cfg.setFileOutConfigList(focList);
        mpg.setCfg(cfg);

        // 4.策略配置
        StrategyConfig strategy = new StrategyConfig();
        //todo 修改需要连接的表名称
        strategy.setInclude("student"); // 对表生成代码 表名,多个英文逗号分割
        strategy.setNaming(NamingStrategy.underline_to_camel);// //数据库表映射到实体的命名策略
        strategy.setTablePrefix(pc.getModuleName() + "_");// 生成实体时去掉表前缀
        strategy.setEntityLombokModel(true);// lombok 模型 @Accessors(chain = true) setter链式操作;
        strategy.setRestControllerStyle(true);// restful api 风格控制器
        strategy.setControllerMappingHyphenStyle(true);// url中驼峰转连字符
        mpg.setTemplateEngine(new FreemarkerTemplateEngine()); // 设置模板

        mpg.setStrategy(strategy);

        // 执行
        mpg.execute();
    }
}

5、统一返回类 R类

1、枚举

package com.codertl.springbootbuild.util;

/**
 * 枚举类对象
 */
public enum RCodeEnum {

    // 成功
    SUCCESS(200,"请求成功"),

    // 失败
    FAIL(400, "请求失败"),

    // 未认证(签名错误)
    UNAUTHORIZED(401, "未认证"),

    // 接口不存在
    NOT_FOUND(404, "接口不存在"),

    // 服务器内部错误
    INTERNAL_SERVER_ERROR(500, "服务器暂忙");

    public int code;
    public String message;

    RCodeEnum(int code, String message) {
        this.code = code;
        this.message = message;
    }
}

2、Result类

package com.codertl.springbootbuild.util;

import java.io.Serializable;

public class Result<T> implements Serializable {

    public int code;

    private String msg;

    private T data;

    public Result<T> setCode(RCodeEnum rCodeEnum) {
        this.code = rCodeEnum.code;
        return this;
    }

    public int getCode() {
        return code;
    }

    public Result<T> setCode(int code) {
        this.code = code;
        return this;
    }

    public String getMsg() {
        return msg;
    }

    public Result<T> setMsg(String msg) {
        this.msg = msg;
        return this;
    }

    public T getData() {
        return data;
    }

    public Result<T> setData(T data) {
        this.data = data;
        return this;
    }

}

3、包装返回基类

package com.codertl.springbootbuild.util;

/**
 * @Description 返回基类
 * @Author Admin
 * @Date 2021/9/30
 */
public class BaseResponseUtils {

    public static <T> Result<T> success() {
        return new Result<T>().setCode(RCodeEnum.SUCCESS.code).setMsg(RCodeEnum.SUCCESS.message);
    }

    public static <T> Result<T> success(T data) {
        return new Result<T>().setCode(RCodeEnum.SUCCESS.code).setMsg(RCodeEnum.SUCCESS.message).setData(data);
    }

    public static <T> Result<T> fail() {
        return new Result<T>().setCode(RCodeEnum.FAIL.code).setMsg(RCodeEnum.FAIL.message);
    }

    public static <T> Result<T> fail(String message) {
        return new Result<T>().setCode(RCodeEnum.FAIL.code).setMsg(message);
    }

    public static <T> Result<T> fail(Integer code, String message) {
        return new Result<T>().setCode(code).setMsg(message);
    }

}

6、整合 Swagger

1、添加pom依赖

swagger3 并且添加一个好看的页面

<!-- swagger 美化的ui 2 ,其中自动引入了 swagger 依赖-->
<dependency>
    <groupId>com.github.xiaoymin</groupId>
    <artifactId>knife4j-spring-boot-starter</artifactId>
    <version>2.0.7</version>
</dependency>

也可以用下面的依赖

<!-- swagger -->
<!--<dependency>-->
<!--    <groupId>io.springfox</groupId>-->
<!--    <artifactId>springfox-boot-starter</artifactId>-->
<!--    <version>3.0.0</version>-->
<!--</dependency>-->
<!--<dependency>-->
<!--    <groupId>com.github.xiaoymin</groupId>-->
<!--    <artifactId>swagger-bootstrap-ui</artifactId>-->
<!--    <version>1.9.6</version>-->
<!--</dependency>-->

2、配置 Swagger

  • Swagger最核心的类就是Docket、它可以配置作者信息、扫描类型…
  • 首先创建一个SwaggerConfig配置类,添加@Configuration和 @EnableSwagger2WebMvc 注解。
  • 如果导入了下边的依赖,替换@EnableSwagger2WebMvc 为 @EnableOpenApi 注解即可
  • 然后再向里面丢入Docket类的Bean实例,然后默认就可以访问了
package com.codertl.springbootbuild.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.oas.annotations.EnableOpenApi;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.Contact;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;

import java.util.ArrayList;

/**
 * @Description Swagger配置
 * @Author Admin
 * @Date 2021/9/29 18:27
 * @Version 1.0
 */
@Configuration
@EnableSwagger2WebMvc
//@EnableOpenApi
public class SwaggerConfig {

    // Swagger最核心的类就是Docket、它可以配置作者信息、扫描类型…
     // 配置Docket信息
    @Bean
    Docket docket() {
        return new Docket(DocumentationType.SWAGGER_2)
                .groupName("springboot-build接口文档") // 修改默认分组名称
                .apiInfo(apiInfo()) // 注入主页面信息
                .enable(true) // 是否启用swagger
                .select() // 扫描
                /**
                 * apis指定要扫描的方式
                 * 1. basePackage(): 指定扫描的包
                 * 2. any(): 全部扫描
                 * 3. none(): 都不扫描
                 * 4. withClassAnnotation(): 通过类注解扫描
                 * 5. withMethodAnnotation(): 通过方法上的注解扫描
                 */
                .apis(RequestHandlerSelectors.basePackage("com.codertl.springbootbuild"))
                .build();
    }

    // 配置主页信息
    @Bean
    public  ApiInfo apiInfo() {
        return new ApiInfo("Springboot环境swagger文档",  // title名称
                "Springboot环境搭建案例", // 简介
                "1.0", // 版本
                "http://localhost:9001/api/doc.html", // 服务url
                new Contact("codertl", "https://www.cnblogs.com/codertl", "email"),  // 配置作者的联系方式
                "Apache 2.0", // 许可证
                "http://www.apache.org/licenses/LICENSE-2.0",  // 许可证地址
                new ArrayList<>()  // 供应商拓展
        );
    }
}
  • 访问 ip地址:端口/doc.html页面就可以看到了,/error接口的8种请求方式默认会出现在文档中,以及一些可以配置的信息

3、Swagger 常用注解

Swagger提供了很多的注解,几乎所有需要提供展示的东西都可以使用注解来开启。

  • @Api:配置Controller类
  • @ApiModel:类可以给pojo进行展示
  • @ApiModelProperty:配置pojo的属性
  • @ApiOperation:配置方法

3.1 pojo配置

/**
 * <p>
 * 学生表
 * </p>
 *
 * @author codertl
 * @since 2021-09-29
 */
@Data
@EqualsAndHashCode(callSuper = false)
@ApiModel(value="Student对象", description="学生表")
public class Student implements Serializable {

    private static final long serialVersionUID = 1L;

    @TableId(value = "id", type = IdType.AUTO)
    private Integer id;

    @ApiModelProperty(value = "姓名")
    private String name;

    @ApiModelProperty(value = "年龄")
    private Integer age;
}

3.2 controller配置

/**
 * @Description 环境检查
 * @Author Admin
 * @Date 2021/9/29 17:08
 * @Version 1.0
 */
@RestController
@Api(tags = "健康测试")
public class HealthController {


}

3.3 接口名称配置

@PostMapping("/getUserById")
@ApiOperation("根据id查询学生")
public Result<Student> sendUserMessage(@ApiParam("用户id") @RequestParam("id") Integer id){
    Student student = studentService.getById(id);
    return new Result<Student>().setData(student);
}

7、整合 Redis

springboot2.x之后,操作redis的底层使用的Lettuce,而不是jedis

Jedis:采用的直连,多个线程操作的话,是不安全的,如果想要避免不安全的,使用jedis pool 连接池!

Lettuce:采用netty,实例可以在多个线程中进行共享,不存在线程不安全的情况!可以减少线程数据了!

1、导入 pom 依赖

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

2、配置 application-dev.yml

# redis配置
spring:
  redis:
    # 地址
    host: 127.0.0.1
    # 端口,默认为6379
    port: 6379
    # 数据库索引
    database: 0
    # 密码
    password: 1
    # 连接超时时间
    timeout: 10s
    lettuce:
      pool:
        # 连接池中的最小空闲连接
        min-idle: 0
        # 连接池中的最大空闲连接
        max-idle: 8
        # 连接池的最大数据库连接数
        max-active: 8
        # #连接池最大阻塞等待时间(使用负值表示没有限制)
        max-wait: -1ms

3、编写配置类

package com.codertl.springbootbuild.config;

import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;

import java.net.UnknownHostException;

@Configuration
public class RedisConfig {
    //编写我们的配置类
    @Bean
    @SuppressWarnings("all")
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) throws UnknownHostException {
        RedisTemplate<String, Object> template = new RedisTemplate();
        template.setConnectionFactory(redisConnectionFactory);

        Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Object.class);

        ObjectMapper objectMapper = new ObjectMapper();
        objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        jackson2JsonRedisSerializer.setObjectMapper(objectMapper);
        StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();

        //key采用String的序列化方式
        template.setKeySerializer(stringRedisSerializer);
        //hash的key也采用String的序列化方式
        template.setHashKeySerializer(stringRedisSerializer);
        //value的序列化方式采用jackson
        template.setValueSerializer(jackson2JsonRedisSerializer);
        //hash的value序列化方式采用jackson
        template.setHashValueSerializer(jackson2JsonRedisSerializer);
        template.afterPropertiesSet();

        return template;
    }
}

4、Redis 工具类

package com.codertl.springbootbuild.util;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ZSetOperations;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

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

@Component
public final class RedisUtil {

    @Autowired
    private RedisTemplate redisTemplate;

    /**
     * 根据前缀 批量删除缓存
     * @param prefixStr   指定前缀
     * @return 是否删除成功
     */
    public boolean deletePrefix(String prefixStr) {
        try {
            Set<String> keys = redisTemplate.keys(prefixStr + "*");
            redisTemplate.delete(keys);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 指定缓存失效时间
     *
     * @param key  键
     * @param time 时间(秒)
     * @return
     */
    public boolean expire(String key, long time) {
        try {
            if (time > 0) {
                redisTemplate.expire(key, time, TimeUnit.SECONDS);
            }
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 根据key 获取过期时间
     *
     * @param key 键 不能为null
     * @return 时间(秒) 返回0代表为永久有效
     */
    public long getExpire(String key) {
        return redisTemplate.getExpire(key, TimeUnit.SECONDS);
    }

    /**
     * 判断key是否存在
     *
     * @param key 键
     * @return true 存在 false不存在
     */
    public boolean hasKey(String key) {
        try {
            return redisTemplate.hasKey(key);
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 删除缓存
     *
     * @param key 可以传一个值 或多个
     */
    @SuppressWarnings("unchecked")
    public void del(String... key) {
        if (key != null && key.length > 0) {
            if (key.length == 1) {
                redisTemplate.delete(key[0]);
            } else {
                redisTemplate.delete(CollectionUtils.arrayToList(key));
            }
        }
    }

    //============================String=============================  

    /**
     * 普通缓存获取
     *
     * @param key 键
     * @return 值
     */
    public Object get(String key) {
        return key == null ? null : redisTemplate.opsForValue().get(key);
    }

    /**
     * 普通缓存放入
     *
     * @param key   键
     * @param value 值
     * @return true成功 false失败
     */
    public boolean set(String key, Object value) {
        try {
            redisTemplate.opsForValue().set(key, value);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }

    }

    /**
     * 普通缓存放入并设置时间
     *
     * @param key   键
     * @param value 值
     * @param time  时间(秒) time要大于0 如果time小于等于0 将设置无限期
     * @return true成功 false 失败
     */
    public boolean set(String key, Object value, long time) {
        try {
            if (time > 0) {
                redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS);
            } else {
                set(key, value);
            }
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 递增
     *
     * @param key 键
     * @param delta  要增加几(大于0)
     * @return
     */
    public long incr(String key, long delta) {
        if (delta < 0) {
            throw new RuntimeException("递增因子必须大于0");
        }
        return redisTemplate.opsForValue().increment(key, delta);
    }

    /**
     * 递减
     *
     * @param key 键
     * @param delta  要减少几(小于0)
     * @return
     */
    public long decr(String key, long delta) {
        if (delta < 0) {
            throw new RuntimeException("递减因子必须大于0");
        }
        return redisTemplate.opsForValue().increment(key, -delta);
    }

    //================================Map=================================  

    /**
     * HashGet
     *
     * @param key  键 不能为null
     * @param item 项 不能为null
     * @return 值
     */
    public Object hget(String key, String item) {
        return redisTemplate.opsForHash().get(key, item);
    }

    /**
     * 获取hashKey对应的所有键值
     *
     * @param key 键
     * @return 对应的多个键值
     */
    public Map<Object, Object> hmget(String key) {
        return redisTemplate.opsForHash().entries(key);
    }

    /**
     * HashSet
     *
     * @param key 键
     * @param map 对应多个键值
     * @return true 成功 false 失败
     */
    public boolean hmset(String key, Map<String, Object> map) {
        try {
            redisTemplate.opsForHash().putAll(key, map);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * HashSet 并设置时间
     *
     * @param key  键
     * @param map  对应多个键值
     * @param time 时间(秒)
     * @return true成功 false失败
     */
    public boolean hmset(String key, Map<String, Object> map, long time) {
        try {
            redisTemplate.opsForHash().putAll(key, map);
            if (time > 0) {
                expire(key, time);
            }
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 向一张hash表中放入数据,如果不存在将创建
     *
     * @param key   键
     * @param item  项
     * @param value 值
     * @return true 成功 false失败
     */
    public boolean hset(String key, String item, Object value) {
        try {
            redisTemplate.opsForHash().put(key, item, value);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 向一张hash表中放入数据,如果不存在将创建
     *
     * @param key   键
     * @param item  项
     * @param value 值
     * @param time  时间(秒)  注意:如果已存在的hash表有时间,这里将会替换原有的时间
     * @return true 成功 false失败
     */
    public boolean hset(String key, String item, Object value, long time) {
        try {
            redisTemplate.opsForHash().put(key, item, value);
            if (time > 0) {
                expire(key, time);
            }
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 删除hash表中的值
     *
     * @param key  键 不能为null
     * @param item 项 可以使多个 不能为null
     */
    public void hdel(String key, Object... item) {
        redisTemplate.opsForHash().delete(key, item);
    }

    /**
     * 判断hash表中是否有该项的值
     *
     * @param key  键 不能为null
     * @param item 项 不能为null
     * @return true 存在 false不存在
     */
    public boolean hHasKey(String key, String item) {
        return redisTemplate.opsForHash().hasKey(key, item);
    }

    /**
     * hash递增 如果不存在,就会创建一个 并把新增后的值返回
     *
     * @param key  键
     * @param item 项
     * @param by   要增加几(大于0)
     * @return
     */
    public double hincr(String key, String item, double by) {
        return redisTemplate.opsForHash().increment(key, item, by);
    }

    /**
     * hash递减
     *
     * @param key  键
     * @param item 项
     * @param by   要减少记(小于0)
     * @return
     */
    public double hdecr(String key, String item, double by) {
        return redisTemplate.opsForHash().increment(key, item, -by);
    }

    //============================set=============================  

    /**
     * 根据key获取Set中的所有值
     *
     * @param key 键
     * @return
     */
    public Set<Object> sGet(String key) {
        try {
            return redisTemplate.opsForSet().members(key);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 根据value从一个set中查询,是否存在
     *
     * @param key   键
     * @param value 值
     * @return true 存在 false不存在
     */
    public boolean sHasKey(String key, Object value) {
        try {
            return redisTemplate.opsForSet().isMember(key, value);
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 将数据放入set缓存
     *
     * @param key    键
     * @param values 值 可以是多个
     * @return 成功个数
     */
    public long sSet(String key, Object... values) {
        try {
            return redisTemplate.opsForSet().add(key, values);
        } catch (Exception e) {
            e.printStackTrace();
            return 0;
        }
    }

    /**
     * 将set数据放入缓存
     *
     * @param key    键
     * @param time   时间(秒)
     * @param values 值 可以是多个
     * @return 成功个数
     */
    public long sSetAndTime(String key, long time, Object... values) {
        try {
            Long count = redisTemplate.opsForSet().add(key, values);
            if (time > 0) expire(key, time);
            return count;
        } catch (Exception e) {
            e.printStackTrace();
            return 0;
        }
    }

    /**
     * 获取set缓存的长度
     *
     * @param key 键
     * @return
     */
    public long sGetSetSize(String key) {
        try {
            return redisTemplate.opsForSet().size(key);
        } catch (Exception e) {
            e.printStackTrace();
            return 0;
        }
    }

    /**
     * 移除值为value的
     *
     * @param key    键
     * @param values 值 可以是多个
     * @return 移除的个数
     */
    public long setRemove(String key, Object... values) {
        try {
            Long count = redisTemplate.opsForSet().remove(key, values);
            return count;
        } catch (Exception e) {
            e.printStackTrace();
            return 0;
        }
    }
    //===============================list=================================  

    /**
     * 获取list缓存的内容
     *
     * @param key   键
     * @param start 开始
     * @param end   结束  0 到 -1代表所有值
     * @return
     */
    public List<Object> lGet(String key, long start, long end) {
        try {
            return redisTemplate.opsForList().range(key, start, end);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 获取list缓存的长度
     *
     * @param key 键
     * @return
     */
    public long lGetListSize(String key) {
        try {
            return redisTemplate.opsForList().size(key);
        } catch (Exception e) {
            e.printStackTrace();
            return 0;
        }
    }

    /**
     * 通过索引 获取list中的值
     *
     * @param key   键
     * @param index 索引  index>=0时, 0 表头,1 第二个元素,依次类推;index<0时,-1,表尾,-2倒数第二个元素,依次类推
     * @return
     */
    public Object lGetIndex(String key, long index) {
        try {
            return redisTemplate.opsForList().index(key, index);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 将list放入缓存
     *
     * @param key   键
     * @param value 值
     * @return
     */
    public boolean lSet(String key, Object value) {
        try {
            redisTemplate.opsForList().rightPush(key, value);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 将list放入缓存
     *
     * @param key   键
     * @param value 值
     * @param time  时间(秒)
     * @return
     */
    public boolean lSet(String key, Object value, long time) {
        try {
            redisTemplate.opsForList().rightPush(key, value);
            if (time > 0) expire(key, time);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 将list放入缓存
     *
     * @param key   键
     * @param value 值
     * @return
     */
    public boolean lSet(String key, List<Object> value) {
        try {
            redisTemplate.opsForList().rightPushAll(key, value);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 将list放入缓存
     *
     * @param key   键
     * @param value 值
     * @param time  时间(秒)
     * @return
     */
    public boolean lSet(String key, List<Object> value, long time) {
        try {
            redisTemplate.opsForList().rightPushAll(key, value);
            if (time > 0) expire(key, time);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 根据索引修改list中的某条数据
     *
     * @param key   键
     * @param index 索引
     * @param value 值
     * @return
     */
    public boolean lUpdateIndex(String key, long index, Object value) {
        try {
            redisTemplate.opsForList().set(key, index, value);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 移除N个值为value
     *
     * @param key   键
     * @param count 移除多少个
     * @param value 值
     * @return 移除的个数
     */
    public long lRemove(String key, long count, Object value) {
        try {
            Long remove = redisTemplate.opsForList().remove(key, count, value);
            return remove;
        } catch (Exception e) {
            e.printStackTrace();
            return 0;
        }
    }

    //================有序集合 sort set===================
    /**
     * 有序set添加元素
     *
     * @param key
     * @param value
     * @param score
     * @return
     */
    public boolean zSet(String key, Object value, double score) {
        return redisTemplate.opsForZSet().add(key, value, score);
    }

    public long batchZSet(String key, Set<ZSetOperations.TypedTuple> typles) {
        return redisTemplate.opsForZSet().add(key, typles);
    }

    public void zIncrementScore(String key, Object value, long delta) {
        redisTemplate.opsForZSet().incrementScore(key, value, delta);
    }

    public void zUnionAndStore(String key, Collection otherKeys, String destKey) {
        redisTemplate.opsForZSet().unionAndStore(key, otherKeys, destKey);
    }

    /**
     * 获取zset数量
     * @param key
     * @param value
     * @return
     */
    public long getZsetScore(String key, Object value) {
        Double score = redisTemplate.opsForZSet().score(key, value);
        if(score==null){
            return 0;
        }else{
            return score.longValue();
        }
    }

    /**
     * 获取有序集 key 中成员 member 的排名 。
     * 其中有序集成员按 score 值递减 (从大到小) 排序。
     * @param key
     * @param start
     * @param end
     * @return
     */
    public Set<ZSetOperations.TypedTuple> getZSetRank(String key, long start, long end) {
        return redisTemplate.opsForZSet().reverseRangeWithScores(key, start, end);
    }

}

5、测试代码

package com.codertl.springbootbuild;

import com.codertl.springbootbuild.entity.Student;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.redis.core.RedisTemplate;

import javax.annotation.Resource;

@SpringBootTest
class SpringbootBuildApplicationTests {
    @Resource
    RedisTemplate redisTemplate;

    @Test
    void contextLoads() {
        //    redisTemplate  操作不同的数据类型,api和我们的指令是一样的
        //opsForValue 操作字符串 类似String
        //opsForList  操作list 类似list
        //opsForSet 操作set 类似set
        //......
        //除了基本的操作,我们常用的方法都可以直接i通过redisTemplate操作,比如事务,和本地crud
        //获取redis的连接对象
        //    RedisConnection connection =redisTemplate.getConnectionFactory().getConnection();
        //    connection.flushDb();
        //    connection.flushAll();
        Student student = new Student();
        student.setId(0);
        student.setName("11");
        student.setAge(11);

        redisTemplate.opsForValue().set("name", student);
        System.out.println("得到" + redisTemplate.opsForValue().get("name")); // 得到Student(id=0, name=11, age=11)
    }
}

8、整体配置文件

1、pom文件

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.5.5</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.codertl</groupId>
    <artifactId>springboot-build</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>springboot-build</name>
    <description>Demo project for Spring Boot</description>
    <properties>
        <java.version>1.8</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>2.2.0</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

        <!-- druid 数据源 -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid-spring-boot-starter</artifactId>
            <version>1.2.6</version>
        </dependency>
        <!-- mybatis-plus -->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.4.3.4</version>
        </dependency>
        <!-- mybatis-plus-generator 代码生成器 -->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-generator</artifactId>
            <version>3.4.1</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-test</artifactId>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
        </dependency>
        <!--<dependency>-->
        <!--    <groupId>org.apache.velocity</groupId>-->
        <!--    <artifactId>velocity-engine-core</artifactId>-->
        <!--    <version>2.0</version>-->
        <!--</dependency>-->
        <dependency>
            <groupId>org.freemarker</groupId>
            <artifactId>freemarker</artifactId>
            <version>2.3.28</version>
        </dependency>

        <!-- swagger -->
        <!--<dependency>-->
        <!--    <groupId>io.springfox</groupId>-->
        <!--    <artifactId>springfox-boot-starter</artifactId>-->
        <!--    <version>3.0.0</version>-->
        <!--</dependency>-->
        <!--<dependency>-->
        <!--    <groupId>com.github.xiaoymin</groupId>-->
        <!--    <artifactId>swagger-bootstrap-ui</artifactId>-->
        <!--    <version>1.9.6</version>-->
        <!--</dependency>-->
        <dependency>
            <groupId>com.github.xiaoymin</groupId>
            <artifactId>knife4j-spring-boot-starter</artifactId>
            <version>2.0.7</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.47</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <excludes>
                        <exclude>
                            <groupId>org.projectlombok</groupId>
                            <artifactId>lombok</artifactId>
                        </exclude>
                    </excludes>
                </configuration>
            </plugin>
        </plugins>
    </build>

</project>

2、application.yml文件

spring:
  application:
    name: springboot-build-backend
  profiles:
    active: dev

server:
  port: 9001
  servlet:
    context-path: /api

3、application-dev.yml

spring:
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://192.168.1.1:3306/test_study?useUnicode=true&characterEncoding=utf8&autoReconnect=true&allowMultiQueries=true&useSSL=false&serverTimezone=UTC
    username: root
    password: 123456
    # Druid
    druid:
      # 初始化大小,最小,最大
      initial-size: 5
      max-active: 100
      min-idle: 1
      # 配置获取连接等待超时的时间
      max-wait: 60000
      # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位毫秒
      time-between-eviction-runs-millis: 60000
      # 配置一个连接在池中最小生存时间
      min-evictable-idle-time-millis: 300000
      # 用来检测连接是否有效的sql 必须是一个查询语句 注意没有此语句以下三个属性不会生效
      validation-query: SELECT 1 FROM DUAL
      # 归还连接时会执行validationQuery检测连接是否有效,开启会降低性能,默认为true
      test-on-return: false
      # 申请连接时会执行validationQuery检测连接是否有效,开启会降低性能,默认为true
      test-on-borrow: true
      # 申请连接的时候检测,如果空闲时间大于timeBetweenEvictionRunsMillis,执行validationQuery检测连接是否有效。
      test-while-idle: true
      # 配置监控统计拦截的 Filter,去掉后监控界面 SQL 无法统计,wall 用于防火墙
      filters: stat,wall
      # 通过 connection-properties 属性打开 mergeSql 功能;慢 SQL 记录
      connection-properties: druid.stat.mergeSql\=true;druid.stat.slowSqlMillis\=5000
      # 配置 DruidStatFilter
      web-stat-filter:
        enabled: true
        url-pattern: /*
        exclusions: .js,*.gif,*.jpg,*.bmp,*.png,*.css,*.ico,/druid/*
      # 配置 DruidStatViewServlet
      stat-view-servlet:
        url-pattern: /druid/*
        # IP 白名单,没有配置或者为空,则允许所有访问
        #allow: 127.0.0.1
        # IP 黑名单,若白名单也存在,则优先使用
        #deny: 192.168.31.253
        # 禁用 HTML 中 Reset All 按钮
        reset-enable: true
        # 登录用户名/密码
        login-username: root
        login-password: root
        # 注意 此处必须开启,否则无法访问druid监控面板
        enabled: true
      use-global-data-source-stat: true
  # redis配置
  redis:
    host: 192.168.1.1
    port: 6379
    connect-timeout: 20000
    #    集群环境打开下面注释,单机不需要打开
    #    cluster:
    #      集群信息
    #      nodes: xxx.xxx.xxx.xxx:xxxx,xxx.xxx.xxx.xxx:xxxx,xxx.xxx.xxx.xxx:xxxx
    #      #默认值是5 一般当此值设置过大时,容易报:Too many Cluster redirections
    #      maxRedirects: 3
    password: 123456
    jedis:
      pool:
        max-active: 8
        min-idle: 0
        max-idle: 8
        max-wait: -1
    database: 0


mybatis-plus:
  configuration:
    map-underscore-to-camel-case: true
    auto-mapping-behavior: full
  mapper-locations: classpath:mapper/*.xml
  global-config:
    # 逻辑删除配置
    db-config:
      # 删除前
      logic-not-delete-value: 1
      # 删除后
      logic-delete-value: 0

附录:

详尽的yml配置文件内容:

server:  port: 8085  servlet:    context-path: /testspring:  #redis集群  redis:    host: 127.0.0.1    port: 6379    timeout: 20000    #    集群环境打开下面注释,单机不需要打开    #    cluster:    #      集群信息    #      nodes: xxx.xxx.xxx.xxx:xxxx,xxx.xxx.xxx.xxx:xxxx,xxx.xxx.xxx.xxx:xxxx    #      #默认值是5 一般当此值设置过大时,容易报:Too many Cluster redirections    #      maxRedirects: 3    password: lyja    application:      name: test    jedis:      pool:        max-active: 8        min-idle: 0        max-idle: 8        max-wait: -1    database: 0  autoconfigure:    exclude: com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceAutoConfigure  datasource:    dynamic:      #设置默认的数据源或者数据源组,默认值即为master      primary: master      strict: false      datasource:        master:          driver-class-name: com.mysql.cj.jdbc.Driver          url: jdbc:mysql://127.0.0.1:3306/test?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&useSSL=false          username: root          password: lyja    # 数据源配置    druid:      # druid连接池监控      stat-view-servlet:        enabled: true        url-pattern: /druid/*        login-username: admin        login-password: admin        # 初始化时建立物理连接的个数        initial-size: 5        # 最大连接池数量        max-active: 30        # 最小连接池数量        min-idle: 5        # 获取连接时最大等待时间,单位毫秒        max-wait: 60000        # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒        time-between-eviction-runs-millis: 60000        # 连接保持空闲而不被驱逐的最小时间        min-evictable-idle-time-millis: 300000        # 用来检测连接是否有效的sql,要求是一个查询语句        validation-query: select count(*) from dual        # 建议配置为true,不影响性能,并且保证安全性。申请连接的时候检测,如果空闲时间大于timeBetweenEvictionRunsMillis,执行validationQuery检测连接是否有效。        test-while-idle: true        # 申请连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能。        test-on-borrow: false        # 归还连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能。        test-on-return: false        # 是否缓存preparedStatement,也就是PSCache。PSCache对支持游标的数据库性能提升巨大,比如说oracle。在mysql下建议关闭。        pool-prepared-statements: false        # 要启用PSCache,必须配置大于0,当大于0时,poolPreparedStatements自动触发修改为true。        max-pool-prepared-statement-per-connection-size: 50        # 配置监控统计拦截的filters,去掉后监控界面sql无法统计        filters: stat,wall        # 通过connectProperties属性来打开mergeSql功能;慢SQL记录        connection-properties:          druid.stat.mergeSql: true          druid.stat.slowSqlMillis: 500        # 合并多个DruidDataSource的监控数据        use-global-data-source-stat: true        filter:          stat:            log-slow-sql: true            slow-sql-millis: 1000            merge-sql: true          wall:            config:              multi-statement-allow: true  servlet:    multipart:      # 开启 multipart 上传功能      enabled: true      # 文件写入磁盘的阈值      file-size-threshold: 2KB      # 最大文件大小      max-file-size: 200MB      # 最大请求大小      max-request-size: 215MBmybatis-plus:  configuration:    map-underscore-to-camel-case: true    auto-mapping-behavior: full    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl  mapper-locations: classpath*:mapper/**/*Mapper.xml  global-config:    # 逻辑删除配置    db-config:      # 删除前      logic-not-delete-value: 1      # 删除后      logic-delete-value: 0logging:  level:    root: info    com.example: debug
posted @ 2021-09-29 23:03  CoderTL  阅读(148)  评论(0编辑  收藏  举报