使⽤swagger作为restfulapi的doc⽂档⽣成
初衷
记得以前写接⼝,写完后会整理⼀份API接⼝⽂档,⽽⽂档的格式如果没有具体要求的话,最终展⽰的⽂档则完全决定于开发者的⼼情。也许多点,也许少点。甚⾄,接⼝总是需要适应新需求的,修改了,增加了,这份⽂档维护起来就很困难了。于是发现了swagger,⾃动⽣成⽂档的⼯具。
swagger介绍
⾸先,这样写的:
Swagger – The World's Most Popular Framework for APIs.
因为⾃强所以⾃信。swagger官⽅更新很给⼒,各种版本的更新都有。swagger会扫描配置的API⽂档格式⾃动⽣成⼀份json数据,⽽swagger官⽅也提供了ui来做通常的展⽰,当然也⽀持⾃定义ui的。不过对后端开发者来说,能⽤就可以了,官⽅就可以了。
最强的是,不仅展⽰API,⽽且可以调⽤访问,只要输⼊参数既可以try it out.
效果为先,最终展⽰doc界⾯,也可以设置为中⽂:
在dropwizard中使⽤
详细信息见另⼀篇
在spring-boot中使⽤
以前总是看各种博客来配置,这次也不例外。百度了千篇⼀律却⼜各有细微的差别,甚⾄时间上、版本上各有不同。最终还是去看官⽅⽂档,终于发现了官⽅的sample。针对于各种option的操作完全在demo中了,所以clone照抄就可以⽤了。
github
配置
1.需要依赖两个包:
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>${springfox-version}</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>${springfox-version}</version>
</dependency>
第⼀个是API获取的包,第⼆是官⽅给出的⼀个ui界⾯。这个界⾯可以⾃定义,默认是官⽅的,对于安全问题,以及ui路由设置需要着重思考。
2.swagger的configuration
需要特别注意的是swagger scan base package,这是扫描注解的配置,即你的API接⼝位置。
@Configuration
@EnableSwagger2
public class SwaggerConfig {
public static final String SWAGGER_SCAN_BASE_PACKAGE = "llers";
public static final String VERSION = "1.0.0";
ApiInfo apiInfo() {
return new ApiInfoBuilder()
.title("Swagger API")
.description("This is to show api description")
.license("Apache 2.0")
.licenseUrl("/licenses/LICENSE-2.0.html")
.termsOfServiceUrl("")
.
version(VERSION)
接口文档怎么看.contact(new Contact("","", "miaorf@outlook"))
.build();
}
@Bean
public Docket customImplementation(){
return new Docket(DocumentationType.SWAGGER_2)
.select()
.apis(RequestHandlerSelectors.basePackage(SWAGGER_SCAN_BASE_PACKAGE))
.build()
.directModelSubstitute(org.joda.time.LocalDate.class, java.sql.Date.class)
.
directModelSubstitute(org.joda.time.DateTime.class, java.util.Date.class)
.apiInfo(apiInfo());
}
}
当然,scan package 也可以换成别的条件,⽐如:
@Bean
public Docket api() {
return new Docket(DocumentationType.SWAGGER_2)
.apiInfo(apiInfo())
.select()
.apis(RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class))
.
build();
}
3.在API上做⼀些声明
//本controller的功能描述
@Api(value = "pet", description = "the pet API")
public interface PetApi {
//option的value的内容是这个method的描述,notes是详细描述,response是最终返回的json model。其他可以忽略 @ApiOperation(value = "Add a new pet to the store", notes = "", response = Void.class, authorizations = {
@Authorization(value = "petstore_auth", scopes = {
@AuthorizationScope(scope = "write:pets", description = "modify pets in your account"),
@AuthorizationScope(scope = "read:pets", description = "read your pets")
})
}, tags={ "pet", })
//这⾥是显⽰你可能返回的http状态,以及原因。⽐如404 not found, 303 see other
@ApiResponses(value = {
@ApiResponse(code = 405, message = "Invalid input", response = Void.class) })
@RequestMapping(value = "/pet",
produces = { "application/xml", "application/json" },
consumes = { "application/json", "application/xml" },
method = RequestMethod.POST)
ResponseEntity<Void> addPet(
//这⾥是针对每个参数的描述
@ApiParam(value = "Pet object that needs to be added to the store" ,required=true ) @RequestBody Pet body);案例:
st.llers;
st.ity.City;
st.ity.Hotel;
st.mybatis.domain.mapper.CityMapper;
st.mybatis.domain.mapper.HotelMapper;
st.delmon.BaseResponse;
import io.swagger.annotations.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import java.util.List;
/**
* Created by miaorf on 2016/9/10.
*/
@Api(value = "Test", description = "test the swagger API")
@RestController
public class TestController {
@Autowired
private CityMapper cityMapper;
@Autowired
private HotelMapper hotelMapper;
@ApiOperation(value = "get city by state", notes = "Get city by state", response = City.class)
@ApiResponses(value = {@ApiResponse(code = 405, message = "Invalid input", response = City.class) }) @RequestMapping(value = "/city", method = RequestMethod.GET)
public ResponseEntity<BaseResponse<City>> getCityByState(
@ApiParam(value = "The id of the city" ,required=true ) @RequestParam String state){
City city = cityMapper.findByState(state);
if (city!=null){
BaseResponse response = new BaseResponse(city,true,null);
return new ResponseEntity<>(response, HttpStatus.OK);
}
return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
}
@ApiOperation(value = "save city", notes = "", response = City.class)
@RequestMapping(value = "/city", method = RequestMethod.POST)
public ResponseEntity<BaseResponse<City>> saveCity(
@ApiParam(value = "The id of the city" ,required=true ) @RequestBody City city){
int save = cityMapper.save(city);
if (save>0){
BaseResponse response = new BaseResponse(city,true,null);
return new ResponseEntity<>(response, HttpStatus.OK);
}
return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
}
@ApiOperation(value = "save hotel", notes = "", response = Hotel.class)
@RequestMapping(value = "/hotel", method = RequestMethod.POST)
public ResponseEntity<BaseResponse<Hotel>> saveHotel(
@ApiParam(value = "hotel" ,required=true ) @RequestBody Hotel hotel){
int save = hotelMapper.save(hotel);
if (save>0){
BaseResponse response = new BaseResponse(hotel,true,null);
return new ResponseEntity<>(response, HttpStatus.OK);
}
return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
}
@ApiOperation(value = "get the hotel", notes = "get the hotel by the city id", response = Hotel.class)
@RequestMapping(value = "/hotel", method = RequestMethod.GET)
public ResponseEntity<BaseResponse<Hotel>> getHotel(
@ApiParam(value = "the hotel id" ,required=true ) @RequestParam Long cid){
List<Hotel> hotels = hotelMapper.selectByCityId(cid);
return new ResponseEntity<>(new BaseResponse(hotels,true,null), HttpStatus.OK);
}
@ApiOperation(value = "update the hotel", notes = "update the hotel", response = Hotel.class)
@RequestMapping(value = "/hotel", method = RequestMethod.PUT)
public ResponseEntity<BaseResponse<Hotel>> updateHotel(
@ApiParam(value = "the hotel" ,required=true ) @RequestBody Hotel hotel){
int result = hotelMapper.update(hotel);
return new ResponseEntity<>(new BaseResponse(result,true,null), HttpStatus.OK);
}
@ApiOperation(value = "delete the hotel", notes = "delete the hotel by the hotel id", response = City.class)
@RequestMapping(value = "/hotel", method = RequestMethod.DELETE)
public ResponseEntity<BaseResponse<Hotel>> deleteHotel(
@ApiParam(value = "the hotel id" ,required=true ) @RequestParam Long htid){
int result = hotelMapper.delete(htid);
return new ResponseEntity<>(new BaseResponse(result,true,null), HttpStatus.OK);
}
}
4.设定访问API doc的路由
在配置⽂件中,l中声明:
springfox.documentation.swagger.v2.path: /api-docs
这个path就是json的访问request mapping.可以⾃定义,防⽌与⾃⾝代码冲突。
如果项⽬是⼀个webservice,通常设定home / 指向这⾥:
@Controller
public class HomeController {
@RequestMapping(value = "/swagger")
public String index() {
System.out.println("swagger-ui.html");
return "redirect:swagger-ui.html";
}
}
5.访问
就是上⾯的了。但是,注意到安全问题就会感觉困扰。⾸先,该接⼝请求有⼏个:
localhost:8080/swagger-resources/configuration/ui
localhost:8080/swagger-resources
localhost:8080/api-docs
localhost:8080/swagger-resources/configuration/security
除却⾃定义的url,还有2个ui显⽰的API和⼀个安全问题的API。关于安全问题的配置还没去研究,但⽬前发现⼀个问题是在我的⼀个项⽬中,所有的url必须带有query htid=xxx,这是为了sso portal验证的时候需要。这样这个⼏个路由就不符合要求了。
如果不想去研究安全问题怎么解决,那么可以⾃定ui。只需要将ui下⾯的⽂件拷贝出来,然后修改请求数据⽅式即可。
6. 设置在⽣产环境关闭swagger
参考:
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论