springboot笔记(部分)

教程9-11:

黑马教程基础篇-09-入门案例解析:starter_哔哩哔哩_bilibili

 使用spring boot,在配置依赖的时候可以不需要写依赖坐标,是通过starter实现的,例如想写个依赖只需要这样

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

 spring有容器,spring boot同样也有容器,就在启动类的里面

package spring_01_01_quickstart;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
import spring_01_01_quickstart.com.itheima.controller.BookController;

@SpringBootApplication
public class Spring0101QuickstartApplication {

    public static void main(String[] args) {

        ConfigurableApplicationContext ctx= SpringApplication.run(Spring0101QuickstartApplication.class, args);
        BookController bean=ctx.getBean(BookController.class);
        System.out.println("bean="+ bean);
    }

}

 可以看到在运行后能将bean输出出来

 在点开SpringBootApplication注解后可以看到里面有一个ComponentScan注解,当没有指定包时,这个注解会默认扫描当前类所在包及其子包,所以当有配置类不在这里面的时候,spring boot容器是扫描不到的

 基础篇-11-入门案例:辅助功能_哔哩哔哩_bilibili

spring boot中没有配置tomcat服务器,但是同样能正常运行,原因是将tomcat服务器的执行过程抽取出来变成一个对象,并且交给spring容器去管理,也就是说spring容器中有一个tomcat对象,然后在tomcat这个对象中运行,所以也可以将这个tomcat服务器换成别的 ,如下图是换成了jetty

 Rest风格:

[补]知识加油站-01-REST风格简介_哔哩哔哩_bilibili

[补]知识加油站-02-RESTful入门案例_哔哩哔哩_bilibili

[补]知识加油站-03-RESTful快速开发_哔哩哔哩_bilibili

 

 
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;

import javax.websocket.server.PathParam;

@Controller
public class UserController {

    @RequestMapping(value = "/users",method = RequestMethod.POST)//method后面是设置请求的方式,比如此处为POST请求时
    @ResponseBody
    public String save(){
        System.out.println("user save...");
        return "{'module':'user save'}";
    }

    @RequestMapping(value = "/users",method = RequestMethod.PUT)//method后面是设置请求的方式,比如此处为PUT请求时
    @ResponseBody
    public  String update(@RequestBody User user){
        System.out.println("user = " + user);
        return "{'module':'user update'}";

    }
    @RequestMapping(value = "/users/{id}",method = RequestMethod.DELETE)
    @ResponseBody
    public String delete(@PathVariable Integer id){//@PathVariable注解代表此处需要的参数是从地址中获取的,加上这个参数后还需要在value处加上{}并且其中放入这个参数的名
        System.out.println("user delete"+id);
        return "{'module':'user delete'}";
    }
    

}

 可以看出这个代码中每个方法都有一些重复的东西,比如每个value中都含有/users,都加的ResponseBody注解,这些可以一起放到类上面从而使得更加简洁,如下图

 同时@RequestMapping(method = RequestMethod.POST)也可以用PostMapping注解来代替

// @RequestMapping(method = RequestMethod.POST)
    @PostMapping
    public String save(){
        System.out.println("user save...");
        return "{'module':'user save'}";
    }

配置properties文件的一些

#服务器端口配置
#server.port=80
#修改banner
spring.main.banner-mode=off
#spring.banner.image.location=faker.jpg
#只显示报错时的日志信息
#logging.level.root=error

关于properties文件中的配置可以看这里Common Application Properties (spring.io)

基础篇-15-3种配置文件类型_哔哩哔哩_bilibili

 优先级是properties>yml>yaml,核心格式是数据前面要用空格跟冒号隔开

有时候会出现在配置文件中不出提示的现象,原因是idea未识别出该文件为配置文件,需要进行配置一下

基础篇-19-读取yaml单一属性数据_哔哩哔哩_bilibili

取出yml文件中的内容

yml文件中的内容,以及java读取到zi'fu'ch

country: china
@Value("${country}")
    String country;

想要在yml文件中引用相应的属性的话

a: 1
b: ${a}

这样,b的值就也是1了

a: \n
b: "\n"

像a这样直接写\n的话输出还是\n这样一个字符串,如果想让转义字符\生效的话,需要像b这样写到一个字符串中

也可以使用自动装配将所有数据封装到一个Environment对象中,再输出出来

@Autowired
Environment env;
System.out.println(env.getProperty("b"));
System.out.println(env.getProperty("a"));

自定义对象封装指定数据

后期等到yml文件中的数据多了之后,想让他们分开赋值,如下想让一个对象只含有test中的内容,而其他的内容如country不含有

server:
  port: 81
country: china
a: \n
b: "\n"
test:
  c: 1
  d: 2
  e: 3
  f: 4
  g: 5

