Java's SpringBoot basics, front-end and back-end projects, MyBatisPlus, MySQL, vue, elementUi


foreword

In the basic chapter, my positioning for learners is to get started first, and to be able to use SpringBootand build based on SpringBootproject webdevelopment, so there are fewer content settings, mainly including the following content:
1. SpringBootQuick start
2. SpringBootBasic configuration
3. Based on SpringBootintegrationSSMP


JC-1. Get Started Quickly with SpringBoot

To learn any technology, you must first know what the function of the technology is, otherwise, after learning it, you will not know when to use the technology, that is, the application scenario corresponding to the technology. SpringBootThe technology is Pivotaldeveloped and produced by the team. The simple summary of the function is to accelerate Springthe development of the program. This acceleration should be considered from the following two aspects


1. SpringThe initial construction process of the program
2. SpringThe development process of the program


Through the positioning of the above two aspects, we can generate two vague concepts:
1. SpringBootThe development team thinks that the initial construction of the original Springprogram may be a bit cumbersome, and this process can be simplified. What is Springincluded in the initial construction process of the original program? What's up? Why do you find it cumbersome? The most basic Springprogram has at least one configuration file or configuration class, which is used to describe Springthe configuration information. Could this file not be written? SpringIn addition , most of the current enterprise-level development is for webdevelopment. If you do webdevelopment, you need to webload the specified springconfiguration when loading the environment. This is the most basic requirement. If you don’t write it, how do you know which configuration file to load? What about the configuration class? After changing SpringBootthe technology, do we still need to write these? The answer to the mystery will be revealed later, let’s keep it a secret
2. SpringBootThe development team thinks that the original Springprogram development process is a bit cumbersome, and this process can still be simplified. The development process is nothing more than what technology to use, import the corresponding jar package (or coordinates) and then hand over the core object of this technology to the Springcontainer management, that is, configure it to be Springcontrolled by the container bean. These are all basic operations, can these things SpringBootalso help us simplify?


With the above questions in mind, we started the development of the first SpringBootprogram to see SpringBootto what extent the use of technology can simplify development.


Warm reminder,
ifSpringyou don’t know much about the basic development of the program, you can abandon the pit when you see this. The following content requiresSpringtechnical knowledge, and you can’t learn it if you bite the bullet.


JC-1-1. SpringBoot entry program production (1)

Now let's start the first SpringBootprogram. This course is based on Idea2020.3the version. The version used Mavenis 3.6.1and JDKthe version is 1.8. If your environment is different from the above environment, there may be slight differences in the operation interface and operation process, as long as the software Ideais Mavencompatible It’s all tears).


Next, use SpringBoottechnology to quickly build a SpringMVCprogram, and experience the meaning of the word simplification through this process .


Step ①

Create a new module, select Spring Initializr, and configure basic information about the module

image-20211116125259385


Special attention :When3step is clickedyou need to be connected to the Internet to enter the next page. If you cannot connect to the normal network, you will not be able to correctly reach the setting page on the right, and you will always be connected to the Internet . Special attention :selected in the first stepmatches the versioninstalled on your computeror above, and it is recommended to useor.NextIdea
5javaJDKJDK8811


Step ②

Select the technology set that the current module needs to use

image-20211116125615728


According to the requirements, select on the left web, and then select in the middle Spring Web. After selecting, a new content item appears on the right, which means that the selection is successful.


Note : The version selected hereSpringBootcan use the default version. It needs to be said thatSpringBootthe version upgrade speed is very fast. Maybe the default version was the default version when the project was created yesterday,2.5.4and the default version will become the default version when the project is created today2.5.5. There is not much difference , without getting too entangled, and you can also modify the corresponding version in the configuration file.


Step ③

Develop controller class

// Rest模式
@RestController
@RequestMapping("/books")
public class BookController {
     
     
	@GetMapping
	public String getById(){
     
     
		System.out.println("springboot is running...");
		return "springboot is running...";
	}
}

SpringMVCThe controller made in the entry case is developed based on the style. Of course , there is no problem with the program Restmade in the original format here . The AND annotations in the above example are typical annotations based on development.SpringMVC@RestController@GetMappingRestful


AttentionSpringBoot : The most basic development of the program has been donehereSpringthe program can run normally. Some friends may have doubts.TomcatThe server is not configured,Springand it is not configured. Can it be used without configuring anything? That'sSpringBootthe power of technology. I will talk about the internal workflow later, and concentrate on learning the development process first.


Step ④

Run auto-generated Applicationclasses

image-20211116130152452


Use the running form of the program with mainthe method to run the program. After the running is completed, the console will output the above information.java


8080It is not difficult to see that the port included in the running information , Tomcatthis familiar word, is it possible that Tomcatthe server is started here? Yes, it has been activated here. The server is not configured, where did it come from? More on that later. Now you can access the requested path through the browser and test whether the function is working properly.


访问路径: http://localhost:8080/books

Isn't it amazing? The underlying logic that the current effect depends on is still very complicated, but from the developer's point of view, only two files are currently displayed to the developer.


1、pom.xml

This is maventhe configuration file, which describes the corresponding configuration information when the current project is built.

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

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

    <groupId>com.itheima</groupId>
    <artifactId>springboot_01_01_quickstart</artifactId>
    <version>0.0.1-SNAPSHOT</version>

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

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

There are two pieces of information that need to be paid attention to in the configuration. One is parentthat the current project inherits another project, and what it is used for will be discussed later. There are also dependent coordinates, and what it is used for will be discussed later.


2. Application class

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

The function of this class is very simple, just a sentence of code, the running program is the running class.


At this point, we can boldly speculate that if the above two files do not exist, it SpringBootwill definitely not be possible to play. It seems that the core is these two files. Since it is the first SpringBootprogram to be produced, don't pay attention to the functions of these two files, and explain the internal workflow in detail later.


Through the above production, it is not difficult to find that SpringBootthe program is simply too easy to write, almost nothing is written, and the function is there. This is why SpringBootthe technology is so popular now . Each level has advantages.SpringSpringBoot


class configuration file Spring SpringBoot
Coordinates in the pom file Add manually Tick ​​to add
web3.0 configuration class Handmade none
Spring/SpringMVC configuration class Handmade none
controller Handmade Handmade

To sum it up in one sentence, write less if you can , and don’t write if you can’t . This is SpringBootthe benefit that technology brings to us SpringBoot. That’s it. to help you simplify development.


Summarize

1. The development SpringBootprogram Ideacan be quickly produced according to the wizard based on the premise of networking in the tool.
2. SpringBootThe program needs to be dependent JDK, and the minimum version requirement is JDK8
3. SpringBootWhen a certain function needs to be used in the program, you can select the technology by ticking the form, or you can add it manually The corresponding technology to be used (explained later)
4. Run the SpringBootprogram by running the programApplication


think

As I said in the previous production, this process must be connected to the Internet, but sometimes you will encounter some inexplicable problems. For example, based on Ideadevelopment, you will find that you have configured some coordinates, and then Mavenyou will die slowly when you download the corresponding things. Slow, or even fail. In fact, this phenomenon is related to Ideathis IDEtool. If Ideawe cannot access the network normally, will we not be able to make SpringBootprograms? Let's talk about it in the next section.


JC-1-2. SpringBoot entry program production (2)

If Ideayou can't connect to the Internet normally, can this SpringBootprogram not be made? Are you kidding me? IDEThere are thousands of tools in the world. Does SpringBoottechnology have to be based on Ideait? it's out of the question. The development SpringBootprogram can not IDEbe based on tools, and the program SpringBootcan be directly created on the official website SpringBoot.


SpringBootThe official website and Springthe official website are together, both spring.io. SpringBootYou can find the technical introduction page through the project level by level , and then find the following content in the middle of the page

image-20211122150444816


Step ①

Click Spring Initializrto enter the creation SpringBootprogram interface, and the next step is the process of inputting information, which Ideais the same as making in, but the interface has changed. According to your own requirements, select the corresponding information on the left and enter the corresponding information.

image-20211122150608039


Step ②

The one on the right ADD DEPENDENCIESis used to select which technology to use. It Spring WEBis doing the same thing as the previous check, but the interface is different. Click to open the web version of the technology selection interface.
image-20211122161257361


Step ③

After all the information is set, click GENERATEthe button on the left below to generate a file package.

image-20211122161548022


Step ④

After saving, a compressed file is obtained, which is the created SpringBootproject

image-20211122161709478


Step ⑤

解压缩此文件得到工程目录,在Idea中导入即可直接使用,和之前在Idea环境下根据向导创建的工程完全一样,你可以创建一个Controller测试一下当前工程是否可用。
温馨提示
做到这里其实可以透漏一个小秘密,Idea工具中创建SpringBoot工程其实连接的就是SpringBoot的官网,还句话说这种方式和第一种方式是一模一样的,只不过Idea把界面给整合了一下,读取Spring官网信息,然后展示到Idea界面中而已,可以通过如下信息比对一下


Idea中创建工程时默认选项

image-20211122162443035


SpringBoot官网创建工程时对应的地址

看看SpringBoot官网创建工程的URL地址,是不是和Idea中使用的URL地址是一样的?

image-20211122162820719


总结

1. 打开SpringBoot官网,选择Quickstart Your Project中的Spring Initializr
image-20211122150444816


2. 创建工程。
image-20211122150608039


3. 保存项目文件。

image-20211122161548022


4. 解压项目,通过IDE导入项目后进行编辑使用。


思考

现在创建工程靠的是访问国外的Spring主站,但是互联网信息的访问是可以被约束的,如果一天这个网站你在国内无法访问了,那前面这两种方式就无法创建SpringBoot工程了,这时候又该怎么解决这个问题呢?咱们下一节再说。


JC-1-3.SpringBoot入门程序制作(三)

What should I do if the website mentioned above is restricted? Use your brain to think about it, whether it is method 1 or method 2, they are actually taking the same route, which is to SpringBootcreate a project through the official website SpringBoot. If there is such a website in China that can provide such a function, will it be solved? Inevitably, a new question arises again, is there any website in China that provides such a function? Indeed, Ali provided one, the following questions are simple, just tell us the URL OK, yes, that’s it.


When creating a project, switch to select starterthe service path, and then manually enter the Alibaba Cloud address, address: http://start.aliyun.comorhttps://start.aliyun.com

image-20211122163605950


In order to facilitate the development and use of its own company, Ali hereby adds some Ali's own technologies in the dependency coordinates, and it is also to promote its own technologies, so you have more choices in the dependency selection list. In addition, the address provided by Ali is more in line with the usage habits of domestic developers. There are some SpringBootcoordinates that are not given on the official website. You can take a good look.
image-20211122163937408


SpringBootBut one thing needs to be made clear. The default project version created by Alibaba Cloud is 2.4.1 , so if you want to change to another version, you pomcan manually modify it in the file after creating the project. Don’t forget to refresh and load the new version information .


Note : After the project creation address provided by Alibaba Cloud is initialized, itSpringBootis slightly different from the project created by using the official website, mainly in the form of the configuration file. This information will beSpringBootrevealed later when explaining the program execution process.


Summarize

1. Select startthe source as Custom URL
2. Enter the Alibaba Cloud starteraddress
3. Create a project


think

So far we have three ways to create SpringBoota project, but each method requires you to be able to access the Internet to create a project. If one day, you join a project team with a relatively high level of confidentiality, and the entire project team does not have an external network, can you not do this? Let's talk about it in the next section.


JC-1-4. SpringBoot entry program production (4)

I can't access the Internet and want to create SpringBoota project, can I do it? It can be done, but you have to ask yourself what is the difference between being connected to the Internet and not being connected to the Internet? After you find this difference, you will find that if you have prepared all the things you need to do for networking in advance, you don't need to connect to the Internet.


What does networking do? First of all, SpringBootthe project is also based on Mavenconstruction, and Mavenif you load something in the project that needs to be used but does not exist, you need to download it online. In fact, SpringBootwhen the project is created, it is necessary to download some necessary components. What if these things are prepared in advance? Yes, that's it.


Next, create a SpringBootproject manually. If the things that need to be used are guaranteed mavento exist in the warehouse in advance, the whole process can be independent of the network environment. But we have already created the project in 3 ways SprongBoot, so there is nothing to download below.


Step ①

When creating a project, choose to create a normal Mavenproject.

image-20211122165341684


Step ②

Refer to the standard SpringBootengineering pomdocuments and write your own pomdocuments.

<?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>

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

    <groupId>com.itheima</groupId>
    <artifactId>springboot_01_04_quickstart</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>

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

Write what you use, and don’t write what you don’t need. Of course, now friends may not know what to use and what not to use. The easiest thing is to copy and paste. As you learn later, you will know what can be omitted. Here I have deleted some things that are not necessary at present, but they can still be used. There are two core contents, one is to inherit a parent project, and the other is to add a dependency.


Step ③

Before running SpringBootthe project, a class was needed. This is indispensable. Just write one by hand. It is recommended to create it according to the previous directory structure. Don’t play tricks, learn to walk first and then learn to run. The class name can be customized, and the associated name can be modified synchronously.

@SpringBootApplication
public class Application {
     
     
    public static void main(String[] args) {
     
     
        SpringApplication.run(Application.class);
    }
}

Attention@SpringBootApplication : Don't losethe annotations on the class


Note : The class name can be customized, as long as the class name used in the following code is the same as the name you defined yourself, that is,corresponding namerunin the methodclass


Step ④

Next, you can create a Controllertest yourself to see if it works, and it is no different from before.


Seeing this, you should be able to figure it out. SpringBootThe project created through the wizard or the website is actually writing some code for you, but now it is handwritten by yourself, and the written content is the same, nothing more.


Reminder
If you have never successfully created a project on your computerSpringBoot, naturally you have not downloaded theSpringBootcorresponding coordinate-related resources, then the method of creating by handwriting must not be available if you are not connected to the Internet. The so-called handwriting is actually writing something that others have generated for you, but the resources corresponding to the referenced coordinates must be guaranteedmavento be available in the warehouse. If not, you still have to download them.


Summarize

1. Create a common Mavenproject
2. Inheritance spring-boot-starter-parent
3. Add dependencies spring-boot-starter-web
4. Make a bootstrap classApplication


So far, I have learned 4a way to create SpringBoota project. In fact, the essence is the same. According to SpringBootthe file format requirements of the project, the corresponding files are generated or handwritten in different ways, and the effect is exactly the same.


teach you a trick

IdeaHide specified files/folders in


When creating SpringBoota project, whether you use SpringBoota wizard or Alibaba Cloud, it is all for one purpose, to obtain a standard SpringBootproject file structure. At this time, a new problem appeared. The standard project structure contains some unknown folders, which look particularly awkward during development. This section will talk about how to deal with these files.


