文章目录
用原始的swagger,可对于封装map和实体类,jsaonobject的参数不太方便,但是,用knofe4j就可以实现了
查看路径:http://localhost:8181/sa/doc.html
1. pom依赖
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-spring-boot-starter</artifactId>
<version>2.0.8</version>
</dependency>
2.配置
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.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2WebMvc;
@Configuration
@EnableSwagger2WebMvc
public class SwaggerConfig {
@Bean(value = "api")
public Docket defaultApi2() {
Docket docket=new Docket(DocumentationType.SWAGGER_2)
.apiInfo(new ApiInfoBuilder()
.description("# 文档的描述")
.version("1.0")
.build())
.enable(false) // 关闭swagger
//分组名称
.groupName("1.X版本")
.select()
//这里指定Controller扫描包路径
.apis(RequestHandlerSelectors.basePackage("com.ify.sampleAdmin.web.controller"))
.paths(PathSelectors.any())
.build();
return docket;
}
}
3.使用
@RestController
@RequestMapping("/user")
@Api(tags = "用户模块")
public class UserController extends BaseController {
@GetMapping("/user")
@ApiOperation(value = "获取根据ID获取用户")
@ApiImplicitParam(name = "id",value = "用户id",required = true)
public ResResult getUser(@RequestParam(value = "id") String id) {
return ResResult.success();
}
}
如果报错:Failed to start bean ‘documentationPluginsBootstrapper’
就在启动类上加 @EnableWebMvc,并且创建下面的类
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;
/**
* @author lc
* @version 1.0
* @date 2021/12/27 15:33
*/
@Configuration
public class WebMvcConfig extends WebMvcConfigurationSupport {
/**
* 发现如果继承了WebMvcConfigurationSupport,则在yml中配置的相关内容会失效。 需要重新指定静态资源
*
* @param registry
*/
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/**").addResourceLocations(
"classpath:/static/");
registry.addResourceHandler("doc.html").addResourceLocations(
"classpath:/META-INF/resources/");
registry.addResourceHandler("/webjars/**").addResourceLocations(
"classpath:/META-INF/resources/webjars/");
super.addResourceHandlers(registry);
}
@Override
public void addCorsMappings(CorsRegistry registry) {
//设置允许跨域的路径
registry.addMapping("/**")
//设置允许跨域请求的域名
// .allowedOrigins("*")
.allowedOriginPatterns("*")
//这里:是否允许证书 不再默认开启
.allowCredentials(true)
//设置允许的方法
.allowedMethods("*")
//跨域允许时间
.maxAge(3600);
}
}
http://localhost:你服务器端口/doc.html
注意,加上这个类后可能会影响拦截器的使用,
这个时候假如发现拦截器没有起作用,那可能是因为:有配置类继承了WebMvcConfigurationSupport(比如使用swagger的时候配置了),查询WebMvcConfigurationSupport源码发现其中有拦截器注册方法addInterceptors(InterceptorRegistry registry),所以在版本控制配置类中重写此方法添加拦截器,拦截器生效,问题解决。代码如下:
@Configuration
public class ApiConfig extends WebMvcConfigurationSupport {
// 你自定义的拦截器类
@Autowired
private RequestParamInfoIntorceptor requestParamInfoIntorceptor;
@Override
protected void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(this.requestParamInfoIntorceptor).addPathPatterns("/**").excludePathPatterns("/luser/login", "/luser/register", "/send/message");
super.addInterceptors(registry);
}
}
4.注解介绍
@Api(tags = “”):接口分组
@ApiOperation(value = “”):接口名称
@ApiImplicitParam(name = “id”,value = “用户id”,required = true):接口参数声明
// 提供了过滤和包含参数的注解,可以排除或包含必须参数来简洁文档(用在实体类上)。
@ApiOperationSupport(ignoreParameters = {"id","orderDate.id"})
@ApiOperationSupport(order = 40,includeParameters = {"ignoreLabels","longUser.ids"})
@ApiResponses:
在 Rest 接口上使用,用作返回值的描述
@ApiResponses(value = {
@ApiResponse(code = 200, message = "接口返回成功状态"),
@ApiResponse(code = 500, message = "接口返回未知错误,请联系开发人员调试")
})
@PostMapping("hello")
public Results<UserVO> hello(@RequestBody UserVO userVO){
Results<UserVO> results = new Results<>(200,"SUCCESS", userVO);
return results;
}
@ApiOperation:
用在方法上,说明方法的作用,每一个url资源的定义
@ApiOperation(value = "Hello 测试接口", notes = "访问此接口,返回hello语句,测试接口")
@PostMapping("hello")
public Results<UserVO> hello(@RequestBody UserVO userVO){
Results<UserVO> results = new Results<>(200,"SUCCESS", userVO);
return results;
}
@PathVariable:
是获取get方式,url后面参数,进行参数绑定(单个参数或两个以内参数使用)
@ApiResponses(value = {
@ApiResponse(code = 200, message = "接口返回成功状态"),
@ApiResponse(code = 500, message = "接口返回未知错误,请联系开发人员调试")
})
@ApiOperation(value = "获取用户信息", notes = "访问此接口,返回用户信息")
@PostMapping("/getUser/{id}")
public String getUser(@PathVariable String id) throws InterruptedException {
// 业务...
return "";
}
@RequestBody :
在当前对象获取整个http请求的body里面的所有数据(两个以上参数封装成对象使用)
@ApiResponses(value = {
@ApiResponse(code = 200, message = "接口返回成功状态"),
@ApiResponse(code = 500, message = "接口返回未知错误,请联系开发人员调试")
})
@ApiOperation(value = "Hello 测试接口", notes = "访问此接口,返回hello语句,测试接口")
@PostMapping("hello")
public Results<UserVO> hello(@RequestBody UserVO userVO){
Results<UserVO> results = new Results<>(200,"SUCCESS", userVO);
return results;
}
paramType 的使用
@ApiImplicitParams({
@ApiImplicitParam(name = "id", value = "项目ID", dataType = "String", paramType = "query", required = true),
@ApiImplicitParam(name = "useridlist", value = "用户ID数组", dataType = "String", paramType = "body", allowMultiple = true, required = true ),
@ApiImplicitParam(name = "Authorization", value = "身份验证Token", dataType = "String", paramType = "header"),
})
allowMultiple=true————表示是数组格式的参数
dataType=“body”————表示数组中参数的类型
dataType=“String” 代表请求参数类型为String类型,当然也可以是Map、User、int等;
paramType=“body” 代表参数应该放在请求的什么地方:
header-->放在请求头。请求参数的获取:@RequestHeader(代码中接收注解)
query -->用于get请求的参数拼接。请求参数的获取:@RequestParam(代码中接收注解)
path -->(用于restful接口)-->请求参数的获取:@PathVariable(代码中接收注解)
body -->放在请求体。请求参数的获取:@RequestBody(代码中接收注解)
form -->(不常用)
对于入参是实体类的
@ApiMode + @ApiModelProperty
@ApiModelProperty(value = "商户id-userID", dataType = "String", required = true,example = "123456")
package com.zykj.newsell.pojo.dto;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.time.LocalDateTime;
import java.util.Date;
/**
* 营收统计接口的入参
*
* @author lc
* @version 1.0
* @date 2022/4/15 11:23
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
@ApiModel(value = "RevenueDto", description = "营收dto")
public class RevenueDto {
@ApiModelProperty(value = "商户id-userID", dataType = "String", required = true, example = "123456")
private String currentUserId; // 商户id-userID
// 注意时间的入参格式 2022-04-15 08:45:00 需要补0,还要配置LocalDateTime 的格式,查看我的文章
@ApiModelProperty(value = "开始时间", required = true, example = "2022-10-10 11:11:11")
@JsonFormat(shape= JsonFormat.Shape.STRING, pattern="yyyy-MM-dd HH:mm:ss")
private LocalDateTime dateStart; // 开始时间
@ApiModelProperty(value = "结束时间", required = true, example = "2022-10-10 11:11:11")
@JsonFormat(shape= JsonFormat.Shape.STRING, pattern="yyyy-MM-dd HH:mm:ss")
private LocalDateTime dateEnd; // 结束时间
}
5.拓展
5.1 springsecurity整合knife4j(swagger)
首先,先按照上面的操作把knife4j整合进springboot项目,但是由于项目整合了springsecurity,会把knife4j的接口拦截掉。
解决方法:在springsecurity的配置类中,添加不拦截的路径
import com.zykj.zycx.filter.JwtAuthenticationTokenFilter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.security.web.access.AccessDeniedHandler;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
/**
* security的配置类
*
* @author lc
* @version 1.0
* @date 2022/3/14 16:09
*/
@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class securityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private JwtAuthenticationTokenFilter jwtAuthenticationTokenFilter;
@Autowired
private AuthenticationEntryPoint authenticationEntryPoint;
@Autowired
private AccessDeniedHandler accessDeniedHandler;
// 替换掉默认的密码加密器
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
// AuthenticationManager注入到容器
@Bean
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf().disable()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.authorizeRequests()
.antMatchers("/user/login", "/doc.html/**", "/swagger-ui.html/**", "/webjars/**",
"/v2/api-docs",//swagger api json
"/swagger-resources/configuration/ui",//用来获取支持的动作
"/swagger-resources",//用来获取api-docs的URI
"/swagger-resources/configuration/security",//安全选项
"/swagger-ui.html").anonymous()
.anyRequest().authenticated();
http.addFilterBefore(jwtAuthenticationTokenFilter, UsernamePasswordAuthenticationFilter.class);
//配置异常处理器
http.exceptionHandling()
//配置认证失败处理器
.authenticationEntryPoint(authenticationEntryPoint)
.accessDeniedHandler(accessDeniedHandler);
//允许跨域
http.cors();
}
}