实现这个效果需要先创建一个数据模型封装配置文件中的数据如下

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

//1.定义数据模型封装yml文件中对应的数据
//2.定义为spring管控的bean
@Component
//3.指定加载的数据
@ConfigurationProperties(prefix = "test")
public class MyDataSource {
    private String c;
    private String d;
    private String e;
    private String f;
    private String g;

    @Override
    public String toString() {
        return "MyDataSource{" +
                "c='" + c + '\'' +
                ", d='" + d + '\'' +
                ", e='" + e + '\'' +
                ", f='" + f + '\'' +
                ", g='" + g + '\'' +
                '}';
    }

    public void setC(String c) {
        this.c = c;
    }

    public void setD(String d) {
        this.d = d;
    }

    public void setE(String e) {
        this.e = e;
    }

    public void setF(String f) {
        this.f = f;
    }

    public void setG(String g) {
        this.g = g;
    }

    public String getC() {
        return c;
    }

    public String getD() {
        return d;
    }

    public String getE() {
        return e;
    }

    public String getF() {
        return f;
    }

    public String getG() {
        return g;
    }
}
@Autowired
    MyDataSource myDataSource;
@GetMapping
public void getById(){
    System.out.println(myDataSource);
}

此时运行程序后就会输出下图所示结果

 整合第三方技术(26-31)

基础篇-23-SpringBoot整合JUnit_哔哩哔哩_bilibili

使用测试类时,如果测试类中的package的包与引导类的不一样,将无法运行,解决方法可以在SpringBootTest注解中加入(classes=...),...为引导类名或者再加一个ContextConfiguration(classes=...),这样就能解决这个问题

基础篇-25-SpringBoot整合MyBatis_哔哩哔哩_bilibili

创建新项目,需要勾选这两个选项

先在配置文件中设置相应的datasource数据,然后创建一个实体类以及dao

yml文件:

spring:
    datasource:
        url: jdbc:mysql://localhost:3306/world?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=GMT%2B8
        username: root
        password: 1027wu
        driver-class-name: com.mysql.cj.jdbc.Driver
package com.example.spring_05_mybatis;

public class domain {
    public String ID;
    public String Name;
    public String CountryCode;
    public String District;
    public String Population;

    @Override
    public String toString() {
        return "domain{" +
                "ID='" + ID + '\'' +
                ", Name='" + Name + '\'' +
                ", CountryCode='" + CountryCode + '\'' +
                ", District='" + District + '\'' +
                ", Population='" + Population + '\'' +
                '}';
    }

    public void setID(String ID) {
        this.ID = ID;
    }

    public void setName(String name) {
        Name = name;
    }

    public void setCountryCode(String countryCode) {
        CountryCode = countryCode;
    }

    public void setDistrict(String district) {
        District = district;
    }

    public void setPopulation(String population) {
        Population = population;
    }

    public String getID() {
        return ID;
    }

    public String getName() {
        return Name;
    }

    public String getCountryCode() {
        return CountryCode;
    }

    public String getDistrict() {
        return District;
    }

    public String getPopulation() {
        return Population;
    }
}
package com.example.spring_05_mybatis.dao;

import com.example.spring_05_mybatis.domain;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;

import java.awt.print.Book;
@Mapper
public interface BookDao {
    @Select("select * from city where ID = #{id}")
    public domain getById(Integer id);
}

 在测试类中先依赖注入BookDao,然后在运行的方法中输出即可查看查询结果:

package com.example.spring_05_mybatis;

import com.example.spring_05_mybatis.dao.BookDao;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

@SpringBootTest
class Spring05MybatisApplicationTests {
	@Autowired
	private BookDao bookDao;
	@Test
	void contextLoads() {
		System.out.println("bookDao.getById(1) = " + bookDao.getById(1));
//		bookDao.getById("1");
	}

}

整合mybatis-plus

整合mp时,spring.io这个网站中是找不着这个的,所以在创建项目的时候,要将这个地址改为阿里云的镜像

版本要选为这个(我的java是8版本,jdk是1.8),勾选mysql driver 创建完之后在pom.xml中加入这段依赖,刷新maven加载出来,同样的在yml文件中将datasource配置出来,创建实体类,实体类名要与数据库中的表名相同,创建的接口

数据库中的表名

 实体类:

package com.example.mp;

import com.baomidou.mybatisplus.annotation.TableField;
import org.springframework.beans.factory.annotation.Value;


public class city {
    public String ID;
    public String Name;
    @TableField(value = "CountryCode")
    public String CountryCode;
    public String District;
    public String Population;

    @Override
    public String toString() {
        return "domain{" +
                "ID='" + ID + '\'' +
                ", Name='" + Name + '\'' +
                ", CountryCode='" + CountryCode + '\'' +
                ", District='" + District + '\'' +
                ", Population='" + Population + '\'' +
                '}';
    }

