SpringBoot 整合Swagger2

时间:2025-03-21 10:12:17

第一步:添加Maven依赖

<dependency>
    <groupId></groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--Swagger2在线文档-->
<!--swagger2本身不支持spring mvc的,springfox把swagger包装了一下,让他可以支持springmvc-->
<dependency>
    <groupId></groupId>
    <artifactId>springfox-swagger2</artifactId>
    <version>2.9.2</version>
</dependency>
<dependency>
    <groupId></groupId>
    <artifactId>springfox-swagger-ui</artifactId>
    <version>2.9.2</version>
</dependency>
<dependency>
    <groupId></groupId>
    <artifactId>swagger-bootstrap-ui</artifactId>
    <version>1.9.6</version>
</dependency>

上面代码中的springfox-swagger-ui和swagger-bootstrap-ui是两套UI框架,两者可以同时使用,也可以只使用其中的一个。

第二步:编写Swagger配置类,代码如下:

@Configuration
@EnableSwagger2
//是否开启swagger,正式环境一般是需要关闭的(避免不必要的漏洞暴露!),可根据springboot的多环境配置进行设置
public class SwaggerConfig {
@Bean
public Docket createRestApi() {
return new Docket(DocumentationType.SWAGGER_2)
.apiInfo(apiInfo())
//设置全局参数
.globalOperationParameters(globalParamBuilder())
//设置全局响应参数
.globalResponseMessage(,responseBuilder())
.globalResponseMessage(,responseBuilder())
.globalResponseMessage(,responseBuilder())
.globalResponseMessage(,responseBuilder())
.select()
// 自行修改为自己的包路径
.apis((“”))
.paths(())
//设置安全认证
.build()
.securitySchemes(security());
}
private ApiInfo apiInfo() {
return new ApiInfoBuilder()
.title(“题库系统API文档”) //页面标题
.description("基于SpringBoot和MyBatisPlus的题库管理系统API操作文档 版本1.0 ")//描述
//服务条款网址
.termsOfServiceUrl(“/”)
.version(“1.0”) //版本号
.contact(new Contact(“梁云亮”, “/”, “hcitlife@”))//创建人
.build();
}
// 构建全局参数列表
private List globalParamBuilder(){
List pars = new ArrayList<>();
(parameterBuilder(“token”,“令牌”,“string”,“header”,false).build());
return pars;
}
// 创建参数
private ParameterBuilder parameterBuilder(String name, String desc, String type , String parameterType, boolean required) {
ParameterBuilder tokenPar = new ParameterBuilder();
(name).description(desc).modelRef(new ModelRef(type)).parameterType(parameterType).required(required).build();
return tokenPar;
}
// 安全认证参数
private List security() {
List list=new ArrayList<>();
(new ApiKey(“token”, “token”, “header”));
return list;
}
// 创建全局响应值
private List responseBuilder() {
List responseMessageList = new ArrayList<>();
(new ResponseMessageBuilder().code(200).message(“响应成功”).build());
(new ResponseMessageBuilder().code(500).message(“服务器内部错误”).build());
return responseMessageList;
}
}
select()函数返回一个ApiSelectorBuilder实例,用来控制哪些接口暴露给Swagger来展现。本例采用指定扫描的包路径来定义,Swagger会扫描该包下所有Controller定义的API,并产生文档内容(除了被@ApiIgnore指定的请求)
apiInfo()配置一些基本的信息。apis()指定扫描的包会生成文档。再通过api函数创建Docket的Bean之后,apiInfo()用来创建该Api的基本信息(这些基本信息会展现在文档页面中)。
说明:
 @EnableSwagger2开启swagger2;
 @Configuration注解表明它是一个配置类,等价于XML中配置beans;
 @Bean标注方法等价于XML中配置bean。

第三步:编写实体类:

@ApiModel(value = “Dept”,description = “部门信息”)
public class Dept {
@ApiModelProperty(“部门编号”)
private int deptno;
@ApiModelProperty(“部门名称”)
private String dname;
@ApiModelProperty(“部门地址”)
private String loc;
//……getter/setter、toString()、全参和默认构造方法
}

第四步:数据库模拟类