There are nothing more than two solutions. If you know enough about each file/directory, keep the useful ones, and delete the useless ones. Or don't delete it, but it looks awkward, just set the file as invisible. Not to mention deleting, Deletejust drop it after selecting it. This section talks about how to hide the specified file or folder information.


Since it Ideais a hidden function, it must belong Ideato the setting. The setting method is as follows.


Step ①

Open the settings, 【Files】→【Settings】.

image-20211122173835517


Step ②

After opening the file type setting interface, [ Editor] → [ File Types] → [ Ignored Files and Folders], ignore the file or folder display.

image-20211122174020028


Step ③

Add the name of the file or folder you want to hide, you can use the wildcard character * to indicate anything, and you can set it up.


It's done here, it's actually Ideaa small function of


Summarize

1. 【Files】→【Settings
2. 【Editor】→【File Types】→【Ignored Files and Folders
3. Enter the name to be hidden, support *number wildcard
4. Press Enter to confirm adding


JC-1-5. Introduction to Spring Boot

The introductory case is finished. At this time, recall SpringBootthe function we mentioned before. Do you still remember? Accelerate Springthe development of the program, do you have a deep understanding now? Looking at SpringBootthe original intention of the technology design, it is easy to understand.


SpringBootIt is Pivotala new framework provided by the team, which is designed to simplify Springthe initial construction and development process of the application .


What things have been simplified? SpringIn fact, it is simplified for two aspects of the original program production:


1. Disadvantages of Spring program

Relying on cumbersome settings
used to write Springprograms, and the technologies used had to be written one by one by yourself. Now it is not necessary. If you have done the original program, SpringMVCyou should know that SpringMVCthe most basic spring-weband spring-webmvcthese two coordinates are necessary for writing programs. And that doesn't even include the coordinates you use json, wait, now? One coordinate is done.


The configuration is cumbersome.
Before writing configuration classes or configuration files, you have to write and load beanthese things yourself. What about now? Nothing is written, it still works.


Reviewing
the positioning of the above two aspects, we can come up with two vague concepts:
1. SpringBootThe development team thinks that the initial construction of the original Springprogram may be a bit cumbersome, and this process can be simplified. The Springinitial construction process of the original program includes What things are there? Why do you find it cumbersome? The most basic Springprogram has at least one configuration file or configuration class, which is used to describe Springthe configuration information. Could this file not be written? SpringIn addition , most of the current enterprise-level development is for webdevelopment. If you do webdevelopment, you need to webload the specified springconfiguration when loading the environment. This is the most basic requirement. If you don’t write it, how do you know which configuration file to load? What about the configuration class? After changing SpringBootthe technology, do we still need to write these? The answer to the mystery will be revealed later, let’s keep it a secret

2. SpringBootThe development team thinks that the original Springprogram development process is a bit cumbersome, and this process can still be simplified. The development process is nothing more than what technology to use, import the corresponding jarpackage (or coordinates) and then hand over the core object of this technology to Springthe container management, that is, configure it to be Springcontrolled by the container bean. These are all basic operations, can these things SpringBootalso help us simplify?