    public void setID(String ID) {
        this.ID = ID;
    }

    public void setName(String name) {
        Name = name;
    }

    public void setCountryCode(String countryCode) {
        CountryCode = countryCode;
    }

    public void setDistrict(String district) {
        District = district;
    }

    public void setPopulation(String population) {
        Population = population;
    }

    public String getID() {
        return ID;
    }

    public String getName() {
        return Name;
    }

    public String getCountryCode() {
        return CountryCode;
    }

    public String getDistrict() {
        return District;
    }

    public String getPopulation() {
        return Population;
    }
}
package com.example.mp.dao;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;

@Mapper
public interface BookDao extends BaseMapper<com.example.mp.city> {
}
 <dependency>
        <groupId>com.baomidou</groupId>
        <artifactId>mybatis-plus-boot-starter</artifactId>
        <version>3.4.2</version>
 </dependency>

 测试类:

package com.example.mp;

import com.baomidou.mybatisplus.annotation.TableField;
import com.example.mp.dao.BookDao;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

@SpringBootTest


class MpApplicationTests {
    @Autowired
//    @TableField(value = "")  // 默认为true
    private BookDao bookDao;
    @Test


    void contextLoads() {
        System.out.println("bookDao ==================================================== " + bookDao.selectById(1));
    }

}
spring:
    datasource:
        url: jdbc:mysql://localhost:3306/world?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=GMT%2B8
        username: root
        password: 1027wu
        driver-class-name: com.mysql.cj.jdbc.Driver

运行后我这里出现了一个问题,原因是数据库中

在使用mp后 报这样子的错误

 解决方法也很简单,这个是因为实体类中的CountryCode这个被识别为country_code了,只需要在实体类中的CountryCode这个变量上面加上这个注解即可

    @TableField(value = "CountryCode")
    public String CountryCode;

然后视频中是遇到的另一种情况,他的数据库表名是tbl_book,这样会被mp在数据库中搜索book,结局方法是在配置文件中加上这个

 整合Druid

Maven Repository: com.alibaba » druid-spring-boot-starter (mvnrepository.com)

创建项目的时候,选my sql driver跟mybatis,然后导入坐标(注意我这里导入了两个,视频里只导入druid-spring-boot-starter,但是我那样就会报错)

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

,然后配置文件(这两种都可以):

#spring:
#  datasource:
#    url: jdbc:mysql://localhost:3306/world?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=GMT%2B8
#    username: root
#    password: 1027wu
#    driver-class-name: com.mysql.cj.jdbc.Driver
#    type: com.alibaba.druid.pool.DruidDataSource

spring:
  datasource:
    druid:
      driver-class-name: com.mysql.cj.jdbc.Driver
      url: jdbc:mysql://localhost:3306/world?useUnicode=true&characterEncoding=utf8&useSSL=false
      username: root
      password: 1027wu

其他的跟之前的就差不多一样了

package com.example.druid;


import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;

@Mapper
public interface BookDao  {
    @Select("select * from city where ID = #{id}")
    public city getById(Integer id);

}
package com.example.druid;




public class city {
    public String ID;
    public String Name;

    public String CountryCode;
    public String District;
    public String Population;

    @Override
    public String toString() {
        return "domain{" +
                "ID='" + ID + '\'' +
                ", Name='" + Name + '\'' +
                ", CountryCode='" + CountryCode + '\'' +
                ", District='" + District + '\'' +
                ", Population='" + Population + '\'' +
                '}';
    }

    public void setID(String ID) {
        this.ID = ID;
    }

    public void setName(String name) {
        Name = name;
    }

    public void setCountryCode(String countryCode) {
        CountryCode = countryCode;
    }

    public void setDistrict(String district) {
        District = district;
    }

    public void setPopulation(String population) {
        Population = population;
    }

    public String getID() {
        return ID;
    }

    public String getName() {
        return Name;
    }

    public String getCountryCode() {
        return CountryCode;
    }

    public String getDistrict() {
        return District;
    }

    public String getPopulation() {
        return Population;
    }
}

然后在测试类中运行成功。

工程打包与运行(56-58)

运维实用篇-51-工程打包与运行_哔哩哔哩_bilibili

成功运行完之后在这个文件夹里可以找到

 

点击之后 在文件资源管理器中的地址栏输入cmd,输入java -jar (这个jar包的名字),这个运行的时候一定要注意自己配没配置java的系统环境变量,不然是运行不了的

 

回车后就可以运行了,打开浏览器输入相应的网址会发现已经可以访问了。

在这期间使用apifox的时候发现接收的数据不是json格式的,就比较好奇json应该是怎么发送的,看了好多博客,最后发现可以这样设置一个Map作为返回值,接收到的类型是json的,不过这应该只是其中之一的方法,应该还有别的方法,写到一半发现json数据还可以通过实体类封装后传

 运维实用篇-52-打包插件_哔哩哔哩_bilibili

 

