What is a Swagger

Swagger is a series of RESTful API tools, through Swagger can obtain an interactive document of the project, client SDK automatic generation and other functions.

Swagger’s goal is to define a standard, language-neutral interface for REST APIs that enables people and computers to discover and understand the capabilities of various services without access to source code or documentation or network traffic detection. When the service is defined by Swagger, the consumer can interact with the remote service with a little implementation logic. Like a low-level programming interface, Swagger takes a lot of the guesswork out of calling services.

Swagger is the most popular API in the world.

Swagger is a simple but powerful API presentation tool. It has the largest API tool ecosystem on the planet, with thousands of developers, using almost every modern programming language, all supporting and using Swagger. Using the Swagger generation API, we can get interactive documentation, an SDK for automatically generating code, and API discovery features.

The idea of integrating Swagger with Spring Boot is to use annotations to mark up information that needs to be displayed in API documents, and Swagger will generate corresponding API documents based on the annotations marked in the project. Swagger is known as the most popular API tool in the world, it provides a complete solution for API management, API document management needs to consider the basic factors, here will explain the most common customization content.

Quick learning

Spring Boot integration with Swagger 2.X is easy to implement. It requires the introduction of dependencies and basic configuration.

Adding a dependency package

< the dependency > < groupId > IO. Springfox < / groupId > < artifactId > springfox - swagger2 < / artifactId > < version > 2.8.0 < / version > </dependency> <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger-ui</artifactId> The < version > 2.8.0 < / version > < / dependency >Copy the code

Create the SwaggerConfig configuration class

@Configuration
@EnableSwagger2
public class SwaggerConfig {
}
Copy the code

Add two annotations to SwaggerConfig’s class:

  • @configuration. This class is loaded at startup
  • @enablesWagger2, indicates that this project enables Swagger API documentation

Add two methods to SwaggerConfig:

@ Bean public Docket API () {return new Docket (DocumentationType. SWAGGER_2). ApiInfo (apiInfo ()). The select () / / to modify for their own path .apis(RequestHandlerSelectors.basePackage("com.neo.xxx")) .paths(PathSelectors.any()) .build(); }Copy the code

This method uses @bean, initialized at startup, returns instance Docket (Swagger API abstract), It is important to note here. The apis (RequestHandlerSelectors basePackage (com. Neo. “XXX”)) need to scan the package specified path, only the path of the Controller will automatically generate Swagger API documentation.

