@Api
来划分。注意,对于swagger,不要使用@RequestMapping
因为@RequestMapping支持任意请求方式,swagger会为这个接口生成7种请求方式的接口文档
@Api(tags = "app管理") //可以当作是这个组的名字。
@RestController
@RequestMapping("app")
public class AppController {
@RequestMapping(value = "/hello",method = RequestMethod.GET)
public String hello(){
return "hello swagger!";
}
}
可以理解成基于tags来分组
如果这个Controller下(接口组)下面没有接口,那么在swagger ui中是不会显示的,如果有的话就会这样显示:
@Api
来标注一个Controller之后,如果下面有接口,那么就会默认生成文档,但没有我们自定义的说明:
@ApiOperation
来描述接口,比如: //只要我们的接口中,返回值中存在实体类,他就会被扫描外wagger中
@ApiOperation(value = "获取用户",notes = "获取用户接口")
@GetMapping("/getUser")
public User getUser(String name,String password){
return new User(name,password);
}
常用配置项:
- value:可以当作是接口的简称
- notes:接口的描述
- tags:可以额外定义接口组,比如这个接口外层已经有
@Api(tags = "用户管理")
,将接口划分到了“用户管理”中,但你可以额外的使用tags,例如tags = "角色管理"
让角色管理中也有这个接口文档。
@ApiOperation
来了描述接口,还缺少接口请求参数的说明.对于GET方式,swagger不推荐使用body方式来传递数据,所以虽然Spring MVC可以自动封装参数,也是不希望在GET方式时使用json、form-data等方式来传递,这时候最好使用路径参数或者url参数。(虽然POSTMAN等是支持的,swagger在线测试是不支持这个操作的),所以如果接口传递的数据是json或者form-data方式的,还是使用POST方式好。可翻看之前的博客SpringMVC-09-传递参数的几种方式
此时我们需要使用@ApiModel
来标注实体类,然后在接口中定义入参为实体类即可:
@ApiModel:用来标类,@ApiModel内的注释 不要出现相同 否则会将相同的vo字段进行合并
@ApiModelProperty:用来描述类的字段的意义。
1.给int类型的字段使用@ApiModelPorperty注解时添加example属性
2.去除原swagger中的swagger-models和swagger-annotations,自行引入高版本的annotations和models
io.springfox
springfox-swagger2
2.9.2
io.swagger
swagger-annotations
io.swagger
swagger-models
io.swagger
swagger-annotations
1.5.22
io.swagger
swagger-models
1.5.22
{1,2,3}
代表只能取这三个值;[1,6]
代表取1到6的值;(1,6)
代表1到6的值,不包括1和6;还可以使用infinity或-infinity来无限值,比如[1, infinity]
代表最小值为1,最大值无穷大。@ApiModelProperty
。@Data
@AllArgsConstructor
@NoArgsConstructor
@ApiModel(value = "用户实体类",description = "用户实体对象") // 先使用@ApiModel来标注类
public class User {
// 使用ApiModelProperty来标注字段属性。
@ApiModelProperty(value = "name",required = true,example = "toy")
private String name;
@ApiModelProperty(value = "name",required = true,example = "123456")
private String password;
//swagger在入参赋值时需要的getter,setter来置值
}
@ApiOperation(value = "获取用户",notes = "获取用户通过传递实体json")
@PostMapping("/getUser")
public User getUserPost(@RequestBody User user){
return user;
}
对于非实体类参数,可以使用@ApiImplicitParams
和@ApiImplicitParam
来声明请求参数。
@ApiImplicitParams
用在方法头上,@ApiImplicitParam
定义在@ApiImplicitParams
里面,一个@ApiImplicitParam
对应一个参数。
@ApiImplicitParam
常用配置项:
name:用来定义参数的名字,也就是字段的名字,可以与接口的入参名对应。如果不对应,也会生成,所以可以用来定义额外参数!
value:用来描述参数
required:用来标注参数是否必填
paramType有path,query,body,form,header等方式,但对于对于非实体类参数的时候,常用的只有path,query,header;body和form是不常用的。body不适用于多个零散参数的情况,只适用于json对象等情况。【如果你的接口是form-data
,x-www-form-urlencoded
的时候可能不能使用swagger页面API调试,但可以在后面讲到基于BootstrapUI的swagger增强中调试,基于BootstrapUI的swagger支持指定form-data
或x-www-form-urlencoded
】
也可以仅仅使用@ApiParam作用在方法上参数不用声明,@ApiParam使用配置和@ApiImplicitParam一样对于3.0.0比2.X有点是可以适配所有类型的参数请求方式,2.x需要测试时手动选择
//只要我们的接口中,返回值中存在实体类,他就会被扫描外wagger中 @ApiOperation(value = "获取用户",notes = "获取用户接口") @GetMapping("/getUser") public User getUser(@ApiParam(name = "name",value = "账户",required = true) String name,@ApiParam(name = "password",value = "密码",required = true)String password){ return new User(name,password); }
- 1
- 2
- 3
- 4
- 5
- 6
query方式入参
//query方式入参
@ApiOperation(value = "获取用户1",notes = "获取用户接口1-query方式入参")
@GetMapping("/getUser1")
@ApiImplicitParams({
@ApiImplicitParam(name = "name",value = "账户",required = true,paramType = "query"),
@ApiImplicitParam(name = "password",value = "密码",required = true,paramType = "query")
})
public User getUser1(String name,String password){
return new User(name,password);
}
path方式入参
//path方式入参
@ApiOperation(value = "获取用户2",notes = "获取用户接口2-path方式入参")
@GetMapping("/getUser/{name}/{password}")
@ApiImplicitParams({
@ApiImplicitParam(name = "name",value = "账户",required = true,paramType = "path"),
@ApiImplicitParam(name = "password",value = "密码",required = true,paramType = "path")
})
public User getUser2(@PathVariable("name") String name,@PathVariable("password")String password){
return new User(name,password);
}
header方式入参
//header方式入参
@ApiOperation(value = "获取用户3",notes = "获取用户接口3-header方式入参")
@GetMapping("/getUser3")
@ApiImplicitParams({
@ApiImplicitParam(name = "name",value = "账户",required = true,paramType = "header"),
@ApiImplicitParam(name = "password",value = "密码",required = true,paramType = "header")
})
public User getUser3(@RequestHeader String name,@RequestHeader String password){
return new User(name,password);
}
单件上传入参
文件上传时要用@ApiImplicitParams @ApiImplicitParam @ApiParam作用在方法上作为入参@RequestPart用在参数上,用于将“multipart/form-data”请求的一部分与方法参数相关联的注释
//单件上传入参
@ApiOperation(value = "文件上传1",notes = "文件上传-单文件")
@ApiImplicitParams({
@ApiImplicitParam(name = "uploadFile", paramType="form", value = "上传文件", dataType="uploadFile", required = true)
})
@PostMapping(value = "/upload1", headers = "content-type=multipart/form-data")
public String upload(@RequestPart("uploadFile") MultipartFile uploadFile, HttpSession session, HttpServletRequest req){
String originalFilename = uploadFile.getOriginalFilename();
//若文件名为空则返回到上传页
if (!StringUtils.hasText(originalFilename)) {
return "originalFilename is error";
}
//上传路径保存设置
//String uploadPath = session.getServletContext().getRealPath("/uploadFile/");
System.out.println("fileSavePath====="+fileSavePath);
File file1 = new File(fileSavePath);
if (!file1.exists()) {
file1.mkdirs();
}
try {
uploadFile.transferTo(new File(file1,originalFilename));
} catch (IOException e) {
e.printStackTrace();
return "uploadFile is error!";
}
return req.getScheme()+"://"+req.getServerName()+":"+req.getServerPort()+"/workspace_idea01/uploadFile/"+originalFilename;
}
多件上传入参
多个文件上传时,swagger只能测试单文件上传,需要用postman或Apifox等工具测试
@ApiOperation(value = "文件上传2",notes = "文件上传-多文件")
@PostMapping(value = "/upload2",consumes = "multipart/*", headers = "content-type=multipart/form-data")
public ArrayList upload2(@ApiParam(name = "uploadFile",value = "上传文件",required = true,allowMultiple = true) MultipartFile[] uploadFile, HttpSession session, HttpServletRequest req){
String originalFilename ="";
//若文件名为空则返回到上传页
if (!StringUtils.hasText(originalFilename)) {
System.out.println("originalFilename is error");
}
ArrayList filePathList=new ArrayList();
System.out.println("fileSavePath====="+fileSavePath);
File file1 = new File(fileSavePath);
if (!file1.exists()) {
file1.mkdirs();
}
for (MultipartFile file: uploadFile) {
originalFilename = file.getOriginalFilename();
if (!StringUtils.hasText(originalFilename)) {
System.out.println("originalFilename is error");
}
try {
file.transferTo(new File(file1,originalFilename));
filePathList.add(req.getScheme()+"://"+req.getServerName()+":"+req.getServerPort()+"/workspace_idea01/uploadFile/"+originalFilename);
} catch (IOException e) {
e.printStackTrace();
System.out.println("uploadFile is error!");
}
}
return filePathList;
}
通过reuestbody传递数据等方式
//通过reuestbody传递数据等方式
@ApiOperation(value = "测试requestBody", notes = "测试requestBody")
@ApiImplicitParams({
@ApiImplicitParam(paramType="query", name="userId", value="用户id", dataTypeClass = Integer.class, required = true),
@ApiImplicitParam(paramType="body", name = "body",dataType = "string", example = "", required = false)
})
@PostMapping(value="/command",produces = {"application/json;charset=UTF-8"})
public String getHttpInfo(@RequestBody User user, Integer userId) throws IOException {
//InputStream in = request.getInputStream();
// TODO. LOGIC
return user.toString();
}
public String getHttpInfo(HttpServletRequest request, Integer userId) throws IOException { InputStream in = request.getInputStream(); }
- 1
- 2
- 3
既有文件,又有参数
@ApiOperation(value = "文件上传3",notes = "文件上传-携带参数")
@ApiImplicitParams({
@ApiImplicitParam(name = "uploadFile", paramType="form", value = "上传文件", dataType="uploadFile", required = true),
@ApiImplicitParam(name = "id", paramType="query", value = "参数id", dataTypeClass= Integer.class, required = true)
})
@PostMapping(value = "/upload3", headers = "content-type=multipart/form-data")
public String upload3(@RequestPart("uploadFile") MultipartFile uploadFile,Integer id, HttpServletRequest req){
String originalFilename = uploadFile.getOriginalFilename();
//若文件名为空则返回到上传页
if (!StringUtils.hasText(originalFilename)) {
return "originalFilename is error";
}
//上传路径保存设置
//String uploadPath = session.getServletContext().getRealPath("/uploadFile/");
System.out.println("fileSavePath====="+fileSavePath);
File file1 = new File(fileSavePath);
if (!file1.exists()) {
file1.mkdirs();
}
try {
uploadFile.transferTo(new File(file1,originalFilename));
} catch (IOException e) {
e.printStackTrace();
return "uploadFile is error!";
}
return req.getScheme()+"://"+req.getServerName()+":"+req.getServerPort()+"/workspace_idea01/uploadFile/"+originalFilename+"&id="+id;
}
@ApiModel
来标注类,如果接口返回了这个类,那么这个类上的说明也会作为响应的说明:@ApiOperation(value = "返回实体对象",notes = "返回实体对象描述user")
@PostMapping("/getUser4")
public User getUser4(@RequestBody User user){
return user;
}
@ApiResponses
和@ApiResponse
来实现的。@ApiOperation(value = "返回非实体",notes = "返回非实体描述Stirng")
@PostMapping("/getUser5")
@ApiResponses({
@ApiResponse(code = 200,message = "请求-响应成功"),
@ApiResponse(code = 404,message = "页面异常"),
})
public String getUser5(@RequestBody User user){
return user.toString();
}
com.github.xiaoymin
swagger-bootstrap-ui
1.8.7
@EnableSwaggerBootstrapUI
:@Configuration // 标明是配置类
//@EnableSwagger2 //开启swagger2功能 供3.0以下使用,swagger老版本
@EnableOpenApi
//@Profile({"dev","test"})
@ConditionalOnProperty(name = "swagger.enable",havingValue = "true")
@EnableSwaggerBootstrapUI
public class SwaggerConfig {
...
}
http://localhost:8080/doc.html
,可预览到基于bootstarp的Swagger UI界面。基于BootstrapUI的swagger支持指定form-data
或x-www-form-urlencoded
支持复制单个API文档和导出全部API文档:
在Spring Boot整合Spring Security和Swagger的时候,需要配置拦截的路径和放行的路径,注意是放行以下几个路径。
.antMatchers("/swagger**/**").permitAll()
.antMatchers("/webjars/**").permitAll()
.antMatchers("/v2/**").permitAll()
.antMatchers("/doc.html").permitAll() // 如果你用了bootstarp的Swagger UI界面,加一个这个。
在swagger中只支持了简单的调试,但对于一些接口,我们测试的时候可能需要把token信息写到header中
办法如下:
@Bean
public Docket docket(Environment environment){
RequestParameterBuilder builder = new RequestParameterBuilder();
RequestParameter requestParameter = builder.name("token").description("令牌").in(ParameterType.HEADER).required(false).build();
List globalRequestParameters = new ArrayList<>();
globalRequestParameters.add(requestParameter);
//设置要显示的Swagger环境
Profiles profiles = Profiles.of("dev", "test");
//通过environment.acceptsProfiles配置文件中设置的环境来判断是否在设定的环境中
boolean flag = environment.acceptsProfiles(profiles);
return new Docket(DocumentationType.OAS_30)// DocumentationType.OAS_30 固定的,代表swagger3.0
.groupName("分组1") // 如果配置多个文档的时候,那么需要配置groupName来分组标识
.apiInfo(apiInfo())
.enable(flag)
.select() // select()函数返回一个ApiSelectorBuilder实例,用来控制接口被swagger做成文档
.apis(RequestHandlerSelectors.basePackage("com.example.controller"))// 用于指定扫描哪个包下的接口
//paths 指定扫描路径 PathSelectors.ant("/app/**")在controller包下,请求路径是/app/**可以扫描到
.paths(PathSelectors.any())// 选择所有的API,如果你想只为部分API生成文档,可以配置这里
.build().globalRequestParameters(globalRequestParameters); //建造者模式
}
@ApiImplicitParams
来额外标注一个请求头参数,例如:@ApiOperation(value = "获取用户5",notes = "获取用户接口5-带token的接口")
@GetMapping("/getUser5")
@ApiImplicitParams({
@ApiImplicitParam(name = "name",value = "账户",required = true,paramType = "query"),
@ApiImplicitParam(name = "password",value = "密码",required = true,paramType = "query"),
@ApiImplicitParam(name = "token",value = "令牌",required = true,paramType = "header"),
})
public User getUser5(String name,String password){
return new User(name,password);
}