不加这个的话,打包之后会找不到启动类而且依赖的jar包不会一块下载到打包之后的jar包中等等的,cmd中会报jar中没有主清单属性的这个问题

有时候运行也会出现端口被占用的问题,在打包成jar后就不容易修改了,所以可以通过以下的这些指令查询相应的 端口进程并杀死等等的,当然还有另一种方法来覆盖原始文件中的设置,这样设置就可以将端口改为8080端口,后面可以继续加--相关的配置,格式就是yml中的格式

 运维实用篇-53-Boot工程快速启动(Linux版)_哔哩哔哩_bilibili

 linux在系统还原之后还没装上来就先跳了

 这里是配置相关属性的优先级

 运维实用篇-55-临时属性(开发环境)_哔哩哔哩_bilibili

在这里也可以配置相关的 属性

 配置完之后运行程序,可以发现端口已经更改为8082了

 这个更改的原因是在运行类中的args传入这些属性,在运行之前打印一下args可以发现其中就是server.port

 所以也就是,在run方法中传入args来更改配置的属性,同样,可以创建一个新的字符串数组,并且将run方法中的args数组改为新建的这个,运行后同样可以发现端口已经改为8081了,所以,如果想要防止别人更改jar 包中的一些属性,可以将run方法中的args参数去掉,这样,jar包中的参数就不可以被修改了

配置文件与多环境开发(59-65)

 运维实用篇-56-配置文件4级分类_哔哩哔哩_bilibili

 3级实在resources包下新创建个文件夹叫做config,将yml文件放进去,二级是在将项目打包成jar后,在jar同级目录下放入一个yml文件,一级是在jar包同级目录下创建一个config文件夹,在这个文件夹中放入一个yml文件

运维实用篇-57-自定义配置文件_哔哩哔哩_bilibili

想要更改配置文件的名字的话,可以采用以下的配置

多环境开发

yml文件中设置spring.profiles.active的属性来选择选用下面的哪个配置,每个配置之间需要用---来分隔开


#应用环境
spring:
  profiles:
    active: dev
---
#设置环境
#生产环境
spring:
  config:
    activate:
      on-profile: pro
server:
  port: 80
---
#开发环境
spring:
  config:
    activate:
      on-profile: dev
server:
  port: 81
---
#测试环境
spring:
  config:
    activate:
      on-profile: test
server:
  port: 82

运行后可以看到选择的pro配置已经生效了

这是在一个配置文件中,多个配置文件 

创建一个新的 配置文件命名为application-dev.yml,以及设置端口为82,再在application.yml文件中设置选用哪个配置信息

server:
  port: 82
spring:
  profiles:
    active: dev

运行之后可以发现端口号已经改为82了

同时使多个文件生效的话可以这样子 

配置中后加载的会覆盖先加载的配置文件中相同的属性,但是这样配置active属性对应的文件永远都是最后加载的

这个也可以对配置文件进行分组,比如只启动dev组的 配置文件

spring:
  profiles:
    active: dev
    group:
      "dev": dev1
      "pro": pro1

运行后会发现dev1是在dev后面运行的,也就说明如果有相同类型的话会覆盖掉dev的

 日志相关操作以及热部署(66-73)

发送请求后会发现只打印了三种日志,没有打印debug的日志,原因是默认是info级别的日志,只会打印info日志以及比他级别高的日志信息

private static  final Logger Log= LoggerFactory.getLogger(test.class);

    // @RequestMapping(method = RequestMethod.POST)
    @PostMapping
    public String save(){
        System.out.println("user save...");
        Log.debug("debug...");
        Log.info("info...");
        Log.warn("warn...");
        Log.error("error");
        return "{'module':'user save'}";
    }

这两种方法可以设置成debug级别的日志,第一种是输出调试信息,常用于检查系统运行状况,第二种打印的信息会更加详细,为整体应用日志,这里的debug也可以改成其他级别

#debug: true

logging:
  level:
    root: debug

可以加上@Slf4j注解(需要在pom.xml中导入lombok),这样就不需要初始化Log了,如下图这样,要注意log是小写的

 设置日志文件,将日志保存到文件中去

 热部署导入spring-boot-devtools坐标,每次修改程序运行时需要点build project,这样子每次更新代码就不需要重启服务器了,build project是手动热部署,这个可以让idea改成自动的,分别把这两个位置勾上,然后就实现自动热部署了,在每次idea失去焦点几秒钟就会自动重新build project了

 

 

这样设置可以让系统中的热启动功能彻底关闭,也可以在配置文件中将restart功能设置为false也会关闭第三方bean绑定,松散绑定,Hibernate框架(74-81)

