IDEA 中SpringBoot集成Swagger 2步骤、注意事项、常见问题

最近开始看后端的东西,记录下学习笔记吧。

一、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 值是否为中文不影响.

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值