当前位置:   article > 正文

java-springboot_java spring boot

java spring boot

SpringBoot

一、了解SpringBoot

  • 什么是SpringBoot
  • 为什么要学习SpringBoot
  • SpringBoot特点
1.1 什么是SpringBoot

Spring Boot使得创建独立的,基于生产级别的基于Spring的应用程序变得容易,您可以“运行”它们。

大多数Spring Boot应用程序需要最少的Spring配置。

SpringBoot其实就是构建Spring应用程序的“脚手架”,能够帮助我们快速的搭建一个Spring项目,并且尽可能减少XML的配置,做到“开箱即用”,让程序员只需要关注业务而不是配置!

1.2 为什么要学SpringBoot

1.复杂的配置

2.管理混乱

SpringBoot让这些就变得非常简单了

1.3 SpringBoot的特点
  1. 基于Spring快速开发Spring项目
  2. 开箱即用
  3. 提供可用于生产的功能,例如指标,运行状况检查和外部化配置
  4. 无需配置
  5. 约定大于配置

二、快速入门

采用spring提供的初始化器创建:用SpringBoot搭建一个web工程
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

2.1 创建maven工程
2.2 添加依赖

所有的SpringBoot工程,都必须继承一个父工程spring-boot-starter-parent,因为在该父工程中定了大量的依赖而且已经确定了版本!这样在我们当前工程中只要添加依赖而不用设置版本号!

2.2.1 添加父工程
<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.1.5.RELEASE</version>
    <relativePath/> <!-- lookup parent from repository -->
</parent>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
2.2.2 添加web启动器

在SpringBoot提供了各种自动配置,我们只要引入对应启动器即可,

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
</dependencies>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

在这里插入图片描述

2.2.3 管理JDK版本

默认情况下,maven工程的JDK版本1.5,而我们开始需要的是1.8

<properties>
    <java.version>1.8</java.version>
</properties>
  • 1
  • 2
  • 3
2.3.4 添加maven打包插件

在maven打包时,能够自动将springboot依赖的所有jar包打包在一起!

<build>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
        </plugin>
    </plugins>
</build>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
2.3 启动类

该类是启动SpringBoot程序的入口!

  • 注意:今后创建所有类都应该放在启动类所在的包及其子包下
@SpringBootApplication
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

@SpringBootApplication:说明当前是一个springboot应用程序

SpringApplication.run(Application.class, args):启动springboot程序

2.4 编写Controller

在这里插入图片描述

@RestController
public class HelloController {