d实用开发篇-71-第三方bean属性绑定_哔哩哔哩_bilibili

实用开发篇-72-松散绑定_哔哩哔哩_bilibili

先初始化一下配置,创建一个空的spring boot项目,不勾选任何内容,在pom.xml中导入lombok的坐标,并且application.yml,serverconfig,运行文件的内容分别如下

application.yml:

servers:
  port: 2345
  timeout: -1
  ipAddress: 192.168.0.1

ServerConfig:

package com.example.springboot_configuration.config;

import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

@Data
@Component
@ConfigurationProperties(prefix = "servers")
public class ServerConfig {
    String ipAddress;
    String port;
    String timeout;

}

@Data就是把getter,setter等方法集成了

@ConfigurationProperties中prefix指定的就是配置文件中所要赋值的内容的上一级的名称

这里的ipAddress在绑定属性的时候,名称比较松散,比如配置文件中写的为IPADRESS,或者Ip_address,ip-address这些都可以绑定上,但是这个只局限于@ConfigurationProperties注解所在的类,prefix的属性必须全为小写可以加上中划线-,在配置文件中同样也为忽略大小写下划线中划线等

SpringbootConfigurationApplication:

package com.example.springboot_configuration;

import com.example.springboot_configuration.config.ServerConfig;
import org.springframework.beans.factory.annotation.Configurable;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;

@SpringBootApplication
public class SpringbootConfigurationApplication {

    public static void main(String[] args) {
        ConfigurableApplicationContext ctx= SpringApplication.run(SpringbootConfigurationApplication.class, args);
        ServerConfig bean=ctx.getBean(ServerConfig.class);
        System.out.println("bean = " + bean);
    }

}

运行后可以发现成功将yml文件的内容赋值到ServerConfig中了

 这中间我遇到一个问题,就是

 这上面爆红了,

它的意思是“Spring Boot配置注解执行器没有配置”

配置注解执行器的作用是,当执行类中已经定义了对象和该对象的字段后,在配置文件中对该类赋值时,便会非常方便的弹出提示信息。

解决方法是在pom文件中加入

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>

可能会也会爆红,不用管,直接刷新maven就好了,回到ServerConfig可以发现已经解决了

第三方bean的话跟这个差不多,这个是自定义了一个bean,使用@ConfigurationProperties注解

 @EnableConfigurationProperties()跟@ConfigurationProperties的区别:

前者用法是需要在括号里写入需要进行属性绑定的类,比如加上server.class,加上之后则不能在这个类中写component注解了,多个类需要{}将其括起来,ConfigurationProperties是让这个类在配置文件中能找到自己绑定的属性

计量单位

 

DataSize是内存大小,上面这张图片表示M,可能会出现配置文件的属性格式与定义的不匹配,可以采用bean属性校验:

1,在pom.xml中加入这段

        <dependency>
            <groupId>javax.validation</groupId>
            <artifactId>validation-api</artifactId>
        </dependency>

 2,在需要进行属性校验的类加入@Valid,在相应的变量前加上需要限制的注解

3,再加入,使用Hibernate框架提供的校验器做实现类

        <dependency>
            <groupId>org.hibernate.validator</groupId>
            <artifactId>hibernate-validator</artifactId>
        </dependency>

将配置文件中的timeout设置为99999,超出了设定,运行程序可以发现已经成功了

 设定还有:

 在这里配置的属性的优先级是高于配置文件的属性的

测试类 :

在测试的时候想加载外部bean的话,可以考虑使用Import注解,如下图在测试类中新建一个测试bean

 在运行程序里加入一个import注解

运行后可以发现会输出"测试",证明导入成功了 ,但是如果项目是一个web项目的话,这个测试文件是不能启动服务器的,需要再对SpringBootTest注解进行设置,这样启动 的是随机端口,启动目前不被占用的端口,每次基本都不会相同

 也可以这样设置成默认端口

 

匹配网页响应的相关信息(82-86)

 实用开发篇-80-匹配响应执行状态_哔哩哔哩_bilibili

实用开发篇-81-匹配响应体_哔哩哔哩_bilibili

这几集主要就是匹配网页访问响应的内容,比如访问网站地址出错,响应的内容出错等等的,差不多都是这样子,这里只写的响应状态以及响应体,header没有写,这些内容都是基本一样的,项目开发中常常把这些放到一个方法中同时检测很多东西

首先需要导入lombok

创建一个实体类Book:

package com.example.springboot_configuration.domain;

import lombok.Data;

@Data
public class Book {
    int id;
    String name;
    String type;
    String description;

}

BookConfig:

package com.example.springboot_configuration;

