ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

SpringBoot学习笔记

2022-06-26 23:33:47  阅读:180  来源: 互联网

标签:return SpringBoot param 学习 笔记 key public redisTemplate String


一、简介

回顾Spring

Spring是一个开源框架,2003 年兴起的一个轻量级的Java 开发框架,作者:Rod Johnson

Spring是为了解决企业级应用开发的复杂性而创建的,简化开发。

Spring是如何简化Java开发的

为了降低Java开发的复杂性,Spring采用了以下4种关键策略:

  1. 基于POJO的轻量级和最小侵入性编程,所有东西都是bean;

  2. 通过IOC,依赖注入(DI)和面向接口实现松耦合;

  3. 基于切面(AOP)和惯例进行声明式编程;

  4. 通过切面和模版减少样式代码,RedisTemplate,xxxTemplate;

什么是springBoot

	什么是SpringBoot呢,就是一个javaweb的开发框架,和SpringMVC类似,对比其他javaweb框架的好处,官方说是简化开发,约定大于配置,  you can "just run",能迅速的开发web应用,几行代码开发一个HTTP接口。`

	企业为了提高开发效率,嫌弃原先的各类配置过于麻烦,于是开始提倡**“约定大于配置”**,进而衍生出一些一站式的解决方案。

	这就是==Java企业级应用->J2EE->spring->springboot==的过程

SpringBoot集成第三方库

	它集成了大量常用的第三方库配置(例如 Redis、MongoDB、Jpa、RabbitMQ、Quartz 等等),**Spring Boot 应用中这些第三方库几乎可以零配置的开箱即用。**

SpringBoot主要优点

  • 为所有Spring开发者更快的入门
  • 开箱即用,提供各种默认配置来简化项目配置
  • 内嵌式容器简化Web项目
  • 没有冗余代码生成和XML配置的要求

二、Hello,World!

1.环境准备

  • java 8
  • Maven-3.6.1
  • SpringBoot 2.x 最新版

2.开发工具

  • IDEA-2021

3.创建基础项目说明

3.1-官方创建

使用Spring Initializr 的 Web页面创建项目

  1. 打开 https://start.spring.io/

  2. 填写项目信息

  3. 点击”Generate Project“按钮生成项目;下载此项目

  4. 解压项目包,并用IDEA以Maven项目导入,一路下一步即可,直到项目导入完毕。

  5. 如果是第一次使用,可能速度会比较慢,包比较多、需要耐心等待一切就绪。

3.2-IDEA创建

  1. 创建一个新项目

  2. 选择spring initalizr , 可以看到默认就是去官网的快速构建工具那里实现

  3. 填写项目信息

  4. 选择初始化的组件(初学勾选 Web 即可)

  5. 填写项目路径

  6. 等待项目构建成功

4.项目结构分析

目录结构分析

通过上面步骤完成了基础项目的创建。就会自动生成以下文件。

  1. 程序的主启动类

  2. 一个 application.properties 配置文件

  3. 一个 测试类

  4. 一个 pom.xml

pom.xml分析

<!--父依赖-->    
<parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.6.6</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
<!--web场景启动器-->    
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
<!--springboot单元测试--> 
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <!--打包插件--> 
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

5.编写HTTP接口

1、在主程序的同级目录下,新建一个controller包,一定要在同级目录下,否则识别不到

2、在包中新建一个HelloController类

@RestControllerpublic class HelloController {
    @RequestMapping("/hello")    
    public String hello() {
        return "Hello World";
    }    
}

3、编写完毕后,从主程序启动项目,浏览器发起请求localhost:端口号/hello,看页面返回;控制台输出了 Tomcat 访问的端口号!

三、Yaml

1.概述

YAML是 "YAML Ain't a Markup Language" (YAML不是一种标记语言)的递归缩写。在开发的这种语言时,YAML 的意思其实是:"Yet Another Markup Language"(仍是一种标记语言)

这种语言以数据作为中心,而不是以标记语言为重点!

以前的配置文件,大多数都是使用xml来配置;比如一个简单的端口配置,我们来对比下yaml和xml

传统xml配置:

<server>
	<port>8081<port>
</server>

yaml配置:

server:
	prot: 8080

配置文件

  • 文件格式:xxx.yml

  • SpringBoot使用一个全局的配置文件 , 配置文件名称是固定的

    • application.properties

      • 语法结构 :key=value
    • application.yml

      • 语法结构 :key:空格 value

配置文件作用

配置文件的作用 :修改SpringBoot自动配置的默认值,因为SpringBoot在底层都给我们自动配置好了;

比如我们可以在配置文件中修改Tomcat 默认启动的端口号!测试一下!

server.port=1214

yaml基础语法

说明:语法要求严格!

  1. 空格不能省略

  2. 以缩进来控制层级关系,只要是左边对齐的一列数据都是同一个层级的。

  3. 属性和值的大小写都是十分敏感的。

字面量:普通的值 [ 数字,布尔值,字符串 ]

字面量直接写在后面就可以 , 字符串默认不用加上双引号或者单引号;

k: v

注意:

  • “ ” 双引号,不会转义字符串里面的特殊字符 , 特殊字符会作为本身想表示的意思;

    比如 :name: "kuang \n shen" 输出 :kuang 换行 shen

  • '' 单引号,会转义特殊字符 , 特殊字符最终会变成和普通字符一样输出

    比如 :name: ‘kuang \n shen’ 输出 :kuang \n shen

对象、Map(键值对)

#对象、Map格式
k:
	v1:
    v2:

在下一行来写对象的属性和值得关系,注意缩进;比如:

student:
	name: qinjiang
    age: 3

行内写法

student: {name: qinjiang,age: 3}

数组( List、set )

用 - 值表示数组中的一个元素,比如:

pets:
	- cat
    - dog
    - pig

行内写法

pets: [cat,dog,pig]

修改SpringBoot的默认端口号

配置文件中添加,端口号的参数,就可以切换端口;

server:
	port: 8082

2.注入配置文件

1、在springboot项目中的resources目录下新建一个文件 application.yml

2、编写一个实体类 Dog;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
//添加到spring组件中,注册bean到容器中
@Component
public class Dog {
    @Value("豆豆")
    private String name;
    @Value("3")
    private int age;

    public Dog(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public Dog() {
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "Dog{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

3.测试类

import com.dragon.pojo.Dog;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

@SpringBootTest
class Spring02ApplicationTests {

    @Autowired//自动注入Dog类
    private Dog dog;
    @Test
    void contextLoads() {
        System.out.println(dog);
    }

}

结果成功输出!

使用yaml配置的方式进行注入

  1. application.yml

    person:
      name: Dawson${random.uuid}
      age: ${random.int}
      happy: false
      birth: 2019/11/02
      maps: {k1: v1,k2: v2}
      lists:
        - code
        - music
        - girl
      dog:
        name: ${person.hello:hello}_豆豆
        age: 3
    
    
  2. Person.java

    /*
    @ConfigurationProperties作用:
    
    将配置文件中配置的每一个属性的值,映射到这个组件中;
    告诉SpringBoot将本类中的所有属性和配置文件中相关的配置进行绑定
    
    参数 prefix = “person” : 将配置文件中的person下面的所有属性一一对应
    */
    @Component //注册bean
    @ConfigurationProperties(prefix = "person")
    public class Person {
        private String name;
        private Integer age;
        private Boolean happy;
        private Date birth;
        private Map<String,Object> maps;
        private List<Object> lists;
        private Dog dog;
    }
    
  3. IDEA 提示,springboot配置注解处理器没有找到,让我们看文档,我们可以查看文档,找到一个依赖!

    <!-- 导入配置文件处理器,配置文件进行绑定就会有提示,需要重启 -->
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-configuration-processor</artifactId>
      <optional>true</optional>
    </dependency>
    
  4. 测试类

    @SpringBootTest
    class DemoApplicationTests {
    
        @Autowired
        Person person; //将person自动注入进来
    
        @Test
        public void contextLoads() {
            System.out.println(person); //打印person信息
        }
    
    }
    

结果:所有值全部注入成功!

配置文件占位符

配置文件还可以编写占位符生成随机数

person:
	name: qinjiang${random.uuid} # 随机uuid
    age: ${random.int}  # 随机int
    happy: false
    birth: 2000/01/01
    maps: {k1: v1,k2: v2}
    lists:
    	- code
        - girl
        - music
    dog:
    	name: ${person.hello:other}_旺财
        age: 1

3.回顾properties配置

我们上面采用的yaml方法都是最简单的方式,开发中最常用的;也是springboot所推荐的!那我们来唠唠其他的实现方式,道理都是相同的;写还是那样写;配置文件除了yml还有我们之前常用的properties , 我们没有讲,我们来唠唠!

注意】properties配置文件在写中文的时候,会有乱码 , 我们需要去IDEA中设置编码格式为UTF-8;

settings-->FileEncodings 中配置;

4.对比小结

@Value这个使用起来并不友好!我们需要为每个属性单独注解赋值,比较麻烦;我们来看个功能对比图

图片

1、@ConfigurationProperties只需要写一次即可 , @Value则需要每个字段都添加

2、松散绑定:这个什么意思呢? 比如我的yml中写的last-name,这个和lastName是一样的, - 后面跟着的字母默认是大写的。这就是松散绑定。可以测试一下

3、JSR303数据校验 , 这个就是我们可以在字段是增加一层过滤器验证 , 可以保证数据的合法性

4、复杂类型封装,yml中可以封装对象 , 使用value就不支持

结论:

配置yml和配置properties都可以获取到值 , 强烈推荐 yml;

如果我们在某个业务中,只需要获取配置文件中的某个值,可以使用一下 @value;

如果说,我们专门编写了一个JavaBean来和配置文件进行一一映射,就直接@configurationProperties,不要犹豫!

四、JSR303校验

基本使用

  1. 依赖

    <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-validation -->
    <dependency>
       <groupId>org.springframework.boot</groupId>
       <artifactId>spring-boot-starter-validation</artifactId>
       <version>2.6.3</version>
    </dependency>
    
  2. 使用

    import org.springframework.boot.context.properties.ConfigurationProperties;
    import org.springframework.stereotype.Component;
    import org.springframework.validation.annotation.Validated;
    
    import javax.validation.constraints.Email;
    import java.util.Date;
    import java.util.List;
    import java.util.Map;
    //可以扫描到
    @Component
    @ConfigurationProperties(prefix = "person")
    @Validated
    public class Person {
        @Email(message = "邮箱输入的不对")
        private String name;
    }
    
  3. 使用数据校验,可以保证数据的正确性;

常见参数

@NotNull(message="名字不能为空")
private String userName;
@Max(value=120,message="年龄最大不能查过120")
private int age;
@Email(message="邮箱格式错误")
private String email;

//空检查
@Null	验证对象是否为null
@NotNull	验证对象是否不为null, 无法查检长度为0的字符串
@NotBlank	检查约束字符串是不是Null还有被Trim的长度是否大于0,只对字符串,且会去掉前后空格.
@NotEmpty	检查约束元素是否为NULL或者是EMPTY.
    
//Booelan检查
@AssertTrue		验证 Boolean 对象是否为 true
@AssertFalse	验证 Boolean 对象是否为 false
    
//长度检查
@Size(min=, max=) 验证对象(Array,Collection,Map,String)长度是否在给定的范围之内  @Length(min=, max=) string is between min and max included.
    
//日期检查
@Past	验证 Date 和 Calendar 对象是否在当前时间之前
@Future		验证 Date 和 Calendar 对象是否在当前时间之后
@Pattern	验证 String 对象是否符合正则表达式的规则
//.......等等除此以外,我们还可以自定义一些数据校验规则

五、整合JDBC

1.SpringData

	对于数据访问层,无论是 SQL(关系型数据库) 还是 NOSQL(非关系型数据库),**Spring Boot 底层都是采用 Spring Data 的方式进行统一处理。**

	**Spring Boot 底层都是采用 Spring Data 的方式进行统一处理各种数据库**,Spring Data 也是 Spring 中与 Spring Boot、Spring Cloud 等齐名的知名项目。

	Sping Data 官网:https://spring.io/projects/spring-data

数据库相关的启动器 :可以参考官方文档:

https://docs.spring.io/spring-boot/docs/2.2.5.RELEASE/reference/htmlsingle/#using-boot-starter

2.HelloJDBC

项目基本依赖

  • Spring Web
  • JDBC API
  • MySQL Driver

启动器

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
   <scope>runtime</scope>
</dependency>

创建application.yml文件

spring:
  datasource:
    username: root
    password: root
    url: jdbc:mysql://localhost:3306/mybatis?serverTimezone=UTC&characterEncoding=UTF-8
    driver-class-name: com.mysql.cj.jdbc.Driver

测试

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.SQLException;

@SpringBootTest
class SpringbootJdbcApplicationTests {
    @Autowired
    DataSource dataSource;
    @Test
    void contextLoads() throws SQLException {
        System.out.println(dataSource.getClass());
        Connection connection = dataSource.getConnection();
        System.out.println(connection);
        connection.close();
    }

}

结果:我们可以看到他默认给我们配置的数据源为 : class com.zaxxer.hikari.HikariDataSource , 我们并没有手动配置

我们来全局搜索一下,找到数据源的所有自动配置都在 :DataSourceAutoConfiguration文件:

@Import(
    {Hikari.class, Tomcat.class, Dbcp2.class, Generic.class, DataSourceJmxConfiguration.class})
protected static class PooledDataSourceConfiguration {
    protected PooledDataSourceConfiguration(){
    }
}

这里导入的类都在 DataSourceConfiguration 配置类下,可以看出 Spring Boot 2.2.5 默认使用HikariDataSource 数据源,而以前版本,如 Spring Boot 1.5 默认使用 org.apache.tomcat.jdbc.pool.DataSource 作为数据源;

HikariDataSource 号称 Java WEB 当前速度最快的数据源,相比于传统的 C3P0 、DBCP、Tomcat jdbc 等连接池更加优秀;

可以使用 spring.datasource.type 指定自定义的数据源类型,值为 要使用的连接池实现的完全限定名。

关于数据源我们并不做介绍,有了数据库连接,显然就可以 CRUD 操作数据库了。但是我们需要先了解一个对象 JdbcTemplate

JdbcTemplate

  1. 有了数据源(com.zaxxer.hikari.HikariDataSource),然后可以拿到数据库连接(java.sql.Connection),有了连接,就可以使用原生的 JDBC 语句来操作数据库;

  2. 即使不使用第三方第数据库操作框架,如 MyBatis等,Spring 本身也对原生的JDBC 做了轻量级的封装,即JdbcTemplate。

  3. 数据库操作的所有 CRUD 方法都在 JdbcTemplate 中。

  4. Spring Boot 不仅提供了默认的数据源,同时默认已经配置好了 JdbcTemplate 放在了容器中,程序员只需自己注入即可使用

  5. JdbcTemplate 的自动配置是依赖 org.springframework.boot.autoconfigure.jdbc 包下的 JdbcTemplateConfiguration 类

JdbcTemplate主要提供以下几类方法:

  • execute方法:可以用于执行任何SQL语句,一般用于执行DDL语句;
  • update方法及batchUpdate方法:update方法用于执行新增、修改、删除等语句;batchUpdate方法用于执行批处理相关语句;
  • query方法及queryForXXX方法:用于执行查询相关语句;
  • call方法:用于执行存储过程、函数相关语句。

执行查询

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;
import java.util.Map;

@RestController
@RequestMapping("/jdbc")
public class JdbcController {
    /**
     * Spring Boot 默认提供了数据源,默认提供了 org.springframework.jdbc.core.JdbcTemplate
     * JdbcTemplate 中会自己注入数据源,用于简化 JDBC操作
     * 还能避免一些常见的错误,使用起来也不用再自己来关闭数据库连接
     */
    @Autowired
    JdbcTemplate jdbcTemplate;
    @RequestMapping("/getAllStudent")
    public List<Map<String, Object>> userList(){
        String sql="select * from student";
        List<Map<String,Object>> maps = jdbcTemplate.queryForList(sql);
        return maps;
    }
}

六、整合Druid

1.简介

	java程序很大一部分要操作数据库,为了提高性能操作数据库的时候,又不得不使用数据库连接池。

Druid 是阿里巴巴开源平台上一个数据库连接池实现,结合了 C3P0、DBCP 等 DB 池的优点,同时加入了日志监控

Druid 可以很好的监控 DB 池连接和 SQL 的执行情况,天生就是针对监控而生的 DB 连接池。

Druid已经在阿里巴巴部署了超过600个应用,经过一年多生产环境大规模部署的严苛考验。

Spring Boot 2.0 以上默认使用 Hikari 数据源,可以说 Hikari 与 Driud 都是当前 Java Web 上最优秀的数据源,我们来重点介绍 Spring Boot 如何集成 Druid 数据源,如何实现数据库监控。

Github地址:https://github.com/alibaba/druid/

2.HelloDruid

  1. 导入相关依赖

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-jdbc</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
       <scope>runtime</scope>
    </dependency>
    <!-- https://mvnrepository.com/artifact/com.alibaba/druid -->
    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>druid</artifactId>
        <version>1.2.8</version>
    </dependency>
    
  2. 切换数据源; Spring Boot 2.0 以上默认使用 com.zaxxer.hikari.HikariDataSource 数据源,但可以 通过 spring.datasource.type指定数据源。

    spring:
      datasource:
        username: root
        password: root
        url: jdbc:mysql://localhost:3306/mybatis?serverTimezone=UTC&characterEncoding=utf-8
        driver-class-name: com.mysql.cj.jdbc.Driver
        type: com.alibaba.druid.pool.DruidDataSource # 自定义数据源
        #Spring Boot 默认是不注入这些属性值的,需要自己绑定
        #druid 数据源专有配置
        initialSize: 5
        minIdle: 5
        maxActive: 20
        maxWait: 60000
        timeBetweenEvictionRunsMillis: 60000
        minEvictableIdleTimeMillis: 300000
        validationQuery: SELECT 1 FROM DUAL
        testWhileIdle: true
        testOnBorrow: false
        testOnReturn: false
        poolPreparedStatements: true
        #配置监控统计拦截的filters,stat:监控统计、log4j:日志记录、wall:防御sql注入
        #如果允许时报错  java.lang.ClassNotFoundException: org.apache.log4j.Priority
        #则导入 log4j 依赖即可,Maven 地址:https://mvnrepository.com/artifact/log4j/log4j
        filters: stat,wall,log4j
        maxPoolPreparedStatementPerConnectionSize: 20
        useGlobalDataSourceStat: true
        connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=500
    
  3. 现在需要程序员自己为 DruidDataSource 绑定全局配置文件中的参数,再添加到容器中,而不再使用 Spring Boot 的自动生成了;我们需要 自己添加 DruidDataSource 组件到容器中,并绑定属性;

    import com.alibaba.druid.pool.DruidDataSource;
    import org.springframework.boot.context.properties.ConfigurationProperties;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    
    import javax.sql.DataSource;
    
    @Configuration
    public class DruidConfig {
    
        /*
           将自定义的 Druid数据源添加到容器中,不再让 Spring Boot 自动创建
           绑定全局配置文件中的 druid 数据源属性到 com.alibaba.druid.pool.DruidDataSource从而让它们生效
           @ConfigurationProperties(prefix = "spring.datasource"):作用就是将 全局配置文件中
           前缀为 spring.datasource的属性值注入到 com.alibaba.druid.pool.DruidDataSource 的同名参数中
         */
        @ConfigurationProperties(prefix = "spring.datasource")
        @Bean
        public DataSource druidDataSource() {
            return new DruidDataSource();
        }
    
    }
    
  4. 测试类

    @SpringBootTest
    class SpringbootDataJdbcApplicationTests {
    
        //DI注入数据源
        @Autowired
        DataSource dataSource;
    
        @Test
        public void contextLoads() throws SQLException {
            //看一下默认数据源
            System.out.println(dataSource.getClass());
            //获得连接
            Connection connection =   dataSource.getConnection();
            System.out.println(connection);
    
            DruidDataSource druidDataSource = (DruidDataSource) dataSource;
            System.out.println("druidDataSource 数据源最大连接数:" + druidDataSource.getMaxActive());
            System.out.println("druidDataSource 数据源初始化连接数:" + druidDataSource.getInitialSize());
    
            //关闭连接
            connection.close();
        }
    }
    

七、整合MyBatis

资源过滤

<resources>
    <resource>
        <directory>src/main/java</directory>
        <includes>
            <include>**/*.xml</include>
        </includes>
        <filtering>true</filtering>
    </resource>
    <resource>
        <directory>src/main/resources</directory>
    </resource>
</resources>

小知识:反向缩进 SHIFT+TAB

所需依赖

<!-- https://mvnrepository.com/artifact/org.mybatis.spring.boot/mybatis-spring-boot-starter -->
<dependency>
    <groupId>org.mybatis.spring.boot</groupId>
    <artifactId>mybatis-spring-boot-starter</artifactId>
    <version>2.1.3</version>
</dependency>
  • WEB-start
  • JDBC-start
  • MySql-Driver

YAML文件配置

mybatis:
  type-aliases-package: com.dragon.pojo
  mapper-locations: classpath:mapper/*.xml
spring:
  datasource:
    username: root
    password: root
    url: jdbc:mysql://localhost:3306/mybatis?serverTimezone=UTC&characterEncoding=UTF-8&useSSL=false
    driver-class-name: com.mysql.cj.jdbc.Driver

Mapper层

  • 接口

    import com.dragon.pojo.Users;
    import org.apache.ibatis.annotations.Mapper;
    import org.springframework.stereotype.Repository;
    
    import java.util.List;
    
    //@Mapper : 表示本类是一个 MyBatis 的 Mapper
    @Mapper
    @Repository
    public interface UsersMapper {
        List<Users> getUsers();
    }
    
  • 映射文件

    <?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.dragon.mapper.UsersMapper">
        <select id="getUsers" resultType="Users">
            select id,name,pwd from mybatis.users
        </select>
    </mapper>
    

Controller

import com.dragon.mapper.UsersMapper;
import com.dragon.pojo.Users;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;

@RestController
@RequestMapping("/first")
public class UsersController {
    @Autowired
    private UsersMapper usersMapper;
    @GetMapping("/getAll")
    public List<Users> getAll(){
        return usersMapper.getUsers();
    }
}

八、静态资源处理

  • 在以前项目中都是会有web目录的,我们可以把静态资源放入其中,但是现在并没有。
  • 存放静态资源明文规定:
    • "classpath:/META-INF/resources/"
    • "classpath:/resources/"
    • "classpath:/static/"
    • "classpath:/public/"

1.静态资源映射规则

SpringBoot中,SpringMVC的web配置都在 WebMvcAutoConfiguration 这个配置类里面;

我们可以去看看 WebMvcAutoConfigurationAdapter 中有很多配置方法;

有一个方法:addResourceHandlers 添加资源处理

@Overridepublic void addResourceHandlers(ResourceHandlerRegistry registry) {
    if (!this.resourceProperties.isAddMappings()) {
        // 已禁用默认资源处理
        logger.debug("Default resource handling disabled");
        return;
    }
    // 缓存控制
    Duration cachePeriod = this.resourceProperties.getCache().getPeriod();
    CacheControl cacheControl = this.resourceProperties.getCache().getCachecontrol().toHttpCacheControl();
    // webjars 配置
    if (!registry.hasMappingForPattern("/webjars/**")) {        customizeResourceHandlerRegistration(registry.addResourceHandler("/webjars/**")                        	.addResourceLocations("classpath:/META-INF/resources/webjars/")                        .setCachePeriod(getSeconds(cachePeriod)).setCacheControl(cacheControl));
                                                       }
    // 静态资源配置
    String staticPathPattern = this.mvcProperties.getStaticPathPattern();
    if (!registry.hasMappingForPattern(staticPathPattern)) {        customizeResourceHandlerRegistration(registry.addResourceHandler(staticPathPattern)                                             .addResourceLocations(getResourceLocations(this.resourceProperties.getStaticLocations()))                                             .setCachePeriod(getSeconds(cachePeriod)).setCacheControl(cacheControl));
   }
}

读下源码:比如所有的 /webjars/** , 都需要去 classpath:/META-INF/resources/webjars/找对应的资源;

2.什么是webjars 呢?

Webjars本质就是以jar包的方式引入我们的静态资源 , 我们以前要导入一个静态资源文件,直接导入即可。

使用SpringBoot需要使用Webjars,我们可以去搜索一下:

网站:https://www.webjars.org

要使用jQuery,我们只要要引入jQuery对应版本的pom依赖即可!

<dependency>
    <groupId>org.webjars</groupId>
    <artifactId>jquery</artifactId>
    <version>3.4.1</version>
</dependency>

导入完毕,查看webjars目录结构,并访问Jquery.js文件!

图片

访问:只要是静态资源,SpringBoot就会去对应的路径寻找资源,我们这里访问:http://localhost:8080/webjars/jquery/3.4.1/jquery.js

图片

3.第二种静态资源映射规则

那我们项目中要是使用自己的静态资源该怎么导入呢?我们看下一行代码;

我们去找staticPathPattern发现第二种映射规则 :/** , 访问当前的项目任意资源,它会去找 resourceProperties 这个类,我们可以点进去看一下分析:

// 进入方法
public String[] getStaticLocations() {
    return this.staticLocations;
}// 找到对应的值
private String[] staticLocations = CLASSPATH_RESOURCE_LOCATIONS;
// 找到路径
private static final String[] CLASSPATH_RESOURCE_LOCATIONS = {
    "classpath:/META-INF/resources/",
    "classpath:/resources/",
    "classpath:/static/",
    "classpath:/public/" 
};

ResourceProperties 可以设置和我们静态资源有关的参数;这里面指向了它会去寻找资源的文件夹,即上面数组的内容。

所以得出结论,以下四个目录存放的静态资源可以被我们识别:

"classpath:/META-INF/resources/"
"classpath:/resources/"
"classpath:/static/"
"classpath:/public/"

我们可以在resources根目录下新建对应的文件夹,都可以存放我们的静态文件;

比如我们访问 http://localhost:8080/1.js , 他就会去这些文件夹中寻找对应的静态资源文件;

4.自定义静态资源路径

我们也可以自己通过配置文件来指定一下,哪些文件夹是需要我们放静态资源文件的,在application.properties中配置;

spring.resources.static-locations=
classpath:/coding/,
classpath:/kuang/

一旦自己定义了静态文件夹的路径,原来的自动配置就都会失效了!

首页处理

静态资源文件夹说完后,我们继续向下看源码!可以看到一个欢迎页的映射,就是我们的首页!

@Beanpublic
WelcomePageHandlerMapping welcomePageHandlerMapping(ApplicationContext applicationContext,                                                           FormattingConversionService mvcConversionService,                                                           ResourceUrlProvider mvcResourceUrlProvider) {    WelcomePageHandlerMapping welcomePageHandlerMapping = new WelcomePageHandlerMapping(        new TemplateAvailabilityProviders(applicationContext), applicationContext, getWelcomePage(), // getWelcomePage 获得欢迎页
this.mvcProperties.getStaticPathPattern());
welcomePageHandlerMapping.setInterceptors(getInterceptors(mvcConversionService, mvcResourceUrlProvider));
return welcomePageHandlerMapping;}

点进去继续看

private Optional<Resource> getWelcomePage() {
    String[] locations = getResourceLocations(this.resourceProperties.getStaticLocations());
    // ::是java8 中新引入的运算符
    // Class::function的时候function是属于Class的,应该是静态方法
    // this::function的funtion是属于这个对象的。
    // 简而言之,就是一种语法糖而已,是一种简写
    return Arrays.stream(locations).map(this::getIndexHtml).filter(this::isReadable).findFirst();}
// 欢迎页就是一个location下的的 index.html 而已
private Resource getIndexHtml(String location) {
    return this.resourceLoader.getResource(location + "index.html");
}

欢迎页,静态资源文件夹下的所有 index.html 页面;被 /** 映射。

比如我访问 http://localhost:8080/ ,就会找静态资源文件夹下的 index.html

新建一个 index.html ,在我们上面的3个目录中任意一个;然后访问测试 http://localhost:8080/ 看结果!

关于网站图标说明

图片

与其他静态资源一样,Spring Boot在配置的静态内容位置中查找 favicon.ico。如果存在这样的文件,它将自动用作应用程序的favicon。

1、关闭SpringBoot默认图标

#关闭默认图标
spring.mvc.favicon.enabled=false

2、自己放一个图标在静态资源目录下,我放在 public 目录下

3、清除浏览器缓存!刷新网页,发现图标已经变成自己的了!

图片

九、Thymeleaf模板引擎

为什么使用Thymeleaf?

	前端交给我们的页面,是html页面。如果是我们以前开发,我们需要把他们转成jsp页面,jsp好处就是当我们查出一些数据转发到JSP页面以后,我们可以用jsp轻松实现数据的显示,及交互等。

jsp支持非常强大的功能,包括能写Java代码,但是呢,我们现在的这种情况,SpringBoot这个项目首先是以jar的方式,不是war,像第二,我们用的还是嵌入式的Tomcat,所以呢,他现在默认是不支持jsp的

  • 作用:

    模板引擎的作用就是我们来写一个页面模板,比如有些值呢,是动态的,我们写一些表达式。而这些值,从哪来呢,就是我们在后台封装一些数据。然后把这个模板和这个数据交给我们模板引擎,模板引擎按照我们这个数据帮你把这表达式解析、填充到我们指定的位置,然后把这个数据最终生成一个我们想要的内容给我们写出去,这就是我们这个模板引擎

springBoot如何使用?

  • 怎么引入呢,对于springboot来说,什么事情不都是一个start的事情嘛,我们去在项目中引入一下。给大家三个网址:

    Thymeleaf 官网:https://www.thymeleaf.org/

    Thymeleaf 在Github 的主页:https://github.com/thymeleaf/thymeleaf

    Spring官方文档:找到我们对应的版本

    https://docs.spring.io/spring-boot/docs/2.2.5.RELEASE/reference/htmlsingle/#using-boot-starter

    找到对应的pom依赖:可以适当点进源码看下本来的包!

    <!--thymeleaf-->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-thymeleaf</artifactId>
    </dependency>
    
  • 分析

    我们首先得按照SpringBoot的自动配置原理看一下我们这个Thymeleaf的自动配置规则,在按照那个规则,我们进行使用。

    我们去找一下Thymeleaf的自动配置类:ThymeleafProperties

    @ConfigurationProperties(
        prefix = "spring.thymeleaf"
    )
    public class ThymeleafProperties {
        private static final Charset DEFAULT_ENCODING;
        public static final String DEFAULT_PREFIX = "classpath:/templates/";
        public static final String DEFAULT_SUFFIX = ".html";
        private boolean checkTemplate = true;
        private boolean checkTemplateLocation = true;
        private String prefix = "classpath:/templates/";
        private String suffix = ".html";
        private String mode = "HTML";
        private Charset encoding;
    }
    

    我们可以在其中看到默认的前缀和后缀!

    我们只需要把我们的html页面放在类路径下的templates下,thymeleaf就可以帮我们自动渲染了。

    使用thymeleaf什么都不需要配置,只需要将他放在指定的文件夹下即可!

  • 导入命名空间

     xmlns:th="http://www.thymeleaf.org"
    
  • 前端获取

    <!DOCTYPE html>
    <html lang="en" xmlns:th="http://www.thymeleaf.org">
        <head>
            <meta charset="UTF-8">
            <title>狂神说</title>
        </head>
        <body>
            <h1>测试页面</h1>
    <!--th:text就是将div中的内容设置为它指定的值,和之前学习的Vue一样-->
            <div th:text="${msg}"></div>
        </body>
    </html>
    

Thymeleaf语法

我们可以使用任意的 th:attr 来替换Html中原生属性的值!

图片

2、我们能写哪些表达式呢?

Simple expressions:(表达式语法)
Variable Expressions: ${...}:获取变量值;OGNL;
    1)、获取对象的属性、调用方法    
    2)、使用内置的基本对象:#18
        #ctx : the context object.
        #vars: the context variables.
        #locale : the context locale.
        #request : (only in Web Contexts) the HttpServletRequest object.
        #response : (only in Web Contexts) the HttpServletResponse object.
        #session : (only in Web Contexts) the HttpSession object.
        #servletContext : (only in Web Contexts) the ServletContext object.
    3)、内置的一些工具对象:
        #execInfo : information about the template being processed.
        #uris : methods for escaping parts of URLs/URIs
        #conversions : methods for executing the configured conversion service (if any).
        #dates : methods for java.util.Date objects: formatting, component extraction, etc.
        #calendars : analogous to #dates , but for java.util.Calendar objects.
        #numbers : methods for formatting numeric objects.
        #strings : methods for String objects: contains, startsWith, prepending/appending, etc.
        #objects : methods for objects in general.
        #bools : methods for boolean evaluation.
        #arrays : methods for arrays.
        #lists : methods for lists.
        #sets : methods for sets.
        #maps : methods for maps.
        #aggregates : methods for creating aggregates on arrays or collections.
==================================================================================
  Selection Variable Expressions: *{...}:选择表达式:和${}在功能上是一样;
    Message Expressions: #{...}:获取国际化内容
    Link URL Expressions: @{...}:定义URL;
    Fragment Expressions: ~{...}:片段引用表达式
Literals(字面量)
    Text literals: 'one text' , 'Another one!' ,…
    Number literals: 0 , 34 , 3.0 , 12.3 ,…
    Boolean literals: true , false
    Null literal: null
    Literal tokens: one , sometext , main ,…
Text operations:(文本操作)
    String concatenation: +
    Literal substitutions: |The name is ${name}|
Arithmetic operations:(数学运算)
    Binary operators: + , - , * , / , %
    Minus sign (unary operator): -
Boolean operations:(布尔运算)
    Binary operators: and , or
    Boolean negation (unary operator): ! , not
Comparisons and equality:(比较运算)
    Comparators: > , < , >= , <= ( gt , lt , ge , le )
    Equality operators: == , != ( eq , ne )
Conditional operators:条件运算(三元运算符)
    If-then: (if) ? (then)
    If-then-else: (if) ? (then) : (else)
	Default: (value) ?: (defaultvalue)
Special tokens:
	No-Operation: _

练习测试:

1、 我们编写一个Controller,放一些数据

@RequestMapping("/t2")
public String test2(Map<String,Object> map){
    //存入数据
    map.put("msg","<h1>Hello</h1>");
    map.put("users", Arrays.asList("qinjiang","kuangshen"));    //classpath:/templates/test.html
    return "test";
}

2、测试页面取出数据

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
    <head>
        <meta charset="UTF-8">
        <title>狂神说</title>
    </head>
    <body>
        <h1>测试页面</h1>
<div th:text="${msg}"></div>
        <!--不转义-->
        <div th:utext="${msg}"></div>
<!--遍历数据-->
        <!--th:each每次遍历都会生成当前这个标签:官网#9-->
        <h4 th:each="user :${users}" th:text="${user}"></h4>
<h4>
    <!--行内写法:官网#12-->
    <span th:each="user:${users}">[[${user}]]</span>
</h4>
</body></html>

十、异步任务

两个注解

  • @EnableAsync:异步注解开启
  • @Async:使该方法为异步方法,在springboot启动时,创建线程池

环境

  • 业务层

    import org.springframework.scheduling.annotation.Async;
    import org.springframework.stereotype.Service;
    
    @Service
    public class AsyncService {
        @Async
        public void hello(){
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("hello async");
        }
    }
    
  • 控制层

    import com.dragon.service.AsyncService;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;
    
    @RestController
    public class AsyncController {
        @Autowired
        AsyncService asyncService;
        @RequestMapping({"/","/hello"})
        public String hello(){
            asyncService.hello();
            return "hello";
        }
    }
    
  • 启动

    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.scheduling.annotation.EnableAsync;
    @EnableAsync
    @SpringBootApplication
    public class SpringbootAsyApplication {
    
        public static void main(String[] args) {
            SpringApplication.run(SpringbootAsyApplication.class, args);
        }
    
    }
    
  • 执行效果

    页面先显示"hello",3s后控制台打印"hello async"

  • 目的

    提高用户使用效果

十一、Redis集成

1.下载安装

https://github.com/MicrosoftArchive/redis/releases

下载完成,正常解压即可

配置properties

spring.redis.port=6379
spring.redis.host=localhost

引入依赖

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

配置工具类

import org.springframework.data.redis.connection.DataType;
import org.springframework.data.redis.core.Cursor;
import org.springframework.data.redis.core.ScanOptions;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ZSetOperations.TypedTuple;
import org.springframework.stereotype.Component;

import java.util.Collection;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.concurrent.TimeUnit;
@Component
@SuppressWarnings("all")
public class RedisUtils {

        private StringRedisTemplate redisTemplate;

        public void setRedisTemplate(StringRedisTemplate redisTemplate) {
            this.redisTemplate = redisTemplate;
        }

        public StringRedisTemplate getRedisTemplate() {
            return this.redisTemplate;
        }

        /** -------------------key相关操作--------------------- */

        /**
         * 删除key
         *
         * @param key
         */
        public void delete(String key) {
            redisTemplate.delete(key);
        }

        /**
         * 批量删除key
         *
         * @param keys
         */
        public void delete(Collection<String> keys) {
            redisTemplate.delete(keys);
        }

        /**
         * 序列化key
         *
         * @param key
         * @return
         */
        public byte[] dump(String key) {
            return redisTemplate.dump(key);
        }

        /**
         * 是否存在key
         *
         * @param key
         * @return
         */
        public Boolean hasKey(String key) {
            return redisTemplate.hasKey(key);
        }

        /**
         * 设置过期时间
         *
         * @param key
         * @param timeout
         * @param unit
         * @return
         */
        public Boolean expire(String key, long timeout, TimeUnit unit) {
            return redisTemplate.expire(key, timeout, unit);
        }

        /**
         * 设置过期时间
         *
         * @param key
         * @param date
         * @return
         */
        public Boolean expireAt(String key, Date date) {
            return redisTemplate.expireAt(key, date);
        }

        /**
         * 查找匹配的key
         *
         * @param pattern
         * @return
         */
        public Set<String> keys(String pattern) {
            return redisTemplate.keys(pattern);
        }

        /**
         * 将当前数据库的 key 移动到给定的数据库 db 当中
         *
         * @param key
         * @param dbIndex
         * @return
         */
        public Boolean move(String key, int dbIndex) {
            return redisTemplate.move(key, dbIndex);
        }

        /**
         * 移除 key 的过期时间,key 将持久保持
         *
         * @param key
         * @return
         */
        public Boolean persist(String key) {
            return redisTemplate.persist(key);
        }

        /**
         * 返回 key 的剩余的过期时间
         *
         * @param key
         * @param unit
         * @return
         */
        public Long getExpire(String key, TimeUnit unit) {
            return redisTemplate.getExpire(key, unit);
        }

        /**
         * 返回 key 的剩余的过期时间
         *
         * @param key
         * @return
         */
        public Long getExpire(String key) {
            return redisTemplate.getExpire(key);
        }

        /**
         * 从当前数据库中随机返回一个 key
         *
         * @return
         */
        public String randomKey() {
            return redisTemplate.randomKey();
        }

        /**
         * 修改 key 的名称
         *
         * @param oldKey
         * @param newKey
         */
        public void rename(String oldKey, String newKey) {
            redisTemplate.rename(oldKey, newKey);
        }

        /**
         * 仅当 newkey 不存在时,将 oldKey 改名为 newkey
         *
         * @param oldKey
         * @param newKey
         * @return
         */
        public Boolean renameIfAbsent(String oldKey, String newKey) {
            return redisTemplate.renameIfAbsent(oldKey, newKey);
        }

        /**
         * 返回 key 所储存的值的类型
         *
         * @param key
         * @return
         */
        public DataType type(String key) {
            return redisTemplate.type(key);
        }

        /** -------------------string相关操作--------------------- */

        /**
         * 设置指定 key 的值
         *
         * @param key
         * @param value
         */
        public void set(String key, String value) {
            redisTemplate.opsForValue().set(key, value);
        }

        /**
         * 获取指定 key 的值
         *
         * @param key
         * @return
         */
        public String get(String key) {
            return redisTemplate.opsForValue().get(key);
        }

        /**
         * 返回 key 中字符串值的子字符
         *
         * @param key
         * @param start
         * @param end
         * @return
         */
        public String getRange(String key, long start, long end) {
            return redisTemplate.opsForValue().get(key, start, end);
        }

        /**
         * 将给定 key 的值设为 value ,并返回 key 的旧值(old value)
         *
         * @param key
         * @param value
         * @return
         */
        public String getAndSet(String key, String value) {
            return redisTemplate.opsForValue().getAndSet(key, value);
        }

        /**
         * 对 key 所储存的字符串值,获取指定偏移量上的位(bit)
         *
         * @param key
         * @param offset
         * @return
         */
        public Boolean getBit(String key, long offset) {
            return redisTemplate.opsForValue().getBit(key, offset);
        }

        /**
         * 批量获取
         *
         * @param keys
         * @return
         */
        public List<String> multiGet(Collection<String> keys) {
            return redisTemplate.opsForValue().multiGet(keys);
        }

        /**
         * 设置ASCII码, 字符串'a'的ASCII码是97, 转为二进制是'01100001', 此方法是将二进制第offset位值变为value
         *
         * @param key   位置
         * @param value 值,true为1, false为0
         * @return
         */
        public boolean setBit(String key, long offset, boolean value) {
            return redisTemplate.opsForValue().setBit(key, offset, value);
        }

        /**
         * 将值 value 关联到 key ,并将 key 的过期时间设为 timeout
         *
         * @param key
         * @param value
         * @param timeout 过期时间
         * @param unit    时间单位, 天:TimeUnit.DAYS 小时:TimeUnit.HOURS 分钟:TimeUnit.MINUTES
         *                秒:TimeUnit.SECONDS 毫秒:TimeUnit.MILLISECONDS
         */
        public void setEx(String key, String value, long timeout, TimeUnit unit) {
            redisTemplate.opsForValue().set(key, value, timeout, unit);
        }

        /**
         * 只有在 key 不存在时设置 key 的值
         *
         * @param key
         * @param value
         * @return 之前已经存在返回false, 不存在返回true
         */
        public boolean setIfAbsent(String key, String value) {
            return redisTemplate.opsForValue().setIfAbsent(key, value);
        }

        /**
         * 用 value 参数覆写给定 key 所储存的字符串值,从偏移量 offset 开始
         *
         * @param key
         * @param value
         * @param offset 从指定位置开始覆写
         */
        public void setRange(String key, String value, long offset) {
            redisTemplate.opsForValue().set(key, value, offset);
        }

        /**
         * 获取字符串的长度
         *
         * @param key
         * @return
         */
        public Long size(String key) {
            return redisTemplate.opsForValue().size(key);
        }

        /**
         * 批量添加
         *
         * @param maps
         */
        public void multiSet(Map<String, String> maps) {
            redisTemplate.opsForValue().multiSet(maps);
        }

        /**
         * 同时设置一个或多个 key-value 对,当且仅当所有给定 key 都不存在
         *
         * @param maps
         * @return 之前已经存在返回false, 不存在返回true
         */
        public boolean multiSetIfAbsent(Map<String, String> maps) {
            return redisTemplate.opsForValue().multiSetIfAbsent(maps);
        }

        /**
         * 增加(自增长), 负数则为自减
         *
         * @param key
         * @return
         */
        public Long incrBy(String key, long increment) {
            return redisTemplate.opsForValue().increment(key, increment);
        }

        /**
         * @param key
         * @return
         */
        public Double incrByFloat(String key, double increment) {
            return redisTemplate.opsForValue().increment(key, increment);
        }

        /**
         * 追加到末尾
         *
         * @param key
         * @param value
         * @return
         */
        public Integer append(String key, String value) {
            return redisTemplate.opsForValue().append(key, value);
        }

        /** -------------------hash相关操作------------------------- */

        /**
         * 获取存储在哈希表中指定字段的值
         *
         * @param key
         * @param field
         * @return
         */
        public Object hGet(String key, String field) {
            return redisTemplate.opsForHash().get(key, field);
        }

        /**
         * 获取所有给定字段的值
         *
         * @param key
         * @return
         */
        public Map<Object, Object> hGetAll(String key) {
            return redisTemplate.opsForHash().entries(key);
        }

        /**
         * 获取所有给定字段的值
         *
         * @param key
         * @param fields
         * @return
         */
        public List<Object> hMultiGet(String key, Collection<Object> fields) {
            return redisTemplate.opsForHash().multiGet(key, fields);
        }

        public void hPut(String key, String hashKey, String value) {
            redisTemplate.opsForHash().put(key, hashKey, value);
        }

        public void hPutAll(String key, Map<String, String> maps) {
            redisTemplate.opsForHash().putAll(key, maps);
        }

        /**
         * 仅当hashKey不存在时才设置
         *
         * @param key
         * @param hashKey
         * @param value
         * @return
         */
        public Boolean hPutIfAbsent(String key, String hashKey, String value) {
            return redisTemplate.opsForHash().putIfAbsent(key, hashKey, value);
        }

        /**
         * 删除一个或多个哈希表字段
         *
         * @param key
         * @param fields
         * @return
         */
        public Long hDelete(String key, Object... fields) {
            return redisTemplate.opsForHash().delete(key, fields);
        }

        /**
         * 查看哈希表 key 中,指定的字段是否存在
         *
         * @param key
         * @param field
         * @return
         */
        public boolean hExists(String key, String field) {
            return redisTemplate.opsForHash().hasKey(key, field);
        }

        /**
         * 为哈希表 key 中的指定字段的整数值加上增量 increment
         *
         * @param key
         * @param field
         * @param increment
         * @return
         */
        public Long hIncrBy(String key, Object field, long increment) {
            return redisTemplate.opsForHash().increment(key, field, increment);
        }

        /**
         * 为哈希表 key 中的指定字段的整数值加上增量 increment
         *
         * @param key
         * @param field
         * @param delta
         * @return
         */
        public Double hIncrByFloat(String key, Object field, double delta) {
            return redisTemplate.opsForHash().increment(key, field, delta);
        }

        /**
         * 获取所有哈希表中的字段
         *
         * @param key
         * @return
         */
        public Set<Object> hKeys(String key) {
            return redisTemplate.opsForHash().keys(key);
        }

        /**
         * 获取哈希表中字段的数量
         *
         * @param key
         * @return
         */
        public Long hSize(String key) {
            return redisTemplate.opsForHash().size(key);
        }

        /**
         * 获取哈希表中所有值
         *
         * @param key
         * @return
         */
        public List<Object> hValues(String key) {
            return redisTemplate.opsForHash().values(key);
        }

        /**
         * 迭代哈希表中的键值对
         *
         * @param key
         * @param options
         * @return
         */
        public Cursor<Entry<Object, Object>> hScan(String key, ScanOptions options) {
            return redisTemplate.opsForHash().scan(key, options);
        }

        /** ------------------------list相关操作---------------------------- */

        /**
         * 通过索引获取列表中的元素
         *
         * @param key
         * @param index
         * @return
         */
        public String lIndex(String key, long index) {
            return redisTemplate.opsForList().index(key, index);
        }

        /**
         * 获取列表指定范围内的元素
         *
         * @param key
         * @param start 开始位置, 0是开始位置
         * @param end   结束位置, -1返回所有
         * @return
         */
        public List<String> lRange(String key, long start, long end) {
            return redisTemplate.opsForList().range(key, start, end);
        }

        /**
         * 存储在list头部
         *
         * @param key
         * @param value
         * @return
         */
        public Long lLeftPush(String key, String value) {
            return redisTemplate.opsForList().leftPush(key, value);
        }

        /**
         * @param key
         * @param value
         * @return
         */
        public Long lLeftPushAll(String key, String... value) {
            return redisTemplate.opsForList().leftPushAll(key, value);
        }

        /**
         * @param key
         * @param value
         * @return
         */
        public Long lLeftPushAll(String key, Collection<String> value) {
            return redisTemplate.opsForList().leftPushAll(key, value);
        }

        /**
         * 当list存在的时候才加入
         *
         * @param key
         * @param value
         * @return
         */
        public Long lLeftPushIfPresent(String key, String value) {
            return redisTemplate.opsForList().leftPushIfPresent(key, value);
        }

        /**
         * 如果pivot存在,再pivot前面添加
         *
         * @param key
         * @param pivot
         * @param value
         * @return
         */
        public Long lLeftPush(String key, String pivot, String value) {
            return redisTemplate.opsForList().leftPush(key, pivot, value);
        }

        /**
         * @param key
         * @param value
         * @return
         */
        public Long lRightPush(String key, String value) {
            return redisTemplate.opsForList().rightPush(key, value);
        }

        /**
         * @param key
         * @param value
         * @return
         */
        public Long lRightPushAll(String key, String... value) {
            return redisTemplate.opsForList().rightPushAll(key, value);
        }

        /**
         * @param key
         * @param value
         * @return
         */
        public Long lRightPushAll(String key, Collection<String> value) {
            return redisTemplate.opsForList().rightPushAll(key, value);
        }

        /**
         * 为已存在的列表添加值
         *
         * @param key
         * @param value
         * @return
         */
        public Long lRightPushIfPresent(String key, String value) {
            return redisTemplate.opsForList().rightPushIfPresent(key, value);
        }

        /**
         * 在pivot元素的右边添加值
         *
         * @param key
         * @param pivot
         * @param value
         * @return
         */
        public Long lRightPush(String key, String pivot, String value) {
            return redisTemplate.opsForList().rightPush(key, pivot, value);
        }

        /**
         * 通过索引设置列表元素的值
         *
         * @param key
         * @param index 位置
         * @param value
         */
        public void lSet(String key, long index, String value) {
            redisTemplate.opsForList().set(key, index, value);
        }

        /**
         * 移出并获取列表的第一个元素
         *
         * @param key
         * @return 删除的元素
         */
        public String lLeftPop(String key) {
            return redisTemplate.opsForList().leftPop(key);
        }

        /**
         * 移出并获取列表的第一个元素, 如果列表没有元素会阻塞列表直到等待超时或发现可弹出元素为止
         *
         * @param key
         * @param timeout 等待时间
         * @param unit    时间单位
         * @return
         */
        public String lBLeftPop(String key, long timeout, TimeUnit unit) {
            return redisTemplate.opsForList().leftPop(key, timeout, unit);
        }

        /**
         * 移除并获取列表最后一个元素
         *
         * @param key
         * @return 删除的元素
         */
        public String lRightPop(String key) {
            return redisTemplate.opsForList().rightPop(key);
        }

        /**
         * 移出并获取列表的最后一个元素, 如果列表没有元素会阻塞列表直到等待超时或发现可弹出元素为止
         *
         * @param key
         * @param timeout 等待时间
         * @param unit    时间单位
         * @return
         */
        public String lBRightPop(String key, long timeout, TimeUnit unit) {
            return redisTemplate.opsForList().rightPop(key, timeout, unit);
        }

        /**
         * 移除列表的最后一个元素,并将该元素添加到另一个列表并返回
         *
         * @param sourceKey
         * @param destinationKey
         * @return
         */
        public String lRightPopAndLeftPush(String sourceKey, String destinationKey) {
            return redisTemplate.opsForList().rightPopAndLeftPush(sourceKey,
                    destinationKey);
        }

        /**
         * 从列表中弹出一个值,将弹出的元素插入到另外一个列表中并返回它; 如果列表没有元素会阻塞列表直到等待超时或发现可弹出元素为止
         *
         * @param sourceKey
         * @param destinationKey
         * @param timeout
         * @param unit
         * @return
         */
        public String lBRightPopAndLeftPush(String sourceKey, String destinationKey,
                                            long timeout, TimeUnit unit) {
            return redisTemplate.opsForList().rightPopAndLeftPush(sourceKey,
                    destinationKey, timeout, unit);
        }

        /**
         * 删除集合中值等于value得元素
         *
         * @param key
         * @param index index=0, 删除所有值等于value的元素; index>0, 从头部开始删除第一个值等于value的元素;
         *              index<0, 从尾部开始删除第一个值等于value的元素;
         * @param value
         * @return
         */
        public Long lRemove(String key, long index, String value) {
            return redisTemplate.opsForList().remove(key, index, value);
        }

        /**
         * 裁剪list
         *
         * @param key
         * @param start
         * @param end
         */
        public void lTrim(String key, long start, long end) {
            redisTemplate.opsForList().trim(key, start, end);
        }

        /**
         * 获取列表长度
         *
         * @param key
         * @return
         */
        public Long lLen(String key) {
            return redisTemplate.opsForList().size(key);
        }

        /** --------------------set相关操作-------------------------- */

        /**
         * set添加元素
         *
         * @param key
         * @param values
         * @return
         */
        public Long sAdd(String key, String... values) {
            return redisTemplate.opsForSet().add(key, values);
        }

        /**
         * set移除元素
         *
         * @param key
         * @param values
         * @return
         */
        public Long sRemove(String key, Object... values) {
            return redisTemplate.opsForSet().remove(key, values);
        }

        /**
         * 移除并返回集合的一个随机元素
         *
         * @param key
         * @return
         */
        public String sPop(String key) {
            return redisTemplate.opsForSet().pop(key);
        }

        /**
         * 将元素value从一个集合移到另一个集合
         *
         * @param key
         * @param value
         * @param destKey
         * @return
         */
        public Boolean sMove(String key, String value, String destKey) {
            return redisTemplate.opsForSet().move(key, value, destKey);
        }

        /**
         * 获取集合的大小
         *
         * @param key
         * @return
         */
        public Long sSize(String key) {
            return redisTemplate.opsForSet().size(key);
        }

        /**
         * 判断集合是否包含value
         *
         * @param key
         * @param value
         * @return
         */
        public Boolean sIsMember(String key, Object value) {
            return redisTemplate.opsForSet().isMember(key, value);
        }

        /**
         * 获取两个集合的交集
         *
         * @param key
         * @param otherKey
         * @return
         */
        public Set<String> sIntersect(String key, String otherKey) {
            return redisTemplate.opsForSet().intersect(key, otherKey);
        }

        /**
         * 获取key集合与多个集合的交集
         *
         * @param key
         * @param otherKeys
         * @return
         */
        public Set<String> sIntersect(String key, Collection<String> otherKeys) {
            return redisTemplate.opsForSet().intersect(key, otherKeys);
        }

        /**
         * key集合与otherKey集合的交集存储到destKey集合中
         *
         * @param key
         * @param otherKey
         * @param destKey
         * @return
         */
        public Long sIntersectAndStore(String key, String otherKey, String destKey) {
            return redisTemplate.opsForSet().intersectAndStore(key, otherKey,
                    destKey);
        }

        /**
         * key集合与多个集合的交集存储到destKey集合中
         *
         * @param key
         * @param otherKeys
         * @param destKey
         * @return
         */
        public Long sIntersectAndStore(String key, Collection<String> otherKeys,
                                       String destKey) {
            return redisTemplate.opsForSet().intersectAndStore(key, otherKeys,
                    destKey);
        }

        /**
         * 获取两个集合的并集
         *
         * @param key
         * @param otherKeys
         * @return
         */
        public Set<String> sUnion(String key, String otherKeys) {
            return redisTemplate.opsForSet().union(key, otherKeys);
        }

        /**
         * 获取key集合与多个集合的并集
         *
         * @param key
         * @param otherKeys
         * @return
         */
        public Set<String> sUnion(String key, Collection<String> otherKeys) {
            return redisTemplate.opsForSet().union(key, otherKeys);
        }

        /**
         * key集合与otherKey集合的并集存储到destKey中
         *
         * @param key
         * @param otherKey
         * @param destKey
         * @return
         */
        public Long sUnionAndStore(String key, String otherKey, String destKey) {
            return redisTemplate.opsForSet().unionAndStore(key, otherKey, destKey);
        }

        /**
         * key集合与多个集合的并集存储到destKey中
         *
         * @param key
         * @param otherKeys
         * @param destKey
         * @return
         */
        public Long sUnionAndStore(String key, Collection<String> otherKeys,
                                   String destKey) {
            return redisTemplate.opsForSet().unionAndStore(key, otherKeys, destKey);
        }

        /**
         * 获取两个集合的差集
         *
         * @param key
         * @param otherKey
         * @return
         */
        public Set<String> sDifference(String key, String otherKey) {
            return redisTemplate.opsForSet().difference(key, otherKey);
        }

        /**
         * 获取key集合与多个集合的差集
         *
         * @param key
         * @param otherKeys
         * @return
         */
        public Set<String> sDifference(String key, Collection<String> otherKeys) {
            return redisTemplate.opsForSet().difference(key, otherKeys);
        }

        /**
         * key集合与otherKey集合的差集存储到destKey中
         *
         * @param key
         * @param otherKey
         * @param destKey
         * @return
         */
        public Long sDifference(String key, String otherKey, String destKey) {
            return redisTemplate.opsForSet().differenceAndStore(key, otherKey,
                    destKey);
        }

        /**
         * key集合与多个集合的差集存储到destKey中
         *
         * @param key
         * @param otherKeys
         * @param destKey
         * @return
         */
        public Long sDifference(String key, Collection<String> otherKeys,
                                String destKey) {
            return redisTemplate.opsForSet().differenceAndStore(key, otherKeys,
                    destKey);
        }

        /**
         * 获取集合所有元素
         *
         * @param key
         * @return
         */
        public Set<String> setMembers(String key) {
            return redisTemplate.opsForSet().members(key);
        }

        /**
         * 随机获取集合中的一个元素
         *
         * @param key
         * @return
         */
        public String sRandomMember(String key) {
            return redisTemplate.opsForSet().randomMember(key);
        }

        /**
         * 随机获取集合中count个元素
         *
         * @param key
         * @param count
         * @return
         */
        public List<String> sRandomMembers(String key, long count) {
            return redisTemplate.opsForSet().randomMembers(key, count);
        }

        /**
         * 随机获取集合中count个元素并且去除重复的
         *
         * @param key
         * @param count
         * @return
         */
        public Set<String> sDistinctRandomMembers(String key, long count) {
            return redisTemplate.opsForSet().distinctRandomMembers(key, count);
        }

        /**
         * @param key
         * @param options
         * @return
         */
        public Cursor<String> sScan(String key, ScanOptions options) {
            return redisTemplate.opsForSet().scan(key, options);
        }

        /**------------------zSet相关操作--------------------------------*/

        /**
         * 添加元素,有序集合是按照元素的score值由小到大排列
         *
         * @param key
         * @param value
         * @param score
         * @return
         */
        public Boolean zAdd(String key, String value, double score) {
            return redisTemplate.opsForZSet().add(key, value, score);
        }

        /**
         * @param key
         * @param values
         * @return
         */
        public Long zAdd(String key, Set<TypedTuple<String>> values) {
            return redisTemplate.opsForZSet().add(key, values);
        }

        /**
         * @param key
         * @param values
         * @return
         */
        public Long zRemove(String key, Object... values) {
            return redisTemplate.opsForZSet().remove(key, values);
        }

        /**
         * 增加元素的score值,并返回增加后的值
         *
         * @param key
         * @param value
         * @param delta
         * @return
         */
        public Double zIncrementScore(String key, String value, double delta) {
            return redisTemplate.opsForZSet().incrementScore(key, value, delta);
        }

        /**
         * 返回元素在集合的排名,有序集合是按照元素的score值由小到大排列
         *
         * @param key
         * @param value
         * @return 0表示第一位
         */
        public Long zRank(String key, Object value) {
            return redisTemplate.opsForZSet().rank(key, value);
        }

        /**
         * 返回元素在集合的排名,按元素的score值由大到小排列
         *
         * @param key
         * @param value
         * @return
         */
        public Long zReverseRank(String key, Object value) {
            return redisTemplate.opsForZSet().reverseRank(key, value);
        }

        /**
         * 获取集合的元素, 从小到大排序
         *
         * @param key
         * @param start 开始位置
         * @param end   结束位置, -1查询所有
         * @return
         */
        public Set<String> zRange(String key, long start, long end) {
            return redisTemplate.opsForZSet().range(key, start, end);
        }

        /**
         * 获取集合元素, 并且把score值也获取
         *
         * @param key
         * @param start
         * @param end
         * @return
         */
        public Set<TypedTuple<String>> zRangeWithScores(String key, long start,
                                                        long end) {
            return redisTemplate.opsForZSet().rangeWithScores(key, start, end);
        }

        /**
         * 根据Score值查询集合元素
         *
         * @param key
         * @param min 最小值
         * @param max 最大值
         * @return
         */
        public Set<String> zRangeByScore(String key, double min, double max) {
            return redisTemplate.opsForZSet().rangeByScore(key, min, max);
        }

        /**
         * 根据Score值查询集合元素, 从小到大排序
         *
         * @param key
         * @param min 最小值
         * @param max 最大值
         * @return
         */
        public Set<TypedTuple<String>> zRangeByScoreWithScores(String key,
                                                               double min, double max) {
            return redisTemplate.opsForZSet().rangeByScoreWithScores(key, min, max);
        }

        /**
         * @param key
         * @param min
         * @param max
         * @param start
         * @param end
         * @return
         */
        public Set<TypedTuple<String>> zRangeByScoreWithScores(String key,
                                                               double min, double max, long start, long end) {
            return redisTemplate.opsForZSet().rangeByScoreWithScores(key, min, max,
                    start, end);
        }

        /**
         * 获取集合的元素, 从大到小排序
         *
         * @param key
         * @param start
         * @param end
         * @return
         */
        public Set<String> zReverseRange(String key, long start, long end) {
            return redisTemplate.opsForZSet().reverseRange(key, start, end);
        }

        /**
         * 获取集合的元素, 从大到小排序, 并返回score值
         *
         * @param key
         * @param start
         * @param end
         * @return
         */
        public Set<TypedTuple<String>> zReverseRangeWithScores(String key,
                                                               long start, long end) {
            return redisTemplate.opsForZSet().reverseRangeWithScores(key, start,
                    end);
        }

        /**
         * 根据Score值查询集合元素, 从大到小排序
         *
         * @param key
         * @param min
         * @param max
         * @return
         */
        public Set<String> zReverseRangeByScore(String key, double min,
                                                double max) {
            return redisTemplate.opsForZSet().reverseRangeByScore(key, min, max);
        }

        /**
         * 根据Score值查询集合元素, 从大到小排序
         *
         * @param key
         * @param min
         * @param max
         * @return
         */
        public Set<TypedTuple<String>> zReverseRangeByScoreWithScores(
                String key, double min, double max) {
            return redisTemplate.opsForZSet().reverseRangeByScoreWithScores(key,
                    min, max);
        }

        /**
         * @param key
         * @param min
         * @param max
         * @param start
         * @param end
         * @return
         */
        public Set<String> zReverseRangeByScore(String key, double min,
                                                double max, long start, long end) {
            return redisTemplate.opsForZSet().reverseRangeByScore(key, min, max,
                    start, end);
        }

        /**
         * 根据score值获取集合元素数量
         *
         * @param key
         * @param min
         * @param max
         * @return
         */
        public Long zCount(String key, double min, double max) {
            return redisTemplate.opsForZSet().count(key, min, max);
        }

        /**
         * 获取集合大小
         *
         * @param key
         * @return
         */
        public Long zSize(String key) {
            return redisTemplate.opsForZSet().size(key);
        }

        /**
         * 获取集合大小
         *
         * @param key
         * @return
         */
        public Long zZCard(String key) {
            return redisTemplate.opsForZSet().zCard(key);
        }

        /**
         * 获取集合中value元素的score值
         *
         * @param key
         * @param value
         * @return
         */
        public Double zScore(String key, Object value) {
            return redisTemplate.opsForZSet().score(key, value);
        }

        /**
         * 移除指定索引位置的成员
         *
         * @param key
         * @param start
         * @param end
         * @return
         */
        public Long zRemoveRange(String key, long start, long end) {
            return redisTemplate.opsForZSet().removeRange(key, start, end);
        }

        /**
         * 根据指定的score值的范围来移除成员
         *
         * @param key
         * @param min
         * @param max
         * @return
         */
        public Long zRemoveRangeByScore(String key, double min, double max) {
            return redisTemplate.opsForZSet().removeRangeByScore(key, min, max);
        }

        /**
         * 获取key和otherKey的并集并存储在destKey中
         *
         * @param key
         * @param otherKey
         * @param destKey
         * @return
         */
        public Long zUnionAndStore(String key, String otherKey, String destKey) {
            return redisTemplate.opsForZSet().unionAndStore(key, otherKey, destKey);
        }

        /**
         * @param key
         * @param otherKeys
         * @param destKey
         * @return
         */
        public Long zUnionAndStore(String key, Collection<String> otherKeys,
                                   String destKey) {
            return redisTemplate.opsForZSet()
                    .unionAndStore(key, otherKeys, destKey);
        }

        /**
         * 交集
         *
         * @param key
         * @param otherKey
         * @param destKey
         * @return
         */
        public Long zIntersectAndStore(String key, String otherKey,
                                       String destKey) {
            return redisTemplate.opsForZSet().intersectAndStore(key, otherKey,
                    destKey);
        }

        /**
         * 交集
         *
         * @param key
         * @param otherKeys
         * @param destKey
         * @return
         */
        public Long zIntersectAndStore(String key, Collection<String> otherKeys,
                                       String destKey) {
            return redisTemplate.opsForZSet().intersectAndStore(key, otherKeys,
                    destKey);
        }

        /**
         * 匹配获取键值对,ScanOptions.NONE为获取全部键值对;ScanOptions.scanOptions().match("C").build()匹配获取键位map1的键值对,不能模糊匹配。
         *
         * @param key
         * @param options
         * @return
         */
        public Cursor<TypedTuple<String>> zScan(String key, ScanOptions options) {
            return redisTemplate.opsForZSet().scan(key, options);
        }

}

基本使用

redisTemplate01.opsForValue().set("name","张三");
System.out.println(redisTemplate01.opsForValue().get("name"));

因为有了工具类,所以不需要再去写繁琐的语句,直接调用响应方法即可。

标签:return,SpringBoot,param,学习,笔记,key,public,redisTemplate,String
来源: https://www.cnblogs.com/Z-Dragon/p/16414697.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有