Interested friends can go to know about the other several, your praise is the biggest support for me, thank you!

  • The article directories

SpringBoot takeoff road -HelloWorld

(two) SpringBoot takeoff road – analysis of the principle of entry

(three) SpringBoot takeoff road -YAML configuration summary (entry must know will)

(4) SpringBoot takeoff road – static resource processing

(five) SpringBoot takeoff road -Thymeleaf template engine

(6) SpringBoot takeoff road – integration jdbctemplate-druid-mybatis

(7) SpringBoot launch road – integration of SpringSecurity (Mybatis, JDBC, memory)

(eight) SpringBoot take-off path – integration Shiro detailed tutorial (MyBatis, Thymeleaf)

SpringBoot -Swagger 2 And 3

Description:

  • 3.0 version is not used much, just a simple integration, maybe there are some imperfections, welcome to share
  • SpringBoot takeoff road series of articles source, are synchronized to github, there is a need for small partners, go down at will
    • Github.com/ideal-20/Sp…

A person that Swagger

Skip the foreshadowing and go straight to the second largest point

(a) first talk about the separation of the front and back ends

Back in the early Days of JavaWeb, if you wanted to return a page, you would print line by line, and concatenate strings yourself if you encountered variables

Public class TestServlet extends HttpServlet {
	@Override  
    public void doGet(HttpServletRequest request, HttpServletResponseresp response) 
            throws ServletException, IOException {  
        String name = req.getParameter("name");  
        String age = req.getParameter("age");  
        PrintWriter out = resp.getWriter();  
        out.println("<html>");  
        out.println();  
        out.println("<body>name:" + name + "<br/> age: " + age +"</body>");  
        out.println("</html>"); }}Copy the code

Then JSP came along, which was essentially a Servlet, but it was written in much the same way as HTML, but JSP began to allow us to introduce Java code into our pages, This means that you can display dynamic content in JSP pages by writing Java code, such as defining methods in JSP pages, writing console output statements, and so on. Most of the logic you can think of can be done here

Later a look at this is not ah, business logic and view logic are mixed, the more write more chaos, a page on hundreds of lines or even thousands of lines, really terrible ah, then we thought of a way, with MVC to decouple ah, the JSP business extraction to the background Serlvet to do, JSP used to carry data, display pages

Fetch the data from the session and iterate through the JSP, but with some simple tags, which we’ll talk about later