Private ApiInfo ApiInfo () {return new ApiInfoBuilder().title(" client management ").description(" client management API 1.0 operation documentation ") // Terms of Service url TermsOfServiceUrl (" http://www.ityouknow.com/ "). The version (" 1.0 "). Contact (new contact (" pure smile," "http://www.ityouknow.com/", "[email protected]")) .build(); }Copy the code

This configuration is relatively important. The basic information displayed on the main configuration page includes title, description, version, terms of service, and contact information. Check the source code of the ApiInfo class to find that license configuration is supported.

public class ApiInfo { public static final Contact DEFAULT_CONTACT = new Contact("", "", ""); public static final ApiInfo DEFAULT; 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

All of the above information can be configured in this method, or the default values can be used. Start the project after configuration is complete, enter http://localhost:8080/swagger-ui.html in the browser, you can see the above configuration information, the effect is as follows:

No Operations defined in spec! “, meaning that the relevant API content is not found, because the corresponding Controller information has not been added, the following code will introduce the use of each annotation one by one.

Swagger

Swagger indicates that the interface will generate documents through annotations, including interface name, request method, parameters, returned information, etc. Commonly used annotations are as follows:

scope API Use location
Protocol Set Description @Api For the Controller class
Protocol description @ApiOperation Let’s use the Controller method
A non-object parameter set @ApiImplicitParams In the @apiImplicitParams method
The response set @ApiResponses Let’s use the Controller method
Response information parameter @ApiResponse Used in @ApiResponses
Describes the meaning of the returned object @ApiModel Used on return object classes
Object properties @ApiModelProperty Used on fields of the inbound and outbound parameter objects

Build on the example project covered in Lessons 2-8 and add examples of RESTful API documentation.

@ the use of Api

The Api applies to the Controller Class as a Swagger resource. This annotation marks a Controller (Class) as a Swagger resource (Api). By default, Swagger-core only scans and resolves classes with @API annotations, and automatically ignores annotations from other categories of resources (JAX-RS endpoints, Servlets, and so on).

Example:

@api (value = "message ", description =" message operation Api ", position = 100, protocols = "http") @RestController @RequestMapping("/") public class MessageController { }Copy the code

Used in conjunction with the Controller annotation, the properties are configured as shown in the table:

The attribute name note
value Path value of the URL
tags If you set this value, the value of value is overwritten
description Description of API resources
produces For example, “application/json, application/xml”
consumes For example, “application/json, application/xml”
protocols Possible values: http, https, ws, wss
authorizations This parameter is configured for advanced feature authentication
hidden Setting it to true will be hidden in the document

After the restart the project, input http://localhost:8080/swagger-ui.html#/message-controller in the browser, you can see the following effects:

The methods in the MessageController are automatically mapped and the request method for each method is indicated.

The use of the @ ApiOperation

ApiOperation is defined on a method and describes the method name, method interpretation, return information, tags, and other information.

Example:

@APIOperation (value =" message list ", Notes =" Complete message content list ", Produces ="application/json, application/ XML ", consumes="application/json, application/xml", response = List.class) @GetMapping(value = "messages") public List<Message> list() { }Copy the code
The attribute name note
value Path value of the URL
tags If you set this value, the value of value will be overwritten
produces For example, “application/json, application/xml”
consumes For example, “application/json, application/xml”
protocols Possible values: http, https, ws, wss
authorizations This parameter is configured for advanced feature authentication
hidden Setting it to true will be hidden in the document
response Object returned
responseContainer These objects are valid “List”, “Set” or “Map”, and others are invalid
httpMethod “GET”, “HEAD”, “POST”, “PUT”, “DELETE”, “OPTIONS” and “PATCH”
code The default HTTP status code is 200
extensions Extended attributes

After the restart the project, input http://localhost:8080/swagger-ui.html#/message-controller/listUsingGET in the browser, you can see the following effects:

Use of @apiIMPLicitParams and @apiIMPLicitParam

@apiIMPLICITParams is used to describe the information returned by the method, in conjunction with the @apiIMPLicitParam annotation; @apiIMPLICITParam Describes information about a parameter, including the parameter name, type, and limit.

Example:

@apiImplICITParams ({@apiIMPLICITParam (name = "id", value = "message ID", Required = true, dataType = "Long", paramType = "query"), @APIIMPLICITParam (name = "text", value = "text", Required = true, dataType = "String", paramType = "query"), @APIIMPLICITParam (name = "summary", value = "summary", required = false, dataType = "String", paramType = "query"), }) @PostMapping(value = "message") public Message create(Message message) { }Copy the code
The attribute name note
Name Name of the receiving parameter
Value Indicates the description of the received parameters
Whether the required parameter must be true or false
The dataType of the dataType parameter is indicated only as a flag and is not actually validated

ParamType Specifies the query parameter type. The value is as follows: Path submits data as an address query automatically maps directly to parameters Body submits data as a stream, Only the POST header parameter is supported. Submit a form from request Headers. Submit the form as a form

After the restart the project, input http://localhost:8080/swagger-ui.html#/message-controller/createUsingPOST in the browser, you can see the following effects:

The use of @apiresponses and @apiResponse

@APIresponses mainly encapsulates the return information of the method and @APIResponse is configured to be used. @APIResponse defines the specific information returned, including return code and return information.

Example:

@apiOperation (value = "modify message ", Notes = "Modify messages according to parameters ") @putMapping (value = "message") @apiresponses ({@apiResponse (code = 100, message =" request parameters wrong "), @apiResponse (code = 101, message = "unauthorized "), @apiResponse (code = 103, message =" forbidden "), @apiResponse (code = 104, message = "forbidden "), @apiResponse (code = 104, message =" forbidden "), Message = "request path not found "), @apiResponse (code = 200, message =" server internal error ")}) public message modify(message message) {}Copy the code
The attribute name note

Code HTTP status code Message Description Response Default response class Void Reference Reference responseHeaders Encapsulation Return information responseContainer A character string

After the restart the project, input http://localhost:8080/swagger-ui.html#/message-controller/modifyUsingPUT in the browser, you can see the following effects:

Use of @APIModel and @APIModelProperty

In real projects, we often encapsulate an object as a return value. @APIModel is responsible for describing the information of the object, and @APIModelProperty is responsible for describing the properties of the object.

Example:

@apiModel (description = "response object ") public class BaseResult<T> {private static final int SUCCESS_CODE = 0; Private static final String SUCCESS_MESSAGE = "success "; @APIModelProperty (value = "response code", name = "code", Required = true, example =" + SUCCESS_CODE) private int code; @APIModelProperty (value = "response message ", name =" MSG ", Required = true, example = SUCCESS_MESSAGE) private String MSG; @apiModelProperty (value = "data", name = "data") private T data; }Copy the code

The following table shows the attribute configuration:

The attribute name note
value Property description
name If override attribute name is configured
allowableValues Allowed values
access Do not configure
notes Don’t use
dataType The data type
required Specifies whether this parameter is mandatory
position The sequential position displayed
hidden If so
example For example,
readOnly read-only
reference reference

So we can wrap the return information in the Controller like this:

@PatchMapping(value="/message/text")
public BaseResult<Message> patch(Message message) {
    Message messageResult=this.messageRepository.updateText(message);
    return BaseResult.successWithData(messageResult);
}
Copy the code

After the restart the project, input http://localhost:8080/swagger-ui.html in the browser, why page Models drawer, you can see the following effects:

These are some of the most commonly used annotations in a project and can be used flexibly to automatically build clear API documentation.

Try it out

The online API created with Swagger also has a very powerful capability to test the availability of the interface directly on the page, making it very convenient to use this capability for interface validation in the event of problems with front-end and back-end interface debugging. In the above parameter explanation, we found that there is a button “Try it Out” on the right of each interface description. Click “Try it Out” to enter the form page, as follows:

Curl curl curl curl curl curl curl curl curl curl curl curl curl curl

curl -X POST "http://localhost:8080/message? id=6&summary=%E8%BF%99%E6%98%AF%E4%B8%80%E4%B8%AA%E6%B6%88%E6%81%AF&text=hello" -H "accept: */*"Copy the code

You can see the change of the parameters of the curl command by adjusting Swagger parameters in the back end.

Export the Swagger2 document using Swagger2Markup

Introduce dependencies and plug-ins

<! <dependency> <groupId> IO. Github. Swagger2markup </groupId> <artifactId> The < version > 1.3.3 < / version > < / dependency >Copy the code
<! -> < plugins > -> < plugins > < the groupId > org. Asciidoctor < / groupId > < artifactId > asciidoctor maven - plugin < / artifactId > < version > 1.5.6 < / version > <configuration> <sourceDirectory>./docs/asciidoc/generated</sourceDirectory>
					<outputDirectory>./docs/asciidoc/html</outputDirectory>
					<headerFooter>true</headerFooter>
					<doctype>book</doctype>
					<backend>html</backend>
					<sourceHighlighter>coderay</sourceHighlighter> <attributes> <! Menu bar on the left --> <toc>left</ TOC > <! 3</toclevels> <! --> <sectnums>true</sectnums>
					</attributes>
				</configuration>
			</plugin>
Copy the code

Full of pom

<? 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 > < the parent > < groupId > org. Springframework. Boot < / groupId > The < artifactId > spring - the boot - starter - parent < / artifactId > < version > 2.2.2. RELEASE < / version > < relativePath / > <! -- lookup parent from repository --> </parent> <groupId>com.lichongbing</groupId> < artifactId > springboot -- learn -- swagger docs - study < / artifactId > < version > 0.0.1 - the SNAPSHOT < / version > <name>springboot-learn-swagger-docs-study</name> <description>Demo projectforSpring Boot</description> <properties> <java.version>1.8</java.version> </properties> <dependencies> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> < the groupId > IO. Springfox < / groupId > < artifactId > springfox - swagger2 < / artifactId > < version > 2.9.2 < / version > < / dependency > < the dependency > < groupId > IO. Springfox < / groupId > < artifactId > springfox swagger - UI < / artifactId > < version > 2.9.2 < / version > </dependency> <! --> <dependency> <groupId> IO. Github. Swagger2markup </groupId> <artifactId> < version > 1.3.3 < / version > < / dependency > < the dependency > < groupId > nl. Jworks. Markdown_to_asciidoc < / groupId > < artifactId > markdown_to_asciidoc < / artifactId > < version > 1.1 sources < / version > < / dependency > < the dependency > <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope>
			<exclusions>
				<exclusion>
					<groupId>org.junit.vintage</groupId>
					<artifactId>junit-vintage-engine</artifactId>
				</exclusion>
			</exclusions>
		</dependency>
		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<scope>test</scope> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> <! -> < plugins > -> < plugins > < the groupId > org. Asciidoctor < / groupId > < artifactId > asciidoctor maven - plugin < / artifactId > < version > 1.5.6 < / version > <configuration> <sourceDirectory>./docs/asciidoc/generated</sourceDirectory>
					<outputDirectory>./docs/asciidoc/html</outputDirectory>
					<headerFooter>true</headerFooter>
					<doctype>book</doctype>
					<backend>html</backend>
					<sourceHighlighter>coderay</sourceHighlighter> <attributes> <! Menu bar on the left --> <toc>left</ TOC > <! 3</toclevels> <! --> <sectnums>true</sectnums>
					</attributes>
				</configuration>
			</plugin>

		</plugins>
	</build>

</project>


Copy the code

Write a test class

package com.lichongbing; import io.github.swagger2markup.GroupBy; import io.github.swagger2markup.Language; import io.github.swagger2markup.Swagger2MarkupConfig; import io.github.swagger2markup.Swagger2MarkupConverter; import io.github.swagger2markup.builder.Swagger2MarkupConfigBuilder; import io.github.swagger2markup.markup.builder.MarkupLanguage; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringRunner; import java.net.URL; import java.nio.file.Paths; /** * @author lichongbing * @email [email protected] * @date 2020/01/02 19:31 * com.lichongbing */ @runwith (springrunner.class) @SpringbooTtest Public Class ApplicationIntfTests {/** * Generates AsciiDocs format documents ** @throws Exception */ @test public void generateAsciiDocs() throws Exception {// Output the Ascii format Swagger2MarkupConfig config = new Swagger2MarkupConfigBuilder() .withMarkupLanguage(MarkupLanguage.ASCIIDOC) .withOutputLanguage(Language.ZH) .withPathsGroupedBy(GroupBy.TAGS) .withGeneratedExamples() .withoutInlineSchema() .build(); Swagger2MarkupConverter.from(new URL("http://localhost:8080/v2/api-docs"))
                .withConfig(config)
                .build()
                .toFolder(Paths.get("./docs/asciidoc/generated")); } /** * Generate Markdown format documents ** @throws Exception */ @test public void generateMarkdownDocs() throws Exception {// Output format Markdown Swagger2MarkupConfig config = new Swagger2MarkupConfigBuilder () .withMarkupLanguage(MarkupLanguage.MARKDOWN) .withOutputLanguage(Language.ZH) .withPathsGroupedBy(GroupBy.TAGS) .withGeneratedExamples() .withoutInlineSchema() .build(); Swagger2MarkupConverter.from(new URL("http://localhost:8080/v2/api-docs"))
                .withConfig(config)
                .build()
                .toFolder(Paths.get("./docs/markdown/generated")); ** * Throws Exception */ @test public void generateConfluenceDocs() throws Exception {// The format of the output Confluence was using Swagger2MarkupConfig config = new Swagger2MarkupConfigBuilder () .withMarkupLanguage(MarkupLanguage.CONFLUENCE_MARKUP) .withOutputLanguage(Language.ZH) .withPathsGroupedBy(GroupBy.TAGS)  .withGeneratedExamples() .withoutInlineSchema() .build(); Swagger2MarkupConverter.from(new URL("http://localhost:8080/v2/api-docs"))
                .withConfig(config)
                .build()
                .toFolder(Paths.get("./docs/confluence/generated")); } /** * Generate an AsciiDocs document and aggregate it into a file ** @throws Exception */ @test public void generateAsciiDocsToFile() throws Exception { / / output Ascii to single file Swagger2MarkupConfig config = new Swagger2MarkupConfigBuilder () .withMarkupLanguage(MarkupLanguage.ASCIIDOC) .withOutputLanguage(Language.ZH) .withPathsGroupedBy(GroupBy.TAGS) .withGeneratedExamples() .withoutInlineSchema() .build(); Swagger2MarkupConverter.from(new URL("http://localhost:8080/v2/api-docs"))
                .withConfig(config)
                .build()
                .toFile(Paths.get("./docs/asciidoc/generated/all")); } / * * * generate Markdown document format, and rolled into a file * * @ throws the Exception * / @ Test public void generateMarkdownDocsToFile () throws the Exception {/ / output Markdown to single file Swagger2MarkupConfig config = new Swagger2MarkupConfigBuilder () .withMarkupLanguage(MarkupLanguage.MARKDOWN) .withOutputLanguage(Language.ZH) .withPathsGroupedBy(GroupBy.TAGS) .withGeneratedExamples() .withoutInlineSchema() .build(); Swagger2MarkupConverter.from(new URL("http://localhost:8080/v2/api-docs"))
                .withConfig(config)
                .build()
                .toFile(Paths.get("./docs/markdown/generated/all")); }}Copy the code

Start the project, get the ADDRESS of the JSON file, and then close the project, otherwise the port will be reported to be occupied when the test is allowed later

Run the five tests in Step 2. If the docs/ Markdown folder does not exist, create the folder manually. If there are no exceptions, generated generates an. Adoc file

.├ ── all. ├── All. ├── All ├─ ├─ TXT ├─ TXT ├─ TXT ├─ TXT ├─ TXT ├─ TXT ├─ TXT ├─ TXT ├─ TXT ├─ TXT └── all. School exercises ── all. School Exercises ─ allCopy the code

Run the Maven command asciidoctor:process-asciidoc to generate the HTML

mvn asciidoctor:process-asciidoc

Copy the code

That’s it. Just go to all.html

├ ─ ─ asciidoc │ ├ ─ ─ generated │ │ ├ ─ ─ all the adoc │ │ ├ ─ ─ definitions. The adoc │ │ ├ ─ ─ the overview. The adoc │ │ ├ ─ ─ paths. The adoc │ │ └ ─ ─ Security. The adoc │ └ ─ ─ HTML │ ├ ─ ─ all the HTML │ ├ ─ ─ definitions. The HTML │ ├ ─ ─ the overview. The HTML │ ├ ─ ─ paths. The HTML │ └ ─ ─ security. The HTML ├ ─ ─ confluence was │ └ ─ ─ generated │ ├ ─ ─ definitions. TXT │ ├ ─ ─ the overview. TXT │ ├ ─ ─ paths. TXT │ └ ─ ─ security. TXT └ ─ ─ markdown └── all. School exercises ── definitions. School ExercisesCopy the code

conclusion

Through the learning of this lesson, we have mastered the use of Swagger in Spring Boot project, and rich API documents can be easily constructed by using Swagger’s relevant annotations. Using Swagger can help generate standard API documentation to avoid inefficient communication in interface interaction. As a powerful API generation framework, Swagger actually has more functions, so you can have the opportunity to continue learning offline.

Click here to download the source.

Springboot2. X integrates Swagger2 and outputs offline documents in HTML, ADOc, Markdown, and text formats