Swagger是一个规范和完整的框架,用于生成、描述、调用和可视化 RESTful 风格的 Web 服务。总体目标是使客
户端和文件系统作为服务器以同样的速度来更新。文件的方法,参数和模型紧密集成到服务器端的代码,允许API
来始终保持同步。
作用:
1、接口的文档在线自动生成。
2、功能测试。
Swagger是一组开源项目,其中主要要项目如下:
1、Swagger-tools
:提供各种与Swagger进行集成和交互的工具。例如模式检验、Swagger 1.2文档转换成
Swagger 2.0文档等功能。
2、Swagger-core
:: 用于Java/Scala的的Swagger实现。与JAX-RS(Jersey、Resteasy、CXF…)、Servlets和
Play框架进行集成。
3、Swagger-js
:用于JavaScript的Swagger实现。
4、Swagger-node-express
: Swagger模块,用于node.js的Express web应用框架。
5、Swagger-ui
:一个无依赖的HTML、JS和CSS集合,可以为Swagger兼容API动态生成优雅文档。
6、Swagger-codegen
:一个模板驱动引擎,通过分析用户Swagger资源声明以各种语言生成客户端代码。
Swagger官网 :http://swagger.io/
Github:https://github.com/swagger-api/swagger-core/wiki/Annotations
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0modelVersion>
<parent>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-parentartifactId>
<version>2.1.0.RELEASEversion>
<relativePath/>
parent>
<groupId>com.examplegroupId>
<artifactId>spring-boot-swaggerartifactId>
<version>0.0.1-SNAPSHOTversion>
<name>spring-boot-swaggername>
<description>spring-boot-swaggerdescription>
<properties>
<java.version>1.8java.version>
properties>
<dependencies>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
dependency>
<dependency>
<groupId>io.springfoxgroupId>
<artifactId>springfox-swagger2artifactId>
<version>2.9.2version>
dependency>
<dependency>
<groupId>io.springfoxgroupId>
<artifactId>springfox-swagger-uiartifactId>
<version>2.9.2version>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-testartifactId>
<scope>testscope>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-devtoolsartifactId>
<scope>runtimescope>
<optional>trueoptional>
dependency>
dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-maven-pluginartifactId>
<configuration>
<fork>truefork>
configuration>
plugin>
plugins>
build>
project>
package com.example.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.Contact;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
@Configuration
@EnableSwagger2
public class SwaggerConfig {
@Bean
public Docket api() {
return new Docket(DocumentationType.SWAGGER_2).apiInfo(apiInfo()).select()
// 自行修改为自己的包路径
.apis(RequestHandlerSelectors.basePackage("com.example.controller")).paths(PathSelectors.any()).build();
}
private ApiInfo apiInfo() {
return new ApiInfoBuilder().title("客户管理").description("客户管理中心 API 1.0 操作文档")
// 服务条款网址
.termsOfServiceUrl("http://www.tom.com/").version("1.0").contact(new Contact("tom", "http://www.tom.com/", "[email protected]")).build();
}
}
通过api函数创建Docket的Bean之后,apiInfo用来创建该Api的基本信息(这些基本信息会展现在文档页面中)。
package com.example.config;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
/**
* 通用响应对象
*/
@ApiModel(description = "响应对象")
public class BaseResult<T> {
private static final int SUCCESS_CODE = 0;
private static final String SUCCESS_MESSAGE = "成功";
@ApiModelProperty(value = "响应码", name = "code", required = true, example = "" + SUCCESS_CODE)
private int code;
@ApiModelProperty(value = "响应消息", name = "msg", required = true, example = SUCCESS_MESSAGE)
private String msg;
@ApiModelProperty(value = "响应数据", name = "data")
private T data;
private BaseResult(int code, String msg, T data) {
this.code = code;
this.msg = msg;
this.data = data;
}
private BaseResult() {
this(SUCCESS_CODE, SUCCESS_MESSAGE);
}
private BaseResult(int code, String msg) {
this(code, msg, null);
}
private BaseResult(T data) {
this(SUCCESS_CODE, SUCCESS_MESSAGE, data);
}
public static <T> BaseResult<T> success() {
return new BaseResult<>();
}
public static <T> BaseResult<T> successWithData(T data) {
return new BaseResult<>(data);
}
public static <T> BaseResult<T> failWithCodeAndMsg(int code, String msg) {
return new BaseResult<>(code, msg, null);
}
public static <T> BaseResult<T> buildWithParam(ResponseParam param) {
return new BaseResult<>(param.getCode(), param.getMsg(), null);
}
public int getCode() {
return code;
}
public void setCode(int code) {
this.code = code;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
public static class ResponseParam {
private int code;
private String msg;
private ResponseParam(int code, String msg) {
this.code = code;
this.msg = msg;
}
public static ResponseParam buildParam(int code, String msg) {
return new ResponseParam(code, msg);
}
public int getCode() {
return code;
}
public void setCode(int code) {
this.code = code;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
}
}
package com.example.model;
import io.swagger.annotations.ApiModelProperty;
import java.util.Date;
public class Message {
private Long id;
@ApiModelProperty(value = "消息体")
private String text;
@ApiModelProperty(value = "消息总结")
private String summary;
private Date createDate;
public Long getId() {
return this.id;
}
public void setId(Long id) {
this.id = id;
}
public Date getCreateDate() {
return createDate;
}
public void setCreateDate(Date createDate) {
this.createDate = createDate;
}
public String getText() {
return this.text;
}
public void setText(String text) {
this.text = text;
}
public String getSummary() {
return this.summary;
}
public void setSummary(String summary) {
this.summary = summary;
}
@Override
public String toString() {
return "Message{" + "id=" + id + ", text='" + text + '\'' + ", summary='" + summary + '\'' + ", createDate=" + createDate + '}';
}
}
package com.example.model;
public class User {
private Long id;
private String name;
private int age;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
package com.example.repository;
import com.example.model.Message;
import java.util.List;
public interface MessageRepository {
List<Message> findAll();
Message save(Message message);
Message update(Message message);
Message updateText(Message message);
Message findMessage(Long id);
void deleteMessage(Long id);
}
package com.example.repository;
import com.example.model.Message;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.atomic.AtomicLong;
@Service("messageRepository")
public class InMemoryMessageRepository implements MessageRepository {
private static AtomicLong counter = new AtomicLong();
private final ConcurrentMap<Long, Message> messages = new ConcurrentHashMap<>();
@Override
public List<Message> findAll() {
List<Message> messages = new ArrayList<Message>(this.messages.values());
return messages;
}
@Override
public Message save(Message message) {
Long id = message.getId();
if (id == null) {
id = counter.incrementAndGet();
message.setId(id);
}
this.messages.put(id, message);
return message;
}
@Override
public Message update(Message message) {
this.messages.put(message.getId(), message);
return message;
}
@Override
public Message updateText(Message message) {
Message msg = this.messages.get(message.getId());
msg.setText(message.getText());
this.messages.put(msg.getId(), msg);
return msg;
}
@Override
public Message findMessage(Long id) {
return this.messages.get(id);
}
@Override
public void deleteMessage(Long id) {
this.messages.remove(id);
}
}
package com.example.controller;
import com.example.config.BaseResult;
import com.example.model.User;
import io.swagger.annotations.*;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import springfox.documentation.annotations.ApiIgnore;
import java.util.*;
@Api(value = "用户管理", description = "用户管理API", position = 100, protocols = "http")
@RestController
@RequestMapping(value = "/user")
public class UserController {
static Map<Long, User> users = Collections.synchronizedMap(new HashMap<>());
@ApiOperation(value = "获取用户列表", notes = "查询用户列表")
@RequestMapping(value = {""}, method = RequestMethod.GET)
@ApiResponses({@ApiResponse(code = 100, message = "异常数据")})
public List<User> getUserList() {
return new ArrayList<>(users.values());
}
@ApiOperation(value = "创建用户", notes = "根据User对象创建用户")
@ApiImplicitParams({@ApiImplicitParam(name = "id", value = "用户ID", required = true, dataType = "Long", paramType = "query"), @ApiImplicitParam(name = "name", value = "用户名", required = true, dataType = "String", paramType = "query"), @ApiImplicitParam(name = "age", value = "年龄", required = true, dataType = "String", paramType = "query"), @ApiImplicitParam(name = "ipAddr", value = "ip哟", required = false, dataType = "String", paramType = "query")})
@RequestMapping(value = "", method = RequestMethod.POST)
public BaseResult<User> postUser(@ApiIgnore User user) {
users.put(user.getId(), user);
return BaseResult.successWithData(user);
}
@ApiOperation(value = "获取用户详细信息", notes = "根据url的id来获取用户详细信息")
@ApiImplicitParam(name = "id", value = "用户ID", required = true, dataType = "Long", paramType = "path")
@RequestMapping(value = "/{id}", method = RequestMethod.GET)
public User getUser(@PathVariable Long id) {
return users.get(id);
}
@ApiOperation(value = "更新用户信息", notes = "根据用户ID更新信息")
@ApiImplicitParams({@ApiImplicitParam(name = "id", value = "用户ID", required = true, dataType = "Long", paramType = "query"), @ApiImplicitParam(name = "name", value = "用户名", required = true, dataType = "String", paramType = "query"), @ApiImplicitParam(name = "age", value = "年龄", required = true, dataType = "String", paramType = "query")})
@RequestMapping(value = "/{id}", method = RequestMethod.PUT)
public BaseResult<User> putUser(@PathVariable Long id, @ApiIgnore User user) {
User u = users.get(id);
u.setName(user.getName());
u.setAge(user.getAge());
users.put(id, u);
return BaseResult.successWithData(u);
}
@RequestMapping(value = "/{id}", method = RequestMethod.DELETE)
public String deleteUser(@PathVariable Long id) {
users.remove(id);
return "success";
}
@RequestMapping(value = "/ignoreMe/{id}", method = RequestMethod.DELETE)
public String ignoreMe(@PathVariable Long id) {
users.remove(id);
return "success";
}
}
package com.example.controller;
import com.example.config.BaseResult;
import com.example.model.Message;
import com.example.repository.MessageRepository;
import io.swagger.annotations.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@Api(value = "消息", description = "消息操作 API", position = 100, protocols = "http")
@RestController
@RequestMapping("/")
public class MessageController {
@Autowired
private MessageRepository messageRepository;
@ApiOperation(value = "消息列表", notes = "完整的消息内容列表", produces = "application/json, application/xml", consumes = "application/json, application/xml", response = List.class)
@GetMapping(value = "messages")
public List<Message> list() {
List<Message> messages = this.messageRepository.findAll();
return messages;
}
@ApiOperation(value = "添加消息", notes = "根据参数创建消息")
@ApiImplicitParams({@ApiImplicitParam(name = "id", value = "消息 ID", required = true, dataType = "Long", paramType = "query"), @ApiImplicitParam(name = "text", value = "正文", required = true, dataType = "String", paramType = "query"), @ApiImplicitParam(name = "summary", value = "摘要", required = false, dataType = "String", paramType = "query"),})
@PostMapping(value = "message")
public Message create(Message message) {
System.out.println("message====" + message.toString());
message = this.messageRepository.save(message);
return message;
}
@ApiOperation(value = "修改消息", notes = "根据参数修改消息")
@PutMapping(value = "message")
@ApiResponses({@ApiResponse(code = 100, message = "请求参数有误"), @ApiResponse(code = 101, message = "未授权"), @ApiResponse(code = 103, message = "禁止访问"), @ApiResponse(code = 104, message = "请求路径不存在"), @ApiResponse(code = 200, message = "服务器内部错误")})
public Message modify(Message message) {
Message messageResult = this.messageRepository.update(message);
return messageResult;
}
@PatchMapping(value = "/message/text")
public BaseResult<Message> patch(Message message) {
Message messageResult = this.messageRepository.updateText(message);
return BaseResult.successWithData(messageResult);
}
@GetMapping(value = "message/{id}")
public Message get(@PathVariable Long id) {
Message message = this.messageRepository.findMessage(id);
return message;
}
@DeleteMapping(value = "message/{id}")
public void delete(@PathVariable("id") Long id) {
this.messageRepository.deleteMessage(id);
}
}
Swagger使用的注解及其说明:
注解 | 说明 |
---|---|
@Api |
用在类上,说明该类的作用 |
@ApiOperation |
注解来给API增加方法说明 |
@ApiImplicitParams |
用在方法上包含一组参数说明 |
@ApiImplicitParam |
用来注解来给方法入参增加说明 |
@ApiResponses |
用于表示一组响应 |
@ApiResponse |
用在@ApiResponses中,一般用于表达一个错误的响应信息。code:数字,例如400;message:信息,例如"请求参数没填好";response:抛出异常的类 |
@ApiModel |
描述一个Model的信息(一般用在请求参数无法使用@ApiImplicitParam注解进行描述的时候) |
@ApiModelProperty |
描述一个model的属性 |
@ApiImplicitParam的参数说明:
参数 | 参数说明 |
---|---|
paramType |
指定参数放在哪个地方。可选参数: header:请求参数放置于Request Header,使用@RequestHeader获取; query:请求参数放置于请求地址,使用@RequestParam获取; path:(用于restful接口)–>请求参数的获取:@PathVariable body:(不常用) form(不常用) |
name |
参数名 |
dataType |
参数类型 |
required |
参数是否必须传,可选参数为:true | false |
value |
说明参数的意思 |
defaultValue |
参数的默认值 |
用于类;表示标识这个类是swagger的资源
tags
:表示说明
value
:也是说明,可以使用tags替代 ,但是tags如果有多个值,会生成多个list
@Api(value="用户controller",tags={"用户操作接口"})
@RestController
public class UserController { }
用于方法;表示一个http请求的操作
value
:用于方法描述
notes
:用于提示内容
tags
:可以重新分组(视情况而用)
用于方法,参数,字段说明;表示对参数的添加元数据(说明或是否必填等)
name
:参数名value
:参数说明required
:是否必填@Api(value="用户controller",tags={"用户操作接口"})
@RestController
public class UserController {
@ApiOperation(value="获取用户信息",tags={"获取用户信息copy"},notes="注意问题点")
@GetMapping("/getUserInfo")
public User getUserInfo(@ApiParam(name="id",value="用户id",required=true) Long id,
@ApiParam(name="username",value="用户名") String username) {
// userService可忽略,是业务逻辑
User user = userService.getUserInfo();
return user;
} }
用于类 ;表示对类进行说明,用于参数用实体类接收
value
:表示对象名
description
:描述
用于方法,字段; 表示对model属性的说明或者数据操作更改
value
:字段说明
name
:重写属性名字
dataType
:重写属性类型
required
:是否必填
example
:举例说明
hidden
:隐藏
@ApiModel(value="user对象",description="用户对象user")
public class User implements Serializable{
private static final long serialVersionUID = 1L;
@ApiModelProperty(value="用户名",name="username",example="xingguo")
private String username;
@ApiModelProperty(value="状态",name="state",required=true)
private Integer state;
private String password;
private String nickName;
private Integer isDeleted;
@ApiModelProperty(value="id数组",hidden=true)
private String[] ids;
private List<String> idList;
}
用于类或者方法上,可以不被swagger显示在页面上
比较简单, 这里不做举例
用于方法,表示单独的请求参数
用于方法,包含多个 @ApiImplicitParam
name
:参数ming
value
:参数说明
dataType
:数据类型
paramType
:参数类型
header
–>请求参数的获取:@RequestHeader
query
–>请求参数的获取:@RequestParam
path
(用于restful接口)–>请求参数的获取:@PathVariable
body
(不常用)post请求
form
(不常用)以form表单的形式提交 仅支持POST
example
:举例说明
@ApiOperation("查询测试")
@GetMapping("select")
//@ApiImplicitParam(name="name",value="用户名",dataType="String", paramType = "query")
@ApiImplicitParams({
@ApiImplicitParam(name="name",value="用户名",dataType="string", paramType = "query",example="xingguo"),
@ApiImplicitParam(name="id",value="用户id",dataType="long", paramType = "query")})
public void select(){}
package com.example;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
logging.level.io.swagger.models.parameters.AbstractSerializableParameter=error
<configuration>
<include resource="org/springframework/boot/logging/logback/base.xml"/>
configuration>
package com.example.web;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.MvcResult;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.context.WebApplicationContext;
@RunWith(SpringRunner.class)
@SpringBootTest
public class MessageControllerTest {
@Autowired
private WebApplicationContext wac;
private MockMvc mockMvc;
@Before
public void setup() {
this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).build();
saveMessages();
}
@Test
public void saveMessage() throws Exception {
final MultiValueMap<String, String> params = new LinkedMultiValueMap<>();
params.add("text", "text");
params.add("summary", "summary");
String mvcResult = mockMvc.perform(MockMvcRequestBuilders.post("/message").params(params)).andReturn().getResponse().getContentAsString();
System.out.println("Result === " + mvcResult);
}
@Test
public void getAllMessages() throws Exception {
String mvcResult = mockMvc.perform(MockMvcRequestBuilders.get("/messages")).andReturn().getResponse().getContentAsString();
System.out.println("Result === " + mvcResult);
}
@Test
public void getMessage() throws Exception {
String mvcResult = mockMvc.perform(MockMvcRequestBuilders.get("/message/6")).andReturn().getResponse().getContentAsString();
System.out.println("Result === " + mvcResult);
}
@Test
public void modifyMessage() throws Exception {
final MultiValueMap<String, String> params = new LinkedMultiValueMap<>();
params.add("id", "6");
params.add("text", "text");
params.add("summary", "summary");
String mvcResult = mockMvc.perform(MockMvcRequestBuilders.put("/message").params(params)).andReturn().getResponse().getContentAsString();
System.out.println("Result === " + mvcResult);
}
@Test
public void patchMessage() throws Exception {
final MultiValueMap<String, String> params = new LinkedMultiValueMap<>();
params.add("id", "6");
params.add("text", "text");
String mvcResult = mockMvc.perform(MockMvcRequestBuilders.patch("/message/text").params(params)).andReturn().getResponse().getContentAsString();
System.out.println("Result === " + mvcResult);
}
@Test
public void deleteMessage() throws Exception {
mockMvc.perform(MockMvcRequestBuilders.delete("/message/6")).andReturn();
String mvcResult = mockMvc.perform(MockMvcRequestBuilders.get("/messages")).andReturn().getResponse().getContentAsString();
System.out.println("Result === " + mvcResult);
}
private void saveMessages() {
for (int i = 1; i < 10; i++) {
final MultiValueMap<String, String> params = new LinkedMultiValueMap<>();
params.add("id", "" + i);
params.add("text", "text" + i);
params.add("summary", "summary" + i);
try {
MvcResult mvcResult = mockMvc.perform(MockMvcRequestBuilders.post("/message").params(params)).andReturn();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
http://localhost:8080/swagger-ui.html
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0modelVersion>
<parent>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-parentartifactId>
<version>2.4.5version>
<relativePath/>
parent>
<groupId>com.examplegroupId>
<artifactId>swaggerartifactId>
<version>0.0.1-SNAPSHOTversion>
<name>swaggername>
<description>Demo project for Spring Bootdescription>
<properties>
<java.version>1.8java.version>
properties>
<dependencies>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-testartifactId>
<scope>testscope>
dependency>
<dependency>
<groupId>io.springfoxgroupId>
<artifactId>springfox-swagger2artifactId>
<version>2.7.0version>
dependency>
<dependency>
<groupId>com.github.xiaoymingroupId>
<artifactId>swagger-bootstrap-uiartifactId>
<version>1.9.6version>
dependency>
dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-maven-pluginartifactId>
plugin>
plugins>
build>
project>
package com.example.swagger.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.Contact;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
@Configuration
@EnableSwagger2
public class SwaggerConfig {
@Bean
public Docket createRestApi() {
return new Docket(DocumentationType.SWAGGER_2)
.apiInfo(apiInfo())
.select()
.apis(RequestHandlerSelectors.basePackage("com.example.swagger.controller"))
.paths(PathSelectors.any())
.build();
}
private ApiInfo apiInfo() {
return new ApiInfoBuilder()
.title("Spring Boot中使用Swagger2构建RESTful APIs")
.description("更多请关注http://www.baidu.com")
.termsOfServiceUrl("http://www.baidu.com")
.contact(new Contact("zhangshixing", null, null))
.title("测试Swagger")
.version("1.0")
.build();
}
}
package com.example.swagger.controller;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.springframework.stereotype.Controller;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
/**
* 一个用来测试swagger注解的控制器
* 注意@ApiImplicitParam的使用会影响程序运行,如果使用不当可能造成控制器收不到消息
*/
@Controller
@RequestMapping("/say")
@Api(value = "SayController|一个用来测试swagger注解的控制器")
public class TestController {
@ResponseBody
@RequestMapping(value ="/getUserName", method= RequestMethod.GET)
@ApiOperation(value="根据用户编号获取用户姓名", notes="test: 仅1和2有正确返回")
@ApiImplicitParam(paramType="query", name = "userNumber", value = "用户编号", required = true, dataType = "int")
public String getUserName(@RequestParam Integer userNumber){
if(userNumber == 1){
return "张三丰";
}
else if(userNumber == 2){
return "慕容复";
}
else{
return "未知";
}
}
@ResponseBody
@RequestMapping(value="/updatePassword",method= RequestMethod.PUT)
@ApiOperation(value="修改用户密码", notes="根据用户id修改密码")
@ApiImplicitParams({
@ApiImplicitParam(paramType="query", name = "userId", value = "用户ID", required = true, dataType = "int"),
@ApiImplicitParam(paramType="query", name = "password", value = "旧密码", required = true, dataType = "String"),
@ApiImplicitParam(paramType="query", name = "newPassword", value = "新密码", required = true, dataType = "String")
})
public String updatePassword(@RequestParam(value="userId") Integer userId, @RequestParam(value="password") String password,
@RequestParam(value="newPassword") String newPassword){
if(userId <= 0 || userId > 2){
return "未知的用户";
}
if(StringUtils.isEmpty(password) || StringUtils.isEmpty(newPassword)){
return "密码不能为空";
}
if(password.equals(newPassword)){
return "新旧密码不能相同";
}
return "密码修改成功!!!!";
}
}
package com.example.swagger;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class SwaggerApplication{
public static void main(String[] args) {
SpringApplication.run(SwaggerApplication.class, args);
}
}
http://localhost:8080/doc.html
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0modelVersion>
<parent>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-parentartifactId>
<version>2.4.5version>
<relativePath/>
parent>
<groupId>com.examplegroupId>
<artifactId>swaggerartifactId>
<version>0.0.1-SNAPSHOTversion>
<name>swaggername>
<description>Demo project for Spring Bootdescription>
<properties>
<java.version>1.8java.version>
properties>
<dependencies>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-testartifactId>
<scope>testscope>
dependency>
<dependency>
<groupId>io.springfoxgroupId>
<artifactId>springfox-boot-starterartifactId>
<version>3.0.0version>
dependency>
dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-maven-pluginartifactId>
plugin>
plugins>
build>
project>
package com.example.swagger.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.Contact;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
@Configuration
@EnableSwagger2
public class SwaggerConfig {
@Bean
public Docket createRestApi() {
return new Docket(DocumentationType.SWAGGER_2)
.apiInfo(apiInfo())
.select()
.apis(RequestHandlerSelectors.basePackage("com.example.swagger.controller"))
.paths(PathSelectors.any())
.build();
}
private ApiInfo apiInfo() {
return new ApiInfoBuilder()
.title("Spring Boot中使用Swagger2构建RESTful APIs")
.description("更多请关注http://www.baidu.com")
.termsOfServiceUrl("http://www.baidu.com")
.contact(new Contact("zhangshixing", null, null))
.title("测试Swagger")
.version("1.0")
.build();
}
}
package com.example.swagger.controller;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.springframework.stereotype.Controller;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
/**
* 一个用来测试swagger注解的控制器
* 注意@ApiImplicitParam的使用会影响程序运行,如果使用不当可能造成控制器收不到消息
*/
@Controller
@RequestMapping("/say")
@Api(value = "SayController|一个用来测试swagger注解的控制器")
public class TestController {
@ResponseBody
@RequestMapping(value ="/getUserName", method= RequestMethod.GET)
@ApiOperation(value="根据用户编号获取用户姓名", notes="test: 仅1和2有正确返回")
@ApiImplicitParam(paramType="query", name = "userNumber", value = "用户编号", required = true, dataType = "int")
public String getUserName(@RequestParam Integer userNumber){
if(userNumber == 1){
return "张三丰";
}
else if(userNumber == 2){
return "慕容复";
}
else{
return "未知";
}
}
@ResponseBody
@RequestMapping(value="/updatePassword",method= RequestMethod.PUT)
@ApiOperation(value="修改用户密码", notes="根据用户id修改密码")
@ApiImplicitParams({
@ApiImplicitParam(paramType="query", name = "userId", value = "用户ID", required = true, dataType = "int"),
@ApiImplicitParam(paramType="query", name = "password", value = "旧密码", required = true, dataType = "String"),
@ApiImplicitParam(paramType="query", name = "newPassword", value = "新密码", required = true, dataType = "String")
})
public String updatePassword(@RequestParam(value="userId") Integer userId, @RequestParam(value="password") String password,
@RequestParam(value="newPassword") String newPassword){
if(userId <= 0 || userId > 2){
return "未知的用户";
}
if(StringUtils.isEmpty(password) || StringUtils.isEmpty(newPassword)){
return "密码不能为空";
}
if(password.equals(newPassword)){
return "新旧密码不能相同";
}
return "密码修改成功!!!!";
}
}
package com.example.swagger;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class SwaggerApplication{
public static void main(String[] args) {
SpringApplication.run(SwaggerApplication.class, args);
}
}
http://localhost:8080/swagger-ui/
swagger在正常使用时,我们的接口需要登陆才能访问的。即登陆时,要传一个登陆后的token才能访问的。那这
个怎么设置,才可以让所有接口都允许登陆后访问呢。解决方法:
package com.example.swagger.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.*;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spi.service.contexts.SecurityContext;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
import java.util.Collections;
import java.util.List;
@Configuration
@EnableSwagger2
public class SwaggerConfig {
@Bean
public Docket createRestApi() {
return new Docket(DocumentationType.SWAGGER_2).apiInfo(apiInfo()).enable(true).select().apis(RequestHandlerSelectors.basePackage("com.example.swagger.controller")).paths(PathSelectors.any()).build().securityContexts(securityContexts()).securitySchemes(securitySchemes());
}
private List<ApiKey> securitySchemes() {
return Collections.singletonList(new ApiKey("Authorization", "Authorization", "header"));
}
private List<SecurityContext> securityContexts() {
return Collections.singletonList(SecurityContext.builder().securityReferences(defaultAuth()).build());
}
private List<SecurityReference> defaultAuth() {
AuthorizationScope authorizationScope = new AuthorizationScope("global", "accessEverything");
AuthorizationScope[] authorizationScopes = new AuthorizationScope[1];
authorizationScopes[0] = authorizationScope;
return Collections.singletonList(new SecurityReference("Authorization", authorizationScopes));
}
private ApiInfo apiInfo() {
return new ApiInfoBuilder().title("Spring Boot中使用Swagger2构建RESTful APIs").description("更多请关注http://www.baidu.com").termsOfServiceUrl("http://www.baidu.com").contact(new Contact("zhangshixing", null, null)).title("测试Swagger").version("1.0").build();
}
}
此问题是由 swagger2 中的 swagger-annotations 和 swagger-models 依赖版本过低导致的,解决方式如下:
<dependency>
<groupId>io.springfoxgroupId>
<artifactId>springfox-swagger2artifactId>
<version>2.9.2version>
<exclusions>
<exclusion>
<groupId>io.swaggergroupId>
<artifactId>swagger-annotationsartifactId>
exclusion>
<exclusion>
<groupId>io.swaggergroupId>
<artifactId>swagger-modelsartifactId>
exclusion>
exclusions>
dependency>
<dependency>
<groupId>io.springfoxgroupId>
<artifactId>springfox-swagger-uiartifactId>
<version>2.9.2version>
dependency>
<dependency>
<groupId>io.swaggergroupId>
<artifactId>swagger-annotationsartifactId>
<version>1.5.21version>
dependency>
<dependency>
<groupId>io.swaggergroupId>
<artifactId>swagger-modelsartifactId>
<version>1.5.21version>
dependency>