Let’s take a look at the two questions raised above. There are already answers, they are all simplified, and there is no need to write them. This is the SpringBootbenefit to us. These simplified operations SpringBoothave professional terms in "SpringBoot" and are also the core functions and advantages of the `SpringBoot program:


2. Start dependency (simplifies dependency configuration)

The writing simplification of dependency configuration is achieved by this starting dependency.


3. Automatic configuration (simplifies common project-related configuration)

The configuration is too cumbersome, and the automatic configuration can be used to simplify it accordingly, but the interior is still very complicated, which will be explained in detail later.


4. Accessibility (built-in server, ...)

In addition to the above functions, SpringBootthe program actually has some other advantages. For example, we have not configured Tomcata server, but it can run normally. This is SpringBoota perceivable function in the entry program, and it is also SpringBootone of the auxiliary functions. An auxiliary function can do this 6, it's amazing.


Let’s talk about the aspects of these simplified operations in combination with the introductory program, which are divided into 4three aspects

parent
starter
bootstrap class
embeddedtomcat


parent

SpringBootIt is concerned that developers often have a fixed collocation format for the selection of dependent versions when developing, and the selection of these dependent versions cannot be randomly matched. For example , when Athe technical 2.0version is Bused in conjunction with the technical version, it can work together with Bthe technical version, but there will be conflicts when it is developed and used in cooperation with the technical version. In fact, many developers have always wanted to do one thing, which is to collect and organize the common dependency versions used with various technologies, and create the most reasonable dependency version configuration scheme, which is much more convenient to use.3.5B3.7


SpringBootSeeing this situation so easy, I sorted out the common usage schemes of all technical versions for developers. In the future, developers can directly use the version schemes provided by it, so they don’t have to worry about conflicts, which is equivalent to doing SpringBootcountless A list of technical version collocations. The name of this technical collocation list is parent .


The parent itself has many versions, and each parent version contains hundreds of version numbers of other technologies, andparentthe version numbers of various technologies used between different versions may change. When developers use certain technologies,they canSpringBootprovided parent , and the parent will help developers uniformly manage the versions of various technologies.


SpringFor example, if you want to use cooperative development now MyBatis, parentwhat would you do before? Select a Springspecific version, then select a MyBatisspecific version, and then determine the versions of other technologies associated with the use of these technologies one by one. When your Springversion changes and needs to be switched, your MyBatisversion may also be switched accordingly. What about the associated technology? You may have to switch, and other problems may arise after switching. Now all this work can be left parentto do. You don't need to pay attention to the version conflicts between these technologies, you only need to pay attention to which technology you use, and the conflicts are handled by the parent .


Someone may ask, what if the parent imports some dependencies that I don't want to use? Remember clearly, this is very important, parent only helps us with version management, it is not responsible for importing coordinates for you, to put it bluntly, you decide what to use, but you don't need to manage the version. On the whole, using parent can help developers to manage versions in a unified way.


Note :parentAfter the definition is made, it is not used directly. It is only a manual for the developer, but it is not actually used. This must be confirmed clearly.


So SpringBoothow does this work? You can consult SpringBootthe configuration source code to see these definitions.


A coordinate is inherited in pom.xml in the project

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

After opening, you can check that it has inherited another coordinate

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-dependencies</artifactId>
    <version>2.5.4</version>
</parent>

Two sets of information are defined in this coordinate

The first group is all kinds of dependent version number attributes. The following lists the part of dependent version attributes. It can be seen that the dependent version numbers of several technologies are defined.

<properties>
    <activemq.version>5.16.3</activemq.version>
    <aspectj.version>1.9.7</aspectj.version>
    <assertj.version>3.19.0</assertj.version>
    <commons-codec.version>1.15</commons-codec.version>
    <commons-dbcp2.version>2.8.0</commons-dbcp2.version>
    <commons-lang3.version>3.12.0</commons-lang3.version>
    <commons-pool.version>1.6</commons-pool.version>
    <commons-pool2.version>2.9.0</commons-pool2.version>
    <h2.version>1.4.200</h2.version>
    <hibernate.version>5.4.32.Final</hibernate.version>
    <hibernate-validator.version>6.2.0.Final</hibernate-validator.version>
    <httpclient.version>4.5.13</httpclient.version>
    <jackson-bom.version>2.12.4</jackson-bom.version>
    <javax-jms.version>2.0.1</javax-jms.version>
    <javax-json.version>1.1.4</javax-json.version>
    <javax-websocket.version>1.1</javax-websocket.version>
    <jetty-el.version>9.0.48</jetty-el.version>
    <junit.version>4.13.2</junit.version>
</properties>

The second group is all kinds of dependency coordinate information. It can be seen that there is no specific dependency version number in the dependency coordinate definition, but the dependency version attribute value defined in the first group of information is referenced.

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-core</artifactId>
            <version>${hibernate.version}</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>${junit.version}</version>
        </dependency>
    </dependencies>
</dependencyManagement>

Note : The above dependency coordinate definition appears in the label, which is the dependency management of reference coordinates, not the actual coordinates used. Therefore, when this set of information is inherited in your projectparent, if the corresponding coordinates are not used, the previous set of definitions will not specifically import a certain dependency.


Attention : Becausemaventhere is only one opportunity to inherit in , the above-mentioned inheritance format can also be switched to the import form, andstarterthis form is used when creating projects in Alibaba Cloud.

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-dependencies</artifactId>
            <version>${spring-boot.version}</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

Summarize

1. The development SpringBootprogram must be inherited spring-boot-starter-parent
2. spring-boot-starter-parentSeveral dependency managements are defined in
3. The inheritance parentmodule can avoid dependency version conflicts when multiple dependencies use the same technology
4. parentThe form of inheritance can also be achieved by introducing dependencies


think

parentSeveral dependent version management are defined in , but they are not used, so this setting will not take effect. Who is using these definitions?


starter

SpringBootWhen paying attention to actual development, developers often have some fixed combinations for the use of dependent coordinates, such as using spring-webmvcmust use spring-web. It is very cumbersome to write with a fixed collocation every time, and the format is fixed without any technical content.


SpringBootLooking at this situation, it seems that some help needs to be brought to the developers. Arrange and develop the fixed collocation format used by all technologies. In the future, when you use a certain technology, you don’t need to write a bunch of dependencies every time, and it’s easy to make mistakes. I’ll make you a thing that represents a bunch of things. When developers use it, they can just use the thing I made. For such a fixed technology collocation, SpringBootI gave it a name called starter .


starterIt is also an optimal solution to define a fixed collocation format for dependencies when using a certain technology. Using starters can help developers reduce dependency configurations .


This thing has actually been used in the introductory case, and webthe function in the introductory case uses this method to add dependencies. You can consult SpringBootthe configuration source code to see these definitions.


The pom.xml in the project defines the use of SpringMVC technology, but does not write the coordinates of SpringMVC, but adds a dependency that includes starter in the name

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

Several specific dependent coordinates are defined in spring-boot-starter-web

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter</artifactId>
        <version>2.5.4</version>
        <scope>compile</scope>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-json</artifactId>
        <version>2.5.4</version>
        <scope>compile</scope>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-tomcat</artifactId>
        <version>2.5.4</version>
        <scope>compile</scope>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-web</artifactId>
        <version>5.3.9</version>
        <scope>compile</scope>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-webmvc</artifactId>
        <version>5.3.9</version>
        <scope>compile</scope>
    </dependency>
</dependencies>

As mentioned before, the coordinates SpringMVCthat need to be imported for the development program spring-webmvcand the coordinates for springintegrated webdevelopment are the last two in the above group of coordinates.


But we found that besides these two coordinates, there are other coordinates. For example, the second one is called spring-boot-starter-json. You can tell from the name that this is jsonthe coordinates related to and, but the name is not the same as the last two. It also has it in the name. starterOpen it and see what is inside?

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter</artifactId>
        <version>2.5.4</version>
        <scope>compile</scope>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-web</artifactId>
        <version>5.3.9</version>
        <scope>compile</scope>
    </dependency>
    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-databind</artifactId>
        <version>2.12.4</version>
        <scope>compile</scope>
    </dependency>
    <dependency>
        <groupId>com.fasterxml.jackson.datatype</groupId>
        <artifactId>jackson-datatype-jdk8</artifactId>
        <version>2.12.4</version>
        <scope>compile</scope>
    </dependency>
    <dependency>
        <groupId>com.fasterxml.jackson.datatype</groupId>
        <artifactId>jackson-datatype-jsr310</artifactId>
        <version>2.12.4</version>
        <scope>compile</scope>
    </dependency>
    <dependency>
        <groupId>com.fasterxml.jackson.module</groupId>
        <artifactId>jackson-module-parameter-names</artifactId>
        <version>2.12.4</version>
        <scope>compile</scope>
    </dependency>
</dependencies>

We can find that this startercontains a number of coordinates. In fact, it is SpringMVCusually used in use and development Json, and it jsonis inseparable from the coordinates defined here. It seems that it is really convenient SpringBootto use the things we use in development. Everything is prepared in advance. If you read it carefully, you will find that there are some things in it that you have never used. It is true that there is such a possibility of excessive imports, it does not matter, you can maveneliminate some of them by excluding dependencies in . But it’s okay if you don’t care about it, the big deal is to import too much.


At this point, I basically got a piece of information, which startercan help developers quickly configure dependencies. In the past, writing depends on 3one coordinate, but now writing and importing one can be done, which speeds up the configuration of dependencies.


The difference between starter and parent

It feels vaguely starterand parentseems to help us simplify the configuration, but the functions are different, let's sort it out.


The starter defines several coordinates in one coordinate. In the past, multiple coordinates were written, but now one is written, which is used to reduce the amount of writing depending on the configuration .


The parent defines hundreds of dependency version numbers. In the past, you need to manually control the version when you write dependencies. Now it isSpringBootmanaged uniformly, so that there will be no version conflicts, and it is used to reduce dependency conflicts .


Actual development and application method

  • If you need to use any technology in actual development, first find out if there is any corresponding technologystarter

1. If there is a corresponding one starter, write it directly starter, and there is no need to specify the version, the version parentis provided by
2. If there is no corresponding one starter, just write the coordinates by hand


  • If you find conflicts in the coordinates during actual development, confirm the feasible version number you want to use, add the corresponding dependencies by handwriting, and overwrite the SpringBootconfiguration management provided to us

1. Directly write the coordinates
2. The version number defined in the overlay is the following pile of things, which one conflicts and overwrites OKit


<properties>
    <activemq.version>5.16.3</activemq.version>
    <aspectj.version>1.9.7</aspectj.version>
    <assertj.version>3.19.0</assertj.version>
    <commons-codec.version>1.15</commons-codec.version>
    <commons-dbcp2.version>2.8.0</commons-dbcp2.version>
    <commons-lang3.version>3.12.0</commons-lang3.version>
    <commons-pool.version>1.6</commons-pool.version>
    <commons-pool2.version>2.9.0</commons-pool2.version>
    <h2.version>1.4.200</h2.version>
    <hibernate.version>5.4.32.Final</hibernate.version>
    <hibernate-validator.version>6.2.0.Final</hibernate-validator.version>
    <httpclient.version>4.5.13</httpclient.version>
    <jackson-bom.version>2.12.4</jackson-bom.version>
    <javax-jms.version>2.0.1</javax-jms.version>
    <javax-json.version>1.1.4</javax-json.version>
    <javax-websocket.version>1.1</javax-websocket.version>
    <jetty-el.version>9.0.48</jetty-el.version>
    <junit.version>4.13.2</junit.version>
</properties>

Kind tips

SpringBootThe official has given a lot of starterdefinitions, which are convenient for us to use, and the names are all in the following format

命名规则:spring-boot-starter-技术名称

So when I saw spring-boot-starter-aaasuch a name later, this is SpringBootthe official starterdefinition. Is there any unofficial definition? Yes, the specific naming method will be discussed in the chapter of integrating technologies.


Summarize

1. SpringBootWhen the development program needs to import coordinates, it usually imports the corresponding coordinates. starter
2. Each different starterfunction usually contains multiple dependent coordinates.
3. Using it startercan achieve the effect of quick configuration and achieve the purpose of simplifying configuration


Boot class

After finishing the configuration, we found that SpringBootit really helped us reduce a lot of configuration work. Let's talk about how the program works. At present, the entry point for program operation is SpringBootthe class that comes with the project when it is created, that is, mainthe class with methods. Running this class can start SpringBootthe operation of the project.

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

SpringBootIt is designed to speed up Springthe development of the program, and Springthe basis for the program to run is to create Springa container object ( IoCcontainer) and place all objects in Springthe container for management, that is, one by one Bean. Now switch to SpringBootaccelerated development Springprogram, is this container still there? Needless to say, this question must be there. In fact, after the current class is run, a Springcontainer object will be generated, and this object can be saved and directly operated through the container object Bean.

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

Through the above operations, it is not difficult to see that SpringBoota container object is actually created when the program starts Spring. The currently running class SpringBootis the entry point of all functions in the program, called the boot class .

The most typical feature of being a boot class is that an annotation @SpringBootApplication is declared above the current class .


Summarize

1. SpringBootThe project provides a bootstrap class to start the program
2. SpringBootCreate and initialize Springthe container after the project starts


think

The program is now running, through mainthe methods of the bootstrap class. But javashouldn't the running program end after execution? But we have obviously started a webserver now, otherwise how can the web page be accessed normally? Where is this server written?


Embedded tomcat

The current SpringBootintroductory case we have checked Spring-webthe functions and imported the corresponding ones starter.

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

SpringBootI found out that since you want to make weba program, you must use weba server, so let’s help people to the end, send Buddha to the west, and I will help you build a webserver. If you are willing to use it, just use it directly. SpringBootThinking about it again, what if providing a server does not meet the needs of developers? Just let me give you a few more options, and you can switch at will. In case you don't want to use what I provide you, that's fine, you can do it yourself.


Since this function does not belong to the main function of the program, it can be used or not, so SpringBootit is positioned as an auxiliary function. Don't underestimate such an auxiliary function, it can help us developers reduce a lot of setting work.


The following will focus on this built-in webserver, which can also be said to be a built-in tomcatserver, to study a few questions:
1. Where is this server defined
? 2. How does this server work
? 3. If you want to change this server, how do you change it? Although this demand is very rubbish, it makes developers feel weblike there are many servers. Isn't it good to use others to provide it? don't bother yourself


Embedded Tomcat definition location

When it comes to the location of the definition, we thought, if we don't develop webthe program, will we use webthe server? Definitely don't need it. So if this thing is added to your program, what technology does it come with? It must be weba related function, that's right, it is what webthe related function imported earlier starterdoes.

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

Open webthe corresponding starterto see what has been imported.

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter</artifactId>
        <version>2.5.4</version>
        <scope>compile</scope>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-json</artifactId>
        <version>2.5.4</version>
        <scope>compile</scope>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-tomcat</artifactId>
        <version>2.5.4</version>
        <scope>compile</scope>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-web</artifactId>
        <version>5.3.9</version>
        <scope>compile</scope>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-webmvc</artifactId>
        <version>5.3.9</version>
        <scope>compile</scope>
    </dependency>
</dependencies>

The third dependency is tomcatthe corresponding thing, and it is also one starter, so open it again.

<dependencies>
    <dependency>
        <groupId>jakarta.annotation</groupId>
        <artifactId>jakarta.annotation-api</artifactId>
        <version>1.3.5</version>
        <scope>compile</scope>
    </dependency>
    <dependency>
        <groupId>org.apache.tomcat.embed</groupId>
        <artifactId>tomcat-embed-core</artifactId>
        <version>9.0.52</version>
        <scope>compile</scope>
        <exclusions>
            <exclusion>
                <artifactId>tomcat-annotations-api</artifactId>
                <groupId>org.apache.tomcat</groupId>
            </exclusion>
        </exclusions>
    </dependency>
    <dependency>
        <groupId>org.apache.tomcat.embed</groupId>
        <artifactId>tomcat-embed-el</artifactId>
        <version>9.0.52</version>
        <scope>compile</scope>
    </dependency>
    <dependency>
        <groupId>org.apache.tomcat.embed</groupId>
        <artifactId>tomcat-embed-websocket</artifactId>
        <version>9.0.52</version>
        <scope>compile</scope>
        <exclusions>
            <exclusion>
                <artifactId>tomcat-annotations-api</artifactId>
                <groupId>org.apache.tomcat</groupId>
            </exclusion>
        </exclusions>
    </dependency>
</dependencies>

There is a core coordinate, tomcat-embed-core, which is called tomcatthe embedded core. This is what tomcatbrings functionality into our programs. At present, the first problem has been solved, and the root has been found. Who tomcatintroduced it into the program? Made spring-boot-starter-webin . spring-boot-starter-tomcatThe reason why you feel strange is that this thing is added to the program by default, so it feels amazing that there are webfunctions corresponding to the server without doing anything. Let's talk about the second question, how does this server work.


Embedded Tomcat operating principle

TomcatThe server is a piece of software, and it is a javasoftware developed in a language. tomcatIf you are familiar with it, you should know that tomcatthere are many files stored in the installation directory jar.


The following question arises. Since it is developed in a language, it must conform to the principle of program operation javawhen running . What does the program rely on? Objects, everything is an object, everything is an object. How about running it ? It is also an object.javajavatomcat


If it is an object, then Springthe container is used to manage the object. Can this object be Springmanaged by the container? If you remove the ?, any object can be handed over to Springthe container for management. That’s it. Now it works. The server actually runs in the container tomcatin the form of an object . SpringNo wonder we didn't install this tomcatbut it still works. After a day of trouble, this thing finally exists in the form of an object, which is stored in Springthe container and runs quietly. What exactly is it running? In fact, it is the embedded core mentioned above tomcat.

<dependencies>
    <dependency>
        <groupId>org.apache.tomcat.embed</groupId>
        <artifactId>tomcat-embed-core</artifactId>
        <version>9.0.52</version>
        <scope>compile</scope>
    </dependency>
</dependencies>

Since it is an object, if this object Springis removed from the container, will there be no webserver function? Yes, this webserver function can be removed by dependency exclusion.

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
        <exclusions>
            <exclusion>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-tomcat</artifactId>
            </exclusion>
        </exclusions>
    </dependency>
</dependencies>

The above web-starterhas done an operation, and the used exclusion mavendependency has been removed . Now, there is no such object in the container. Restart the program to observe that the program is running, but it is not a running service as before, but it is stopped directly. This is the reason.tomcatstarter


Replace Embedded Tomcat

Then according to the above operation, we think whether we can change the server? It is necessary. According to SpringBootthe working mechanism, what technology to use, and what dependencies to add. A built-in server SpringBootis provided : 3
1. tomcat(Default): apacheProduced, with many fans and wide applications, loaded with several heavier components
2. jetty: Lighter, with far lower load performance tomcat
3. undertow: Barely outperformed by load performancetomcat


Whichever you want to use, just add a coordinate OK. The premise is to tomcatexclude it, because tomcatit is loaded by default.

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
        <exclusions>
            <exclusion>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-tomcat</artifactId>
            </exclusion>
        </exclusions>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-jetty</artifactId>
    </dependency>
</dependencies>

Now that the server has been successfully replaced web, the core idea is to add the corresponding coordinates with whatever. If available starter, use it first starter.


Summarize

1. The embedded Tomcatserver is SpringBootone of the auxiliary functions
2. The working principle of the embedded server Tomcatis to Tomcatrun the server as an object and hand over the object to Springthe container for management
3. The idea of ​​changing the embedded server is to remove the existing server and add a new server


到这里第一章快速上手SpringBoot就结束了,这一章我们学习了两大块知识
1. 使用了4种方式制作了SpringBoot的入门程序,不管是哪一种,其实内部都是一模一样的
2. 学习了入门程序的工作流程,知道什么是parent,什么是starter,这两个东西是怎么配合工作的,以及我们的程序为什么启动起来是一个tomcat服务器等等

第一章到这里就结束了,再往下学习就要去基于会创建SpringBoot工程的基础上,研究SpringBoot工程的具体细节了。


JC-2.SpringBoot基础配置

入门案例做完了,下面就要研究SpringBoot的用法了。通过入门案例,各位小伙伴能够感知到一个信息,SpringBoot没有具体的功能,它是辅助加快Spring程序的开发效率的。我们发现,现在几乎不用做任何配置功能就有了,确实很好用。但是仔细想想,没有做配置意味着什么?意味着配置已经做好了,不用你自己写了。但是新的问题又来了,如果不想用已经写好的默认配置,该如何干预呢?这就是这一章咱们要研究的问题。


如果想修改默认的配置,这个信息应该写在什么位置呢?目前我们接触的入门案例中一共有3个文件,第一是pom.xml文件,设置项目的依赖,这个没什么好研究的,相关的高级内容咱们到原理篇再说,第二是引导类,这个是执行SpringBoot程序的入口,也不像是做功能配置的地方,其实还有一个信息,就是在resources目录下面有一个空白的文件,叫做application.properties。一看就是个配置文件,咱们这一章就来说说配置文件怎么写,能写什么,怎么覆盖SpringBoot的默认配置修改成自己的配置。


JC-2-1.属性配置

SpringBootThe default configuration can be modified through the configuration file application.properties, so let’s find a simple configuration to start with. The tomcatdefault port for current access is 8080very familiar, but it’s not easy to write. Let’s change it first, and get 80familiar with it through this operation SpringBootWhat does the configuration format look like.

image-20211123165428245


How should I write it? propertiesThe file writing specification of the format iskey=value

name=itheima

This format must not be subverted, so just write it tentatively, change the port, and write port. When you enter port, something magical happens, this thing has prompts, which is great.

image-20211123165719091
Press Enter according to the prompt, enter 80the port, and it's done.

server.port=80

Now you can run the program directly and test the effect.


We were surprised to find SpringBootthat this thing is ruthless. Where did you modify the port before? tomcatChange in the configuration file of the server, now? SpringBootChanging in a dedicated configuration file, does it mean that all future configurations can be written in this file? Yes, simplify the writing position of developer configuration and centralize management. Wonderful, mom no longer has to worry that I can't find the configuration file.


In fact, here we should get the following three information:
1. SpringBootThe program can application.propertiesconfigure attributes in the file
. 2. application.propertiesJust enter the attribute keyword to be configured in the file, and you can set it according to the prompt.
3. SpringBootConcentrate the configuration information in one file and write it. , whether you are server configuration or database configuration, they are all written together to escape the embarrassing situation of more than a dozen configuration file formats for a project


Summarize

SpringBootThe default configuration file isapplication.properties


After finishing the configuration of the port, strike while the iron is hot, and do a few more configurations. At present, some log information will be displayed when the project starts, so let’s change some settings here.


Close the running log chart (banner)

spring.main.banner-mode=off

Set the display level of the running log

logging.level.root=debug

You will find that it is so cool to do configuration like this now. How did you do configuration before? Different technologies have their own dedicated configuration files, and the file formats are not uniform. What about now? There is no need to run around looking for configuration files to write configurations, and the format is unified. This is the Great Qin Empire, unifying the six countries. SpringBootIt is more ruthless than Daqin, because the technology that will appear in the future has not yet appeared, but it has been confirmed now, and the configuration is written in this file.


We have now configured 3a piece of information, but there are new problems. Is this configuration written casually? Can it match anything? Is there a thing that shows all configurable items? In addition, what is this configuration related to? Will it be because I wrote something that I can write some configuration later? For example, if I have not written anything related to the database, can I configure the data? Come one by one, let's talk about the first question first, what can be configured.


Open SpringBootthe official website, find SpringBootthe official document, and open it to view the appendix Application Propertiesto get the corresponding configuration items. The URL is here.


The problem of what can be written is solved, let’s talk about the second question, what is this configuration item related to. pomComment out the import in , spring-boot-starter-weband then refresh the project, you will find that the configuration prompt disappears. It took a long time to set what technology to use to configure what configuration. It is also reasonable, otherwise the corresponding technology is not used, and the configuration is useless.


Warm reminder
that all middlewarestarterwill rely on the followingstarter, calledspring-boot-starter. Thisstarteris allthe relevant basic configurationis defined in itSpringBootwillexplain this in depth in the development and application chapter and the principle chapter.starterSpringBootstarter

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter</artifactId>
    <version>2.5.4</version>
    <scope>compile</scope>
</dependency>

Summarize

1. After SpringBootimporting the correspondence starter, provide the corresponding configuration properties
2. Write SpringBootthe configuration in the form of keyword +prompts


JC-2-2. Configuration file classification

Now it is possible to perform SpringBootrelevant configurations, but propertiesthe format configuration always feels uncomfortable to write, so it is expected that there is a configuration format that is easier to write for developers to use. Have it? Really, SpringBootin addition to supporting propertiesconfiguration files in two formats, it also supports configuration files in two other formats. The three configuration file formats are as follows:
propertiesFormat
ymlFormat
yamlFormat


When you see the brand new file format, you must think, now you have to learn a new grammar format. how to say? From the perspective of knowledge, you need to learn, but from the perspective of development, you don't need to learn. why? Because there are prompts SpringBootfor the configuration under Ideathe tool, just follow the prompts. The following are examples of the same attributes configured in three different file formats, let’s get to know them first.


application.properties(properties格式)

server.port=80

application.yml (yml format)

server:
  port: 81

application.yaml (yaml format)

server:
  port: 82

If you look carefully, you will find that ymlthe format and yamlformat are different except for the file name suffix. The format is exactly the same. This is the same as the file format, ymlbut yamlthe file suffix is ​​different, so it can be combined into one format. For these three formats, which one will be used more in the future? Remember, ymlthe format will basically be used in the future. All the knowledge in this course will be based on ymlthe format. In the future, there will be the most opportunities to use this format in the process of enterprise development, so you must focus on mastering it.


Summarize

SpringBootProvides 3two configuration file formats
1, properties(traditional format/default format)
2,yml(Mainstream format)
3.yaml


thinking

Now that we know that all three formats can be used for configuration, curious babies will have a new soul torture. If I write all three, who will have the final say among them? fight?


Profile Priority

In fact, if the three files coexist, whoever takes effect is the priority level of configuration file loading. First of all, although this kind of situation will rarely happen in the future, this knowledge can still be learned. We let the three configuration files write the same information, such as configuring the port, and then we make the port number of each file configuration different. Finally, after starting the program, look at the number of the starting port to know whose loading priority is higher. .


application.properties(properties格式)

server.port=80

application.yml (yml format)

server:
  port: 81

application.yaml (yaml format)

server:
  port: 82

After startup, it is found that the current startup port is 80, 80delete the corresponding file, and then start again, and now the port is changed again 81. Now we already know 3what the loading priority of each file is.


application.properties  >  application.yml  >  application.yaml

Although a knowledge conclusion has been obtained, when we actually develop it, we still need to see the final effect. That is to say, it is clear what the final effect you want, and the above conclusions can only help you analyze the reasons for the conclusions. It is enough to understand this knowledge, because it is really rare to write multiple configuration file formats at the same time in the future.


Finally, we modify the content of the configuration file


application.properties(properties格式)

server.port=80
spring.main.banner-mode=off

application.yml (yml format)

server:
  port: 81
logging: 
  level: 
    root: debug

application.yaml (yaml format)

server:
  port: 82

We found that not only the port has taken effect, 80but also the other two configurations have taken effect at the same time. It seems that the items in each configuration file will take effect, but if there are multiple configuration files with the same type of configuration, the file with higher priority will be given Override configuration in files with lower priority. If the configuration items are different, all configuration items will take effect.


Summarize

1. The loading priority between configuration files properties(highest) > yml> yaml(lowest)
2. The same configuration in different configuration files overrides each other according to the loading priority, and the different configurations in different configuration files are all reserved


teach you a trick

The solution to the disappearance of the automatic prompt function


In the process of making the program, some friends may have no prompts in the configuration file due to various reasons. This is really a headache, so let me tell you how to solve it if the automatic prompt function disappears.


First of all, we must clarify a core point, that is, the automatic prompt function is not SpringBootprovided by technology, but by Ideaprogramming under the tool, which is provided by this programming tool. After understanding this point, let's talk about why this phenomenon occurs. In fact, there are many reasons why the automatic prompt function disappears. If you want to solve this problem, you must know why it disappears. The general reasons are as follows 2:
1. IdeaI think the configuration file you are writing now is not a configuration file, so I refuse to give it to you Provide prompt function
2. IdeaIt is determined that you are a reasonable configuration file, but Ideathe corresponding prompt information cannot be loaded


Here we mainly solve the first phenomenon, and explain the second phenomenon in the principle chapter. The solution to the first phenomenon is as follows:


Step ①

Open the settings, 【Files】→【Project Structure…】

image-20211126160548690


Step ②

In the pop-up window, select [ Facets] on the left, and select Springthe corresponding module name under the path on the right, that is, the module whose automatic prompt function disappears

image-20211126160726589


image-20211126160844372


Step ③

Click Customize Spring Bootthe button, and you can see the configuration files corresponding to the current module. If there is no file format you want to call a configuration file, there is a chance that the prompt will not pop up

image-20211126160946448


image-20211126160954338


Step ④

OKChoose to add a configuration file, and then select the specific file to be used as a configuration file
image-20211126161145082


image-20211126161156324


It's done here, it's actually Ideaa small function of
image-20211126161301699


Summarize

Specify SpringBootthe configuration file
1, SettingProject StructureFacets
2, select the corresponding project/project
3, Customize Spring Boot
4, select the configuration file


JC-2-3.yaml file

SpringBootIn the future, the configuration will mainly use ymlthis file format at the end, and the correct format can be loaded in the form of a prompt when writing. However, this kind of document still has strict writing format requirements. Let's talk about the specific grammatical format.


YAML( YAML Ain't Markup Language), a data serialization format. It has the characteristics of easy reading, easy interaction with scripting language, data-centric, heavy data and light format. There are two common file extensions:
1. .ymlFormat (mainstream)
2. .yamlFormat


The specific grammatical format requirements are as follows:
1. Case-sensitive
2. Use multi-line descriptions for attribute hierarchical relationships,End each line with a colon
3. Use indentation to indicate the hierarchical relationship, align to the left of the same level, and only spaces are allowed ( Tabkeys are not allowed)
4. Add spaces in front of attribute values ​​(a colon +space is used as a separator between attribute names and attribute values)
5 #. note


Don't memorize the above rules by rote, but adapt slowly according to the writing habits, Ideaand because of the reminder function, just adapt to the writing format slowly. One of the core rules to remember is that the data should be preceded by a space and a colon to separate it .


The common data writing formats are listed below, familiarize yourself with

boolean: TRUE  						 #TRUE,true,True,FALSE,false,False均可
float: 3.14    						 #6.8523015e+5  #支持科学计数法
int: 123       						 #0b1010_0111_0100_1010_1110    #支持二进制、八进制、十六进制
null: ~        						 #使用~表示null
string: HelloWorld      			 #字符串可以直接书写
string2: "Hello World"  			 #可以使用双引号包裹特殊字符
date: 2018-02-17        			 #日期必须使用yyyy-MM-dd格式
datetime: 2018-02-17T15:02:31+08:00  #时间和日期之间使用T连接,最后使用+代表时区

In addition, yamlthe format can also represent an array, using a minus sign as the data start symbol below the writing position of the attribute name, writing one data per line, and separating the minus sign and the data with a space.

subject:
	- Java
	- 前端
	- 大数据
enterprise:
	name: itcast
    age: 16
    subject:
    	- Java
        - 前端
        - 大数据
likes: [王者荣耀, 刺激战场]		 								#数组书写缩略格式
users:							 								#对象数组格式一
  - name: Tom
   	age: 4
  - name: Jerry
    age: 5
users:							 								#对象数组格式二
  -  
    name: Tom
    age: 4
  -   
    name: Jerry
    age: 5			    
users2: [ {
    
     name: Tom , age: 4 } , {
    
     name: Jerry , age: 5 } ]	#对象数组缩略格式

Summarize

1. yamlGrammatical rules
1.1, case-sensitive
1.2, use multi-line descriptions for attribute hierarchical relationships, and end each line with a colon
1.3, use indentation to indicate hierarchical relationships, align to the left of the same level, and only spaces are allowed (keys are not allowed Tab)
1.4. Add a space in front of the attribute value (a colon space is used as a separator between the attribute name and the attribute value +)
1.5. #The sign indicates a note
2. Note that there is a space between the attribute name and the data after the colonspace
3. Literal value, object data format, array data format


think

Now that we know that there are strict data format requirements, and the files yamlcan be written correctly , then these files are actually defining some data after writing. yamlWho is this data for? Most of them are SpringBootused within the framework, but if we want to configure some data for our own use, can we use it? The answer is yes, so how to read yamlthe data in the file? Let's talk about it in the next section.


JC-2-4.yaml data reading

For yamlthe data in the file, in fact, you can imagine that this is a small database, which contains several data, and each data has an independent name. If you want to read the data in it, it must be supported. The following Here is 3how to read data.


read single data

yamlA single data saved in , you can use Springthe annotation in @Valueto read a single data, attribute name reference method: ${first-level attribute name.second-level attribute name...}

image-20211126180433356


Remember @Valueto write the annotation above a specified Springcontrolled beanproperty name when using annotations, so that the beancorresponding single data can be read when initialization is performed.


Summarize

1. Use @Valuecooperation SpELto read a single data
2. If there are multiple levels in the data, just write the level names one by one


read all data

Reading single data can solve the problem of reading data, but if the amount of defined data is too large, it will definitely be exhausting to write one by one. An SpringBootobject is provided that can encapsulate all the data into this object. This The object is called Environment, and all yamlthe data can be encapsulated into this object by using the automatic assembly annotation

image-20211126180738569


The data is encapsulated into Environmentthe object. When obtaining the attribute, Environmentit is performed through the interface operation. The specific method is getProperties( String), and the parameter can be filled with the attribute name


Summarize

1. Use Environmentobjects to encapsulate all configuration information
2. Use @Autowiredautomatic assembly data into Environmentobjects


read object data

Reading and writing a single data is cumbersome, and reading all data is too packaged, and each time you take the data one by one getProperties(), it is not very comfortable to use. Since Javait is an object-oriented language, in many cases, we will encapsulate a set of data into an object. SpringBootIt also provides operations that can yamlencapsulate a set of object data into an objectJava


First define an object, and bring the object into Springthe scope of management and control, that is, define it as one bean, and then use annotations @ConfigurationPropertiesto specify which group yamlof configuration information the object loads.

image-20211126181126382


This @ConfigurationPropertiesmust tell him what the prefix of the loaded data is, so that all attributes under the specified prefix are encapsulated into this object. Remember that the data attribute name must correspond to the variable name of the object one by one, otherwise it cannot be encapsulated. In fact, if you want to define a set of data for your own use in the future, you can first write an object, then define the properties, and then write according to this format in the configuration.

image-20211126181423432


Reminder
Careful friends will find a problem. When this kind of custom datayamlis written in the file, there is no pop-up prompt. Let’s go to the principle chapter to reveal how to pop up the prompt.


Summary
1. Use @ConfigurationPropertiesannotations to bind configuration information to the encapsulation class
2. The encapsulation class needs to be defined as Springmanaged bean, otherwise property injection cannot be performed


Data references in yaml files

If you are writing yamldata, the following phenomenon often occurs, for example, many files have the same directory prefix

center:
	dataDir: /usr/local/fire/data
    tmpDir: /usr/local/fire/tmp
    logDir: /usr/local/fire/log
    msgDir: /usr/local/fire/msgDir

or

center:
	dataDir: D:/usr/local/fire/data
    tmpDir: D:/usr/local/fire/tmp
    logDir: D:/usr/local/fire/log
    msgDir: D:/usr/local/fire/msgDir

At this time, you can use the reference format to define the data. In fact, you just create a variable name and then reference the variable. The format is as follows:

baseDir: /usr/local/fire
center:
    dataDir: ${
     
     baseDir}/data
    tmpDir: ${
     
     baseDir}/tmp
    logDir: ${
     
     baseDir}/log
    msgDir: ${
     
     baseDir}/msgDir

There is another note. When writing a string, if you need to use escape characters, you need to wrap the data string in double quotes

lesson: "Spring\tboot\nlesson"

Summarize

1. In the configuration file, you can use ${属性名}the method to quote the attribute value
2. If there are special characters in the attribute, you can use double quotes to wrap them as characters for parsing


At this point, yamlthe basic use of relevant documents will come to an end, and we will continue to study more in-depth content in the practical chapter.


JC-3. SSMP integration based on SpringBoot

The highlight is here. SpringBootThe reason why it is easy to use is that it can easily and quickly integrate other technologies. In this part, let’s talk about the integration methods of some technologies. Through the study of this chapter, you can feel how cool it is SpringBoot. In this chapter, we learn the integration methods of the following technologies
1, integration JUnit
2, integration MyBatis
3, integration MyBatis-Plus
4, integrationDruid


After the above technologies are integrated, let's make a small case, which can be regarded as useful for learning. There are many technologies involved, so let's use them comprehensively.


JC-3-1. Integrate JUnit

SpringBootThe positioning of technology is used to simplify development, and more specifically, to simplify Springthe development of programs. So when integrating any technology, if you want to feel the effect of simplification intuitively, you must first know SpringBoothow the corresponding integration is done when using non-technical, and then see SpringBoothow the based integration is done, in order to compare and simplify Where is it.


Let's first look at how integration can be done without SpringBoottechnologySpringJUnit

// 加载spring整合junit专用的类运行器
@RunWith(SpringJUnit4ClassRunner.class)
// 指定对应的配置信息
@ContextConfiguration(classes = SpringConfig.class)
public class AccountServiceTestCase {
    
    
    // 注入你要测试的对象
    @Autowired
    private AccountService accountService;
    @Test
    public void testGetById(){
    
    
        // 执行要测试的对象对应的方法
        System.out.println(accountService.findById(2));
    }
}

The core code is the first two annotations. The first annotation @RunWithis to set up Springa dedicated test class runner. Simply put, Springthe program execution program has its own set of independent ways of running the program. The JUnitprovided class running mode cannot be used. Specify it, but the format is fixed. Think about it, specify the same thing every time. This thing is written without technical content. The second annotation @ContextConfigurationis used to set Springthe core configuration file or configuration class. Simply put, it is Springloaded For the environment, you need to tell Springwhere the specific environment configuration is written. Although the files loaded each time may be different, think about it carefully. If the file name is fixed, this seems to be a fixed format. Since it may be a fixed format, it is possible to write the same thing every time, which is also a content writing without technical content


SpringBoot seizes the above two non-technical contents to write and simplify development. If you can take the default value, you can take the default value, and if you can’t write it, don’t write it. The specific format is as follows

@SpringBootTest
class Springboot04JunitApplicationTests {
    
    
    // 注入你要测试的对象
    @Autowired
    private BookDao bookDao;
    @Test
    void contextLoads() {
    
    
        // 执行要测试的对象对应的方法
        bookDao.save();
        System.out.println("two...");
    }
}

Let's see what the simplification has become this time. One annotation is all it takes, and there are no parameters yet. Let's experience the SpringBootadvantages of integrating other technologies, just two words - simplification . Replaced the previous two annotations with one annotation @SpringBootTest. As for what's going on inside? Same as before, but with default values.


At this time, someone asked, which configuration class or configuration file did you load? It is the bootstrap class we used to start the program earlier. If you want to manually specify the boot class, there are two ways. The first way is to use the form of attributes, @SpringBootTestadding classesattributes to the annotation to specify the configuration class

@SpringBootTest(classes = Springboot04JunitApplication.class)
class Springboot04JunitApplicationTests {
    
    
    // 注入你要测试的对象
    @Autowired
    private BookDao bookDao;
    @Test
    void contextLoads() {
    
    
        // 执行要测试的对象对应的方法
        bookDao.save();
        System.out.println("two...");
    }
}

The second method returns to the original configuration method, still using @ContextConfigurationannotations, the effect is the same

@SpringBootTest
@ContextConfiguration(classes = Springboot04JunitApplication.class)
class Springboot04JunitApplicationTests {
    
    
    // 注入你要测试的对象
    @Autowired
    private BookDao bookDao;
    @Test
    void contextLoads() {
    
    
        // 执行要测试的对象对应的方法
        bookDao.save();
        System.out.println("two...");
    }
}

A warm reminder
to useSpringBootthe integrationJUnitto ensure that thetestcorresponding ones are importedstarter. Since this item is imported by default when the project is initialized, it is not mentioned here. In fact, it is the same as the previous learning content,starterjust use any technology to import the corresponding ones.


Summarize

1. Import the test corresponding to starter
2. The test class uses @SpringBootTestmodification
3. Use the form of automatic assembly to add the object to be tested
4. If the test class exists in the package or sub-package where the boot class is located, there is no need to specify the boot class
5. If the test class does not exist In the package or subpackage where the boot class is located, classesthe boot class needs to be specified through attributes


JC-3-2. Integrate MyBatis

After the integration JUnit, let's talk about integration MyBatis. This technology is used by most companies and must be mastered. If you are not familiar with Springthe integration MyBatis, review it carefully. The following lists all the contents of the original integration, taking the configuration class as an example.


1. Import coordinates. MyBatis coordinates are indispensable. Spring integrates MyBatis and has its own dedicated coordinates. In addition, Spring’s jdbc coordinates for database operations are necessary, and the rest are mysql driver coordinates. In this example, the Druid data source is used. This it's okay not to

<dependencies>
    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>druid</artifactId>
        <version>1.1.16</version>
    </dependency>
    <dependency>
        <groupId>org.mybatis</groupId>
        <artifactId>mybatis</artifactId>
        <version>3.5.6</version>
    </dependency>
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>5.1.47</version>
    </dependency>
    <!--1.导入mybatis与spring整合的jar包-->
    <dependency>
        <groupId>org.mybatis</groupId>
        <artifactId>mybatis-spring</artifactId>
        <version>1.3.0</version>
    </dependency>
    <!--导入spring操作数据库必选的包-->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-jdbc</artifactId>
        <version>5.2.10.RELEASE</version>
    </dependency>
</dependencies>

2. Spring core configuration

@Configuration
@ComponentScan("com.itheima")
@PropertySource("jdbc.properties")
public class SpringConfig {
    
    
}

3. The bean that MyBatis will hand over to Spring to take over

// 定义mybatis专用的配置类
@Configuration
public class MyBatisConfig {
    
    
	// 定义创建SqlSessionFactory对应的bean
    @Bean
    public SqlSessionFactoryBean sqlSessionFactory(DataSource dataSource){
    
    
        // SqlSessionFactoryBean是由mybatis-spring包提供的,专用于整合用的对象
        SqlSessionFactoryBean sfb = new SqlSessionFactoryBean();
        // 设置数据源替代原始配置中的environments的配置
        sfb.setDataSource(dataSource);
        // 设置类型别名替代原始配置中的typeAliases的配置
        sfb.setTypeAliasesPackage("com.itheima.domain");
        return sfb;
    }
	// 定义加载所有的映射配置
    @Bean
    public MapperScannerConfigurer mapperScannerConfigurer(){
    
    
        MapperScannerConfigurer msc = new MapperScannerConfigurer();
        msc.setBasePackage("com.itheima.dao");
        return msc;
    }
}

4. The bean corresponding to the data source, the Druid data source is used here

@Configuration
public class JdbcConfig {
    
    
    @Value("${jdbc.driver}")
    private String driver;
    @Value("${jdbc.url}")
    private String url;
    @Value("${jdbc.username}")
    private String userName;
    @Value("${jdbc.password}")
    private String password;

    @Bean("dataSource")
    public DataSource dataSource(){
    
    
        DruidDataSource ds = new DruidDataSource();
        ds.setDriverClassName(driver);
        ds.setUrl(url);
        ds.setUsername(userName);
        ds.setPassword(password);
        return ds;
    }
}

5. Database connection information (properties format)

jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/spring_db?useSSL=false
jdbc.username=root
jdbc.password=root

The above format is basically the simplest format, and there are quite a lot of things to write. Let's take a look at SpringBoothe t integration MyBaitsformat


Step ①

create module

image-20211129092156020


Step ②

Check the technology to be used, MyBatis, because you need to operate the database, you also need to check the corresponding database
image-20211129092210993


Or manually import the startercoordinates of the corresponding technology and the corresponding database

<dependencies>
    <!--1.导入对应的starter-->
    <dependency>
        <groupId>org.mybatis.spring.boot</groupId>
        <artifactId>mybatis-spring-boot-starter</artifactId>
        <version>2.2.0</version>
    </dependency>

    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <scope>runtime</scope>
    </dependency>
</dependencies>

Step ③

Configure the relevant information of the data source. Without this information, you don’t know which database you are connected to.

# 2.配置相关信息
spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/ssm_db
    username: root
    password: root

It's over, that's all, it's over. Some people are wondering, is this the end? Yes, this is the end, SpringBootsimplifying all possible common configurations in the configuration. Write a MyBatisprogram that needs to run Dao(or Mapper) and it can run


Entity class

public class Book {
    
    
    private Integer id;
    private String type;
    private String name;
    private String description;
}

Mapping interface (Dao)

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

test class

@SpringBootTest
class Springboot05MybatisApplicationTests {
    
    
    @Autowired
    private BookDao bookDao;
    @Test
    void contextLoads() {
    
    
        System.out.println(bookDao.getById(1));
    }
}

Perfect, development has become so simple since then. Then experience SpringBoothow to integrate third-party technology, isn't it excellent? The specific internal principles will be explained in the principle chapter


Note : The currently usedSpringBootversion isused by the driver2.5.4in the corresponding coordinate setting. There will be a small problemwhen using, that is,the time zone is required to be configured afterthe driver is upgradedThe solution is very simple,just add the corresponding settings onMysql8xSpringBoot2.4.3BUGMySQL8url

# 2.配置相关信息
spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/ssm_db?serverTimezone=UTC
    username: root
    password: root

The global standard time is set here UTC, and you can also understand it as British time. China is in the East Eighth District, and hours need to be added to this basis 8so that it can correspond to the time in China. You can also modify the configuration to Asia/Shanghai, the same can solve this problem.

# 2.配置相关信息
spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/ssm_db?serverTimezone=Asia/Shanghai
    username: root
    password: root

If you don't want to set this thing every time, you can also modify mysqlthe configuration file in mysql.ini, and mysqldadding it to the item default-time-zone=+8:00can also solve this problem. In fact, there are many ways and methods, so here are so many.


In addition, a prompt will be given when running the program, saying that the database driver is outdated, just modify the configuration according to the prompt, discard it com.mysql.jdbc.Driver, and use com.mysql.cj.jdbc.Driver instead . In the previous example, the driver has been replaced, let me explain here.

Loading class `com.mysql.jdbc.Driver'. This is deprecated. The new driver class is `com.mysql.cj.jdbc.Driver'. The driver is automatically registered via the SPI and manual loading of the driver class is generally unnecessary.