public class DeptTable {
private static ArrayList depts = new ArrayList<>();

static {
    (new Dept(10, "ACCOUNTING", "CHICAGO"));
    (new Dept(20, "RESEARCH", "DALLAS"));
    (new Dept(30, "SALES", "CHICAGO"));
    (new Dept(40, "OPERATIONS", "BOSTON"));
}

public static boolean insert(Dept dept) {
    boolean res = (dept);
    return res;
}

public static boolean update(Dept dept) {
    Integer deptno = ();
    boolean flag = false;
    for (int i = 0; i < (); i++) {
        Dept temp = (i);
        if (().equals(deptno)) {
            (i, dept);
            flag = true;
        }
    }
    return flag;
}

public static boolean delete(Integer deptno) {
    boolean flag = false;
    for (int i = 0; i < (); i++) {
        Dept dept = (i);
        if (().equals(deptno)) {
            (i);
            flag = true;
        }
    }
    return flag;
}

public static Dept selectById(Integer deptno) {
    for (int i = 0; i < (); i++) {
        Dept dept = (i);
        if (().equals(deptno)) {
            return dept;
        }
    }
    return null;
}

public static List<Dept> selectAll() {
    return depts;
}

}

第四步:编写Controller框架

@RestController
@RequestMapping(value = “/dept”)
@Api(value = “DeptController-部门接口模拟”,tags= “DeptController-部门接口模拟”)
@ApiResponses({
@ApiResponse(code = 200, message = “OK”),
@ApiResponse(code = 400, message = “客户端请求错误”),
@ApiResponse(code = 404, message = “找不到路径”),
@ApiResponse(code = 500, message = “编译异常”)
})
public class DeptController {

}
部署项目
请求网址:http://localhost/is/

具体CRUD
添加Dept
Controller类中添加如下代码:
@PostMapping(value = “/v1/dept”)
@ApiOperation(value = “添加部门信息”, notes = “”, httpMethod = “POST”)
public List addDept(@RequestBody Dept dept) throws Exception {
(dept);
return ();
}
运行项目,打开页面http://localhost:8080/,效果如下:

打开页面http://localhost:8080/,效果如下:

修改部门信息
Controller类中添加如下代码:
@PutMapping(value = “/v1/{deptno}”)
@ApiOperation(value = “修改部门信息”, notes = “”, httpMethod = “PUT”)
@ApiImplicitParams({
@ApiImplicitParam(paramType = “path”, name = “deptno”, value = “部门ID”, required = true, dataType = “Integer”),
@ApiImplicitParam(paramType=“body”,name = “dept”, value = “用户实体,传入更改后的数据”, required = true, dataType = “Dept”)
})
public List updateDept1(@PathVariable(value = “deptno”, required = true) Integer deptno, @RequestBody Dept dept) {
(deptno);
(dept);
return ();
}
@PutMapping("/v1/updateDept")
@ApiOperation(value = “修改部门地址”, notes = “根据部门编号修改部门地址”)
@ApiImplicitParams({
@ApiImplicitParam(paramType = “query”, name = “deptno”, value = “部门ID”, required = true, dataType = “Integer”),
@ApiImplicitParam(paramType = “query”, name = “dname”, value = “部门名称”, required = true, dataType = “String”),
@ApiImplicitParam(paramType = “query”, name = “loc”, value = “部门地址”, required = true, dataType = “String”)
})
public List updateDept2(@RequestParam(value = “deptno”) Integer deptno,
@RequestParam(value = “dname”) String dname,
@RequestParam(value = “loc”) String loc) {
Dept dept = new Dept(deptno, dname, loc);
(dept);
return ();
}
解释:

  1. paramType会直接影响程序的运行期,如果paramType与方法参数获取使用的注解不一致,会直接影响到参数的接收。
  2. Conntroller中定义的方法必须在@RequestMapper中显示的指定RequestMethod类型,否则SawggerUi会默认为全类型皆可访问, API列表中会生成多条项目。
  3. 在后台采用对象接收参数时,Swagger自带的工具采用的是JSON传参,测试时需要在参数上加入@RequestBody,正常运行采用form或URL提交时候请删除。
    效果:

