springboot集成swagger2

1、swagger简介

  Swagger是一款RESTful接口的文档在线自动生成、功能测试功能框架。一个规范和完整的框架,用于生成、描述、调用和可视化RESTful风格的Web服务,加上swagger-ui,可以有很好的呈现。

  当我们在后台的接口修改了后,swagger可以实现自动的更新,而不需要人为的维护这个接口进行测试。

       knife4j是一款对swagger功能增强的插件,优化展示页面及接口调试功能,具体介绍参见-----Knife4j官方介绍  下一篇 介绍集成过程

       例如:

       springboot集成swagger2_第1张图片springboot集成swagger2_第2张图片

2:基于前面的知识点

  本知识点在springboot使用基于Mybatis注解方式实现的CRUD的基础上进行的。

3、springboot与swagger的集成:

  第一步:(单独集成swagger2)jar包的引入:

  
  
     io.springfox
     springfox-swagger-ui
     2.4.0
  
  
     io.springfox
     springfox-swagger2
     2.4.0
  

第二步:swagger的配置启动类编写:

         要使用swagger要进行一些配置,这个在界面的图上是可以显示的:类似于说明书:在这个类中我们会使用注解来进行启动 swagger:

  springboot集成swagger2_第3张图片

具体配置如下:

单独配置 swagger 如下配置   没有权限校验的

package cn.xdf.springboot;
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 Swagger2 {

     @Value("${swagger.enable}")
     private boolean swagger;        

     // swagger2的配置文件,这里可以配置swagger2的一些基本的内容,比如扫描的包等等
     @Bean
     public Docket createRestApi() {
          return new Docket(DocumentationType.SWAGGER_2)
                   .apiInfo(apiInfo())
                   .select()
                   // 为当前包路径
                  .apis(RequestHandlerSelectors.basePackage("cn.xdf.springboot.controller"))
                   .paths(PathSelectors.any())
                   .build();
     }
     // 构建 api文档的详细信息函数,注意这里的注解引用的是哪个
     private ApiInfo apiInfo() {
          return new ApiInfoBuilder()
                   // 页面标题
                   .title("Spring Boot 测试使用 Swagger2 构建RESTful API")
                   // 创建人信息
                   .contact(new Contact("MrZhang",  "https://www.cnblogs.com/zs-notes/category/1258467.html",  "[email protected]"))
                   // 版本号
                   .version("1.0")
                   // 描述
                   .description("API 描述")
                   .build();
     }
}

如果有权限校验  则修改

 ParameterBuilder ticketPar = new ParameterBuilder();
        List pars = new ArrayList();
        ticketPar.name("Authorization").description("token")
                .modelRef(new ModelRef("string"))
                .parameterType("header")
                .defaultValue("Bearer-")
                .required(false)
                .build();
        pars.add(ticketPar.build());
        return new Docket(DocumentationType.SWAGGER_2)
                .apiInfo(apiInfo())
                .select()
                .apis(RequestHandlerSelectors.basePackage("cn.xdf.springboot.controller"))
                .paths(PathSelectors.any())
                .build()
                .globalOperationParameters(pars);

此外,放开swagger资源

@Configuration
@EnableWebMvc
@Log4j2
public class InterceptorConfiguration implements WebMvcConfigurer {

    @Value("${image_url}")
    private String imageUrl;

    @Resource
    private AuthorizationInterceptor authorizationInterceptor;
    @Autowired
    private IgnoredUrlsProperties ignoredUrlsProperties;