    @RequestMapping("/hello")
    public String hello(){
        return "<h1>Hello World!</h1>";
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
2.5 启动测试

直接运行main方法,就表示运行springboot应用程序!
在这里插入图片描述

  • 监听的端口默认是8080
  • SpringMVC映射的路径是:/
  • /hello 映射的控制器是HelloCotroller中的hello方法

也可以直接启动jar包的方式运行SpringBoot程序:

java -jar SpringBoot程序.jar

三、Java配置

在SpringBoot中已经不推荐使用XML方式进行项目配置,那么现在我们想构造一个DataSource对象,如何进行?

之前:在xml文件中进行如何配置

<bean class="xxxxx.DataSource">
 <property name="driverClassName" value="">
 <property name="url" value="">
 <property name="username" value="">
 <property name="password" value="">
</bean>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
3.1 Spring发展历史
  • Spring1.0时代,jdk1.5刚刚出来,spring主要使用的是xml配置
  • Spring2.0时代,推出了注解方式,因为注解还不是非常完善,所以注解+xml结合
  • Spring3.0时代,注解非常完善,提出采用Java配置方式替代xml
  • Spring4.0时代,随着SpringBoot大行其道,完全不采用xml方式,注解和Java配置方式来实现项目的管理
3.2 Java配置
@Configuration
@PropertySource("classpath:jdbc.properties")
public class JavaConfig {
    @Value("${jdbc.driver}")
    private String driverClassName;

    @Value("${jdbc.url}")
    private String url;

    @Value("${jdbc.username}")
    private String username;

    @Value("${jdbc.password}")
    private String password;

    @Bean
    public DataSource dataSource() {
        DruidDataSource dataSource = new DruidDataSource();
        dataSource.setDriverClassName(driverClassName);
        dataSource.setUrl(url);
        dataSource.setUsername(username);
        dataSource.setPassword(password);
        return dataSource;
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25

@Configuration:说明当前类是一个配置类,等价于之前的xml配置文件

@Bean:创建了一个Bean对象放在Spring容器中了,默认方法名就是对象名称, 等价于之前在xml文件中定义的bean标签

@PropertySource:读取外部配置文件

@Value:注入基本类型和字符串类型的值

3.3 SpringBoot的属性注入

上面方式所面临的问题:

  • @Value这种注入方式不能注入复杂的数据类型
  • 我依然还需要定义大量的properties配置文件

SpringBoot定义了另外一种预定,配置文件命名为application.yml或者application.properties,SpringBoot启动时自动加载该配置文件!

在application.yml文件中定义如下配置:

jdbc:
  driverClassName: com.mysql.jdbc.Driver
  url: jdbc:mysql://localhost:3306/dbname
  username: root
  password: 123456
person:
  name: 张晓伟
  age: 17
  gender:hobby:hobbies:
    - 美女
    - 大美女
    - 小美女
    - 帅哥
  address:
    province: 上海
    city: 上海
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

获取配置文件中的参数,并封装到对应对象中去

@Configuration
public class JavaConfig2 {
    @Bean
    @ConfigurationProperties(prefix = "jdbc")//自动从application.yml文件中根据该前缀获取对应的配置参数,并且注入到当前方法返回的对象属性中
    public DataSource dataSource2(){
        DruidDataSource dataSource = new DruidDataSource();
        return dataSource;
    }

    @Bean
    @ConfigurationProperties(prefix = "person")
    public Person person(){
        Person p = new Person();
        return p;
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

四、SpringBoot自动配置原理(面试题)

在SpringBoot项目中只需要添加对应的“启动器”就自动完成相关配置!

4.1 SpringBootApplication注解

实现自动配置
在这里插入图片描述

@SpringBootConfiguration:说明当前是一个配置类@Configuration

@EnableAutoConfiguration:实现自动配置

SpringFactoriesLoader

//读取该文件META-INF/spring.factories中的key为org.springframework.boot.autoconfigure.EnableAutoConfiguration的内容,并存入在一个List集合中

public static List<String> loadFactoryNames(Class<?> factoryClass, @Nullable ClassLoader classLoader) {
 String factoryClassName = factoryClass.getName();
 return loadSpringFactories(classLoader).getOrDefault(factoryClassName, Collections.emptyList());
}
  • 1
  • 2
  • 3
  • 4
factoryClassName=org.springframework.boot.autoconfigure.EnableAutoConfiguration
  • 1
public static final String FACTORIES_RESOURCE_LOCATION = "META-INF/spring.factories";
  • 1
SpringFactoriesLoader.loadSpringFactories:从META-INF/spring.factories这个文件中将所有的内容全部读取出来,并存储在一个Map集合中
  • 1

在这里插入图片描述

public static List<String> loadFactoryNames(Class<?> factoryClass, @Nullable ClassLoader classLoader) {
		String factoryClassName = factoryClass.getName();
		return loadSpringFactories(classLoader).getOrDefault(factoryClassName, Collections.emptyList());//返回以org.springframework.boot.autoconfigure.EnableAutoConfiguration为key的所有内容,这些都是SpringBoot实现的一些自动配置类
}
  • 1
  • 2
  • 3
  • 4

总结:

@EnableAutoConfiguration在SpringBoot启动时将EnableAutoConfiguration为key的所有配置类(META-INF/spring.factories)读取出来,每个配置类生效是有各自的条件【需要添加对应的启动器】

@ComponentScan:起始扫描包的路径

4.2 SpringApplication.run方法

启动SpringBoot程序

1.创建SpringApplication对象:准备环境,并准备初始化数据

2.调用run方法:启动springboot程序

五、SpringBoot整合MyBatis

5.1 添加依赖
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.itluma</groupId>
    <artifactId>day57-springboot</artifactId>
    <version>1.0-SNAPSHOT</version>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.5.RELEASE</version>
    </parent>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
		  <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>2.1.0</version>
        </dependency>
    </dependencies>

</project>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
5.2 准备实体类
@Data
public class Employees implements Serializable {
    private Long employeeId;
    private String firstName;
    private String lastName;
    private String email;
    private String phoneNumber;
    private Date hireDate;
    private String jobId;
    private Long salary;
    private Double comm;
    private Long managerId;
    private Long departmentId;
    private String pic;

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
5.3 MyBatis的相关配置

定义接口

package com.itluam.springboot.mapper;

import com.itluam.springboot.entity.Employees;

import java.util.List;

/**
 * @author 飞鸟
 * @create 2020-08-25 11:59
 */
public interface EmployeesMapper {
    List<Employees> list();
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

定义映射文件

<?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.itluam.springboot.mapper.EmployeesMapper">
    <select id="list" resultType="Employees">
        select * from t_employees
    </select>
</mapper>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

在application.yml中定义相关配置

mybatis:
  configuration:
    map-underscore-to-camel-case: true #是否启动驼峰标识
  mapper-locations: classpath:mapper/*.xml #定义mapper映射文件的位置
  type-aliases-package: com.itluam.springboot.entity #定义别名包的位置

spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/companydb?serverTimezone=GMT
    username: root
    password: 123456
    type: com.zaxxer.hikari.HikariDataSource #连接池的类型,可以省略
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
5.4 定义Mapper接口的扫描

在这里插入图片描述

5.5 分页实现

添加分页启动类

<dependency>
    <groupId>com.github.pagehelper</groupId>
    <artifactId>pagehelper-spring-boot-starter</artifactId>
    <version>1.2.10</version>
</dependency>
  • 1
  • 2
  • 3
  • 4
  • 5

在需要分页位置通过PageHelper.startPage(page,size)启动分页

@RequestMapping("/list3")
public PageInfo<Employees> list3(Employees employees, @RequestParam(defaultValue = "1") Integer page,@RequestParam(defaultValue = "10") Integer size) {
    PageHelper.startPage(page,size);
    List<Employees> list = employeesMapper.findByWhere(employees);
    PageInfo<Employees> pages = new PageInfo<>(list);
    return pages;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

六、SpringBoot整合JSP(了解)

添加依赖

<!--JSP核心引擎依赖-->
<dependency>
    <groupId>org.apache.tomcat.embed</groupId>
    <artifactId>tomcat-embed-jasper</artifactId>
</dependency>
<dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>jstl</artifactId>
</dependency>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

创建JSP页面
在这里插入图片描述

配置视图解析器的前缀和后缀

spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/companydb?serverTimezone=GMT
    username: root
    password: 123456
    type: com.zaxxer.hikari.HikariDataSource #连接池的类型,可以省略
  mvc:
    view:
      prefix: /WEB-INF/jsp/  #配置前缀
      suffix: .jsp 			 #配置后缀
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

在控制器中进行页面跳转

@Controller
public class EmployeesController {
    @Autowired
    private EmployeesMapper employeesMapper;

    @RequestMapping("/employee/list")
    public String show(Employees employees, Model model, @RequestParam(defaultValue = "1") Integer page, @RequestParam(defaultValue = "10") Integer size) {
        PageHelper.startPage(page, size);

        List<Employees> list = employeesMapper.list();

        PageInfo<Employees> pageInfo = new PageInfo<>(list);
        model.addAttribute("pageInfo", pageInfo);
        return "list";
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

七、SpringBoot整合Thymeleaf模板引擎

freemarker/velocity/thymeleaf
在这里插入图片描述

提供了关于thymeleaf模板引擎的相关自动配置过程
在这里插入图片描述

添加依赖

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
  • 1
  • 2
  • 3
  • 4

关闭thymeleaf的缓存

spring:
  thymeleaf:
    cache: false #关闭thymeleaf的缓存
  • 1
  • 2
  • 3

注意:thymeleaf默认模板存在templates目录中,而且文件的后缀名为.html,但是该页面不是一个静态页面,而是一个符合Thymeleaf模板引擎规范的模板页面,在该页面中可以使用模板的语法!

在页面中展示数据!!!!!!!!!!!!!!!!!!!!!!!

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>员工中心</title>
</head>
<body>
<h1>展示员工列表</h1>

<div th:each="e : ${pageInfo.list}">
    <span th:text="${e.employeeId}"></span> --[[${e.firstName}]]
</div>
</body>
</html>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

thymeleaf的基本语法:

  • 在html标签上引入命名空间:xmlns:th="http://www.thymeleaf.org"
  • th:each遍历
  • th:text显示数据

八、SpringBoot综合案例

实现客户的增加、删除、修改、查询操作!

需要将客户数据同步到es中,因为查询动作是针对于es进行。修改、添加、删除动作是针对于数据库,操作之后需要将对应的数据同步到es中!
在这里插入图片描述

1。需要开发两个系统,客户模块、搜索模块

2。向客户模块进行搜索时,需要将请求转发给搜索模块实现搜索过程

3。数据的同步,在客户模块中对数据进行增、删、改的同时需要将对应的数据同步到ES中

8.1 搜索模块
8.1.1 生成索引及文档数据

添加依赖

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.itluma</groupId>
    <artifactId>day58-search</artifactId>
    <version>1.0-SNAPSHOT</version>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.5.RELEASE</version>
    </parent>

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

        <!--lombok-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>

        <!--es-->
        <dependency>
            <groupId>org.elasticsearch</groupId>
            <artifactId>elasticsearch</artifactId>
            <version>6.5.4</version>
        </dependency>
        <dependency>
            <groupId>org.elasticsearch.client</groupId>
            <artifactId>elasticsearch-rest-high-level-client</artifactId>
            <version>6.5.4</version>
        </dependency>

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

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

        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12-beta-3</version>
        </dependency>
    </dependencies>
</project>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59

创建启动类

@SpringBootApplication
public class SearchApplication {
    public static void main(String[] args) {
        SpringApplication.run(SearchApplication.class, args);
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

定义es的配置类

@Data
@Component
@ConfigurationProperties(prefix = "elasticsearch")
public class ElasticSearchProperties {
    private String host;
    private Integer port;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
@Configuration
@EnableConfigurationProperties(ElasticSearchProperties.class)
public class SearchConfig {
    @Autowired
    private ElasticSearchProperties elasticSearchProperties;

    @Bean
    public RestHighLevelClient client(){
        String host = elasticSearchProperties.getHost();
        Integer port = elasticSearchProperties.getPort();
        HttpHost httpHost = new HttpHost(host, port);

        RestClientBuilder clientBuilder = RestClient.builder(httpHost);

        RestHighLevelClient client = new RestHighLevelClient(clientBuilder);
        return client;
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

定义es的参数

elasticsearch:
  host: 192.168.136.129
  port: 9200
  • 1
  • 2
  • 3

测试生成索引和文档

package com.itluma.es;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.itluma.es.entity.Customer;
import org.elasticsearch.action.admin.indices.create.CreateIndexRequest;
import org.elasticsearch.action.admin.indices.create.CreateIndexResponse;
import org.elasticsearch.action.bulk.BulkRequest;
import org.elasticsearch.action.bulk.BulkResponse;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.common.xcontent.json.JsonXContent;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import java.io.IOException;

/**
 * @author 飞鸟
 * @create 2020-08-26 10:42
 */
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes = SearchApplication.class)
public class EsTest {
    @Autowired
    private RestHighLevelClient client;


    String index = "openapi_customer";
    String type = "customer";


    @Test
    public void createIndex() throws IOException {
        //1. 准备关于索引的settings
        Settings.Builder settings = Settings.builder()
                .put("number_of_shards", 5)
                .put("number_of_replicas", 1);

        //2. 准备关于索引的结构mappings
        XContentBuilder mappings = JsonXContent.contentBuilder()
                .startObject()
                .startObject("properties")
                .startObject("id")
                .field("type","integer")
                .endObject()
                .startObject("username")
                .field("type","keyword")
                .endObject()
                .startObject("password")
                .field("type","keyword")
                .endObject()
                .startObject("nickname")
                .field("type","text")
                .endObject()
                .startObject("money")
                .field("type","long")
                .endObject()
                .startObject("address")
                .field("type","text")
                .endObject()
                .startObject("state")
                .field("type","integer")
                .endObject()
                .endObject()
                .endObject();


        //3. 将settings和mappings封装到一个Request对象
        CreateIndexRequest request = new CreateIndexRequest(index)
                .settings(settings)
                .mapping(type,mappings);

        //4. 通过client对象去连接ES并执行创建索引
        CreateIndexResponse resp = client.indices().create(request, RequestOptions.DEFAULT);

        //5. 输出
        System.out.println("resp:" + resp.toString());

    }
    @Test
    public void bulkCreateDoc() throws IOException {
        //1. 准备多个json数据
        Customer c1 = new Customer();
        c1.setId(1);
        c1.setUsername("haier");
        c1.setPassword("111111");
        c1.setNickname("海尔集团");
        c1.setMoney(2000000L);
        c1.setAddress("青岛");
        c1.setState(1);

        Customer c2 = new Customer();
        c2.setId(2);
        c2.setUsername("lianxiang");
        c2.setPassword("111111");
        c2.setNickname("联想");
        c2.setMoney(1000000L);
        c2.setAddress("联想");
        c2.setState(1);

        Customer c3 = new Customer();
        c3.setId(3);
        c3.setUsername("google");
        c3.setPassword("111111");
        c3.setNickname("谷歌");
        c3.setMoney(1092L);
        c3.setAddress("没过");
        c3.setState(1);

        ObjectMapper mapper = new ObjectMapper();

        String json1 = mapper.writeValueAsString(c1);
        String json2 = mapper.writeValueAsString(c2);
        String json3 = mapper.writeValueAsString(c3);

        //2. 创建Request,将准备好的数据封装进去
        BulkRequest request = new BulkRequest();
        request.add(new IndexRequest(index,type,c1.getId().toString()).source(json1, XContentType.JSON));
        request.add(new IndexRequest(index,type,c2.getId().toString()).source(json2,XContentType.JSON));
        request.add(new IndexRequest(index,type,c3.getId().toString()).source(json3,XContentType.JSON));

        //3. 用client执行
        BulkResponse resp = client.bulk(request, RequestOptions.DEFAULT);

        //4. 输出结果
        System.out.println(resp.toString());
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
8.1.2 实现关键词搜索

定义搜索接口

@RestController
@RequestMapping("/search")
public class SearchController {
    @Autowired
    private CustomerService customerService;

    @GetMapping("/table")
    public String table(@RequestBody Map<String,Object> param){
        //1.进行查询
        String result = customerService.searchCustomerByQuery(param);

        //2.返回结构
        return result;
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

根据关键词进行es搜索

package com.itluma.es.service.impl;

import com.itluma.es.entity.Customer;
import com.itluma.es.service.CustomerService;
import com.itluma.es.utils.JSON;
import com.itluma.es.vo.LayUITable;
import org.apache.commons.beanutils.BeanUtils;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * @author 飞鸟
 * @create 2020-08-26 11:22
 */
@Service
public class CustomerServiceImpl implements CustomerService {
    private String index = "openapi_customer";
    private String type = "customer";

    @Autowired
    private RestHighLevelClient client;

    @Override
    public String searchCustomerByQuery(Map<String, Object> param) throws IOException {
        //1.创建SearchRequest
        SearchRequest request = new SearchRequest(index);
        request.types(type);

        //2.设置查询条件QueryBuilder
        SearchSourceBuilder builder = new SearchSourceBuilder();

        Integer page = (Integer) param.get("page");
        Integer limit = (Integer) param.get("limit");

        builder.from((page - 1) * limit);//设置其实位置
        builder.size(limit);//设置每一页的大小

        String username = (String) param.get("username");

        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
        if (!StringUtils.isEmpty(username)) {
            boolQueryBuilder.must(QueryBuilders.termQuery("username", username));
        }

        Object obj = param.get("state");
        if (obj != null) {
            boolQueryBuilder.must(QueryBuilders.termQuery("state", obj));
        }
        builder.query(boolQueryBuilder);

        request.source(builder);

        //3.执行查询
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);

        //4.封装对象
        LayUITable<Customer> layUITable = new LayUITable<>();
        SearchHit[] searchHits = response.getHits().getHits();
        if(searchHits!=null && searchHits.length>0){
            List<Customer> list = new ArrayList<>();
            //将搜索的结果存放到List集合中
            for(SearchHit hit : searchHits){
                Map<String, Object> sourceAsMap = hit.getSourceAsMap();
                Customer c = new Customer();
                try {
                    //将map集合中的元素封装到c对象实体中去,要求是map中的key要和c对象的属性名称一致
                    BeanUtils.populate(c, sourceAsMap);
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                } catch (InvocationTargetException e) {
                    e.printStackTrace();
                }
                list.add(c);
            }

            layUITable.setData(list);//设置当前页的数据
            layUITable.setCode(0);//设置状态码
            layUITable.setMsg("查询成功");//设置提示消息
            layUITable.setCount(response.getHits().getTotalHits());//设置总记录个数
        }

        //需要将layUITable转换成JSON

        return JSON.toJSON(layUITable);
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101

es搜索的restfull接口

GET /openapi_customer/customer/_search
{
  "from": 0,
  "size": 1,
  "query": {
    "bool": {
      "must": [
        {
          "term": {
            "username": {
              "value": "lianxiang"
            }
          }
        },
        {
          "term": {
            "state": {
              "value": "1"
            }
          }
        }
      ]
    }
  }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
8.1.3 增加索引

添加增加索引的接口

@PostMapping("/add")
public String add(@RequestBody Customer customer) throws IOException {
    boolean result = customerService.saveCustomer(customer);
    return result ? "yes" : "no";
}
  • 1
  • 2
  • 3
  • 4
  • 5

在业务层实现索引的添加

@Override
public boolean saveCustomer(Customer customer) throws IOException {
    //1.准备json数据
    String json = JSON.toJSON(customer);

    //2.创建IndexRequest对象
    IndexRequest request = new IndexRequest(index, type, customer.getId() + "");
    request.source(json, XContentType.JSON);

    //3.执行添加
    IndexResponse response = client.index(request, RequestOptions.DEFAULT);

    //4.返回
    if ("CREATED".equalsIgnoreCase(response.getResult().toString())) {
        return true;
    }
    return false;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
8.2 客户模块
8.2.1 显示搜索内容

添加项目依赖

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.itluma</groupId>
    <artifactId>day58-customer</artifactId>
    <version>1.0-SNAPSHOT</version>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.5.RELEASE</version>
    </parent>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>2.1.0</version>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
        </dependency>
    </dependencies>
</project>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40

添加静态页面
在这里插入图片描述

定义搜索接口

@RestController
@RequestMapping("/sys/customer")
public class CustomerController {
    @Autowired
    private CustomerService customerService;

    @GetMapping("/table")
    public String table(@RequestParam Map<String,Object> map) {
        String result = customerService.findCustomerByQuery(map);
        return result;
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

在客户模块中通过RestTemplate对象向搜索服务发请求

@Service
public class CustomerServiceImpl implements CustomerService {
    @Autowired
    private RestTemplate restTemplate;


    @Override
    public String findCustomerByQuery(Map<String, Object> param) {
        //调用day58-search工程中的localhost:8080/search/table接口
        //我们需要以json格式发送数据
        String json = JSON.toJSON(param);
        HttpHeaders headers = new HttpHeaders();
        //设置内容格式
        headers.setContentType(MediaType.parseMediaType("application/json;charset=utf-8"));
        //设置消息体
        HttpEntity<String> entity = new HttpEntity<>(json, headers);

        String result = restTemplate.postForObject("http://localhost:8080/search/table",entity, String.class);
        return result;
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
8.2.2 实现客户添加

控制层接口

@PostMapping("/add")
public ResultVo add(Customer customer) {
    try {
        customerService.add(customer);
        return new ResultVo(true, "添加成功!", null);
    } catch (Exception e) {
        e.printStackTrace();
        return new ResultVo(false, e.getMessage(), null);
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

实现业务层

@Override
@Transactional
public void add(Customer customer) {
    //1.添加数据库
    Integer count = customerMapper.save(customer);

    if (count != 1) {
        throw new RuntimeException("添加失败!");
    }

    //2.发送请求到搜索服务器,实现文档的添加
    //http://localhost:8080/search/add
    String json = JSON.toJSON(customer);
    HttpHeaders header = new HttpHeaders();
    header.setContentType(MediaType.APPLICATION_JSON_UTF8);
    HttpEntity entity = new HttpEntity(json, header);
    String result = restTemplate.postForObject("http://localhost:8080/search/add", entity, String.class);

    if(result.equalsIgnoreCase("no")){
        throw new RuntimeException("索引添加失败!");
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
8.3 Mapper启动器的使用

Mapper启动器是一个基于JDBC的通过反射的ORM框架,提供了一些通用的CRUD操作,而且不需要定义SQL的映射文件,直接采用注解实现SQL语句

1、添加启动器的依赖

<dependency>
    <groupId>tk.mybatis</groupId>
    <artifactId>mapper-spring-boot-starter</artifactId>
    <version>2.0.3</version>
</dependency>
  • 1
  • 2
  • 3
  • 4
  • 5

2、定义接口

package com.itluma.client.mapper;

import com.itluma.client.pojo.Customer;
import tk.mybatis.mapper.common.BaseMapper;

/**
 * @author 飞鸟
 * @create 2020-11-17 10:36
 */
public interface CustomerMapper extends BaseMapper<Customer> {
    
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

3、在启动类上添加Mapper接口的扫描

注意:@MapperScan这个注解所引入的包

package com.itluma.client;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;
import tk.mybatis.spring.annotation.MapperScan;

/**
 * @author 飞鸟
 * @create 2020-11-16 15:19
 */
@SpringBootApplication
@MapperScan("com.itluma.client.mapper")
public class CustomerApplication {


    @Bean
    public RestTemplate restTemplate(){
        return new RestTemplate();
    }

    public static void main(String[] args) {
        SpringApplication.run(CustomerApplication.class, args);
    }
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27

面试题分享

@SpringBootApplication

  • SpringBootConfiguration->Configuartion:当前是一个配置类
  • EnableAutoConfiguration:创建自动配置的对象
    • AutoConfiguartionPackage:获取当前类的包及其子包
      • Register:实现包的注册过程
    • AutoConfigurationImportSelector:将类路径下META-INF/spring.factories文件中的xxx.xxx.xxx.EanableAutoConfiguartion为key的配置类对象构造出来,每个对象的构造都有各自的生产条件
  • ComponentScan:根据包所在的位置构造对象
声明:本文内容由网友自发贡献,转载请注明出处:【wpsshop博客】
推荐阅读
相关标签
  

闽ICP备14008679号