依赖
<!--swagger -->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.9.2</version>
</dependency>
<!--swagger-ui.html模式 -->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.9.2</version>
</dependency>
<!--doc.html模式 -->
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>swagger-bootstrap-ui</artifactId>
<version>1.9.2</version>
</dependency>
配置端口号
server.port=1313
#启动会报错(原因:Springfox使用的路径匹配基于AntPathMatcher,而Spring Boot 2.6.X使用的是PathPatternMatcher。)
#org.springframework.context.ApplicationContextException: Failed to start bean 'documentationPluginsBootstrapper'; nested exception is java.lang.NullPointerException
spring.mvc.pathmatch.matching-strategy=ant_path_matcher
启动类添加注解( @EnableSwagger2 )
@EnableSwagger2
@SpringBootApplication
public class JavaApplication {
public static void main(String[] args) {
SpringApplication.run(JavaApplication.class, args);
}
}
注解介绍
/**
* Api注解:定义接口名称
* ApiOperation注解:定义方法名称
* ApiImplicitParam注解:定义param参数的各个属性
*
* ApiModel注解:定义对象名称
* ApiModelProperty注解:定义参数名称
*/
@Api(tags = "测试接口")
@RestController
public class TestController {
@ApiOperation(value = "测试01")
@GetMapping("/test01")
public String Test01(){
return "Test01";
}
}
访问地址:http://localhost:1313/swagger...
或者http://localhost:1313/doc.html
新增配置类
/**
* @EnableSwagger2:开启swagger,此处也需要使用。
* @Profile("swagger"):指定组件在哪个环境的情况下才能被注册到容器中,不指定,任何环境下都能注册这个组件。
*
* spring.profiles.active=swagger
*
*/
@Configuration
@EnableSwagger2
@Profile("swagger")
public class SwaggerConfig {
/**
* 创建API应用 apiInfo() 增加API相关信息
* 通过select()函数返回一个ApiSelectorBuilder实例,用来控制哪些接口暴露给Swagger来展现,
* 本例采用指定扫描的包路径来定义指定要建立API的目录。
*
* @return
*/
@Bean
public Docket createRestApi() {
// 选择那些路径和api会生成document
return new Docket(DocumentationType.SWAGGER_2).apiInfo(apiInfo()).pathMapping("/").select()
// 对所有api进行监控
.apis(RequestHandlerSelectors.any())
.apis(RequestHandlerSelectors.withClassAnnotation(RestController.class)).build()
// 配置token
.globalOperationParameters(setHeaderToken());
}
/**
* 配置token
*
* @return
*/
private List<Parameter> setHeaderToken() {
ParameterBuilder tokenPar = new ParameterBuilder();
List<Parameter> pars = new ArrayList<>();
tokenPar.name("Authorization").description("token").modelRef(new ModelRef("string")).parameterType("header")
.required(false).build();
pars.add(tokenPar.build());
return pars;
}
/**
* 创建该API的基本信息(这些基本信息会展现在文档页面中)
*
* @return
*/
private ApiInfo apiInfo() {
return new ApiInfoBuilder().title("测试接口文档").description("测试接口文档").version("1.0").build();
}
}
拦截器
@Component
public class TokenInterceptor implements HandlerInterceptor {
@Autowired
private UserMapper userMapper;
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
userMapper.selectList(null);
//跨域请求会首先发一个option请求,直接返回正常状态并通过拦截器
if (request.getMethod().equals("OPTIONS")){
response.setStatus(HttpServletResponse.SC_OK);
return true;
}
response.setCharacterEncoding("utf-8");
String token = request.getHeader("token");
if (token!=null){
Boolean result = TokenUtils.verify(token);
if (result){
System.out.println("通过拦截器");
return true;
}
}
response.setContentType("application/json; charset=utf-8");
try {
JSONObject json = new JSONObject();
json.put("msg","token verify fail");
json.put("code","500");
response.getWriter().append(json.toString());
System.out.println("认证失败,通过拦截器失败");
}catch (Exception e){
return false;
}
return false;
}
}
WebMVC配置
@Configuration
public class WebConfiguration implements WebMvcConfigurer {
@Bean
public HandlerInterceptor getTokenInterceptor(){
return new TokenInterceptor();
}
/**
* 异步请求配置
* @param configurer
*/
@Override
public void configureAsyncSupport(AsyncSupportConfigurer configurer) {
configurer.setTaskExecutor(new ConcurrentTaskExecutor(Executors.newFixedThreadPool(3)));
configurer.setDefaultTimeout(30000);
}
/**
* 配置拦截器、拦截路径
* 每次请求到拦截的路径,就会去执行拦截器中的方法
* @param registry
*/
@Override
public void addInterceptors(InterceptorRegistry registry) {
List<String> excludePath = new ArrayList<>();
//排除拦截,除了注册登录(此时还没token),其他都拦截
excludePath.add("/login"); //登录
excludePath.add("/register"); //注册
excludePath.add("/doc.html"); //swagger
excludePath.add("/swagger-ui.html"); //swagger
excludePath.add("/swagger-resources/**"); //swagger
excludePath.add("/v2/api-docs"); //swagger
excludePath.add("/webjars/**"); //swagger
// excludePath.add("/static/**"); //静态资源
// excludePath.add("/assets/**"); //静态资源
registry.addInterceptor(getTokenInterceptor())
.addPathPatterns("/**")
.excludePathPatterns(excludePath);
WebMvcConfigurer.super.addInterceptors(registry);
}
/**
* 解决跨域请求
* @param registry
*/
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedHeaders("*")
.allowedMethods("*")
// .allowedOrigins("*")
.allowedOriginPatterns("*")
.allowCredentials(true);
}
}
token生成
public class TokenUtils {
//token到期时间10小时
private static final long EXPIRE_TIME= 10*60*60*1000;
//密钥盐
private static final String TOKEN_SECRET="ljdyaishijin**3nkjnj??";
/**
* 生成token
* @param user
* @return
*/
public static String sign(User user){
String token=null;
try {
Date expireAt=new Date(System.currentTimeMillis()+EXPIRE_TIME);
token = JWT.create()
//发行人
.withIssuer("auth0")
//存放数据
.withClaim("username",user.getUserName())
//过期时间
.withExpiresAt(expireAt)
.sign(Algorithm.HMAC256(TOKEN_SECRET));
} catch (IllegalArgumentException| JWTCreationException je) {
}
return token;
}
/**
* token验证
* @param token
* @return
*/
public static Boolean verify(String token){
try {
//创建token验证器
JWTVerifier jwtVerifier=JWT.require(Algorithm.HMAC256(TOKEN_SECRET)).withIssuer("auth0").build();
DecodedJWT decodedJWT=jwtVerifier.verify(token);
System.out.println("认证通过:");
System.out.println("username: " + decodedJWT.getClaim("username").asString());
System.out.println("过期时间: " + decodedJWT.getExpiresAt());
} catch (IllegalArgumentException | JWTVerificationException e) {
//抛出错误即为验证不通过
return false;
}
return true;
}
}
token生成
public class Token {
//token到期时间(毫秒)
private static final long TIME = 10 * 60 * 1000;
//密钥盐
private static final String TOKEN = "123";
/**
* 生成token
*
* @return
*/
public static String sign() {
String token = null;
try {
Date date = new Date(System.currentTimeMillis() + TIME);
token = JWT.create()
//发行人
.withIssuer("lll")
//存放数据
.withClaim("username", "linweibin")
//设置过期时间
.withExpiresAt(date)
//加密
.sign(Algorithm.HMAC256(TOKEN));
} catch (Exception e) {
e.printStackTrace();
}
return token;
}
/**
* token验证
*
* @param token
* @return
*/
public static Boolean verify(String token) {
try {
//创建token验证器
JWTVerifier jwtVerifier = JWT.require(Algorithm.HMAC256(TOKEN)).withIssuer("lll").build();
DecodedJWT verify = jwtVerifier.verify(token);
//解密获取数据
System.out.println("username: " + verify.getClaim("username").asString());
System.out.println("过期时间: " + verify.getExpiresAt());
} catch (Exception e) {
return false;
}
return true;
}
}
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。