import com.example.springboot_configuration.domain.Book;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RequestMapping("/books")
@RestController
public class BookConfig {
    @GetMapping
    public String getById(){
        System.out.println("getById....");
        return "getById";
    }
    @GetMapping("/json")
    public Book get1(){
        Book b=new Book();
        b.setDescription("1");
        b.setId(1);
        b.setType("1");
        b.setName("1");
        return b;
    }
}

还有一个测试类,这些方法分别是发送虚拟请求,匹配相应状态,匹配响应体还有匹配json:

package com.example.springboot_configuration;

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.web.servlet.MockHttpServletRequestDsl;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.ResultActions;
import org.springframework.test.web.servlet.ResultMatcher;
import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.result.ContentResultMatchers;
import org.springframework.test.web.servlet.result.MockMvcResultMatchers;
import org.springframework.test.web.servlet.result.StatusResultMatchers;

@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
//开启虚拟mvc调用
@AutoConfigureMockMvc
public class WebTest {
    @Test
    void test(){

    }
    @Test
    void testWeb(@Autowired MockMvc mvc) throws Exception {
        //创建虚拟请求,当前访问/books
        MockHttpServletRequestBuilder builder= MockMvcRequestBuilders.get("/books");
        //执行对应的请求
        mvc.perform(builder);
    }
    @Test
    void testStatus(@Autowired MockMvc mvc) throws Exception {
        //创建虚拟请求,当前访问/books
        MockHttpServletRequestBuilder builder= MockMvcRequestBuilders.get("/books");
        //执行对应的请求
       ResultActions actions= mvc.perform(builder);
        //设定预期值 与真实值进行比较,成功测试通过 失败测试失败
        //定义本次调用的预期值
        StatusResultMatchers status= MockMvcResultMatchers.status();
        //预计本次调用成功时:状态200
        ResultMatcher ok=status.isOk();
        //添加预计值到本次调用过程中进行匹配
        actions.andExpect(ok);
    }
    @Test
    void testBody(@Autowired MockMvc mvc) throws Exception {
        MockHttpServletRequestBuilder builder= MockMvcRequestBuilders.get("/books");
        ResultActions actions= mvc.perform(builder);
        //设定预期值 与真实值进行比较,成功测试通过 失败测试失败
        //定义本次调用的预期值
        ContentResultMatchers content= MockMvcResultMatchers.content();
        //添加预计值到本次调用过程中进行匹配
        ResultMatcher result=content.string("getById");
        actions.andExpect(result);
    }
    @Test
    void testJson(@Autowired MockMvc mvc) throws Exception {
        MockHttpServletRequestBuilder builder= MockMvcRequestBuilders.get("/books");
        ResultActions actions= mvc.perform(builder);
        //设定预期值 与真实值进行比较,成功测试通过 失败测试失败
        //定义本次调用的预期值
        ContentResultMatchers content= MockMvcResultMatchers.content();
        //添加预计值到本次调用过程中进行匹配
        ResultMatcher result=content.json("{\"id\":1,\"name\":\"1\",\"type\":\"1\",\"description\":\"1\"}");
        actions.andExpect(result);
    }

}

同时在这里也发现了传json数据可以用一个实体类

相关技术的整合(87-106)

实用开发篇-84-业务层测试事务回滚_哔哩哔哩_bilibili

在测试类中运行数据库的一些增加等操作时会对数据库进行更改,但是当不想对数据库进行更改时需要让其进行回滚,在测试类上面加一个@Transactional注解,这样在运行程序后,就会进行回滚,可以加一个@Rollback注解并且设置为false,默认是True,改为false后会发现,即使加上@Transactional注解也一样会保存到数据库中

实用开发篇-85-测试用例设置随机数据_哔哩哔哩_bilibili

实用开发篇-86-内置数据源_哔哩哔哩_bilibili

使用hikari数据源时我这里报了一个错是Exception during pool initialization.

这个问题可能是datasource配置出现问题了,我改了一下url路径为jdbc:mysql://localhost:3306/world就成功了

 Druid数据源的两种配置:

 数据库H2(替换tomcat):

首先加入这两个配置

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        <dependency>
            <groupId>com.h2database</groupId>
            <artifactId>h2</artifactId>
            <scope>runtime</scope>
        </dependency>

配置文件中是这样配置的

    spring:
      h2:
        console:
          path: /h2
          enabled: true

运行后,因为我这个没设置端口所以是默认端口8080,注意在输入地址的时候要加上8080,即访问localhost:8080/h2会到达这个界面

 第一次登陆需要在配置文件中加入这些,这样是可以初始化数据源,后面再次登陆就可以不用加了

spring:
  datasource:
    url: jdbc:h2:~/test
    hikari:
      driver-class-name: org.h2.Driver
      username: sa
      password: 123456

成功连接后的操作跟sql差不多就一样了

 实用开发篇-89-redis下载安装与基本使用_哔哩哔哩_bilibili

实用开发篇-90-SpringBoot整合Redis_哔哩哔哩_bilibili