Finally the JSPS are compiled into servlets

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"% > < %@page import="cn.ideal.pojo.Good"% > <! - request/index.doInitialize --> <! DOCTYPE HTML PUBLIC"- / / / / W3C DTD HTML 4.01 Transitional / / EN">
<html>  
   <body>
    <img src="img/cart.jpg" height="60px" width="60px">
    <a href="cart.view"<c:out value="${sumNum}" default="Nothing."/> Merchandise </a><br> <br> <table border="1">    
   <%
      ArrayList<Good> goodList = (ArrayList<Good>)session.getAttribute("goodList");
      for (Good good : goodList){ 
        out.println("<tr>"); out.println("<td> <img src='" + good.getGoodImg() + "'> </td>");
        String id = good.getGoodId();
        out.println("  + id + Purchasing "> < / a > < / td >");
        out.println("</tr>"); 
       } 
    %>
    </table></body>
</html>
Copy the code

Although JSP does not handle business logic, it looks less bloated, but as shown above, JSP to get some content from the Servlet, still need to get through %%, such as after getting traversal, judgment and other content also need to write Java code in JSP

EL and JSTL expressions come in, with some defined tags, to simply get the data and display it

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"% > <! - request/index.doInitialize --> <! DOCTYPE HTML PUBLIC"- / / / / W3C DTD HTML 4.01 Transitional / / EN">
<html>  
   <body>
    <img src="img/cart.jpg" height="60px" width="60px">
    <a href="showCart.jsp"<c:out value="${sessionScope.cart.sumNum}" default="Nothing."<br> <br> <table border="1">    
    <c:forEach var="good" items="${cart.goodList}">
    <tr>
    	<td><img src='${good.goodImg}'></td>
    	<td><c:out value='${good.getPrice()}'/> meta </td> <td><a href="shopping.view? id=${good.bookId}&type=1&method=1"Purchasing > < / a > < / td > < / tr > < / c: forEach > < / table > < / body > < / HTML >Copy the code

More recently, Freemarker, Thymeleaf, Velocity, etc., came along with template engines that wrote expressions much like JSP and had their own set of expressions to fetch and process data, such as this:

<table border="1">
  <tr>
    <th>Name</th>
    <th>Age</th>
  </tr>
  <tr th:each="user : ${userList}">
    <td th:text="${user.nickname}">NULL</td>
    <td th:text="${user.age}">0</td>
  </tr>
</table>
Copy the code

Such a set of old development model, in fact, most of the pressure on the back end staff, because from a front-end HTML, for example, the back-end also needs to be modified for the JSP, also is to use tags to replace some of the fixed content, realize the dynamic effect, but the project is larger, no matter from the human or the development cost is not appropriate, It would be nice if the back end only had to take care of its own back-end business

At this time, the front end began to rise. They began to use simple HTML and CSS to display data, that is, pure page display. They used JS to fill the data obtained from data requests. The front end is starting to use MVC, which is HTML as a view, JS as a controller, asynchronous requests, presenting data through tags, filling data directly into HTML pages

<! DOCTYPEhtml>
<html lang="en" xmlns:v-on="http://www.w3.org/1999/xhtml">
<head>
  <meta charset="UTF-8">
  <title>Title</title>
  <style>
    [v-clock] {
      display: none;
    }
  </style>
</head>
<body>
<div id="hello-8" v-clock>
  <div>{{info.name}}</div>
  <div>{{info.blog}}</div>
  <div>{{info.about.country}}</div>
  <div>{{info.about.phone}}</div>
  <div>{{info.students[0].name}}</div>
</div>

<script src="https://cdn.jsdelivr.net/npm/[email protected]"></script>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>

<script>
    var vm = new Vue({
        el: "#hello-8".data() {
            return {
                info: {}}}.mounted() {
            axios.get(".. /json/data.json").then(response= > (this.info = response.data)); }})</script>
</body>
</html>
Copy the code

This means that the back end only needs to return the data required by the front-end interface (such as JSON)

This way of interacting through the API is also loosely coupled, with both sides being flexible and independent

B: Why Swagger

Feeling has been talking in front of the digression, but the problem is that this, this kind of module development, under the condition of before and after the separation, front or back end communication is very important, sometimes I couldn’t timely consultation, will appear a lot of unexpected problems, before and after the end of separation is popular at the same time, also represents the interface call will appear a lot of, If your API interconnects with multiple Web, IOS, Android, etc., it is necessary to document all the details of the interface in order to reduce the cost of communication

However, how to create a large and complex document is a very difficult thing, after all, there are many places to consider, and as the code iteration, API document update management must be strictly controlled, otherwise it will bring unnecessary trouble, obviously traditional Wiki

Writing a document by hand must have been a very cumbersome process, Swagger here he is

What is Swagger

Swagger is a canonical and complete framework for generating, describing, invoking, and visualizing RESTful Web services

The overall goal is to have clients and file systems update at the same rate as servers. File methods, parameters, and models are tightly integrated into server-side code, allowing the API to always be in sync.

When Swagger started out, it was just a specification. During product development iterations, interface documentation and client/server code were generated by updating the description file, but developers sometimes forgot to update this file and changed the code. Established the Spring-Swagger project, now SpringFox (Swagger2)

The biggest advantage is that the API and documentation can be synchronized in real time, and the rich functionality can be experienced through simple integration and some annotations

By far, most projects still use Swagger2. As can be seen from Maven repository, 2.9.2 is the most used version. Also, we will show Swagger3 later, because it is just released this year, it simplifies a lot of configuration, and I feel it is relatively nice

instructions

Springboot integrates Swagger 2

(a) dependency and initialization

Initialize a Springboot project

(1) Introducing dependencies

<! -- https://mvnrepository.com/artifact/io.springfox/springfox-swagger2 -->
<dependency>
   <groupId>io.springfox</groupId>
   <artifactId>springfox-swagger2</artifactId>
   <version>2.9.2</version>
</dependency>
<! -- https://mvnrepository.com/artifact/io.springfox/springfox-swagger-ui -->
<dependency>
   <groupId>io.springfox</groupId>
   <artifactId>springfox-swagger-ui</artifactId>
   <version>2.9.2</version>
</dependency>
Copy the code

(2) writing the Controller

@RestController
@RequestMapping("test/")
public class TestController {
    @RequestMapping("/testA")
    public String testA(a){
        return "This is a test"; }}Copy the code

(3) Create Swagger configuration class

@Configuration / / configuration class
@EnableSwagger2 // Enable automatic configuration of Swagger2
public class SwaggerConfig {  
    // Temporarily empty
}
Copy the code

Note: We use Swagger2

(4) Access test

To test whether the controller has any problems, then access swagger’s interface through the following address

http://localhost:8080/swagger-ui.html

As you can see, this page is roughly divided into three parts. The top part is some introduction information, the middle part is interface information one by one, and the bottom part is entity

2. Configure Swagger information

We need to configure something in our custom Swagger configuration class, we need to import a Bean, Swagger instance Bean is a Docket, so we need to instantiate a Docket

/** * Set docket and Swagger parameters *@return* /
@Bean 
public Docket docket(a) {
    return newDocket (DocumentationType SWAGGER_2); }Copy the code

If you open up the Docket source code, you can see that it introduces the ApiInfo class, which defines some basic information such as version, title and so on

public static final Contact DEFAULT_CONTACT = new Contact("".""."");
  public static final ApiInfo DEFAULT = new ApiInfo("Api Documentation"."Api Documentation"."1.0"."urn:tos",
          DEFAULT_CONTACT, "Apache 2.0"."http://www.apache.org/licenses/LICENSE-2.0".new ArrayList<VendorExtension>());

  private final String version;
  private final String title;
  private final String description;
  private final String termsOfServiceUrl;
  private final String license;
  private final String licenseUrl;
  private final Contact contact;
  private final List<VendorExtension> vendorExtensions;
Copy the code

As you can probably already see, the content of this place is responsible for the header Documentation that we just opened up that Swagger-UI page, and its default values for example Api Documentation, 1.0, Apache 2.0 you can check for yourself

Ok, now that we know its classes and basic structure, we are ready to customize this information

/** * Configures the document information *@return* /
private ApiInfo apiInfo(a) {
    Contact contact = new Contact("BWH_Steven"."https://www.ideal-20.cn"."[email protected]");
    return new ApiInfo(
            "Swagger2 learning -- More than 20 years of ideal"./ / title - the title
            Learn how to configure Swagger2./ / the description - description
            "v1.0"./ / version - version
            "https://www.ideal-20.cn".// termsOfServiceUrl- Organization link
            contact, // contact- Indicates the contact information
            "Apach 2.0 License"./ / license - license
            "Permission link".// licenseUrl- License connection
            new ArrayList<>()/ / vendorExtensions - extension
    );
}
Copy the code

Once configured, we haven’t hooked it up to the Docket instance yet

/** * Set docket and Swagger parameters *@return* /
@Bean
public Docket docket(a) {
   return new Docket(DocumentationType.SWAGGER_2).apiInfo(apiInfo());
}
Copy the code

Visit the address again and see what happens

http://localhost:8080/swagger-ui.html

(3) Configure the user-defined scan mode

(1) How to configure it

For those of you who are paying attention, there is still a default basic-Seeor-Controller on the first access, but it is missing. This is because I forgot to comment out my custom scan mode when demonstrating the configuration information

So, let’s talk about how to define which interfaces to scan

In Docket, you can configure the interface for scanning by calling the Select () method. To use this method, you must follow build after it. This is one of the design patterns, builder mode. Because we need a requestHandlerSelector in the apis, requestHandlerSelector is where we’re going to end up configuring it

Let’s start with an example and look at the explanation above

/** * Set docket and Swagger parameters *@return* /
@Bean
public Docket docket(a) {
    return new Docket(DocumentationType.SWAGGER_2)
    	.apiInfo(apiInfo())
        Select () to configure the scanning interface
        .select()
        // RequestHandlerSelectors Sets the mode of scanning interfaces
        .apis(RequestHandlerSelectors.basePackage("cn.ideal.controller")) 
        .build();
}
Copy the code

(2) Optional scan mode

You can click on the RequestHandlerSelectors to see what else basePackage is

any()

  • Scan all interfaces in the project

none()

  • No interface is scanned

withMethodAnnotation(final Class<? extends Annotation> annotation)

  • Scanning with annotations on methods, such as withMethodAnnotation(getMapping.class) scans only get requests

withClassAnnotation(final Class<? extends Annotation> annotation)

  • Scanning with annotations on a class, such as.WithClassAnnotation (Controller.class) scans only interfaces in classes that have Controller annotations

basePackage(final String basePackage)

  • Scan interfaces based on packet paths

(3) Configure scan filtering

When you write a Select and build, all you really have in between are apis and paths, which is the scan filter

/** * Set docket and Swagger parameters *@return* /
@Bean
public Docket docket(a) {
    return new Docket(DocumentationType.SWAGGER_2)
            .apiInfo(apiInfo())
            .select()
            .apis(RequestHandlerSelectors.basePackage("cn.ideal.controller"))
            // How does the configuration filter through path
        	// Only interfaces whose requests begin with /test are scanned
            .paths(PathSelectors.ant("/test/**"))
            .build();
}
Copy the code

An optional way

any()

  • Scanning all requests

none()

  • No requests are scanned

regex(final String pathRegex)

  • According to the regular expression

ant(final String antPattern)

  • Control via ant() (some wildcards can be used as shown in the code above)

(4) Configure Swagger on and off

You can control Swagger on and off by calling enable(Boolean externallyConfiguredFlag) in Docket

As a practical example, we usually turn Swagger on during development and testing, but turn it off when we go live

So, we have to configure it dynamically

First, let’s create dev and Test and prod, respectively

  • Create application-dev.properties and set server.port=8080

  • Create application-test.properties and set server.port=8081

  • Create application-prod.properties and set server.port=8082

/** * Set docket and Swagger parameters *@return* /
@Bean
public Docket docket(Environment environment) {

    // Set the environment to display Swagger
    Profiles of = Profiles.of("dev"."test");
    // Determine whether the current environment
    boolean flag = environment.acceptsProfiles(of);

    return new Docket(DocumentationType.SWAGGER_2)
            .apiInfo(apiInfo())
            // Accept with enable() to determine whether to display
            .enable(flag)
            .select()
            .apis(RequestHandlerSelectors.basePackage("cn.ideal.controller"))
            .paths(PathSelectors.ant("/test/**"))
            .build();
}
Copy the code

In the main configuration appplication. Properties, specify the current development version as Spring.profiles. active=dev

In this way, you can access the corresponding set 8080, and if you set it to something else, you can only access something else

(5) Configure groups

In the UI you can actually notice there’s a default in the top right corner and a drop-down option.

This is the concept of grouping, that is, we are going to implement the classification of API interfaces

The method is very simple, just by calling groupName() in the Docket

@Bean
public Docket docketA(a){
    return new Docket(DocumentationType.SWAGGER_2).groupName("groupA");
}
@Bean
public Docket docketB(a){
    return new Docket(DocumentationType.SWAGGER_2).groupName("groupB");
}
@Bean
public Docket docketC(a){
    return new Docket(DocumentationType.SWAGGER_2).groupName("groupC");
}
Copy the code

After the restart, you can see the effect of groups. Different configurations in different groups can achieve different access effects

(6) Commonly used annotations

(a) function in class

(1) @Api()

I have written some common annotations and their parameters, not all, but should be enough

Swagger with notes more fragrant Oh ~

@api () : indicates that this class is a Swagger resource

  • Tags: Indicates the description. You can omit the attribute name by simply writing tags
  • Value: Same description, but replaced by tags
@api (value = "test interface value", tags =" test interface tags ")
@RestController
@RequestMapping("test/")
public class TestController {... }Copy the code

Tags and value are both defined above, and only tags are displayed at the end. Both can be used separately

(2) function in the method

(1) @ApiOperation()

@apiOperation () : A description of a method, with annotations on the method

  • Value: description of the method
  • Notes: Additional notes
  • Response: Object returned
  • Tags: This method will be isolated and regrouped
@apiOperation (value = "User information query method value ", notes =" This is the annotation of User information query method ", response = user.class, tags = {" User information query method tags "})
@GetMapping("/queryUser")
public User queryUser(a) {... }Copy the code

Note: Comments need to be clicked on each method to see them

Add: if you use @requestMapping () annotations on methods, there will be various types of instructions in the document, such as GET, POST, etc., so we usually specify the request type, such as @getMapping (“/queryUser”).

(2) @ApiParam()

@apiParam () : Specifies method arguments

  • Name: parameter name
  • Value: indicates the parameter description
  • Required: Indicates whether the field is mandatory
@apiOperation (value = "user login method ", notes =" user login notes ")
@PostMapping("/login")
public String login(@apiparam (name = "username", value = "username", required = true) String username,
                    @apiparam (name = "password", value = "password", required = true) String password) {
    if ("123".equals(username) && "123".equals(password)) {
        return "Login successful";
    } else {
        return "Login failed"; }}Copy the code

Click on this method and you can see that the annotations are present in the document

(3) function in model class

(1) @ApiModel()

@ApiModel() applies to model classes, such as VO and BO, to describe the class

  • Value: indicates the name of the model
  • Description: A description

(2) @ApiModelProperty()

The @apiModelProperty () function applies to class methods and properties and represents the description of the properties

  • Value: indicates the field description
  • Name: Override attribute name
  • DataType: Override attribute type
  • Required: Indicates whether the field is mandatory
  • It’s an example
  • Hidden hidden:

This model specification is displayed on the first page of the document and when the specific method is involved

Springboot integrates Swagger3

Most of it has been mentioned above, so here are just a few of the differences

One is relying on a 3.0 starter

Return new Docket(documentationType.oas_30)

The @enablesWagger2 annotation is not needed

@enableOpenAPI is required to start a class

※ The boot path becomes

http://localhost:8080/swagger-ui/index.html

(1) Introduce dependency

<dependency>
    <groupId>io.springfox</groupId>
    <artifactId>springfox-boot-starter</artifactId>
    <version>3.0.0</version>
</dependency>
Copy the code

(2) Configuration classes

@Configuration
public class Swagger3Config {
    @Bean
    public Docket createRestApi(Environment environment) {
        // Set the environment to display Swagger
        Profiles of = Profiles.of("dev"."test");
        // Determine whether the current environment
        boolean flag = environment.acceptsProfiles(of);

        return new Docket(DocumentationType.OAS_30)
                .apiInfo(apiInfo())
                // Accept with enable() to determine whether to display
                .enable(flag)
                Select () to configure the scanning interface
                .select()
                // RequestHandlerSelectors Sets the mode of scanning interfaces
                .apis(RequestHandlerSelectors.basePackage("cn.ideal.controller"))
                .paths(PathSelectors.ant("/test/**"))
                .build();
    }

    private ApiInfo apiInfo(a) {
        Contact contact = new Contact("BWH_Steven"."https://www.ideal-20.cn"."[email protected]");
        return new ApiInfo(
                "Swagger3 learning -- More than 20 years of ideal"./ / title
                Learn how to configure Swagger2./ / description
                "v1.0"./ / version
                "https://www.ideal-20.cn".// Organize links
                contact, // Contact information
                "Apache 2.0 License"./ / permission
                "Permission link".// Permit connection
                new ArrayList<>()/ / extension); }}Copy the code

See the effect

Four Swagger test

Swagger is not just a generic document, it can be tested directly on the generated document, along with documentation instructions, which is very easy to test

For example, after you click Try it out, you can test a query method with no parameters, so you can click Excute and see the response

In response to the results