    //解决跨域问题配置
    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**")
                .allowCredentials(true)
                .allowedHeaders("*")
                .allowedOrigins("*")
                .allowedMethods("GET","POST","PUT","DELETE");

    }

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/**").addResourceLocations("classpath:/resources/",imageUrl).setCachePeriod(0);
//        registry.addResourceHandler("swagger-ui.html")
//                .addResourceLocations("classpath:/META-INF/resources/");

        registry.addResourceHandler("/webjars/**")
                .addResourceLocations("classpath:/META-INF/resources/webjars/");

        registry.addResourceHandler("doc.html").addResourceLocations("classpath:/META-INF/resources/");

}

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        // 注册拦截器
        InterceptorRegistration ir = registry.addInterceptor(authorizationInterceptor);
        // 配置拦截的路径
        ir.addPathPatterns("/**");
        // 配置不拦截的路径
        ir.excludePathPatterns(ignoredUrlsProperties.getUrls());
    }

}

security 的配置类  放开 过滤资源  配置在配置文件中 jgnoreUrls

 @Override
    protected void configure(HttpSecurity httpSecurity) throws Exception {

        //忽略路径
        List urls = ignoredUrlsProperties.getUrls();
        String [] ignoreUrls = urls.toArray(new String [urls.size()]);

        httpSecurity.csrf().disable()
                .httpBasic().authenticationEntryPoint(authenticationEntryPoint)
                //session状态  无状态
                .and().sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                //请求之前的认证过滤器  token校验
                .and().authorizeRequests()
                .antMatchers(ignoreUrls).permitAll()
                // 所有请求都需要认证
                .anyRequest().authenticated().and().cors();

        httpSecurity
                .headers()
                .frameOptions().sameOrigin()  // required to set for H2 else H2 Console will be blank.
                .cacheControl();

        //httpSecurity.authorizeRequests().requestMatchers(CorsUtils::isPreFlightRequest).permitAll();
        httpSecurity.exceptionHandling().accessDeniedHandler(authAccessDeniedHandler);
        httpSecurity.addFilterBefore(authenticationRequestFilter, UsernamePasswordAuthenticationFilter.class);
    }

    修改添加application.properties文件  设置接口api生效的环境  参数

#是否激活 swagger true or false
swagger.enable=true



# 忽略鉴权url controller 不鉴权
ignored:
  urls:
    - /swagger-ui.html
    - /swagger-ui.html/**
    - /swagger-resources/**
    - /webjars/**
    - /swagger/**
    - /v2/**

  第三步:使用swagger来进行模拟测试:

         使用swagger2来进行测试接口主要是在哪些类中使用:这里我们依然选择在controller层:

package cn.xdf.springboot.controller;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.validation.Valid;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import  org.springframework.beans.factory.annotation.Autowired;
import  org.springframework.web.bind.annotation.DeleteMapping;
import  org.springframework.web.bind.annotation.GetMapping;
import  org.springframework.web.bind.annotation.PathVariable;
import  org.springframework.web.bind.annotation.PostMapping;
import  org.springframework.web.bind.annotation.PutMapping;
import  org.springframework.web.bind.annotation.RequestBody;
import  org.springframework.web.bind.annotation.RequestMapping;
import  org.springframework.web.bind.annotation.RequestParam;
import  org.springframework.web.bind.annotation.RestController;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import cn.xdf.springboot.mapper.CategoryMapper;
import cn.xdf.springboot.pojo.Category;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiOperation;
/**
* 控制层 简单演示增删改查及分页
*
*/
@RestController
@RequestMapping("api")
@Api("swaggerDemoController相关的api")
public class SwaggerDemoController {