查询单个
Controller类中添加如下代码:
@GetMapping(value = “/v1/{deptno}”)
@ApiOperation(value = “获取部门详细信息”, notes = “根据url的deptno来获取部门详细信息”, httpMethod = “GET”)
@ApiImplicitParam(name = “deptno”, value = “部门ID”, required = true, dataType = “Integer”, paramType = “path”)
public Dept getDeptByDeptno1(@PathVariable Integer deptno) {
return (deptno);
}
@GetMapping(value = “/v2/{deptno}”)
@ApiOperation(value = “获取部门详细信息”, notes = “根据url的deptno来获取部门详细信息”, httpMethod = “GET”)
public Dept getDeptByDeptno2(@PathVariable Integer deptno) {
return (deptno);
}
@GetMapping(value = “/v3/getDeptByDeptno”)
@ApiOperation(value = “获取部门详细信息”, notes = “根据id获取部门详细信息”)
@ApiImplicitParam(paramType = “query”, name = “deptno”, value = “部门ID”, required = true, dataType = “Integer”)
public Dept getDeptByDeptno3(@RequestParam Integer deptno) {
return (deptno);
}
效果:

查询列表
Controller类中添加如下代码:
@GetMapping(value = “/v1/list”)
@ApiOperation(value = “获取部门列表”, notes = “一次全部取,不分页”, httpMethod = “GET”)
@ApiImplicitParams({
@ApiImplicitParam(paramType = “header”, name = “token”, value = “token”, required = true, dataType = “String”),
@ApiImplicitParam(paramType = “query”, name = “pageNum”, value = “当前页数”, required = false, dataType = “String”),
@ApiImplicitParam(paramType = “query”, name = “pageSize”, value = “每页记录数”, required = true, dataType = “String”),
})
public List getDoctorList(@RequestParam(value = “pageNum”, required = false, defaultValue = “1”) Integer pageNum,
@RequestParam(value = “pageSize”, required = false) Integer pageSize) throws RuntimeException {
return ();
}
效果:

测试效果:

删除部门
Controller类中添加如下代码:
@DeleteMapping(value = “/v1/{deptno}”)
@ApiOperation(value = “删除部门信息”, notes = “”)
//不知道为什么此处写成path会报错
@ApiImplicitParam(paramType = “path”, name = “deptno”, value = “部门ID”, required = true, dataType = “int”)
public List deleteDept(@PathVariable(value = “deptno”) Integer deptno) {
(deptno);
return ();
}
效果:

忽略
@ApiIgnore //使用该注解忽略这个API
@GetMapping(value = “/hi”)
public String jsonTest() {
return " hi you!";
}

在Security中的配置
如果我们的Spring Boot项目中集成了Spring Security,那么如果不做额外配置,Swagger2文档可能会被拦截,此时只需要在Spring Security的配置类中重写configure方法,添加如下过滤即可:
@Override
public void configure(WebSecurity web) throws Exception {
()
.antMatchers("/")
.antMatchers("/v2/")
.antMatchers("/swagger-resources/
");
}
如此之后,Swagger2文件就不需要认证就能访问了。

问题:异常
项目启动之后,打开网页http://127.0.0.1:8080/#/ ,会发现控制台报错:

是数值类型转换异常,原因是输入了一个空字符串 ,而且是把String转换成Long类型数值的过程中发生异常。分析后知道我们刚刚定义的Dept类中,有一个Integer类型的属性deptno.
@ApiModelProperty(“部门编号”)
private int deptno;
而在DeptController中,我们没有给方法的参数deptno设置默认值。这样系统会自动把我们输入的String类型的id,转换成Integer类型的deptno,再保存成JSON数据。这个转换过程调用的就是(),注意要求的是非空字符串!由于我们没有给这个addDept()这个方法设置默认值,所以系统已启动,就自动尝试把空字符串转换成Integer类型数值,所以就报错了。所以,解决办法就很简单——给参数id设置任意一个默认值。如下:
@ResponseBody
// @PostMapping(value = “/add”)
@RequestMapping(value = “/add”, method = , consumes = MediaType.APPLICATION_JSON_VALUE)
@ApiOperation(value = “添加部门信息”, notes = “”, httpMethod = “POST”)
@ApiImplicitParam(name = “deptno”,value = “部门id”,defaultValue = “10”)
public List addDept(@RequestBody Dept dept) throws Exception {
(dept);
return deptList;
}
设置完,再启动项目就不会报错了。
或者:
实体类中,Integer类型的属性加@ApiModelProperty时,必须要给example参数赋值,且值必须为数字类型。
@ApiModelProperty(value = “部门编号”,example = “10”)
private Integer deptno;
大功告成!