实用开发篇-91-SpringBoot读写Redis的客户端_哔哩哔哩_bilibili

实用开发篇-92-SpringBoot操作Redis客户端实现技术切换(jedis)_哔哩哔哩_bilibili

连接redis时候出现这个错误

 原因是6379端口已绑定。应该是因为上次服务没有关闭。这样输入后再次运行就成功了

 

 哈希存储的话,简单来说就是先是一个key对应多个键值对的key,这些key再对应一个value

哈希存储的时候我这里报错了,内容就是权限不允许,再以管理员的身份运行命令提示符窗口,重新启动一下redis,再put就成功了

redis提供的api

整合redis Redis下载地址:Releases · tporadowski/redis (github.com)

1,先是在创建项目的时候勾选redis

 2,配置文件中进行配置

spring:
  redis:
    host: localhost
    port: 6379

3,测试文件中对一些set,get,put进行测试

package com.example.springboot_redis;

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.redis.core.HashOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;

@SpringBootTest
class SpringbootRedisApplicationTests {

	@Autowired
	private RedisTemplate redisTemplate;

	@Test
	void set() {
		ValueOperations ops= redisTemplate.opsForValue();
		ops.set("age",41);
	}

	@Test
	void get(){
		ValueOperations ops= redisTemplate.opsForValue();
		Object age= ops.get("age");
		System.out.println("age = " + age);
	}

	@Test
	void hset(){
		HashOperations hashOperations= redisTemplate.opsForHash();
		hashOperations.put("info","a","aa");
	}

	@Test
	void hget(){
		HashOperations ops= redisTemplate.opsForHash();
		Object a=ops.get("info","a");
		System.out.println("a = " + a);
	}

}

在java程序中将数据set或者put都是以对象的方式进行处理,读取的时候也是在程序中以文件的形式读取出来,但是如果在命令窗口set一个值,在java程序中还是以同样的方法是读取不出来的,因为在命令窗口set的值是 String类型的,读取的话需要用

@Autowired
StringRedisTemplate stringRedisTemplate;

这样定义完之后,剩下的操作就跟上面的一样了

整合Mongodb

 整合ES:

首先还是要启动ES啊(运行的时候给忘了)

视频中是老版的,所以spring boot没有集成ES,现在已经集成了,搜了一下

(2条消息) 《SpringBoot篇》16.SpringBoot整合Elasticsearch_陈老老老板的博客-CSDN博客

这个写的感觉很好,看完这个基本就会整合了

整合过程中我这里也报了一个错误是Elasticsearch exception [type=illegal_argument_exception, reason=request [/user] contains unrecognized parameter: [include_type_name]] ],原因是create方法导入的包已经过时了

我导入的 是这个包,这个已经过时了
import org.elasticsearch.action.admin.indices.create.CreateIndexRequest;

换成下面这个包就能正常运行了
import org.elasticsearch.client.indices.CreateIndexRequest;

(3条消息) 【ES报错】Unable to parse response body for Response{requestLine=PUT /index/_doc...HTTP/1.1 201 Created}_老坛聊开发的博客-CSDN博客

在查询的时候视频里用的是termQuery,因为我数据库的Name都含有大写字母,所以查找的时候在termQuery("name",""),后面的name的value也都写的是有大写字母的单词,这样是搜不到的,因为文档里保存的数据是小写的,差不多是这样子,所以查找的话termQuery中的value必须改为小写的。当然也可以用matchQuery这个,他们的格式都是一样的,但是matchQuery中可以用大写的字母来查找,emm,我看黑马的这个课后面有讲解ES的,就没有深入研究了

具体的代码如下(因为我用的之前的一个数据库,数据库定义的内容跟老师讲的不一样,所以有些地方也不太一样):

pom.xml:

        <dependency>
            <groupId>org.elasticsearch</groupId>
            <artifactId>elasticsearch</artifactId>

        </dependency>

        <dependency>
            <groupId>org.elasticsearch.client</groupId>
            <artifactId>elasticsearch-rest-high-level-client</artifactId>

        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.60</version>
        </dependency>


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

        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid-spring-boot-starter</artifactId>
            <version>1.2.8</version>
        </dependency>
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.4.2</version>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>

测试文件:

package com.example.springboot_es;


import net.minidev.json.JSONObject;
import org.apache.http.HttpHost;
import org.elasticsearch.action.bulk.BulkRequest;
import org.elasticsearch.action.get.GetRequest;
import org.elasticsearch.action.get.GetResponse;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.indices.CreateIndexRequest;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestClientBuilder;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.xcontent.XContentType;
import com.alibaba.fastjson.JSON;

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

import java.awt.print.Book;
import java.io.IOException;
import java.util.List;

@SpringBootTest
class SpringbootEsApplicationTests {