    @Autowired
    CategoryMapper categoryMapper;
    private static final Logger logger=  LoggerFactory.getLogger(SwaggerDemoController.class);
    //1.商品添加
    //@PutMapping("add") 添加方法--restful风格
    @PutMapping("add")
    @ApiOperation(value="商品新增")
    //正常业务时, 需要在category类里或者server层进行事务控制,控制层一般不进行业务控制的。
    //@Transactional(rollbackFor = Exception.class)
    //@RequestParam 接收页面中的请求的参数
    public Map addCategory(@RequestParam  String name){
      Category category = new Category();
      category.setName(name);
      categoryMapper.save(category);
      logger.info("开始新增某个商品信息");
        Map result = new  HashMap();
        result.put("respCode", "01");
        result.put("respMsg", "新增成功!");
        result.put("data", category);
        return result;
    }
    //2.商品修改
    //@PostMapping("update")  修改方法--restful风格
    @PostMapping("update")  
    @ApiOperation(value = "商品修改", notes = "修改数据库中某个的商品信息")
    //@RequestBody 接收页面中的请求的参数对象(适用于post请求)
    //当入参为实体对象时,需要在方法上加@Valid或@Validated或者在参数前加@Valid或@Validated,或者在类上加@Validated
    public Map updateCategory(@Valid  @RequestBody  Category category) {
      Map result = new  HashMap();
      Category categoryGet =  categoryMapper.get(category.getId());
      if(categoryGet == null || "".equals(categoryGet)){
          try {
                   throw new Exception("修改的该商品不存在!");
              } catch (Exception e) {
                   e.printStackTrace();
              }
           result.put("respCode", "03");
           result.put("respMsg", "修改的该商品不存在!");
           result.put("data", category);
           return result;
      }
        categoryMapper.update(category);
        logger.info("开始修改某个商品信息");
        result.put("respCode", "03");
         result.put("respMsg", "修改成功!");
         result.put("data", category);
        return result;
    }
    //3.商品删除
    //@DeleteMapping("/delete/{id}") 删除方法--restful风格
    @DeleteMapping("/delete/{id}")
    @ApiOperation(value = "根据id删除商品", notes = "商品删除")
    @ApiImplicitParam(name = "id", value = "商品ID",  paramType = "path", required = true, dataType =  "Integer")
     public Map  deleteCategory(@PathVariable int id)throws Exception{   //@PathVariable 获取/delete/{id}中id
      Category category = categoryMapper.get(id);
      Map result = new  HashMap();
      if (category == null) {
          try {
                   throw new Exception("用户ID:" + id +  ",未找到");
              } catch (Exception e) {
                   e.printStackTrace();
              }
           result.put("respCode", "02");
           result.put("respMsg", "数据库无该商品信息,删除失败!");
           result.put("data", category);
           return result;
          }else{
              categoryMapper.delete(id);
              logger.info("开始删除某个商品信息");
              result.put("respCode", "01");
              result.put("respMsg", "删除成功!");
              result.put("data", category);
              return result;  
          }
     }
    //4.根据ID查询商品信息
    //@GetMapping("")  查询方法--restful风格
    @GetMapping("/get/{id}")
    @ApiOperation(value = "根据id查询商品", notes = "查询数据库中某个的商品信息")
    @ApiImplicitParam(name = "id", value = "商品ID",  paramType = "path", required = true, dataType =  "Integer")
    public Map getCategory(@PathVariable  int id) { //@PathVariable 获取/get/{id}中id
      Category category = categoryMapper.get(id);
      logger.info("开始查询某个商品信息");
      Map result = new  HashMap();
      if (category == null) {
          try {
                   throw new Exception("用户ID:" + id +  ",未找到");
              } catch (Exception e) {
                   e.printStackTrace();
              }
           result.put("respCode", "02");
           result.put("respMsg", "数据库无该商品信息");
           result.put("data", category);
           return result;
          }else{
             result.put("respCode", "01");
             result.put("respMsg", "查询成功!");
             result.put("data", category);
             return result;
          }
    }
    //5.分页查询
    //@GetMapping("")  查询方法--restful风格
    @GetMapping("/page")
    @ApiOperation(value="商品查询(分页)")        
    public Map  pageCategory(@RequestParam(value="start",defaultValue="0")int start,@RequestParam(value = "size", defaultValue =  "5") int size) throws Exception {
      //1. 在参数里接受当前是第几页 start ,以及每页显示多少条数据  size。 默认值分别是0和5。
          //2. 根据start,size进行分页,并且设置id 倒排序
          PageHelper.startPage(start,size,"id desc");
          //3. 因为PageHelper的作用,这里就会返回当前分页的集合了
          List cs = categoryMapper.findAll();
          logger.info("开始分页查询商品信息");
          //4. 根据返回的集合,创建PageInfo对象
          PageInfo page = new PageInfo<>(cs);
          
        Map result = new  HashMap();
        result.put("respCode", "01");
        result.put("respMsg", "成功");
        result.put("data", page);
        return result;
    }
    
}

这样swagger2与springboot就集成完毕了。

看下最终效果吧:

访问路径:  http://localhost:8080/swagger-ui.html

调试:点击需要访问的api列表,点击try it out!按钮,表示 执行。

springboot集成swagger2_第4张图片

----------------------------------------------------------------------------------------------------------------------------------------------------------------

springboot集成swagger2_第5张图片

而且这些方法是实时更新的!!!

 

接下来测试一个新增方法:

springboot集成swagger2_第6张图片

 

 查询方法:

 springboot集成swagger2_第7张图片

另外,大家可下载示例,查看自定义的字符出现的位置,这样可以对其有个大致了解,各字段的作用领域是哪里

Controller层添加注解

@Api:用于类;表示标识这个类是swagger的资源

 

属性名称 数据类型   默认值  说明
 value      String  ""  字段说明
  tags    String[]  ""  标签说明 
 description   String   ""  详情描述 
 basePath
 
 String   ""  基本路径可以不配置 
 position  int   ""  如果配置多个Api 想改变显示的顺序位置
 produces  String   ""  提供者 (For example, "application/json, application/xml")
 consumes  String   ""  消费者(For example, "application/json, application/xml")
 protocols  String   ""  协议(Possible values: http, https, ws, wss.)
 authorizations  Authorization[]   ""  高级特性认证时配置
 hidden  boolean   ""  配置为true 将在文档中隐藏

@ApiResponses:在 Rest 接口上使用,用作返回值的描述

参数

属性名称 数据类型 默认值 说明
value ApiResponse[] "" 访问对象 

ApiResponse参数

属性名称 数据类型 默认值 说明
code String  "" 响应的HTTP状态码
message String  "" 响应的信息内容 
response Class "" 用于描述消息有效负载的可选响应类,对应于响应消息对象的 schema 字段
reference String  "" 指定对响应类型的引用,指定的应用可以使本地引用,也可以是远程引用,将按原样使用,并将覆盖任何指定的response()类 
responseHeaders ResponseHeader[] "" 声明包装响应的容器,有效值为List或Set,任何其他值都将被覆盖
responseContainer String "" 声明响应的容器,有效值为List,Set,Map,任何其他值都将被忽略
examples Example  "" 例子

 

@ApiOperation:用在方法上,说明方法的作用,每一个url资源的定义

