swagger的使用
最近公司使用了前后端分离的的形式,第一次接触到了swagger这个工具,在与前端配合的过程中踩了很多坑,今天抽出时间来记录一下。本人小白说错了请使劲喷。
日(粘)常(贴)简(复)介(制):
Swagger 是一套围绕 OpenAPI 规范构建的开源工具,可以帮助您设计,构建,记录和使用 REST API。
Swagger 是一个规范和完整的框架,用于生成、描述、调用和可视化 RESTful 风格的 Web 服务。Swagger 的目标是对 REST API 定义一个标准的和语言无关的接口,可让人和计算机无需访问源码、文档或网络流量监测就可以发现和理解服务的能力。当通过 Swagger 进行正确定义,用户可以理解远程服务并使用最少实现逻辑与远程服务进行交互。
说人话
- 是一款让你更好的书写API文档的规范且完整框架,让开发者简化编写文档的步骤。
- 让你编写的api文档可视化,让前端同学能更好的看懂,少来怼你
少啰嗦,先看东西
上图就是通过swagger生成的可视化api接口文档
只要1999,呸!!!!这TM绝对是来捣乱的。串场了串场了抱歉抱歉
咳咳~~
以下是快速食用方式
一、Maven添加
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.7.0</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.7.0</version>
</dependency>
二、添加Swagger配置类
@Configuration
@EnableSwagger2
public class Swagger2 {
//配置核心配置信息
@Bean
public Docket createRestApi(){
return new Docket(DocumentationType.SWAGGER_2)
.apiInfo(apiInfo())
.select()
.apis(RequestHandlerSelectors.basePackage("包路径"))
.paths(PathSelectors.any())
.build();
}
//声明api/文档属性 构建器
private ApiInfo apiInfo(){
return new ApiInfoBuilder()
.title("前端调试接口文档")
.description("前端调试接口文档")
.version("1.0.0")
.build();
}
}
上代码:
@Slf4j
@Controller
@RequestMapping("/function")
@Api(value = "functionController", tags = {"功能性接口"})
public class FunctionApiController extends PortalBaseController {
@ResponseBody
@ApiOperation(value = "获取回调返回接入方平台页面地址")
@PostMapping("/getCallbackUrl")
public Result<GetCallbackUrlResponse> getCallbackUrl(HttpServletRequest request,
@RequestBody @Validated BaseRequest baseRequest) {
log.info("前端-获取回调返回接入方平台页面地址---入参{}", baseRequest);
GetCallbackUrlResponse response = new GetCallbackUrlResponse();
try {
response.setCallbackUrl("https://www.baidu.com");
return Result.success(response);
} catch (BusinessException b) {
return Result.error(b.getMessage());
} catch (Exception e) {
return Result.error(CommonErrorCodes.INTERNAL_ERROR.getMessage());
}
}
}
@Getter
@Setter
@Validated
public class BaseRequest extends InfoBase {
/**
*
*/
private static final long serialVersionUID = 1L;
@NotEmpty(message = "投保单号不能为空")
@ApiModelProperty(value = "投保单号", required = true)
private String insuranceNo;
/**
* 客户端来源平台 WEB、PC端; ANDROID、安卓端; IOS、苹果端
*/
// @NotEmpty(message = "客户端来源平台")
@ApiModelProperty(value = "客户端来源平台(苹果端:IOS;安卓端:ANDROID;PC端:WEB)", required = true)
private String sourcePlatform;
}
@Getter
@Setter
public class GetCallbackUrlResponse extends InfoBase {
@ApiModelProperty(value = "跳转页面地址url")
private String callbackUrl;
}
经过以上两段代码后,启动项目访问 http://127.0.0.1:8080/swagger-ui.html.,就会生成以上文档,然后你就可以点开微信把这个地址甩给你们前端童鞋,内里~我写的接口拿切看。
如何自测
这里我用的是postman感兴趣的童鞋可以点击下载,下面都会以postman来做测试
你这时候相当于把一个空壳子给了前端同学,可以忽悠前端同学一时,但是联调的时候还是会找你要具体实现测试的。我们在开发的过程中可能会遇到代码写好后(没错就是我咯)不知道如何测试
打开postman 如下图操作
异常的处理
我们在调试的过程中会,前端同学可能会忘记校验某些字段,举个栗子,例如用户个人信息填写,接口要求手机号不能为空,但是页面并没有校验该值。这个时候后端就会报出一段异常
后端错误日志
ERROR [http-nio-8080-exec-6] GlobalExceptionHandler:92-:-
org.springframework.web.bind.MethodArgumentNotValidException: Validation failed for argument [1] in public com.test.insurance.portal.base.Result<com.test.insurance.portal.dto.GetCallbackUrlResponse> com.test.insurance.portal.FunctionApiController.getCallbackUrl(javax.servlet.http.HttpServletRequest,com.test.insurance.portal.base.BaseRequest): [Field error in object 'baseRequest' on field 'insuranceNo': rejected value [null]; codes [NotEmpty.baseRequest.insuranceNo,NotEmpty.insuranceNo,NotEmpty.java.lang.String,NotEmpty]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [baseRequest.insuranceNo,insuranceNo]; arguments []; default message [insuranceNo]]; default message [投保单号不能为空]]
at org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor.resolveArgument(RequestResponseBodyMethodProcessor.java:138)
at org.springframework.web.method.support.HandlerMethodArgumentResolverComposite.resolveArgument(HandlerMethodArgumentResolverComposite.java:126)
at org.springframework.web.method.support.InvocableHandlerMethod.getMethodArgumentValues(InvocableHandlerMethod.java:167)
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:134)
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:104)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:892)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:797)
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1039)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:942)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1005)
at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:908)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:660)
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:882)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:741)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
这个时候你要是前端同学,你会是什么反应,你品,你细品
这个时候我们需要在他调用的时候就把锅给他直接甩出去,而不是他来问候你
思路:我们首选要清楚系统抛出来的是什么异常,再根据这个异常来统一做处理
MethodArgumentNotValidException:这个异常是我们使用@Validated 验证因为传入的入参不合法所抛出的异常。
上代码
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
@Slf4j
@RestControllerAdvice
public class PortalExceptionHandler {
@ExceptionHandler(MethodArgumentNotValidException.class)
public Result handleException(MethodArgumentNotValidException e) {
Result result = new Result();
BindingResult bindingResult = e.getBindingResult();
FieldError fieldError = bindingResult.getFieldErrors().get(0);
result.setStatus(StatusEnum.fail);
result.setMsg(fieldError.getDefaultMessage());
return result;
}
}
最后
非常非常感谢您看到这里,我是第一次写博客,如果有什么不对请重重的喷我,毕竟你喷我就代表我有问题,你是鞭策我进步-,-
我是一个迷途小菜鸟,以前用的是我们公司封装框架写openApi接口,是第一次接触到swagger,期间遇到的问题做个记录,方便和我一样新接触swagger的童鞋