Summarize

1. The integration operation needs to check MyBatisthe technology, that is, import MyBatisthe corresponding starter
2. The database connection related information is converted into configuration
3. The database SQLmapping needs to be added @Mapperto be recognized by the container
4. MySQL 8.XThe driver is mandatory to set the time zone
4.1, modify url, add serverTimezonesettings
4.2, modify MySQLDatabase configuration
5. The driver class is outdated, remind you to replace it withcom.mysql.cj.jdbc.Driver


JC-3-3. Integrate MyBatis-Plus

After completing the integration of the two technologies, everyone should learn to summarize, which ones are the core of our integration? To sum up, just two sentences
1. Import starterthe coordinates of the corresponding technology
2. Configure according to the requirements of the corresponding technology


Although it seems a bit hypocritical, it is indeed the reason. Let's strike while the iron is hot and change another technique to see if it is the above two steps.


Next, MyBatiswe will upgrade and integrate MyBaitsPlus(referred to as MP) the technology developed by the Chinese in line with the development habits of the Chinese. Whoever uses it will know. Come on, let's do the integration together


Step ①

Import the correspondingstarter

<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-boot-starter</artifactId>
    <version>3.4.3</version>
</dependency>

Regarding this coordinate, here is a point to explain. We have seen it before starter, spring-boot-starter-???that is to say, it is all in the following format

