Swagger简单使用
介绍
使用Swagger,只需要按照它的规范去定义接口及接口相关的信息,再通过Swagger衍生出来的一系列项目和工具,就可以做到生成各种格式的接口文档,以及在线接口调试页面等等。
官网:https://swagger.io/
knife4j是为Java MVC框架集成Swagger生成Api文档的增强解决方案。
使用方式
1、导入knife4j的maven坐标
<!-- https://mvnrepository.com/artifact/com.github.xiaoymin/knife4j-spring-boot-starter -->
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-spring-boot-starter</artifactId>
<version>3.0.2</version>
</dependency>
2、导入knife4j相关配置类
@Configuration
@EnableSwagger2
@EnableKnife4j
public class SwaggerConfig {
@Bean
public Docket createRestApi() {
// 文档类型
return new Docket(DocumentationType.SWAGGER_2)
.apiInfo(apiInfo())
.select()
.apis(RequestHandlerSelectors.basePackage("com.aiw.waimai.controller"))
.paths(PathSelectors.any())
.build();
}
private ApiInfo apiInfo() {
return new ApiInfoBuilder()
.contact(new Contact("Aiw", "http://www.tovi.top", "xxx@163.com"))
//文档标题
.title("外卖")
//文档描述
.description("外卖接口文档")
//文档版本
.version("1.2")
.build();
}
}
3、设置静态资源映射
@Configuration
public class WebConfig implements WebMvcConfigurer {
/**
* 设置静态资源映射
*
* @param registry
*/
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("doc.html").addResourceLocations("classpath:/META-INF/resources/");
registry.addResourceHandler("/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/");
registry.addResourceHandler("/**").addResourceLocations("classpath:/static/");
}
}
参考前期博客:Spring Boot 配置静态资源路径
4、在 过滤器/拦截器
中设置不需要处理的请求路径
新增如下请求路径:
"/doc.html", "/webjars/**", "/swagger-resources", "/v2/api-docs"
若未设置
过滤器/拦截器
,则可以跳过该步骤
过滤器
具体示例如下:
@Slf4j
@WebFilter
public class LoginCheckFilter implements Filter {
// 路径匹配器,支持通配符
public static final AntPathMatcher PATH_MATCHER = new AntPathMatcher();
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) servletRequest;
HttpServletResponse response = (HttpServletResponse) servletResponse;
log.info("拦截到的请求:{}", request.getRequestURI());
// 1、获取本次请求的URI
String requestURI = request.getRequestURI();
// 定义不需要处理的请求路径
String[] urls = new String[]{"/employee/login", "/employee/logout", "/backend/**", "/front/**", "/common/**", "/user/sendMsg", "/user/login",
"/doc.html", "/webjars/**", "/swagger-resources", "/v2/api-docs"};
// 2、判断本次请求是否需要处理
boolean check = check(urls, requestURI);
// 3、如果不需要处理,则直接放行
if (check) {
log.info("本次请求{}不需要处理", requestURI);
filterChain.doFilter(request, response);
return;
}
// 4、判断登录状态,如果已登录,则直接放行
if (Objects.nonNull(request.getSession().getAttribute("employee"))) {
log.info("用户已登录,用户id为:{}", request.getSession().getAttribute("employee"));
filterChain.doFilter(request, response);
return;
}
// 5、如果未登录则返回未登录结果,通过输出流方式向客户端页面响应数据
log.info("用户未登录");
response.setContentType("text/html;charset=UTF-8");
// 1、使用Fastjson(默认过滤null值)
//response.getWriter().write(JSON.toJSONString(R.error("NOTLOGIN")));
// 2、使用默认的Jackson,在配置文件中关于Jackson配置的相关属性会失效
response.getWriter().write(new ObjectMapper().writeValueAsString(R.error("NOTLOGIN")));
return;
}
/**
* 路径匹配,检查本次请求是否需要放行
*
* @param urls
* @param requestURI
* @return
*/
public boolean check(String[] urls, String requestURI) {
for (String url : urls) {
boolean match = PATH_MATCHER.match(url, requestURI);
if (match) return true;
}
return false;
}
}
拦截器
具体示例如下:
@Configuration
public class WebConfig implements WebMvcConfigurer {
/**
* 设置静态资源映射
*
* @param registry
*/
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("doc.html").addResourceLocations("classpath:/META-INF/resources/");
registry.addResourceHandler("/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/");
registry.addResourceHandler("/**").addResourceLocations("classpath:/static/");
}
/**
* 注册拦截器
*
* @param registry
*/
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new LoginCheckInterceptor())
.addPathPatterns("/**")
// 排除的请求路径
.excludePathPatterns("/employee/login", "/employee/logout", "/backend/**", "/front/**", "/common/**", "/user/sendMsg", "/user/login",
"/doc.html", "/webjars/**", "/swagger-resources", "/v2/api-docs");
}
}
具体
过滤器/拦截器
配置实现,参考前期博客:SpringBoot+Session 实现接口验证(过滤器+拦截器)
5、功能测试
启动项目,在浏览器输入http://localhost:8080/doc.html
如下:
SpringBoot 2.6.X版本及以上会启动报错, 在application.yml里配置如下:
spring: mvc: pathmatch: matching-strategy: ant_path_matcher
在左侧点击任意接口,即可查看对应的接口文档:
并且还可以进行接口的调试
还支持接口文档的导出,点击文档管理
->离线文档
,可以导出markdown/html等格式
常用注解
@Api
用在请求的类上,例如Controller,表示对类的说明
@Api(tags = "用户相关接口")
@RestController
@RequestMapping("/user")
public class UserController {
在浏览器查看,如下:
@ApiOperation
用在请求的方法上,对方法进行总体描述
@ApiOperation(value = "移动端用户登录", notes = "接口描述信息")
@RequestMapping(value = "/login", method = RequestMethod.POST)
public R<?> login(@RequestBody Map map, HttpSession session) {
在浏览器查看,如下:
@ApiParam
用在请求的方法参数上,对参数进行描述或说明是否为必填项等说明
@RequestMapping(value = "/userPage", method = RequestMethod.GET)
public R<?> userPage(@ApiParam(value = "当前页", required = true) @RequestParam Integer page,
@ApiParam(value = "每页显示几条数据", required = true) @RequestParam Integer pageSize) {
在浏览器查看,如下:
@ApiModel
用在类上,通常是实体类,表示一个返回响应数据的信息
@Data
@ApiModel("返回结果")
@NoArgsConstructor
@AllArgsConstructor
public class R<T> implements Serializable {
在浏览器查看Swagger Models
,如下:
@ApiModelProperty
用在属性上,描述响应类的属性
@Data
@ApiModel("返回结果")
@NoArgsConstructor
@AllArgsConstructor
public class R<T> implements Serializable {
@ApiModelProperty(value = "响应码", required = true)
private Integer code; //响应码:1成功,0和其它数字为失败
@ApiModelProperty(value = "错误信息", required = true)
private String msg; //错误信息
@ApiModelProperty(value = "数据", required = true)
private T data; //数据
}
在浏览器查看Swagger Models
,如下:
在浏览器查看接口的响应参数,如下:
@ApiIgnore
用于请求的类/请求的方法/请求的方法参数上,表示这个请求的类/请求的方法/请求的方法参数被忽略。
@ApiIgnore
@RestController
@RequestMapping("/category")
public class CategoryController {
在浏览器无法查看到该控制器下的接口
@ApiImplicitParam
用在请求的方法上,表示一个参数说明
@ApiImplicitParam(name = "page", value = "页码", required = true)
@RequestMapping(value = "/page", method = RequestMethod.GET)
public R<?> page(@RequestParam Integer page, @RequestParam Integer pageSize, @RequestParam(required = false) String name) {
name属性必须和请求方法参数名保持一致
在浏览器查看,如下:
@ApiImplicitParams
用在请求的方法上,表示一组参数说明
@ApiImplicitParams({
@ApiImplicitParam(name = "page", value = "页码", required = true),
@ApiImplicitParam(name = "pageSize", value = "每页记录数", required = true),
@ApiImplicitParam(name = "name", value = "套餐名称", required = true),
})
@RequestMapping(value = "/page", method = RequestMethod.GET)
public R<?> page(@RequestParam Integer page, @RequestParam Integer pageSize, @RequestParam(required = false) String name) {
在浏览器查看,如下:
@ApiImplicitParam的required属性优先于@RequestParam的required属性