Select only the web from https://start.spring.io/ and create it quickly
I didn't have a Swagger, so I brought it from the Maven Repository
Please refer to build.gradle
for version etc.
Sample code https://github.com/ririkku/swagger-demo
build.gradle
plugins {
id 'org.springframework.boot' version '2.2.1.RELEASE'
id 'io.spring.dependency-management' version '1.0.8.RELEASE'
id 'java'
}
group = 'com.example'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '1.8'
repositories {
mavenCentral()
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-web'
//Minimum required for Swagger
implementation "io.springfox:springfox-swagger2:2.9.2"
implementation "io.springfox:springfox-swagger-ui:2.9.2"
testImplementation('org.springframework.boot:spring-boot-starter-test') {
exclude group: 'org.junit.vintage', module: 'junit-vintage-engine'
}
}
test {
useJUnitPlatform()
}
SwaggerDemoApplication.java
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class SwaggerDemoApplication {
public static void main(String[] args) {
SpringApplication.run(SwaggerDemoApplication.class, args);
}
}
SwaggerDemoConfiguration.java
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
@Configuration
@EnableSwagger2 // swagger2.Use 0
public class SwaggerDemoConfiguration {
@Bean
public Docket petApi() {
return new Docket(DocumentationType.SWAGGER_2) // Swagger2.Declaration to use 0
.select()
.paths(PathSelectors.ant("/apis/**"))
.build();
}
}
SwaggerDemoRestController.java
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("apis")
public class SwaggerDemoRestController {
@GetMapping
public String get() {
return "get";
}
}
I usually start it from Intellij IDEA, but some people are not in that environment, so I start it with Gradle
./gradlew bootRun
Access on localhost
http://localhost:8080/swagger-ui.html
(Since it did not fit, it was divided into two)
UI is good! !! !! I didn't write much code and it might be practical But it feels a lot of humor, let's customize it a little
SwaggerDemoConfiguration.java
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.service.Contact;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
@Configuration
@EnableSwagger2 // swagger2.Use 0
public class SwaggerDemoConfiguration {
@Bean
public Docket petApi() {
return new Docket(DocumentationType.SWAGGER_2) // Swagger2.Declaration to use 0
.select()
.paths(PathSelectors.ant("/apis/**"))
.build()
.apiInfo(new ApiInfoBuilder()
.title("Customise Title Swagger Demo Application")
.description("I customized it to my liking")
.contact(new Contact("customise-name", "http://customise-contact", "customise-email"))
.version("1.0")
.termsOfServiceUrl("http://customise.com")
.license("Customise License").licenseUrl("http://customise-license-url") //Text if only license, link if licenseUrl is set
.build());
}
}
The place where the suffix of Customise
was rewritten
Can I change the parts of Base URL
and http // localhost: 8080 / v2 / api-docs
? Impressions
Also, ʻextensions can be set in the ʻApiInfoBuilder
class
Do you use it when you want to create your own plug-in? (https://swagger.io/docs/specification/2-0/swagger-extensions/)
No, what does the Http method look like?
SwaggerDemoRestController.java
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("apis")
public class SwaggerDemoRestController {
@GetMapping
public String get() {
return "get";
}
@PostMapping
public void post() {
}
@DeleteMapping
public void delete() {
}
@PutMapping
public void put() {
}
@PatchMapping
public void patch() {
}
}
I saw GET a while ago, so next time I feel like POST
Colorful and easy to see (PATCH or something) It seems that the details of the API will be taken into consideration in various ways (status code, etc.) Next, let's customize the details
I changed my mind and created a new class
On purpose, @PathVariable
is bound to a class, and @RequestParam
is bound to a String!
Identifier.java
public class Identifier {
private String value;
public Identifier(String value) {
this.value = value;
}
public String value() {
if (value == null) return "";
return value;
}
}
SwaggerDemoCustomiseRestController.java
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("apis/customise")
public class SwaggerDemoCustomiseRestController {
@GetMapping("{identifier}")
public String detail(@RequestHeader("X-Customise-Header") String customiseHeader,
@PathVariable("identifier") Identifier identifier,
@RequestParam(value = "name", required = false) String name,
@RequestParam("limit") int limit) {
return identifier.value();
}
}
I tried putting @RequestHeader
, @PathVariable
, @RequestParam
Mandatory things are now marked with required
, which is convenient.
By the way, when you press the Try it out
button, the following display is displayed and you can enter the value and verify it!
Press ʻExecute and you'll get
curl,
Request URL,
ResponseCode,
ResponseBody, and
ResponseHeaders`!
Looks pretty convenient Next, let's limit the response status that is generated arbitrarily to only what you want
By setting ʻuseDefaultResponseMessages, only
200` will be set as the default.
SwaggerDemoConfiguration.java
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.service.Contact;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
@Configuration
@EnableSwagger2 // swagger2.Use 0
public class SwaggerDemoConfiguration {
@Bean
public Docket petApi() {
return new Docket(DocumentationType.SWAGGER_2) // Swagger2.Declaration to use 0
.select()
.paths(PathSelectors.ant("/apis/**"))
.build()
.useDefaultResponseMessages(false) // <-add to
.apiInfo(new ApiInfoBuilder()
.title("Customise Title Swagger Demo Application")
.description("I customized it to my liking")
.contact(new Contact("customise-name", "http://customise-contact", "customise-email"))
.version("1.0")
.termsOfServiceUrl("http://customise.com")
.license("Customise License").licenseUrl("http://customise-license-url") //Text if only license, link if licenseUrl is set
.build());
}
}
Oshisuke disappeared Next, let's define all the APIs of the cases that are likely to be actually used.
I just want to use Swagger, so the processing content is appropriate of appropriate
LessonIdentifier.java
class LessonIdentifier {
private Integer value;
LessonIdentifier(String value) {
this.value = Integer.valueOf(value);
}
LessonIdentifier(int value) {
this.value = value;
}
Integer value() {
if (value == null) return 0;
return value;
}
}
LessonRequest.java
public class LessonRequest {
private String studentName;
private String tutorName;
public LessonRequest(String studentName, String tutorName) {
this.studentName = studentName;
this.tutorName = tutorName;
}
public String getStudentName() {
return studentName;
}
public String getTutorName() {
return tutorName;
}
}
LessonResponse.java
public class LessonResponse {
private int id;
private String studentName;
private String tutorName;
LessonResponse(int id, String studentName, String tutorName) {
this.id = id;
this.studentName = studentName;
this.tutorName = tutorName;
}
public int getId() {
return id;
}
public String getStudentName() {
return studentName;
}
public String getTutorName() {
return tutorName;
}
}
LessonIdentifierResponse.java
public class LessonIdentifierResponse {
private int value;
LessonIdentifierResponse(LessonIdentifier lessonIdentifier) {
this.value = lessonIdentifier.value();
}
public int getValue() {
return value;
}
}
ErrorResponse.java
public class ErrorResponse {
private String message;
public ErrorResponse(String message) {
this.message = message;
}
public String getMessage() {
return message;
}
}
LessonController.java
import io.swagger.annotations.ApiResponse;
import io.swagger.annotations.ApiResponses;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.*;
import java.util.Arrays;
import java.util.List;
@RestController
@RequestMapping("apis/lessons")
public class LessonController {
@ApiResponse(code = 400, message = "Bad Request", response = ErrorResponse.class)
@GetMapping
@ResponseStatus(HttpStatus.OK)
public List<LessonResponse> list() {
//Acquisition process
return Arrays.asList(
new LessonResponse(1, "studentName1", "tutorName1"),
new LessonResponse(2, "studentName2", "tutorName2"),
new LessonResponse(3, "studentName3", "tutorName3"));
}
@ApiResponses(value = {
@ApiResponse(code = 400, message = "Bad Request", response = ErrorResponse.class),
@ApiResponse(code = 404, message = "Not Found", response = ErrorResponse.class)})
@GetMapping("{lessonIdentifier}")
@ResponseStatus(HttpStatus.OK)
public LessonResponse detail(@PathVariable("lessonIdentifier") LessonIdentifier lessonIdentifier) {
//Acquisition process
return new LessonResponse(1, "studentName1", "tutorName1");
}
@ApiResponses(value = {
@ApiResponse(code = 400, message = "Bad Request", response = ErrorResponse.class),
@ApiResponse(code = 404, message = "Not Found", response = ErrorResponse.class)})
@PostMapping
@ResponseStatus(HttpStatus.CREATED)
public LessonIdentifierResponse add(@RequestBody LessonRequest lessonRequest) {
//Additional processing
return new LessonIdentifierResponse(new LessonIdentifier(4));
}
@ApiResponses(value = {
@ApiResponse(code = 400, message = "Bad Request", response = ErrorResponse.class),
@ApiResponse(code = 404, message = "Not Found", response = ErrorResponse.class)})
@DeleteMapping("{lessonIdentifier}")
@ResponseStatus(HttpStatus.NO_CONTENT)
public void delete(@PathVariable("lessonIdentifier") LessonIdentifier lessonIdentifier) {
//Delete process
}
@ApiResponses(value = {
@ApiResponse(code = 400, message = "Bad Request", response = ErrorResponse.class),
@ApiResponse(code = 404, message = "Not Found", response = ErrorResponse.class)})
@PutMapping("{lessonIdentifier}")
@ResponseStatus(HttpStatus.OK)
public LessonResponse edit(@PathVariable("lessonIdentifier") LessonIdentifier lessonIdentifier,
@RequestBody LessonRequest lessonRequest) {
//Editing process
return new LessonResponse(1, "EditStudentName1", "EditTutorName1");
}
}
There are many, so only some
ʻExample Valuecame out nicely Also, only those specified by
ResponseStatus`!
I've come to a point where I can use it nicely Want to write an API description? So I will write it
I tried adding @ApiOperation
LessonController.java
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiResponse;
import io.swagger.annotations.ApiResponses;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.*;
import java.util.Arrays;
import java.util.List;
@RestController
@RequestMapping("apis/lessons")
public class LessonController {
@ApiOperation(value = "Get a list of lessons", notes = "Take all records without search criteria to stop the time in your browser.")
@ApiResponse(code = 400, message = "Bad Request", response = ErrorResponse.class)
@GetMapping
@ResponseStatus(HttpStatus.OK)
public List<LessonResponse> list() {
//Acquisition process
return Arrays.asList(
new LessonResponse(1, "studentName1", "tutorName1"),
new LessonResponse(2, "studentName2", "tutorName2"),
new LessonResponse(3, "studentName3", "tutorName3"));
}
@ApiOperation(value = "Get a lesson", notes = "ID指定したGet a lesson")
@ApiResponses(value = {
@ApiResponse(code = 400, message = "Bad Request", response = ErrorResponse.class),
@ApiResponse(code = 404, message = "Not Found", response = ErrorResponse.class)})
@GetMapping("{lessonIdentifier}")
@ResponseStatus(HttpStatus.OK)
public LessonResponse detail(@PathVariable("lessonIdentifier") LessonIdentifier lessonIdentifier) {
//Acquisition process
return new LessonResponse(1, "studentName1", "tutorName1");
}
@ApiOperation(value = "Create a lesson", notes = "After creating it, it will return the ID!")
@ApiResponses(value = {
@ApiResponse(code = 400, message = "Bad Request", response = ErrorResponse.class),
@ApiResponse(code = 404, message = "Not Found", response = ErrorResponse.class)})
@PostMapping
@ResponseStatus(HttpStatus.CREATED)
public LessonIdentifierResponse add(@RequestBody LessonRequest lessonRequest) {
//Additional processing
return new LessonIdentifierResponse(new LessonIdentifier(4));
}
@ApiOperation(value = "Delete lesson", notes = "I won't return anything")
@ApiResponses(value = {
@ApiResponse(code = 400, message = "Bad Request", response = ErrorResponse.class),
@ApiResponse(code = 404, message = "Not Found", response = ErrorResponse.class)})
@DeleteMapping("{lessonIdentifier}")
@ResponseStatus(HttpStatus.NO_CONTENT)
public void delete(@PathVariable("lessonIdentifier") LessonIdentifier lessonIdentifier) {
//Delete process
}
@ApiOperation(value = "Edit lesson", notes = "Returns the edited lesson!")
@ApiResponses(value = {
@ApiResponse(code = 400, message = "Bad Request", response = ErrorResponse.class),
@ApiResponse(code = 404, message = "Not Found", response = ErrorResponse.class)})
@PutMapping("{lessonIdentifier}")
@ResponseStatus(HttpStatus.OK)
public LessonResponse edit(@PathVariable("lessonIdentifier") LessonIdentifier lessonIdentifier,
@RequestBody LessonRequest lessonRequest) {
//Editing process
return new LessonResponse(1, "EditStudentName1", "EditTutorName1");
}
}
Details are now available!
However, I don't like the messages written in @ApiOperation
or @ApiResponse
becoming too long. .. ..
I will try it by wondering if it can be made into a separate file
application.properties
LessonController.list.value=Get a list of lessons
LessonController.list.notes=Stop time in your browser by taking all records without search criteria
LessonController.detail.value=Get a lesson
LessonController.detail.notes=Get the lesson with the specified ID
LessonController.add.value=Create a lesson
LessonController.add.notes=After creating it, it will return the ID!
LessonController.delete.value=Delete lesson
LessonController.delete.notes=I won't return anything
LessonController.edit.value=Edit lesson
LessonController.edit.notes=Returns the edited lesson!
LessonController.java
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiResponse;
import io.swagger.annotations.ApiResponses;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.*;
import java.util.Arrays;
import java.util.List;
@RestController
@RequestMapping("apis/lessons")
public class LessonController {
@ApiOperation(value = "${LessonController.list.value}", notes = "${LessonController.list.notes}")
@ApiResponse(code = 400, message = "Bad Request", response = ErrorResponse.class)
@GetMapping
@ResponseStatus(HttpStatus.OK)
public List<LessonResponse> list() {
//Acquisition process
return Arrays.asList(
new LessonResponse(1, "studentName1", "tutorName1"),
new LessonResponse(2, "studentName2", "tutorName2"),
new LessonResponse(3, "studentName3", "tutorName3"));
}
@ApiOperation(value = "${LessonController.detail.value}", notes = "${LessonController.detail.notes}")
@ApiResponses(value = {
@ApiResponse(code = 400, message = "Bad Request", response = ErrorResponse.class),
@ApiResponse(code = 404, message = "Not Found", response = ErrorResponse.class)})
@GetMapping("{lessonIdentifier}")
@ResponseStatus(HttpStatus.OK)
public LessonResponse detail(@PathVariable("lessonIdentifier") LessonIdentifier lessonIdentifier) {
//Acquisition process
return new LessonResponse(1, "studentName1", "tutorName1");
}
@ApiOperation(value = "${LessonController.add.value}", notes = "${LessonController.add.notes}")
@ApiResponses(value = {
@ApiResponse(code = 400, message = "Bad Request", response = ErrorResponse.class),
@ApiResponse(code = 404, message = "Not Found", response = ErrorResponse.class)})
@PostMapping
@ResponseStatus(HttpStatus.CREATED)
public LessonIdentifierResponse add(@RequestBody LessonRequest lessonRequest) {
//Additional processing
return new LessonIdentifierResponse(new LessonIdentifier(4));
}
@ApiOperation(value = "${LessonController.delelte.value}", notes = "${LessonController.delete.notes}")
@ApiResponses(value = {
@ApiResponse(code = 400, message = "Bad Request", response = ErrorResponse.class),
@ApiResponse(code = 404, message = "Not Found", response = ErrorResponse.class)})
@DeleteMapping("{lessonIdentifier}")
@ResponseStatus(HttpStatus.NO_CONTENT)
public void delete(@PathVariable("lessonIdentifier") LessonIdentifier lessonIdentifier) {
//Delete process
}
@ApiOperation(value = "${LessonController.edit.value}", notes = "${LessonController.edit.notes}")
@ApiResponses(value = {
@ApiResponse(code = 400, message = "Bad Request", response = ErrorResponse.class),
@ApiResponse(code = 404, message = "Not Found", response = ErrorResponse.class)})
@PutMapping("{lessonIdentifier}")
@ResponseStatus(HttpStatus.OK)
public LessonResponse edit(@PathVariable("lessonIdentifier") LessonIdentifier lessonIdentifier,
@RequestBody LessonRequest lessonRequest) {
//Editing process
return new LessonResponse(1, "EditStudentName1", "EditTutorName1");
}
}
Let's get out without any problems!
It's very convenient when you want to combine messages into one file However, if you do not overdo it, it tends to be a complicated message file, so be careful when using it.
I understood that it seems to be convenient for the time being However, there are some parts that I haven't been able to investigate, such as after Build or when I don't want the production environment to access swagger-ui, so I'll investigate later.
https://springfox.github.io/springfox/docs/current/
Recommended Posts