Spring-boot-start-***

However, MyBatisthe MyBatisPluswriting of the names of these two coordinates is quite special, with the third-party technical name first bootand starterlast. Here is a brief mention of the naming convention, which will be explained in detail later in the principle chapter

belonging to starter Naming rules example
Officially provided spring-boot-starter-technical name spring-boot-starter-web
spring-boot-starter-test
provided by a third party Third-party technology name-spring-boot-starter mybatis-spring-boot-starter
druid-spring-boot-starter
provided by a third party Third-party technology name-boot-starter (the name of the third-party technology is too long, simplify the naming) mybatis-plus-boot-starter

Warm reminder,
some friends want to find this name by checking the box when creating a project, don’t look it up, there is no. So far,SpringBootthe official website has not included this coordinate, and weIdearead theSpringBootofficial websiteSpring Initializr, so there is no such coordinates. If you switch to the creation project of Alibaba Cloud,urlyou can find the corresponding coordinates.


Step ②

Configure data source related information

# 2.配置相关信息
spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/ssm_db
    username: root
    password: root

No more, that's all, the rest is to write MyBaitsPlusthe program


Mapping interface (Dao)

@Mapper
public interface BookDao extends BaseMapper<Book> {
     
     
}

The core is that Daothe interface inherits an BaseMapperinterface. This interface helps developers to pre-order several commonly used APIinterfaces, which simplifies APIthe development of common interfaces.

image-20211129100313919
Now you can write a test class for testing, which is omitted here.


Kind tips

At present, the table name definition rule of the database is tbl_the module name. In order to correspond to the entity class, a configuration is required. Friends with relevant knowledge can go to the MyBatisPluscourse to learn, and only the solution is given here. Configuration application.ymlfile, just add the following configuration to set the common prefix name of all table names

mybatis-plus:
  global-config:
    db-config:
      table-prefix: tbl_		#设置所有表的通用前缀名称为tbl_

Summarize

1. Manually add MyBatis-Plusthe corresponding starter
2. The data layer interface uses BaseMappersimplified development
3. When the third-party technology to be used cannot be determined by checking, you need to manually add coordinates


JC-3-4. Integrate Druid

After using the SpringBootintegrated 3technology, I found that the routines are basically the same, import the corresponding ones starter, and then configure them. Friends need to strengthen this set of ideas all the time. Next, we will integrate another technology to continue to strengthen this idea.


In the previous integration MyBatisand MyBatisPlusintegration, the data source objects used are SpringBootthe default data source objects. Next, let’s control it manually and specify a data source object by ourselves Druid.


When no data source is specified, our configuration is as follows:

# 2.配置相关信息
spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/ssm_db?serverTimezone=Asia/Shanghai
    username: root
    password: root

Although the data source is not specified at this time, according to SpringBootthe virtues of the company, it must have helped us choose a data source object that it thinks is the best, and this is it HiKari. You can view the corresponding figure through the startup log.

2021-11-29 09:39:15.202  INFO 12260 --- [           main] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Starting...
2021-11-29 09:39:15.208  WARN 12260 --- [           main] com.zaxxer.hikari.util.DriverDataSource  : Registered driver with driverClassName=com.mysql.jdbc.Driver was not found, trying direct instantiation.
2021-11-29 09:39:15.551  INFO 12260 --- [           main] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Start completed.

Each row in the above information has HiKaria figure. If you need to change the data source, it only takes two steps.
1. Import the corresponding technical coordinates
2. Configure to use the specified data source type


Next, switch the data source object


Step ①

Import the corresponding coordinates (note that they are coordinates, not here starter)

<dependencies>
    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>druid</artifactId>
        <version>1.1.16</version>
    </dependency>
</dependencies>

Step ②

Modify the configuration, there is a property in the data source configuration typededicated to specifying the data source type

spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/ssm_db?serverTimezone=UTC
    username: root
    password: root
    type: com.alibaba.druid.pool.DruidDataSource

这里其实要提出一个问题的,目前的数据源配置格式是一个通用格式,不管你换什么数据源都可以用这种形式进行配置。但是新的问题又来了,如果对数据源进行个性化的配置,例如配置数据源对应的连接数量,这个时候就有新的问题了。每个数据源技术对应的配置名称都一样吗?肯定不是啊,各个厂商不可能提前商量好都写一样的名字啊,怎么办?就要使用专用的配置格式了。这个时候上面这种通用格式就不能使用了,怎么办?还能怎么办?按照SpringBoot整合其他技术的通用规则来套啊,导入对应的starter,进行相应的配置即可。


步骤①

导入对应的starter

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

步骤②

修改配置

spring:
  datasource:
    druid:
      driver-class-name: com.mysql.cj.jdbc.Driver
      url: jdbc:mysql://localhost:3306/ssm_db?serverTimezone=UTC
      username: root
      password: root

注意观察,配置项中,在datasource下面并不是直接配置url这些属性的,而是先配置了一个druid节点,然后再配置的url这些东西。言外之意,url这个属性是druid下面的属性,那你能想到什么?除了这4个常规配置外,还有druid专用的其他配置。通过提示功能可以打开druid相关的配置查阅

image-20211129112610729

druid相关的配置超过200条以上,这就告诉你,如果想做druid相关的配置,使用这种格式就可以了,这里就不展开描述了,太多了。


这是我们做的第4个技术的整合方案,还是那两句话:导入对应starter,使用对应配置。没了,SpringBoot整合其他技术就这么简单粗暴。


总结

1. 整合Druid需要导入Druid对应的starter
2. 根据Druid提供的配置方式进行配置
3. 整合第三方技术通用方式
3.1、导入对应的starter
3.2、根据提供的配置格式,配置非默认值对应的配置项


JC-3-5.SSMP整合综合案例

SpringBoot能够整合的技术太多太多了,对于初学者来说慢慢来,一点点掌握。前面咱们做了4个整合了,下面就通过一个稍微综合一点的案例,将所有知识贯穿起来,同时做一个小功能,体会一下。不过有言在先,这个案例制作的时候,你可能会有这种感觉,说好的SpringBoot整合其他技术的案例,为什么感觉SpringBoot整合其他技术的身影不多呢?因为这东西书写太简单了,简单到瞬间写完,大量的时间做的不是这些整合工作。


先看一下这个案例的最终效果


主页面

image-20211129113447844


添加

image-20211129113522459


删除

image-20211129113550829


修改

image-20211129113610966


分页

image-20211129113628969


条件查询

image-20211129113650369


整体案例中需要采用的技术如下,先了解一下,做到哪一个说哪一个
1. 实体类开发————使用Lombok快速制作实体类
2. Dao开发————整合MyBatisPlus,制作数据层测试
3. Service开发————基于MyBatisPlus进行增量开发,制作业务层测试类
4. Controller开发————基于Restful开发,使用PostMan测试接口功能
5. Controller开发————前后端开发协议制作
6. 页面开发————基于VUE+ElementUI制作,前后端联调,页面数据处理,页面消息处理
6.1、列表
6.2、新增
6.3、修改
6.4、删除
6.5、分页
6.6、查询
7. 项目异常处理
8. 按条件查询————页面功能调整、Controller修正功能、Service修正功能


