swagger和市面上的禅道、RAP2等众多图形化接口文档非常类似,经过短时间的摸索,和大量的查阅各类博客,记录下swagger2的使用和理解。
pom角度上讲,springfox-swagger2-ui集成了前端页面,并且不需要我们去管理,并且还可以使用yml预先编写接口,然后在按照HTML页面上进行开发。
个人学习了一个技术,就会进行记录,所以这篇博客也是学习多篇博客,复制出来的内容。没有什么好写,直接放代码。
pom
4.0.0
com.hikktn
my-swagger2-test
1.0-SNAPSHOT
org.springframework.boot
spring-boot-starter-parent
2.1.4.RELEASE
io.springfox
springfox-swagger2
2.9.2
io.springfox
springfox-swagger-ui
2.9.2
com.alibaba
fastjson
1.2.51
org.springframework.boot
spring-boot-starter-test
org.springframework.boot
spring-boot-starter-web
org.springframework.boot
spring-boot-configuration-processor
true
application.yml
#swagger 配置
swagger:
title: API示例
desc: 基于springBoot编写的RESful-API
version: 0.0.1.SNAPSHOT
termsOfServiceUrl: javascript:void(0)
license: Apache 2.0
licenseUrl: http://www.apache.org/licenses/LICENSE-2.0.html
basePackage: com.example.demo.controller
groupName: 默认API示例分组
contactName: name
contactUrl: url
contactEmail: email
#生产环境改为false(改为false后swagger-ui.html则无法访问)
enable: true
#解决Swagger2 异常 NumberFormatException:For input string:""
logging:
level:
io:
swagger:
models:
parameters:
AbstractSerializableParameter: ERROR
Swagger2Application
package com.example.demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
/**
* @ClassName Swagger2Application
* @Description TODO
* @Author lisonglin
* @Date 2021/5/21 23:47
* @Version 1.0
*/
@SpringBootApplication
public class Swagger2Application {
public static void main(String[] args){
SpringApplication.run(Swagger2Application.class,args);
}
}
SwaggerConfig
package com.example.demo.config;
import io.swagger.annotations.ApiOperation;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import springfox.documentation.builders.*;
import springfox.documentation.schema.ModelRef;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.Contact;
import springfox.documentation.service.Parameter;
import springfox.documentation.service.ResponseMessage;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;
/**
* @ClassName SwaggerConfig
* @Description TODO
* @Author lisonglin
* @Date 2021/5/21 23:38
* @Version 1.0
*/
@Configuration
@EnableSwagger2
@EnableWebMvc
@ConfigurationProperties(prefix = "swagger")
@ConditionalOnProperty(name = "swagger.enable", havingValue = "true") // 生产环境禁用swagger2
public class SwaggerConfig {
private String title;
private String desc;
private String version;
private String termsOfServiceUrl;
private String license;
private String licenseUrl;
private String basePackage;
private String groupName;
private String contactName;
private String contactUrl;
private String contactEmail;
/**
* 增加API相关信息
* @return
*/
private ApiInfo apiInfo() {
return new ApiInfoBuilder().title(title) //接口文档的标题
.description(desc) //文档描述
.version(version) //版本号
.termsOfServiceUrl(termsOfServiceUrl) //服务条款URL
.licenseUrl(licenseUrl)
.license(license) //license 规范
.contact(new Contact(contactName, contactUrl, contactEmail)) // 开发文档的作者信息
.build();
}
@Bean
public Docket swaggerApi() {
// ==================== 需要的参数 START ====================
List pars = new ArrayList<>();
ParameterBuilder token = new ParameterBuilder();
token.name("token").description("token").modelRef(new ModelRef("string")).parameterType("header").required(false).build();
pars.add(token.build());
// ==================== 需要的参数 END ====================
return new Docket(DocumentationType.SWAGGER_2).apiInfo(apiInfo()).groupName(groupName)
.directModelSubstitute(LocalDate.class, String.class).genericModelSubstitutes(ResponseEntity.class)
.useDefaultResponseMessages(false)
.globalResponseMessage(RequestMethod.POST, customerResponseMessage())
.globalResponseMessage(RequestMethod.GET, customerResponseMessage())
.forCodeGeneration(true).select()
.apis(RequestHandlerSelectors.basePackage(basePackage)) // api包扫描
.apis(RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class)) // 设置选择器
.paths(PathSelectors.any())
.build().globalOperationParameters(pars);
}
private List customerResponseMessage() {
List list = new ArrayList<>();
list.add(new ResponseMessageBuilder().code(200).message("请求成功").build());
list.add(new ResponseMessageBuilder().code(201).message("资源创建成功").build());
list.add(new ResponseMessageBuilder().code(204).message("服务器成功处理了请求,但不需要返回任何实体内容").build());
list.add(new ResponseMessageBuilder().code(400).message("请求失败,具体查看返回业务状态码与对应消息").build());
list.add(new ResponseMessageBuilder().code(401).message("请求失败,未经过身份认证").build());
list.add(new ResponseMessageBuilder().code(405).message("请求方法不支持").build());
list.add(new ResponseMessageBuilder().code(415).message("请求媒体类型不支持").build());
list.add(new ResponseMessageBuilder().code(500).message("服务器遇到了一个未曾预料的状况,导致了它无法完成对请求的处理").build());
list.add(new ResponseMessageBuilder().code(503).message("服务器当前无法处理请求,这个状况是临时的,并且将在一段时间以后恢复").build());
return list;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getDesc() {
return desc;
}
public void setDesc(String desc) {
this.desc = desc;
}
public String getVersion() {
return version;
}
public void setVersion(String version) {
this.version = version;
}
public String getTermsOfServiceUrl() {
return termsOfServiceUrl;
}
public void setTermsOfServiceUrl(String termsOfServiceUrl) {
this.termsOfServiceUrl = termsOfServiceUrl;
}
public String getLicense() {
return license;
}
public void setLicense(String license) {
this.license = license;
}
public String getLicenseUrl() {
return licenseUrl;
}
public void setLicenseUrl(String licenseUrl) {
this.licenseUrl = licenseUrl;
}
public String getBasePackage() {
return basePackage;
}
public void setBasePackage(String basePackage) {
this.basePackage = basePackage;
}
public String getGroupName() {
return groupName;
}
public void setGroupName(String groupName) {
this.groupName = groupName;
}
public String getContactName() {
return contactName;
}
public void setContactName(String contactName) {
this.contactName = contactName;
}
public String getContactUrl() {
return contactUrl;
}
public void setContactUrl(String contactUrl) {
this.contactUrl = contactUrl;
}
public String getContactEmail() {
return contactEmail;
}
public void setContactEmail(String contactEmail) {
this.contactEmail = contactEmail;
}
}
WebMvcConfig
package com.example.demo.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
/**
* @ClassName WebMvcConfigurer
* @Description 前后端分离项目跨域访问
* @Author lisonglin
* @Date 2021/5/22 1:30
* @Version 1.0
*/
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
public WebMvcConfig(){
}
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**").allowedOrigins(new String[]{"*"});
}
public void addResourceHandlers(ResourceHandlerRegistry registry){
registry.addResourceHandler("swagger-ui.html")
.addResourceLocations("classpath:/META-INF/resources/");
registry.addResourceHandler("/webjars/**")
.addResourceLocations("classpath:/META-INF/resources/webjars/");
}
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new MicroServiceInterceptor()).addPathPatterns(new String[]{"/**"}).excludePathPatterns(new String[]{"/provider", "/getIpAddr", "/gateway"});
}
}
UserController
package com.example.demo.controller;
import io.swagger.annotations.*;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import java.util.HashMap;
import java.util.Map;
/**
* @ClassName UserController
* @Description TODO
* @Author lisonglin
* @Date 2021/5/21 23:39
* @Version 1.0
*/
@RestController
@RequestMapping("user")
@Api(tags = "用户服务接口")
public class UserController {
@GetMapping("findAll")
@ApiOperation(value = "查询所有用户信息", notes = "查询所有用户信息接口")
public Map findAll() {
Map map = new HashMap<>();
map.put("success", "查询所有成功");
map.put("state", true);
return map;
}
@PostMapping("save")
@ApiOperation(value = "保存用户信息", notes = "保存用户信息接口")
@ApiImplicitParams({
@ApiImplicitParam(name = "id", value = "用户id", dataType = "String", defaultValue = "21"),
@ApiImplicitParam(name = "name", value = "用户名", dataType = "String", defaultValue = "zhangsan")
})
@ApiResponses({
@ApiResponse(code = 404, message = "页面不存在"),
@ApiResponse(code = 500, message = "服务器出错")
})
public Map sve(String id, String name) {
Map map = new HashMap<>();
map.put("success", "保存用户信息");
map.put("state", true);
return map;
}
@ApiOperation(value = "测试 - GET请求加入header参数")
@ApiImplicitParams({
@ApiImplicitParam(name = "token", value = "请求token", required = true, paramType = "header"),
})
@GetMapping
public ResponseEntity test(@RequestHeader String token) {
return ResponseEntity.ok("token:" + token);
}
}
http://localhost:8080/swagger-ui.html