最近開始看後端的東西,記錄下學習筆記吧。
一、Swagger定義:http://swagger.io(官網)
Swagger是一個簡單但功能強大的API表達工具。它具有地球上最大的API工具生態系統,數以千計的開發人員,使用幾乎所有的現代編程語言,都在支持和使用Swagger。使用Swagger生成API,我們可以得到交互式文檔,自動生成代碼的SDK以及API的發現特性等。
現在,Swagger已經幫助包括Apigee, Getty圖像, Intuit, LivingSocial, McKesson, 微軟, Morningstar和PayPal等世界知名企業建立起了一套基於RESTful API的完美服務系統。
2.0版本已經發布,Swagger變得更加強大。值得感激的是,Swagger的源碼100%開源在github。
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資源聲明以各種語言生成客戶端代碼。
二、作用
1、接口文檔的在線自動生成
2、功能測試
三、集成
1、maven方式 在pom.xml中增加dependency
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.6.1</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.6.1</version>
</dependency>
2、創建Swagger2配置類(看其他的貼子中寫要和Application同級目錄,但是我沒有放在同一級別也可以,不知原因,知道原因的可以給我留言,互相學習。)
package com.betty.miaosha.config;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.Contact;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
/*
* Create by BettyLi on 2019/12/1 14:40
*
*/
@Configuration
@EnableSwagger2
public class SwaggerConfig extends WebMvcConfigurationSupport {
@Bean
public Docket petApi() {
return new Docket(DocumentationType.SWAGGER_2)
.apiInfo(apiInfo())
.select()
.apis(RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class))
.apis(RequestHandlerSelectors.basePackage("com.betty.miaosha.controller")) //指定提供接口所在的基包
.paths(PathSelectors.any())
.build();
}
/**
* 該套 API 說明,包含作者、簡介、版本、host、服務URL
* @return
*/
private ApiInfo apiInfo() {
return new ApiInfoBuilder()
.title("Betty Swagger學習")
.version("1.0")
//.termsOfServiceUrl("localhost:8090/betty")
.description("betty demo")
.build();
}
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/**").addResourceLocations(
"classpath:/static/");
// 解決 SWAGGER 404報錯
registry.addResourceHandler("/swagger-ui.html").addResourceLocations("classpath:/META-INF/resources/");
registry.addResourceHandler("/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/");
}
}
不加addResourceHandlers的話,我這邊是報錯no mapper錯誤,也有的說是404,我直接就加上了。
做好這些就可以在Controller中添加文檔內容了。
3、在完成了上述配置後,其實已經可以生產文檔內容,但是這樣的文檔主要針對請求本身,描述的主要來源是函數的命名,對用戶並不友好,我們通常需要自己增加一些說明來豐富文檔內容。
Swagger使用的註解及其說明:
@Api:用在類上,說明該類的作用。
@ApiOperation:註解來給API增加方法說明。
@ApiImplicitParams : 用在方法上包含一組參數說明。
@ApiImplicitParam:用來註解來給方法入參增加說明。
@ApiResponses:用於表示一組響應
@ApiResponse:用在@ApiResponses中,一般用於表達一個錯誤的響應信息
l code:數字,例如400
l message:信息,例如"請求參數沒填好"
l response:拋出異常的類
@ApiModel:描述一個Model的信息(一般用在請求參數無法使用@ApiImplicitParam註解進行描述的時候)
l @ApiModelProperty:描述一個model的屬性
注意:@ApiImplicitParam的參數說明:
paramType:指定參數放在哪個地方 |
header:請求參數放置於Request Header,使用@RequestHeader獲取 query:請求參數放置於請求地址,使用@RequestParam獲取 path:(用於restful接口)-->請求參數的獲取:@PathVariable body:(不常用) form(不常用) |
name:參數名 |
|
dataType:參數類型 |
|
required:參數是否必須傳 |
true | false |
value:說明參數的意思 |
|
defaultValue:參數的默認值 |
|
例:
package com.betty.miaosha.controller; import com.alibaba.druid.util.StringUtils; import com.betty.miaosha.controller.viewobject.UserVO; import com.betty.miaosha.error.BusinessException; import com.betty.miaosha.error.EmBusinessError; import com.betty.miaosha.response.CommonReturnType; import com.betty.miaosha.service.UserService; import com.betty.miaosha.service.model.UserModel; import io.swagger.annotations.*; import org.mybatis.spring.annotation.MapperScan; import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; import sun.misc.BASE64Encoder; import javax.servlet.http.HttpServletRequest; import java.io.UnsupportedEncodingException; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.util.Random; /* * Create by BettyLi on 2019/11/21 15:46 * */ @RestController @MapperScan("com.betty.miaosha.dao") @RequestMapping("/user") @Api(value = "UserControllerBetty測試", tags = { "ueser interface" }) //DEFAULT_ALLOWED_HEADERS 允許跨域傳輸所有的headers參數,將用於使用token放入header域做session共享的跨域請求 @CrossOrigin(allowCredentials = "true",allowedHeaders = "*") public class UserController extends BaseController{ @Autowired private UserService userService; @Autowired private HttpServletRequest httpServletRequest; @PostMapping("/login") @ApiOperation(value = "登錄接口") @ApiImplicitParams({ @ApiImplicitParam(name="telphone",value="手機號",required=true,paramType="query"), @ApiImplicitParam(name="password",value="密碼",required=false,paramType="query"), }) @ApiResponses({ @ApiResponse(code=400,message="請求參數沒填好"), @ApiResponse(code=404,message="請求路徑沒有或頁面跳轉路徑不對") }) public CommonReturnType login( @RequestParam("telphone") String telphone, @RequestParam("password") String password) throws BusinessException, UnsupportedEncodingException, NoSuchAlgorithmException { //入參校驗 if(org.apache.commons.lang3.StringUtils.isEmpty(telphone)|| org.apache.commons.lang3.StringUtils.isEmpty(password)){ throw new BusinessException(EmBusinessError.PARAMETER_VALIDATION_ERROR); } //用戶登錄服務用來校驗登錄是否合法 UserModel userModel = userService.validateLogin(telphone,this.EncodeByMD5(password)); //將登錄憑證加入到用戶登錄成功的session內 this.httpServletRequest.getSession().setAttribute("IS_LOGIN",true); this.httpServletRequest.getSession().setAttribute("LOGIN_USER",userModel); return CommonReturnType.create(null); } @PostMapping("/register") @ApiOperation(value = "註冊接口") public CommonReturnType register(@RequestParam("name") String name, @RequestParam("telphone") String telphone, @RequestParam("password") String password, @RequestParam("registerMode") String registerMode, @RequestParam("gender") Integer gender, @RequestParam("age") Integer age, @RequestParam("optCode") String optCode) throws BusinessException, UnsupportedEncodingException, NoSuchAlgorithmException { //驗證手機號和對應的optcode相符合 String intSessionOtpCode = (String)this.httpServletRequest.getSession().getAttribute(telphone); if(!StringUtils.equals(optCode,intSessionOtpCode)){ throw new BusinessException(EmBusinessError.PARAMETER_VALIDATION_ERROR,"短信驗證碼不正確"); } //用戶的註冊流程 UserModel userModel = new UserModel(); userModel.setTelphone(telphone); userModel.setName(name); userModel.setPassword(this.EncodeByMD5(password)); userModel.setAge(age); userModel.setGender(new Byte(String.valueOf(gender.intValue()))); userModel.setRegisterMode(registerMode); userService.register(userModel); return CommonReturnType.create(null); } public String EncodeByMD5(String str) throws UnsupportedEncodingException, NoSuchAlgorithmException { //確定計算方法 MessageDigest md5 = MessageDigest.getInstance("MD5"); BASE64Encoder base64Encoder = new BASE64Encoder(); //加密字符串 String newStr = base64Encoder.encode(md5.digest(str.getBytes("utf-8"))); return newStr; } @GetMapping("/get/{id}") @ApiOperation(value = "根據id獲取用戶信息") public CommonReturnType getUser(@PathVariable("id")int id) throws BusinessException { //調用service服務獲取對應id的用戶對象並返回給前端 UserVO userVO = new UserVO(); UserModel userModel = userService.getUserById(id); if(userModel==null){ throw new BusinessException(EmBusinessError.USER_NOT_EXIST); //return CommonReturnType.create(userModel,"fail"); }else{ //將核心領域模型用戶對象轉化爲可供UI使用的viewobject BeanUtils.copyProperties(userModel,userVO); } return CommonReturnType.create(userVO); } @PostMapping(value = "/getotp",consumes = {"application/x-www-form-urlencoded"}) @ApiOperation(value = "獲取驗證碼") private CommonReturnType getOtp(@RequestParam("telphone")String telphone){ //需要按照一定的規則生成OTP驗證碼 Random random = new Random(); int randonInt = random.nextInt(99999); randonInt = randonInt+10000; String otpCode = String .valueOf(randonInt); //將OTP驗證碼同對應用戶的手機關聯 使用httpsession的方式綁定他的手機號與OTPCODE httpServletRequest.getSession().setAttribute(telphone,otpCode); //將OTP驗證碼通過短信通道發送給用戶,省略 System.out.println("telphone="+telphone+"&otpCode="+otpCode); return CommonReturnType.create(null); } }
完成上述代碼添加上,啓動Spring Boot程序,訪問:http://localhost:server.port/server.servlet.context-path/swagger-ui.html
注:設置server.port 和 server.servlet.context-path要加上。我就是因爲忘記了path坑了很久。
到此基本完成。
遇到的問題也在上面寫了,還有一個是 點擊行不能展開,只能點擊右上角的 List Operations 和 Expand Operations 進行所有方法的 展開和關閉, 使用起來特別麻煩.,最後發現在API註解上的屬性中有 value 和 tags 兩個屬性, Value的值不會展示在 UI界面上, tags會展示在界面上, 如果tags 中的值設置爲中文, 那麼 下面的方法名點擊將不能被展開,改成英文之後正常.value 值是否爲中文不影響.