可以看的出来,东西还是很多的,希望通过这个案例,各位小伙伴能够完成基础开发的技能训练。整体开发过程采用做一层测一层的形式进行,过程完整,战线较长,希望各位能跟紧进度,完成这个小案例的制作。


0.模块创建

对于这个案例如果按照企业开发的形式进行应该制作后台微服务,前后端分离的开发。

image-20211129114306062


我知道这个对初学的小伙伴要求太高了,咱们简化一下。后台做单体服务器,前端不使用前后端分离的制作了。

image-20211129114328967

一个服务器即充当后台服务调用,又负责前端页面展示,降低学习的门槛。


下面我们创建一个新的模块,加载要使用的技术对应的starter,修改配置文件格式为yml格式,并把web访问端口先设置成80


pom.xml

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

application.yml

server:
  port: 80

1.实体类开发

本案例对应的模块表结构如下:

-- ----------------------------
-- Table structure for tbl_book
-- ----------------------------
DROP TABLE IF EXISTS `tbl_book`;
CREATE TABLE `tbl_book`  (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `type` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  `name` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  `description` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 51 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;

-- ----------------------------
-- Records of tbl_book
-- ----------------------------
INSERT INTO `tbl_book` VALUES (1, '计算机理论', 'Spring实战 第5版', 'Spring入门经典教程,深入理解Spring原理技术内幕');
INSERT INTO `tbl_book` VALUES (2, '计算机理论', 'Spring 5核心原理与30个类手写实战', '十年沉淀之作,手写Spring精华思想');
INSERT INTO `tbl_book` VALUES (3, '计算机理论', 'Spring 5 设计模式', '深入Spring源码剖析Spring源码中蕴含的10大设计模式');
INSERT INTO `tbl_book` VALUES (4, '计算机理论', 'Spring MVC+MyBatis开发从入门到项目实战', '全方位解析面向Web应用的轻量级框架,带你成为Spring MVC开发高手');
INSERT INTO `tbl_book` VALUES (5, '计算机理论', '轻量级Java Web企业应用实战', '源码级剖析Spring框架,适合已掌握Java基础的读者');
INSERT INTO `tbl_book` VALUES (6, '计算机理论', 'Java核心技术 卷I 基础知识(原书第11版)', 'Core Java 第11版,Jolt大奖获奖作品,针对Java SE9、10、11全面更新');
INSERT INTO `tbl_book` VALUES (7, '计算机理论', '深入理解Java虚拟机', '5个维度全面剖析JVM,大厂面试知识点全覆盖');
INSERT INTO `tbl_book` VALUES (8, '计算机理论', 'Java编程思想(第4版)', 'Java学习必读经典,殿堂级著作!赢得了全球程序员的广泛赞誉');
INSERT INTO `tbl_book` VALUES (9, '计算机理论', '零基础学Java(全彩版)', '零基础自学编程的入门图书,由浅入深,详解Java语言的编程思想和核心技术');
INSERT INTO `tbl_book` VALUES (10, '市场营销', '直播就该这么做:主播高效沟通实战指南', '李子柒、李佳琦、薇娅成长为网红的秘密都在书中');
INSERT INTO `tbl_book` VALUES (11, '市场营销', '直播销讲实战一本通', '和秋叶一起学系列网络营销书籍');
INSERT INTO `tbl_book` VALUES (12, '市场营销', '直播带货:淘宝、天猫直播从新手到高手', '一本教你如何玩转直播的书,10堂课轻松实现带货月入3W+');

根据上述表结构,制作对应的实体类


实体类

public class Book {
    
    
    private Integer id;
    private String type;
    private String name;
    private String description;
}

实体类的开发可以自动通过工具手工生成get/set方法,然后覆盖toString()方法,方便调试,等等。不过这一套操作书写很繁琐,有对应的工具可以帮助我们简化开发,介绍一个小工具,lombok


Lombok,一个Java类库,提供了一组注解,简化POJO实体类开发,SpringBoot目前默认集成了lombok技术,并提供了对应的版本控制,所以只需要提供对应的坐标即可,在pom.xml中添加lombok的坐标。

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

使用lombok可以通过一个注解@Data完成一个实体类对应的gettersettertoStringequalshashCode等操作的快速添加

import lombok.Data;
@Data
public class Book {
    
    
    private Integer id;
    private String type;
    private String name;
    private String description;
}

到这里实体类就做好了,是不是比不使用lombok简化好多,这种工具在Java开发中还有N多,后面遇到了能用的实用开发技术时,在不增加各位小伙伴大量的学习时间的情况下,尽量多给大家介绍一些。


总结

*1. 实体类制作
2. 使用lombok简化开发
2.1、导入lombok无需指定版本,由SpringBoot提供版本
2.2、@Data注解


2.数据层开发——基础CRUD

数据层开发本次使用MyBatisPlus技术,数据源使用前面学习的Druid,学都学了都用上。


步骤①

导入MyBatisPlusDruid对应的starter,当然mysql的驱动不能少

<dependencies>
    <dependency>
        <groupId>com.baomidou</groupId>
        <artifactId>mybatis-plus-boot-starter</artifactId>
        <version>3.4.3</version>
    </dependency>
    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>druid-spring-boot-starter</artifactId>
        <version>1.2.6</version>
    </dependency>
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <scope>runtime</scope>
    </dependency>
</dependencies>

步骤②

配置数据库连接相关的数据源配置

server:
  port: 80

spring:
  datasource:
    druid:
      driver-class-name: com.mysql.cj.jdbc.Driver
      url: jdbc:mysql://localhost:3306/ssm_db?serverTimezone=UTC
      username: root
      password: root

步骤③

使用MyBatisPlus的标准通用接口BaseMapper加速开发,别忘了@Mapper和泛型的指定

@Mapper
public interface BookDao extends BaseMapper<Book> {
    
    
}

步骤④

制作测试类测试结果,这个测试类制作是个好习惯,不过在企业开发中往往都为加速开发跳过此步,且行且珍惜吧

package com.itheima.dao;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.itheima.domain.Book;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

@SpringBootTest
public class BookDaoTestCase {
    
    

    @Autowired
    private BookDao bookDao;

    @Test
    void testGetById(){
    
    
        System.out.println(bookDao.selectById(1));
    }

    @Test
    void testSave(){
    
    
        Book book = new Book();
        book.setType("测试数据123");
        book.setName("测试数据123");
        book.setDescription("测试数据123");
        bookDao.insert(book);
    }

    @Test
    void testUpdate(){
    
    
        Book book = new Book();
        book.setId(17);
        book.setType("测试数据abcdefg");
        book.setName("测试数据123");
        book.setDescription("测试数据123");
        bookDao.updateById(book);
    }

    @Test
    void testDelete(){
    
    
        bookDao.deleteById(16);
    }

    @Test
    void testGetAll(){
    
    
        bookDao.selectList(null);
    }
}

温馨提示

MyBatisPlus技术默认的主键生成策略为雪花算法,生成的主键ID长度较大,和目前的数据库设定规则不相符,需要配置一下使MyBatisPlus使用数据库的主键生成策略,方式嘛还是老一套,做配置。在application.yml中添加对应配置即可,具体如下

server:
  port: 80

spring:
  datasource:
    druid:
      driver-class-name: com.mysql.cj.jdbc.Driver
      url: jdbc:mysql://localhost:3306/ssm_db?serverTimezone=UTC
      username: root
      password: root

mybatis-plus:
  global-config:
    db-config:
      table-prefix: tbl_		#设置表名通用前缀
      id-type: auto				#设置主键id字段的生成策略为参照数据库设定的策略,当前数据库设置id生成策略为自增

查看MyBatisPlus运行日志

在进行数据层测试的时候,因为基础的CRUD操作均由MyBatisPlus给我们提供了,所以就出现了一个局面,开发者不需要书写SQL语句了,这样程序运行的时候总有一种感觉,一切的一切都是黑盒的,作为开发者我们啥也不知道就完了。如果程序正常运行还好,如果报错了,这个时候就很崩溃,你甚至都不知道从何下手,因为传递参数、封装SQL语句这些操作完全不是你开发出来的,所以查看执行期运行的SQL语句就成为当务之急。


SpringBoot整合MyBatisPlus的时候充分考虑到了这点,通过配置的形式就可以查阅执行期SQL语句,配置如下

mybatis-plus:
  global-config:
    db-config:
      table-prefix: tbl_
      id-type: auto
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

再来看运行结果,此时就显示了运行期执行SQL的情况。

Creating a new SqlSession
SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@2c9a6717] was not registered for synchronization because synchronization is not active
JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@6ca30b8a] will not be managed by Spring
==>  Preparing: SELECT id,type,name,description FROM tbl_book
==> Parameters: 
<==    Columns: id, type, name, description
<==        Row: 1, 计算机理论, Spring实战 第5版, Spring入门经典教程,深入理解Spring原理技术内幕
<==        Row: 2, 计算机理论, Spring 5核心原理与30个类手写实战, 十年沉淀之作,手写Spring精华思想
<==        Row: 3, 计算机理论, Spring 5 设计模式, 深入Spring源码剖析Spring源码中蕴含的10大设计模式
<==        Row: 4, 计算机理论, Spring MVC+MyBatis开发从入门到项目实战, 全方位解析面向Web应用的轻量级框架,带你成为Spring MVC开发高手
<==        Row: 5, 计算机理论, 轻量级Java Web企业应用实战, 源码级剖析Spring框架,适合已掌握Java基础的读者
<==        Row: 6, 计算机理论, Java核心技术 卷I 基础知识(原书第11版), Core Java 第11版,Jolt大奖获奖作品,针对Java SE9、10、11全面更新
<==        Row: 7, 计算机理论, 深入理解Java虚拟机, 5个维度全面剖析JVM,大厂面试知识点全覆盖
<==        Row: 8, 计算机理论, Java编程思想(第4版), Java学习必读经典,殿堂级著作!赢得了全球程序员的广泛赞誉
<==        Row: 9, 计算机理论, 零基础学Java(全彩版), 零基础自学编程的入门图书,由浅入深,详解Java语言的编程思想和核心技术
<==        Row: 10, 市场营销, 直播就该这么做:主播高效沟通实战指南, 李子柒、李佳琦、薇娅成长为网红的秘密都在书中
<==        Row: 11, 市场营销, 直播销讲实战一本通, 和秋叶一起学系列网络营销书籍
<==        Row: 12, 市场营销, 直播带货:淘宝、天猫直播从新手到高手, 一本教你如何玩转直播的书,10堂课轻松实现带货月入3W+
<==        Row: 13, 测试类型, 测试数据, 测试描述数据
<==        Row: 14, 测试数据update, 测试数据update, 测试数据update
<==        Row: 15, -----------------, 测试数据123, 测试数据123
<==      Total: 15

其中清晰的标注了当前执行的SQL语句是什么,携带了什么参数,对应的执行结果是什么,所有信息应有尽有。


此处设置的是日志的显示形式,当前配置的是控制台输出,当然还可以由更多的选择,根据需求切换即可

image-20211129143207295


总结

