SpringBoot 最新教程:SpringBoot 2.7 整合 Swagger3.0 项目搭建-2022年最新图文版本
直接升级springboot版本出现报错:
Failed to start bean 'documentationPluginsBootstrapper';
解决方案:
1.修改SwaggerConfig类
2.修改application.yml
目录
项目代码结构:
一、Pom文件
二、application.yml文件
三、SwaggerConfig 类文件
四、Controller文件
五、返回配置类
六、测试示例
项目代码结构:
一、Pom文件
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>2.7.0</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
<version>2.7.0</version>
</dependency>
<!-- swagger 文档生成 swagger-ui http://localhost:8080/doc.htm -->
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-spring-boot-starter</artifactId>
<version>3.0.2</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.24</version>
</dependency>
二、application.yml文件
spring:
mvc:
pathmatch:
matching-strategy: ant_path_matcher
三、SwaggerConfig 类文件
/***
* @date: 2022/8/3
* @author: 微信公众号:深入技术架构
* @description: TODO
*/
@Configuration
@EnableSwagger2
public class SwaggerConfig {
@Bean
public Docket createRestApi() {
return new Docket(DocumentationType.OAS_30)
.apiInfo(apiInfo())
.groupName("SwaggerGroupOneAPI")
//是否开启 (true 开启 false隐藏。生产环境建议隐藏)
//.enable(false)
.select()
//扫描的路径包,设置basePackage会将包下的所有被@Api标记类的所有方法作为api
.apis(RequestHandlerSelectors.basePackage("com.duoduo.swaggersample.controller"))
//指定路径处理PathSelectors.any()代表所有的路径
.paths(PathSelectors.any())
.build();
}
/**
* 配置基本信息
* @return
*/
@Bean
public ApiInfo apiInfo() {
return new ApiInfoBuilder()
//设置文档标题(API名称)
.title("Swagger-Sample")
//文档描述
.description("API-接口说明")
//服务条款URL
.termsOfServiceUrl("http://localhost:8080/")
//版本号
.version("1.0.0")
//联系人
.contact(new Contact("wx:深入技术架构", "http://localhost", "xxxx@163.com"))
.build();
}
/**
* 增加如下配置可解决Spring Boot 与Swagger 3.0.0 不兼容问题
**/
@Bean
public WebMvcEndpointHandlerMapping webEndpointServletHandlerMapping(WebEndpointsSupplier webEndpointsSupplier, ServletEndpointsSupplier servletEndpointsSupplier, ControllerEndpointsSupplier controllerEndpointsSupplier, EndpointMediaTypes endpointMediaTypes, CorsEndpointProperties corsProperties, WebEndpointProperties webEndpointProperties, Environment environment) {
List<ExposableEndpoint<?>> allEndpoints = new ArrayList();
Collection<ExposableWebEndpoint> webEndpoints = webEndpointsSupplier.getEndpoints();
allEndpoints.addAll(webEndpoints);
allEndpoints.addAll(servletEndpointsSupplier.getEndpoints());
allEndpoints.addAll(controllerEndpointsSupplier.getEndpoints());
String basePath = webEndpointProperties.getBasePath();
EndpointMapping endpointMapping = new EndpointMapping(basePath);
boolean shouldRegisterLinksMapping = this.shouldRegisterLinksMapping(webEndpointProperties, environment, basePath);
return new WebMvcEndpointHandlerMapping(endpointMapping, webEndpoints, endpointMediaTypes, corsProperties.toCorsConfiguration(), new EndpointLinksResolver(allEndpoints, basePath), shouldRegisterLinksMapping, null);
}
private boolean shouldRegisterLinksMapping(WebEndpointProperties webEndpointProperties, Environment environment, String basePath) {
return webEndpointProperties.getDiscovery().isEnabled() && (StringUtils.hasText(basePath) || ManagementPortType.get(environment).equals(ManagementPortType.DIFFERENT));
}
}
四、Controller文件
/**
* @author 微信公众号:深入技术架构
* @description 用户服务-用户管理模块
*/
@Api(value = "用户服务", tags = "用户模块")
@Slf4j
@RestController
public class UserController {
@ApiOperation(value = "1.创建用户信息")
@ApiOperationSupport(order = 1)
@ApiImplicitParams({
@ApiImplicitParam(name = "userID", value = "用户id", paramType = "query", dataType = "String" ,required = true),
})
@PostMapping("user/createUser")
public ApiResult<UserForm> createUser(@Validated @RequestBody UserForm userForm) {
return ApiResult.success(userForm);
}
@ApiOperation(value = "2.获取用户信息")
@ApiOperationSupport(order = 2)
@ApiImplicitParams({
@ApiImplicitParam(name = "userID", value = "用户id", paramType = "query", dataType = "String"),
})
@GetMapping("user/getUser")
public ApiResult<UserVO> getUser() {
UserVO userVO = new UserVO();
userVO.setUserId(1L);
userVO.setUserName("张三");
userVO.setUserSex(1);
return ApiResult.success(userVO);
}
}
/**
* @author 微信公众号:深入技术架构
* @description TODO
* @className UserForm
*/
@Data
@ApiModel(value = "UserForm", description = "用户信息的接收实体对象")
public class UserForm {
@ApiModelProperty(value = "用户名,示例:张三", required = true)
@NotNull(message = "请输入用户名")
@Pattern(regexp = "^\\d+$", message = "用户名格式不正确")
public String userName;
@ApiModelProperty(value = "手机号,示例:18300000000", required = true)
@Pattern(regexp = "^\\d{11}$", message = "手机号格式不正确")
public String phone;
@ApiModelProperty(value = "微博ID,示例:12345", required = true)
@Pattern(regexp = "^\\d{5,20}$", message = "格式不正确")
public String weiboId;
}
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class UserVO {
/**
* 用户id
*/
@ApiModelProperty(value = "用户id", name = "用户name", allowableValues="123")
private Long userId;
/**
* 用户名
*/
private String userName;
/**
* 用户性别
*/
private Integer userSex;
}
五、返回配置类
/**
* @className: Result
* @description: Api接口返回结构
* @version: 1.0.0
* @author: 微信公众号:深入技术架构
* @date: 2020/7/10 11:10 上午
*/
public class ApiResult<T> {
private int code;
private String message;
private T data;
protected ApiResult() {
}
/**
* code和message构造函数
* @param code
* @param message
*/
protected ApiResult(int code, String message) {
this.code = code;
this.message = message;
}
/**
* 全参构造函数
* @param code
* @param message
* @param data
*/
protected ApiResult(int code, String message, T data) {
this.code = code;
this.message = message;
this.data = data;
}
/**
* 成功返回结果
*/
public static <T> ApiResult<T> success() {
return new ApiResult<T>(CommonCode.SUCCESS.getCode(), CommonCode.SUCCESS.getMessage());
}
/**
* 成功返回结果
*
* @param data 返回的数据
*/
public static <T> ApiResult<T> success(T data) {
return new ApiResult<T>(CommonCode.SUCCESS.getCode(), CommonCode.SUCCESS.getMessage(), data);
}
/**
* 失败返回结果
*/
public static <T> ApiResult<T> failed(BaseCode baseCode) {
return new ApiResult<T>(baseCode.getCode(), baseCode.getMessage(), null);
}
/**
* 失败返回结果 code 99999
*
* @param message 提示信息
*/
public static <T> ApiResult<T> failed(String message) {
return new ApiResult<T>(CommonCode.FAILED.getCode(), message, null);
}
/**
* 失败返回结果
*
* @param baseCode 错误码
* @param message 错误信息
*/
public static <T> ApiResult<T> failed(BaseCode baseCode, String message) {
return new ApiResult<T>(baseCode.getCode(), message, null);
}
/**
* 失败返回结果
*
* @param code 错误码
* @param message 错误信息
*/
public static <T> ApiResult<T> failed(int code, String message) {
return new ApiResult<T>(code, message, null);
}
public static <T> ApiResult<T> failed(int code, String message, T data) {
return new ApiResult<T>(code, message, data);
}
public long getCode() {
return code;
}
public void setCode(int code) {
this.code = code;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
}
/**
* @author 微信公众号:深入技术架构
* 0 请求成功
* 99999 未知失败
* 1开头为对通用错误信息
* 2开头为输入参数错误
* 3开头为业务调用错误
* 4开头为数据库数据业务错误
* 5开头为缓存调用错误
* @description 基础返回码
* @className BaseCode
*/
public interface BaseCode {
public int getCode();
public String getMessage();
}
/**
* 微信公众号:深入技术架构
*/
public enum CommonCode implements BaseCode {
/**
* 返回码
*/
SUCCESS(0, "succ"),
FAIL(10000, "通用错误信息"),
SIGN_FAIL(10001, "签名错误"),
TIME_FAIL(10002, "时间戳超时错误"),
TOKEN_FAIL(10003, "token错误"),
AUTH_FAIL(10004, "权限不足"),
PARAM_ERROR(20000, "参数错误"),
PARAM_EMPTY_ERROR(20001, "参数为空"),
PARAM_PATTERN_ERROR(20002, "参数格式不对"),
FAILED(99999, "系统繁忙,请稍后再试.");
/**
* 错误码
*/
private int code;
/**
* 错误信息
*/
private String message;
CommonCode(int code, String message) {
this.code = code;
this.message = message;
}
@Override
public int getCode() {
return code;
}
@Override
public String getMessage() {
return message;
}
}