参数

属性名称 数据类型 默认值 说明
value String "" url的路径值
notes String "" 文本说明 
tags String[] "" 如果设置这个值、value的值会被覆盖
response Class "" 返回的对象
responseContainer String  "" 声明响应的容器,有效值为List,Set,Map,任何其他值都将被忽略
responseReference String  "" 声明包装响应的容器,有效值为List或Set,任何其他值都将被覆盖
httpMethod String  "" "GET", "HEAD", "POST", "PUT", "DELETE", "OPTIONS" and "PATCH"
position int "" 如果配置多个Api 想改变显示的顺序位置
nickname String  "" 昵称 
produces String "" 提供者 (For example, "application/json, application/xml")
consumes String "" 消费者(For example, "application/json, application/xml")
protocols String "" 协议(Possible values: http, https, ws, wss.) 
authorizations Authorization[] "" 高级特性认证时配置
hidden boolean "" 隐藏 
responseHeaders ResponseHeader[] "" 声明包装响应的容器,有效值为List或Set,任何其他值都将被覆盖
code String  "" http的状态码 默认 200
extensions Extension[] "" 扩展属性 
ignoreJsonView boolean "" 是否忽略显示 

 

@PathVariable:是获取get方式,url后面参数,进行参数绑定(单个参数或两个以内参数使用)

参数

属性名称 数据类型 默认值 说明
value String "" url的路径值
name String "" 重写属性名字 
required String "" 是否必填 

 

@RequestBody :在当前对象获取整个http请求的body里面的所有数据(两个以上参数封装成对象使用)

参数

属性名称 数据类型 默认值 说明
required String "" 是否必填 

 

备注:实体类收参

import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
 
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import java.io.Serializable;
 
@ApiModel(description = "登录表单")
public class LoginFormParams implements Serializable {
    /**
     * 用户账号
     */
    @ApiModelProperty(value = "登录账号", name = "account", required = true, example = "admin")
    @NotBlank(message = "账号不允许为空,请输入")
    private String account;
    /**
     * 用户密码
     */
    @ApiModelProperty(value = "登录密码", name = "password", required = true, example = "123456")
    @NotBlank(message = "密码不允许为空,请输入")
    private String password;
    /**
     * 图片验证码
     */
    @ApiModelProperty(value = "验证码", name = "validCode", required = false, example = "TG20")
    /*@NotBlank(message = "验证码不允许为空,请输入")*/
    private String validCode;
 
    /**
     * 记住我
     */
    @ApiModelProperty(value = "记住我", name = "rememberMe", required = false, example = "false")
    private boolean rememberMe;
 
    public String getAccount() {
        return account;
    }
 
    public void setAccount(String account) {
        this.account = account;
    }
 
    public String getPassword() {
        return password;
    }
 
    public void setPassword(String password) {
        this.password = password;
    }
 
    public String getValidCode() {
        return validCode;
    }
 
    public void setValidCode(String validCode) {
        this.validCode = validCode;
    }
 
    public boolean isRememberMe() {
        return rememberMe;
    }
 
    public void setRememberMe(boolean rememberMe) {
        this.rememberMe = rememberMe;
    }
}
    /**
     * 账号登录
     * @param form
     * @param bindingResult
     * @param session
     * @return
     */
    @PostMapping("/ajaxLogin")
    @ApiOperation(value = "用户登录", notes = "用户异步登录处理")
    @ApiImplicitParam(name = "form", value = "用户登录表单", required = true, dataType = "LoginFormParams")
    @ResponseBody
    public JsonResult ajaxLogin(@Valid @RequestBody LoginFormParams form, BindingResult bindingResult, HttpSession session) throws Exception{
        if(bindingResult.hasErrors()){
            for (ObjectError error : bindingResult.getAllErrors()){
                return JsonResult.error(GlobalParams.EX_CODE4.getCode(), error.getDefaultMessage(), null);
            }
        }
 
        // 获取当前用户对象
        Subject subject = SecurityUtils.getSubject();
        // 生成令牌
        UsernamePasswordToken token = new UsernamePasswordToken(form.getAccount(),form.getPassword());
        if(form.isRememberMe()){
            token.setRememberMe(true);
        }else{
            token.setRememberMe(false);
        }
        subject.login(token);
        // 登录成功的用户对象
        SysUser user = (SysUser)subject.getPrincipal();
        // 将信息存储至Redis
        session.setAttribute("user", user);
        return JsonResult.ok(GlobalParams.EX_CODE5, user);
 
    }

【注意】两处地方

@RequestBody 以及

@ApiImplicitParam(name = "form", value = "用户登录表单", required = true, dataType = "LoginFormParams")

其中name 对应的是参数名称,value 是描述,dataType 对应的是参数类型

 

 

 

你可能感兴趣的:(java,java)