1. 手工导入starter坐标(2个),mysql驱动(1个)
2. 配置数据源与MyBatisPlus对应的配置
3. 开发Dao接口(继承BaseMapper
4. 制作测试类测试Dao功能是否有效
5. 使用配置方式开启日志,设置日志输出方式为标准输出即可查阅SQL执行日志


3.数据层开发——分页功能制作

前面仅仅是使用了MyBatisPlus提供的基础CRUD功能,实际上MyBatisPlus给我们提供了几乎所有的基础操作,这一节说一下如何实现数据库端的分页操作。


MyBatisPlus提供的分页操作API如下:

@Test
void testGetPage(){
    
    
    IPage page = new Page(2,5);
    bookDao.selectPage(page, null);
    System.out.println(page.getCurrent());
    System.out.println(page.getSize());
    System.out.println(page.getTotal());
    System.out.println(page.getPages());
    System.out.println(page.getRecords());
}

其中selectPage方法需要传入一个封装分页数据的对象,可以通过new的形式创建这个对象,当然这个对象也是MyBatisPlus提供的,别选错包了。创建此对象时需要指定两个分页的基本数据
1、当前显示第几页
2、每页显示几条数据


可以通过创建Page对象时利用构造方法初始化这两个数据。

IPage page = new Page(2,5);

将该对象传入到查询方法selectPage后,可以得到查询结果,但是我们会发现当前操作查询结果返回值仍然是一个IPage对象,这又是怎么回事?

IPage page = bookDao.selectPage(page, null);

原来这个IPage对象中封装了若干个数据,而查询的结果作为IPage对象封装的一个数据存在的,可以理解为查询结果得到后,又塞到了这个IPage对象中,其实还是为了高度的封装,一个IPage描述了分页所有的信息。下面5个操作就是IPage对象中封装的所有信息了。

@Test
void testGetPage(){
     
     
    IPage page = new Page(2,5);
    bookDao.selectPage(page, null);
    System.out.println(page.getCurrent());		// 当前页码值
    System.out.println(page.getSize());			// 每页显示数
    System.out.println(page.getTotal());		// 数据总量
    System.out.println(page.getPages());		// 总页数
    System.out.println(page.getRecords());		// 详细数据
}

到这里就知道这些数据如何获取了,但是当你去执行这个操作时,你会发现并不像我们分析的这样,实际上这个分页功能当前是无效的。为什么这样呢?这个要源于MyBatisPlus的内部机制。


对于MySQL的分页操作使用limit关键字进行,而并不是所有的数据库都使用limit关键字实现的,这个时候MyBatisPlus为了制作的兼容性强,将分页操作设置为基础查询操作的升级版,你可以理解为IPhone6IPhone6S-PLUS的关系。


基础操作中有查询全部的功能,而在这个基础上只需要升级一下(PLUS)就可以得到分页操作。所以MyBatisPlus将分页操作做成了一个开关,你用分页功能就把开关开启,不用就不需要开启这个开关。而我们现在没有开启这个开关,所以分页操作是没有的。这个开关是通过MyBatisPlus的拦截器的形式存在的,其中的原理这里不分析了,有兴趣的小伙伴可以学习MyBatisPlus这门课程进行详细解读。具体设置方式如下:


定义MyBatisPlus拦截器并将其设置为Spring管控的bean

@Configuration
public class MPConfig {
    
    
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor(){
    
    
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        interceptor.addInnerInterceptor(new PaginationInnerInterceptor());
        return interceptor;
    }
}

上述代码第一行是创建MyBatisPlus的拦截器栈,这个时候拦截器栈中没有具体的拦截器,第二行是初始化了分页拦截器,并添加到拦截器栈中。如果后期开发其他功能,需要添加全新的拦截器,按照第二行的格式继续add进去新的拦截器就可以了。


总结

1. 使用IPage封装分页数据
2. 分页操作依赖MyBatisPlus分页拦截器实现功能
3. 借助MyBatisPlus日志查阅执行SQL语句


4.数据层开发——条件查询功能制作

除了分页功能,MyBatisPlus还提供有强大的条件查询功能。以往我们写条件查询要自己动态拼写复杂的SQL语句,现在简单了,MyBatisPlus将这些操作都制作成API接口,调用一个又一个的方法就可以实现各种条件的拼装。这里给大家普及一下基本格式,详细的操作还是到MyBatisPlus的课程中查阅吧。


下面的操作就是执行一个模糊匹配对应的操作,由like条件书写变为了like方法的调用。

@Test
void testGetBy(){
     
     
    QueryWrapper<Book> qw = new QueryWrapper<>();
    qw.like("name","Spring");
    bookDao.selectList(qw);
}

其中第一句QueryWrapper对象是一个用于封装查询条件的对象,该对象可以动态使用API调用的方法添加条件,最终转化成对应的SQL语句。第二句就是一个条件了,需要什么条件,使用QueryWapper对象直接调用对应操作即可。比如做大于小于关系,就可以使用ltgt方法,等于使用eq方法,等等,此处不做更多的解释了。


这组API使用还是比较简单的,但是关于属性字段名的书写存在着安全隐患,比如查询字段name,当前是以字符串的形态书写的,万一写错,编译器还没有办法发现,只能将问题抛到运行器通过异常堆栈告诉开发者,不太友好。


MyBatisPlus针对字段检查进行了功能升级,全面支持Lambda表达式,就有了下面这组API。由QueryWrapper对象升级为LambdaQueryWrapper对象,这下就避免了上述问题的出现。

@Test
void testGetBy2(){
     
     
    String name = "1";
    LambdaQueryWrapper<Book> lqw = new LambdaQueryWrapper<Book>();
    lqw.like(Book::getName,name);
    bookDao.selectList(lqw);
}

为了便于开发者动态拼写SQL,防止将null数据作为条件使用,MyBatisPlus还提供了动态拼装SQL的快捷书写方式。

@Test
void testGetBy2(){
     
     
    String name = "1";
    LambdaQueryWrapper<Book> lqw = new LambdaQueryWrapper<Book>();
    // if (name != null) lqw.like(Book::getName,name);		// 方式一:JAVA代码控制
    lqw.like(name != null,Book::getName,name);				// 方式二:API接口提供控制开关
    bookDao.selectList(lqw);
}

其实就是个格式,没有区别。关于MyBatisPlus的基础操作就说到这里吧,如果这一块知识不太熟悉的小伙伴建议还是完整的学习一下MyBatisPlus的知识吧,这里只是蜻蜓点水的用了几个操作而已。


总结

1. 使用QueryWrapper对象封装查询条件
2. 推荐使用LambdaQueryWrapper对象
3. 所有查询操作封装成方法调用
4. 查询条件支持动态条件拼装


5.业务层开发

数据层开发告一段落,下面进行业务层开发,其实标准业务层开发很多初学者认为就是调用数据层,怎么说呢?这个理解是没有大问题的,更精准的说法应该是组织业务逻辑功能,并根据业务需求,对数据持久层发起调用。有什么差别呢?目标是为了组织出符合需求的业务逻辑功能,至于调不调用数据层还真不好说,有需求就调用,没有需求就不调用。


一个常识性的知识普及一下,业务层的方法名定义一定要与业务有关,例如登录操作

login(String username,String password);

而数据层的方法名定义一定与业务无关,是一定,不是可能,也不是有可能,例如根据用户名密码查询

selectByUserNameAndPassword(String username,String password);

我们在开发的时候是可以根据完成的工作不同划分成不同职能的开发团队的。比如一个哥们制作数据层,他就可以不知道业务是什么样子,拿到的需求文档要求可能是这样的

接口:传入用户名与密码字段,查询出对应结果,结果是单条数据
接口:传入ID字段,查询出对应结果,结果是单条数据
接口:传入离职字段,查询出对应结果,结果是多条数据

但是进行业务功能开发的哥们,拿到的需求文档要求差别就很大

接口:传入用户名与密码字段,对用户名字段做长度校验,4-15位,对密码字段做长度校验,8到24位,对密码字段做特殊字符校验,不允许存在空格,查询结果为对象。如果为null,返回BusinessException,封装消息码INFO_LOGON_USERNAME_PASSWORD_ERROR

你比较一下,能是一回事吗?差别太大了,所以说业务层方法定义与数据层方法定义差异化很大,只不过有些入门级的开发者手懒或者没有使用过公司相关的ISO标准化文档而已。


多余的话不说了,咱们做案例就简单制作了,业务层接口定义如下:

public interface BookService {
     
     
    Boolean save(Book book);
    Boolean update(Book book);
    Boolean delete(Integer id);
    Book getById(Integer id);
    List<Book> getAll();
    IPage<Book> getPage(int currentPage,int pageSize);
}

业务层实现类如下,转调数据层即可:

@Service
public class BookServiceImpl implements BookService {
    
    

    @Autowired
    private BookDao bookDao;

    @Override
    public Boolean save(Book book) {
    
    
        return bookDao.insert(book) > 0;
    }

    @Override
    public Boolean update(Book book) {
    
    
        return bookDao.updateById(book) > 0;
    }

    @Override
    public Boolean delete(Integer id) {
    
    
        return bookDao.deleteById(id) > 0;
    }

    @Override
    public Book getById(Integer id) {
    
    
        return bookDao.selectById(id);
    }

    @Override
    public List<Book> getAll() {
    
    
        return bookDao.selectList(null);
    }

    @Override
    public IPage<Book> getPage(int currentPage, int pageSize) {
    
    
        IPage page = new Page(currentPage,pageSize);
        bookDao.selectPage(page,null);
        return page;
    }
}

别忘了对业务层接口进行测试,测试类如下:

@SpringBootTest
public class BookServiceTest {
    
    
    @Autowired
    private IBookService bookService;

    @Test
    void testGetById(){
    
    
        System.out.println(bookService.getById(4));
    }
    @Test
    void testSave(){
    
    
        Book book = new Book();
        book.setType("测试数据123");
        book.setName("测试数据123");
        book.setDescription("测试数据123");
        bookService.save(book);
    }
    @Test
    void testUpdate(){
    
    
        Book book = new Book();
        book.setId(17);
        book.setType("-----------------");
        book.setName("测试数据123");
        book.setDescription("测试数据123");
        bookService.updateById(book);
    }
    @Test
    void testDelete(){
    
    
        bookService.removeById(18);
    }

    @Test
    void testGetAll(){
    
    
        bookService.list();
    }

    @Test
    void testGetPage(){
    
    
        IPage<Book> page = new Page<Book>(2,5);
        bookService.page(page);
        System.out.println(page.getCurrent());
        System.out.println(page.getSize());
        System.out.println(page.getTotal());
        System.out.println(page.getPages());
        System.out.println(page.getRecords());
    }
}

总结

1. Service接口名称定义成业务名称,并与Dao接口名称进行区分
2. 制作测试类测试Service功能是否有效


业务层快速开发

其实MyBatisPlus技术不仅提供了数据层快速开发方案,业务层MyBatisPlus也给了一个通用接口,个人观点不推荐使用,凑合能用吧,其实就是一个封装+继承的思想,代码给出,实际开发慎用。


业务层接口快速开发

public interface IBookService extends IService<Book> {
     
     
    // 添加非通用操作API接口
}

业务层接口实现类快速开发,关注继承的类需要传入两个泛型,一个是数据层接口,另一个是实体类。

@Service
public class BookServiceImpl extends ServiceImpl<BookDao, Book> implements IBookService {
     
     
    @Autowired
    private BookDao bookDao;
	// 添加非通用操作API
}

如果感觉MyBatisPlus提供的功能不足以支撑你的使用需要(其实是一定不能支撑的,因为需求不可能是通用的),在原始接口基础上接着定义新的API接口就行了,此处不再说太多了,就是自定义自己的操作了,但是不要和已有的API接口名冲突即可。


总结

1. 使用通用接口(ISerivce<T>)快速开发Service
2. 使用通用实现类(ServiceImpl<M,T>)快速开发ServiceImpl
3. 可以在通用接口基础上做功能重载或功能追加
4. 注意重载时不要覆盖原始操作,避免原始提供的功能丢失


6.表现层开发

终于做到表现层了,做了这么多都是基础工作。其实你现在回头看看,哪里还有什么SpringBoot的影子?前面12步就搞完了。继续完成表现层制作吧,咱们表现层的开发使用基于Restful的表现层接口开发,功能测试通过Postman工具进行。


表现层接口如下:

@RestController
@RequestMapping("/books")
public class BookController2 {
    
    

    @Autowired
    private IBookService bookService;

    @GetMapping
    public List<Book> getAll(){
    
    
        return bookService.list();
    }

    @PostMapping
    public Boolean save(@RequestBody Book book){
    
    
        return bookService.save(book);
    }

    @PutMapping
    public Boolean update(@RequestBody Book book){
    
    
        return bookService.modify(book);
    }

    @DeleteMapping("{id}")
    public Boolean delete(@PathVariable Integer id){
    
    
        return bookService.delete(id);
    }

    @GetMapping("{id}")
    public Book getById(@PathVariable Integer id){
    
    
        return bookService.getById(id);
    }

    @GetMapping("{currentPage}/{pageSize}")
    public IPage<Book> getPage(@PathVariable int currentPage,@PathVariable int pageSize){
    
    
        return bookService.getPage(currentPage,pageSize, null);
    }
}

在使用Postman测试时关注提交类型,对应上即可,不然就会报405的错误码了。


普通GET请求

image-20211129152237371


PUT请求传递json数据,后台实用@RequestBody接收数据

image-20211129152300177


GET请求传递路径变量,后台实用@PathVariable接收数据

image-20211129152320073


总结

1. 基于Restful制作表现层接口
1.1、新增:POST
1.2、删除:DELETE
1.3、修改:PUT
1.4、查询:GET
2. 接收参数
2.1、实体数据:@RequestBody
2.2、路径变量:@PathVariable


7.表现层消息一致性处理

目前我们通过Postman测试后业务层接口功能是通的,但是这样的结果给到前端开发者会出现一个小问题。不同的操作结果所展示的数据格式差异化严重。


增删改操作结果

true

查询单个数据操作结果

{
    
    
    "id": 1,
    "type": "计算机理论",
    "name": "Spring实战 第5版",
    "description": "Spring入门经典教程"
}

查询全部数据操作结果

[
    {
    
    
        "id": 1,
        "type": "计算机理论",
        "name": "Spring实战 第5版",
        "description": "Spring入门经典教程"
    },
    {
    
    
        "id": 2,
        "type": "计算机理论",
        "name": "Spring 5核心原理与30个类手写实战",
        "description": "十年沉淀之作"
    }
]

每种不同操作返回的数据格式都不一样,而且还不知道以后还会有什么格式,这样的结果让前端人员看了是很容易让人崩溃的,必须将所有操作的操作结果数据格式统一起来,需要设计表现层返回结果的模型类,用于后端与前端进行数据格式统一,也称为前后端数据协议

@Data
public class R {
    
    
    private Boolean flag;
    private Object data;
}

其中flag用于标识操作是否成功,data用于封装操作数据,现在的数据格式就变了

{
    
    
    "flag": true,
    "data":{
    
    
        "id": 1,
        "type": "计算机理论",
        "name": "Spring实战 第5版",
        "description": "Spring入门经典教程"
    }
}

表现层开发格式也需要转换一下

image-20211129153301262


image-20211129153319052


image-20211129153332499

结果这么一折腾,全格式统一,现在后端发送给前端的数据格式就统一了,免去了不少前端解析数据的烦恼。


总结

1. 设计统一的返回值结果类型便于前端开发读取数据
2. 返回值结果类型可以根据需求自行设定,没有固定格式
3. 返回值结果模型类用于后端与前端进行数据格式统一,也称为前后端数据协议


8.前后端联通性测试

后端的表现层接口开发完毕,就可以进行前端的开发了。


将前端人员开发的页面保存到lresources目录下的static目录中,建议执行mavenclean生命周期,避免缓存的问题出现。

image-20211129153831990

在进行具体的功能开发之前,先做联通性的测试,通过页面发送异步提交(axios),这一步调试通过后再进行进一步的功能开发。

// 列表
getAll() {
     
     
	axios.get("/books").then((res) => {
     
     
		console.log(res.data);
	});
},

只要后台代码能够正常工作,前端能够在日志中接收到数据,就证明前后端是通的,也就可以进行下一步的功能开发了。


总结

1. 单体项目中页面放置在resources/static目录下
2. created钩子函数用于初始化页面时发起调用
3. 页面使用axios发送异步请求获取数据后确认前后端是否联通


9.页面基础功能开发

F-1.列表功能(非分页版)

列表功能主要操作就是加载完数据,将数据展示到页面上,此处要利用VUE的数据模型绑定,发送请求得到数据,然后页面上读取指定数据即可。


页面数据模型定义

data: {
     
     
	dataList: [],		// 当前页要展示的列表数据
	...
},

异步请求获取数据

// 列表
getAll() {
     
     
    axios.get("/books").then((res) => {
     
     
        this.dataList = res.data.data;
    });
},

这样在页面加载时就可以获取到数据,并且由VUE将数据展示到页面上了。


总结

1. 将查询数据返回到页面,利用前端数据绑定进行数据展示


F-2.添加功能

添加功能用于收集数据的表单是通过一个弹窗展示的,因此在添加操作前首先要进行弹窗的展示,添加后隐藏弹窗即可。因为这个弹窗一直存在,因此当页面加载时首先设置这个弹窗为不可显示状态,需要展示,切换状态即可。


默认状态

data: {
    
    
	dialogFormVisible: false,	// 添加表单是否可见
	...
},

切换为显示状态

// 弹出添加窗口
handleCreate() {
    
    
	this.dialogFormVisible = true;
},

由于每次添加数据都是使用同一个弹窗录入数据,所以每次操作的痕迹将在下一次操作时展示出来,需要在每次操作之前清理掉上次操作的痕迹。


定义清理数据操作

// 重置表单
resetForm() {
    
    
    this.formData = {
    
    };
},

切换弹窗状态时清理数据

// 弹出添加窗口
handleCreate() {
    
    
    this.dialogFormVisible = true;
    this.resetForm();
},

至此准备工作完成,下面就要调用后台完成添加操作了。


添加操作

// 添加
handleAdd () {
    
    
    // 发送异步请求
    axios.post("/books",this.formData).then((res) => {
    
    
        // 如果操作成功,关闭弹层,显示数据
        if (res.data.flag) {
    
    
            this.dialogFormVisible = false;
            this.$message.success("添加成功");
        } else {
    
    
            this.$message.error("添加失败");
        }
    }).finally(() => {
    
    
        this.getAll();
    });
},

1. 将要保存的数据传递到后台,通过post请求的第二个参数传递json数据到后台
2. 根据返回的操作结果决定下一步操作
2.1、如何是true就关闭添加窗口,显示添加成功的消息
2.2、如果是false保留添加窗口,显示添加失败的消息
3. 无论添加是否成功,页面均进行刷新,动态加载数据(对getAll操作发起调用)


取消添加操作

// 取消
cancel(){
    
    
    this.dialogFormVisible = false;
    this.$message.info("操作取消");
},

总结

1. 请求方式使用POST调用后台对应操作
2. 添加操作结束后动态刷新页面加载数据
3. 根据操作结果不同,显示对应的提示信息
4. 弹出添加div时清除表单数据


F-3.删除功能

模仿添加操作制作删除功能,差别之处在于删除操作仅传递一个待删除的数据id到后台即可。


删除操作

// 删除
handleDelete(row) {
    
    
    axios.delete("/books/"+row.id).then((res) => {
    
    
        if (res.data.flag) {
    
    
            this.$message.success("删除成功");
        } else {
    
    
            this.$message.error("删除失败");
        }
    }).finally(() => {
    
    
        this.getAll();
    });
},

删除操作提示信息

// 删除
handleDelete(row) {
    
    
    // 1.弹出提示框
    this.$confirm("此操作永久删除当前数据,是否继续?", "提示", {
    
     type:'info' }).then(() => {
    
    
        // 2.做删除业务
        axios.delete("/books/"+row.id).then((res) => {
    
    
       		if (res.data.flag) {
    
    
            	this.$message.success("删除成功");
        	} else {
    
    
            	this.$message.error("删除失败");
        	}
        }).finally(() => {
    
    
            this.getAll();
        });
    }).catch(() => {
    
    
        // 3.取消删除
        this.$message.info("取消删除操作");
    });
},

总结

1. 请求方式使用Delete调用后台对应操作
2. 删除操作需要传递当前行数据对应的id值到后台
3. 删除操作结束后动态刷新页面加载数据
4. 根据操作结果不同,显示对应的提示信息
5. 删除操作前弹出提示框避免误操作


F-4.修改功能

修改功能可以说是列表功能、删除功能与添加功能的合体。几个相似点如下:
1. 页面也需要有一个弹窗用来加载修改的数据,这一点与添加相同,都是要弹窗
2. 弹出窗口中要加载待修改的数据,而数据需要通过查询得到,这一点与查询全部相同,都是要查数据
3. 查询操作需要将要修改的数据id发送到后台,这一点与删除相同,都是传递id到后台
4. 查询得到数据后需要展示到弹窗中,这一点与查询全部相同,都是要通过数据模型绑定展示数据
5. 修改数据时需要将被修改的数据传递到后台,这一点与添加相同,都是要传递数据


所以整体上来看,修改功能就是前面几个功能的大合体


查询并展示数据

// 弹出编辑窗口
handleUpdate(row) {
    
    
    axios.get("/books/"+row.id).then((res) => {
    
    
        if (res.data.flag) {
    
    
            // 展示弹层,加载数据
            this.formData = res.data.data;
            this.dialogFormVisible4Edit = true;
        } else {
    
    
            this.$message.error("数据同步失败,自动刷新");
        }
    });
},

修改操作

// 修改
handleEdit() {
    
    
    axios.put("/books",this.formData).then((res) => {
    
    
        // 如果操作成功,关闭弹层并刷新页面
        if (res.data.flag) {
    
    
            this.dialogFormVisible4Edit = false;
            this.$message.success("修改成功");
        } else {
    
    
            this.$message.error("修改失败,请重试");
        }
    }).finally(() => {
    
    
        this.getAll();
    });
},

总结

1. 加载要修改数据通过传递当前行数据对应的id值到后台查询数据(同删除与查询全部)
2. 利用前端双向数据绑定将查询到的数据进行回显(同查询全部)
3. 请求方式使用PUT调用后台对应操作(同新增传递数据)
4. 修改操作结束后动态刷新页面加载数据(同新增)
5. 根据操作结果不同,显示对应的提示信息(同新增)


10.业务消息一致性处理

目前的功能制作基本上达成了正常使用的情况,什么叫正常使用呢?也就是这个程序不出BUG,如果我们搞一个BUG出来,你会发现程序马上崩溃掉。比如后台手工抛出一个异常,看看前端接收到的数据什么样子。

{
     
     
    "timestamp": "2021-09-15T03:27:31.038+00:00",
    "status": 500,
    "error": "Internal Server Error",
    "path": "/books"
}

面对这种情况,前端的同学又不会了,这又是什么格式?怎么和之前的格式不一样?

{
     
     
    "flag": true,
    "data":{
     
     
        "id": 1,
        "type": "计算机理论",
        "name": "Spring实战 第5版",
        "description": "Spring入门经典教程"
    }
}

看来不仅要对正确的操作数据格式做处理,还要对错误的操作数据格式做同样的格式处理。


首先在当前的数据结果中添加消息字段,用来兼容后台出现的操作消息。

@Data
public class R{
     
     
    private Boolean flag;
    private Object data;
    private String msg;		// 用于封装消息
}

后台代码也要根据情况做处理,当前是模拟的错误。

@PostMapping
public R save(@RequestBody Book book) throws IOException {
     
     
    Boolean flag = bookService.insert(book);
    return new R(flag , flag ? "添加成功^_^" : "添加失败-_-!");
}

然后在表现层做统一的异常处理,使用SpringMVC提供的异常处理器做统一的异常处理。

@RestControllerAdvice
public class ProjectExceptionAdvice {
     
     
    @ExceptionHandler(Exception.class)
    public R doOtherException(Exception ex){
     
     
        // 记录日志
        // 发送消息给运维
        // 发送邮件给开发人员,ex对象发送给开发人员
        ex.printStackTrace();
        return new R(false,null,"系统错误,请稍后再试!");
    }
}

页面上得到数据后,先判定是否有后台传递过来的消息,标志就是当前操作是否成功,如果返回操作结果false,就读取后台传递的消息。

// 添加
handleAdd () {
     
     
	// 发送ajax请求
    axios.post("/books",this.formData).then((res) => {
     
     
        // 如果操作成功,关闭弹层,显示数据
        if (res.data.flag) {
     
     
            this.dialogFormVisible = false;
            this.$message.success("添加成功");
        } else {
     
     
            this.$message.error(res.data.msg);			// 消息来自于后台传递过来,而非固定内容
        }
    }).finally(() => {
     
     
        this.getAll();
    });
},

总结

1. 使用注解@RestControllerAdvice定义SpringMVC异常处理器用来处理异常的
2. 异常处理器必须被扫描加载,否则无法生效
3. 表现层返回结果的模型类中添加消息属性用来传递消息到页面


11.页面功能开发

F-5.分页功能

分页功能的制作用于替换前面的查询全部,其中要使用到elementUI提供的分页组件。

<!--分页组件-->
<div class="pagination-container">
    <el-pagination
		class="pagiantion"
		@current-change="handleCurrentChange"
		:current-page="pagination.currentPage"
		:page-size="pagination.pageSize"
		layout="total, prev, pager, next, jumper"
		:total="pagination.total">
    </el-pagination>
</div>

为了配合分页组件,封装分页对应的数据模型。

data: {
     
     
	pagination: {
     
     	
		// 分页相关模型数据
		currentPage: 1,	// 当前页码
		pageSize:10,	// 每页显示的记录数
		total:0,		// 总记录数
	}
},

修改查询全部功能为分页查询,通过路径变量传递页码信息参数。

getAll() {
     
     
    axios.get("/books/"+this.pagination.currentPage+"/"+this.pagination.pageSize).then((res) => {
     
     
    });
},

后台提供对应的分页功能。

@GetMapping("/{currentPage}/{pageSize}")
public R getAll(@PathVariable Integer currentPage,@PathVariable Integer pageSize){
     
     
    IPage<Book> pageBook = bookService.getPage(currentPage, pageSize);
    return new R(null != pageBook ,pageBook);
}

页面根据分页操作结果读取对应数据,并进行数据模型绑定。

getAll() {
     
     
    axios.get("/books/"+this.pagination.currentPage+"/"+this.pagination.pageSize).then((res) => {
     
     
        this.pagination.total = res.data.data.total;
        this.pagination.currentPage = res.data.data.current;
        this.pagination.pagesize = res.data.data.size;
        this.dataList = res.data.data.records;
    });
},

对切换页码操作设置调用当前分页操作。

// 切换页码
handleCurrentChange(currentPage) {
     
     
    this.pagination.currentPage = currentPage;
    this.getAll();
},

总结

1. 使用el分页组件
2. 定义分页组件绑定的数据模型
3. 异步调用获取分页数据
4. 分页数据页面回显


F-6.删除功能维护

由于使用了分页功能,当最后一页只有一条数据时,删除操作就会出现BUG,最后一页无数据但是独立展示,对分页查询功能进行后台功能维护,如果当前页码值大于最大页码值,重新执行查询。其实这个问题解决方案很多,这里给出比较简单的一种处理方案。

@GetMapping("{currentPage}/{pageSize}")
public R getPage(@PathVariable int currentPage,@PathVariable int pageSize) {
     
     
    IPage<Book> page = bookService.getPage(currentPage, pageSize);
    // 如果当前页码值大于了总页码值,那么重新执行查询操作,使用最大页码值作为当前页码值
    if (currentPage > page.getPages()) {
     
     
        page = bookService.getPage((int)page.getPages(), pageSize);
    }
    return new R(true, page);
}

F-7.条件查询功能

最后一个功能来做条件查询,其实条件查询可以理解为分页查询的时候除了携带分页数据再多带几个数据的查询。这些多带的数据就是查询条件。比较一下不带条件的分页查询与带条件的分页查询差别之处,这个功能就好做了
1、页面封装的数据:带不带条件影响的仅仅是一次性传递到后台的数据总量,由传递2个分页相关数据转换成2个分页数据加若干个条件
2、后台查询功能:查询时由不带条件,转换成带条件,反正不带条件的时候查询条件对象使用的是null,现在换成具体条件,差别不大
3、查询结果:不管带不带条件,出来的数据只是有数量上的差别,其他都差别,这个可以忽略


经过上述分析,看来需要在页面发送请求的格式方面做一定的修改,后台的调用数据层操作时发送修改,其他没有区别。


页面发送请求时,两个分页数据仍然使用路径变量,其他条件采用动态拼装url参数的形式传递。


页面封装查询条件字段

pagination: {
    
    		
	// 分页相关模型数据
	currentPage: 1,		// 当前页码
	pageSize:10,		// 每页显示的记录数
	total:0,			// 总记录数
	name: "",
	type: "",
	description: ""
},

页面添加查询条件字段对应的数据模型绑定名称

<div class="filter-container">
    <el-input placeholder="图书类别" v-model="pagination.type" class="filter-item"/>
    <el-input placeholder="图书名称" v-model="pagination.name" class="filter-item"/>
    <el-input placeholder="图书描述" v-model="pagination.description" class="filter-item"/>
    <el-button @click="getAll()" class="dalfBut">查询</el-button>
    <el-button type="primary" class="butT" @click="handleCreate()">新建</el-button>
</div>

将查询条件组织成url参数,添加到请求url地址中,这里可以借助其他类库快速开发,当前使用手工形式拼接,降低学习要求

getAll() {
    
    
    // 1.获取查询条件,拼接查询条件
    param = "?name="+this.pagination.name;
    param += "&type="+this.pagination.type;
    param += "&description="+this.pagination.description;
    console.log("-----------------"+ param);
    axios.get("/books/"+this.pagination.currentPage+"/"+this.pagination.pageSize+param).then((res) => {
    
    
        this.dataList = res.data.data.records;
    });
},

后台代码中定义实体类封查询条件

@GetMapping("{currentPage}/{pageSize}")
public R getAll(@PathVariable int currentPage,@PathVariable int pageSize,Book book) {
    
    
    System.out.println("参数=====>"+book);
    IPage<Book> pageBook = bookService.getPage(currentPage,pageSize);
    return new R(null != pageBook ,pageBook);
}

对应业务层接口与实现类进行修正

public interface IBookService extends IService<Book> {
    
    
    IPage<Book> getPage(Integer currentPage,Integer pageSize,Book queryBook);
}

@Service
public class BookServiceImpl2 extends ServiceImpl<BookDao,Book> implements IBookService {
    
    
    public IPage<Book> getPage(Integer currentPage,Integer pageSize,Book queryBook){
    
    
        IPage page = new Page(currentPage,pageSize);
        LambdaQueryWrapper<Book> lqw = new LambdaQueryWrapper<Book>();
        lqw.like(Strings.isNotEmpty(queryBook.getName()),Book::getName,queryBook.getName());
        lqw.like(Strings.isNotEmpty(queryBook.getType()),Book::getType,queryBook.getType());
        lqw.like(Strings.isNotEmpty(queryBook.getDescription()),Book::getDescription,queryBook.getDescription());
        return bookDao.selectPage(page,lqw);
    }
}

页面回显数据

getAll() {
    
    
    // 1.获取查询条件,拼接查询条件
    param = "?name="+this.pagination.name;
    param += "&type="+this.pagination.type;
    param += "&description="+this.pagination.description;
    console.log("-----------------"+ param);
    axios.get("/books/"+this.pagination.currentPage+"/"+this.pagination.pageSize+param).then((res) => {
    
    
        this.pagination.total = res.data.data.total;
        this.pagination.currentPage = res.data.data.current;
        this.pagination.pagesize = res.data.data.size;
        this.dataList = res.data.data.records;
    });
},

总结

1. 定义查询条件数据模型(当前封装到分页数据模型中)
2. 异步调用分页功能并通过请求参数传递数据到后台


基础篇完结

基础篇到这里就全部结束了,在基础篇中带着大家学习了如何创建一个SpringBoot工程,然后学习了SpringBoot的基础配置语法格式,接下来对常见的市面上的实用技术做了整合,最后通过一个小的案例对前面学习的内容做了一个综合应用。整体来说就是一个最基本的入门,关于SpringBoot的实际开发其实接触的还是很少的,我们到实用篇和原理篇中继续吧,各位小伙伴,加油学习,再见。


源码

下载

git clone -b back-end-services https://gitee.com/mssj200224/open-resources.git

项目

1. Find singleFableFullStackthe folder named in the warehouse and copy it out.
2. Use to ideaopen the project to run.
3.Part of the source code is not the same as in the handout, but the effect is the same, the back-end changes are not big, and the front-end changes are slightly larger.
4. Portal .

Guess you like

Origin blog.csdn.net/weixin_51157081/article/details/132549713
Recommended