    @Autowired
    BookDao bookDao;
    @Autowired
    private RestHighLevelClient client;

    @Test
    void testCreateIndex() throws IOException {
        HttpHost host = HttpHost.create("http://localhost:9200");
        RestClientBuilder builder = RestClient.builder(host);
        client = new RestHighLevelClient(builder);
        String json="{\n" +
                "    \"mappings\":{\n" +
                "        \"properties\":{\n" +
                "            \"id\":{\n" +
                "                \"type\":\"keyword\"\n" +
                "            },\n" +
                "            \"name\":{\n" +
                "                \"type\":\"text\",\n" +
                "                \"analyzer\":\"ik_max_word\",\n" +
                "                \"copy_to\":\"all\"            },\n" +
                "            \"type\":{\n" +
                "                \"type\":\"keyword\"\n" +
                "            }\n" +
                "            ,\n" +
                "            \"description\":{\n" +
                "                \"type\":\"text\",\n" +
                "                \"analyzer\":\"ik_max_word\",\n" +
                "                \"copy_to\":\"all\"\n" +
                "            },\n" +
                "            \"all\":{\n" +
                "                \"type\":\"text\",\n" +
                "                \"analyzer\":\"ik_max_word\"\n" +
                "            }\n" +
                "        }\n" +
                "    }\n" +
                "}\n";
        CreateIndexRequest request = new CreateIndexRequest("user");
        request.source(json, XContentType.JSON);
        client.indices().create(request, RequestOptions.DEFAULT);

        client.close();
    }

    //添加文档
    @Test
    void testCreateDoc() throws IOException {
//        city book=bookDao.selectById("1");//查询单个数据

//        IndexRequest request=new IndexRequest("user").id(book.getID().toString());
        IndexRequest request=new IndexRequest("user").id("1");
//        String json=JSON.toJSONString(book);
//
//        request.source(json,XContentType.JSON);
//        try{
//        client.index(request,RequestOptions.DEFAULT);}catch (Exception e){
//            String msg = e.getMessage();
//            if(!msg.contains("201 Created") && !msg.contains("200 OK")) {
//                throw e;
//            }
//        }
        //**********************************************上面为查询一条数据,保存多条数据可以用批处理容器
        List<city> bookList=bookDao.selectList(null);
        BulkRequest bulk=new BulkRequest();//bulk为一个容器,所有的请求都往这里面添加就行了
        for(city book:bookList){
            IndexRequest request=new IndexRequest("user").id(book.getID().toString());//
            String json=JSON.toJSONString(book);
//
            request.source(json,XContentType.JSON);
            bulk.add(request);
        }

        try{
        client.bulk(bulk,RequestOptions.DEFAULT);}catch (Exception e){
            String msg = e.getMessage();
            if(!msg.contains("201 Created") && !msg.contains("200 OK")) {
                throw e;
            }
        }

//        client.close();
    }
    //按id查询
    @Test
    void testGet() throws IOException {
        GetRequest request=new GetRequest("user","1");
        GetResponse response=client.get(request,RequestOptions.DEFAULT);
        String JSON=response.getSourceAsString();
        System.out.println("JSON = " + JSON);
    }
    //按条件查询
    @Test
    void testSearch() throws IOException {
        SearchRequest request=new SearchRequest("user");
        SearchSourceBuilder builder=new SearchSourceBuilder();
        builder.query(QueryBuilders.matchQuery("name","ai"));
        request.source(builder);
        SearchResponse response=client.search(request,RequestOptions.DEFAULT);
        SearchHits hits=response.getHits();
        for(SearchHit hit:hits){
            String source =hit.getSourceAsString();
            System.out.println(source);
        }
    }



}

application.yml文件:

spring:
  datasource:
    druid:
      driver-class-name: com.mysql.cj.jdbc.Driver
      url: jdbc:mysql://localhost:3306/world?serverTimezone=UTC
      username: root
      password: 1027wu
  elasticsearch:
    rest:
#      uris: http://localhost:9200
mybatis-plus:
  global-config:
    db-config:
      id-type: auto
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

BookDao(后面运行的时候才发现我用的数据库名叫city,这里定义的叫BookDao,有点乱了):

package com.example.springboot_es;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
import org.springframework.transaction.annotation.Transactional;

@Mapper
@Transactional
public interface BookDao extends BaseMapper<city> {

}

city(这个类可以看作是视频里的那个Book类):

package com.example.springboot_es;

import com.baomidou.mybatisplus.annotation.TableField;
import lombok.Data;
import lombok.Value;

@Data
public class city {
    String ID;
    String Name;
    @TableField(value = "CountryCode")
    String CountryCode;
    String District;
}

还有一定要注意导包的时候不要导错了,有些方法在好几个包里都有

Memcached的安装按照视频的顺序就行了,比较简单

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值