refactor(youlai-gateway): 网关代码重构,swagger由webflux的注解式调整为函数式编程模型

This commit is contained in:
郝先瑞 2022-05-17 01:06:41 +08:00
parent ae0573c0ac
commit 1cb3ba4880
14 changed files with 264 additions and 162 deletions

View File

@ -1,4 +1,4 @@
package com.youlai.gateway.kaptcha.config;
package com.youlai.gateway.config;
import com.google.code.kaptcha.impl.DefaultKaptcha;
import com.google.code.kaptcha.util.Config;
@ -35,7 +35,7 @@ public class CaptchaConfig {
// KAPTCHA_SESSION_KEY
properties.setProperty("kaptcha.session.key", "kaptchaCodeMath");
// 验证码文本生成器
properties.setProperty("kaptcha.textproducer.impl", "com.youlai.gateway.kaptcha.KaptchaTextCreator");
properties.setProperty("kaptcha.textproducer.impl", "com.youlai.gateway.util.KaptchaTextCreator");
// 验证码文本字符间距 默认为2
properties.setProperty("kaptcha.textproducer.char.space", "3");
// 验证码文本字符长度 默认为5

View File

@ -1,6 +1,6 @@
package com.youlai.gateway.swagger;
package com.youlai.gateway.config;
import lombok.AllArgsConstructor;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.gateway.config.GatewayProperties;
import org.springframework.cloud.gateway.route.RouteLocator;
@ -14,22 +14,19 @@ import java.util.ArrayList;
import java.util.List;
/**
* @Author haoxr
* @Date 2021-02-25 16:21
* @Version 1.0.0
* @ https://gitee.com/xiaoym/swagger-bootstrap-ui-demo/blob/master/knife4j-spring-cloud-gateway/service-doc/src/main/java/com/xiaominfo/swagger/service/doc/config/SwaggerResourceConfig.java
* @author haoxr
* @date 2022/5/17 16:21
*/
@Slf4j
@Component
@Primary
@AllArgsConstructor
@RequiredArgsConstructor
@Slf4j
public class SwaggerResourceConfig implements SwaggerResourcesProvider {
private final RouteLocator routeLocator;
private final GatewayProperties gatewayProperties;
@Override
public List<SwaggerResource> get() {
List<SwaggerResource> resources = new ArrayList<>();

View File

@ -1,8 +1,9 @@
package com.youlai.gateway.log;
package com.youlai.gateway.filter;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.reactivestreams.Publisher;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
@ -51,7 +52,7 @@ import java.util.stream.Collectors;
)
@Component
@Slf4j
public class LogFilter implements GlobalFilter, Ordered {
public class GatewayLogFilter implements GlobalFilter, Ordered {
private final List<HttpMessageReader<?>> messageReaders = HandlerStrategies.withDefaults().messageReaders();
@ -216,4 +217,81 @@ public class LogFilter implements GlobalFilter, Ordered {
public int getOrder() {
return -1;
}
@Data
public static class TraceLog {
/**
* 请求路径
*/
private String requestPath;
/**
* 请求方法
*/
private String requestMethod;
/**
* 查询参数
*/
private String queryParams;
/**
* 请求载荷
*/
private String requestBody;
/**
* 响应数据
*/
private String responseBody;
/**
* 请求时间
*/
private String requestTime;
/**
* 响应时间
*/
private String responseTime;
/**
* 执行耗时(毫秒)
*/
private Long executeTime;
public String toRequestString() {
return
"^^^^^^^^请求日志^^^^^^^^: " + requestMethod + ':' + requestPath + '\n' +
"查询参数:" + queryParams + '\n' +
"请求载荷:" + requestBody + '\n' +
"请求时间:" + requestTime;
}
public String toResponseString() {
return
"$$$$$$$$响应日志$$$$$$$$: " + requestMethod + ':' + requestPath + '\n' +
"请求时间:" + requestTime + '\n' +
"响应时间:" + responseTime + '\n' +
"响应数据:" + responseBody + '\n' +
"执行耗时:" + executeTime + "毫秒";
}
@Override
public String toString() {
return "========网关请求响应日志========\n" +
"请求路径:" + requestPath + '\n' +
"请求方法:" + requestMethod + '\n' +
"请求参数:" + requestBody + '\n' +
"响应数据:" + responseBody + '\n' +
"请求时间:" + requestTime + '\n' +
"响应时间:" + responseTime + '\n' +
"执行耗时:" + executeTime + "毫秒";
}
}
}

View File

@ -1,4 +1,4 @@
package com.youlai.gateway.security;
package com.youlai.gateway.filter;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONObject;

View File

@ -1,4 +1,4 @@
package com.youlai.gateway.kaptcha.handler;
package com.youlai.gateway.handler;
import cn.hutool.core.codec.Base64;
import cn.hutool.core.io.FastByteArrayOutputStream;
@ -24,7 +24,7 @@ import java.util.concurrent.TimeUnit;
/**
* @author <a href="mailto:xianrui0365@163.com">haoxr</a>
* @author haoxr
* @date 2021/10/4
*/
@Component
@ -35,7 +35,7 @@ public class CaptchaHandler implements HandlerFunction<ServerResponse> {
private final StringRedisTemplate redisTemplate;
@Override
public Mono<ServerResponse> handle(ServerRequest serverRequest) {
public Mono<ServerResponse> handle(ServerRequest request) {
// 生成验证码
String capText = producer.createText();
String capStr = capText.substring(0, capText.lastIndexOf("@"));
@ -56,6 +56,6 @@ public class CaptchaHandler implements HandlerFunction<ServerResponse> {
resultMap.put("uuid", uuid);
resultMap.put("img", Base64.encode(os.toByteArray()));
return ServerResponse.status(HttpStatus.OK).body(BodyInserters.fromValue(Result.success(resultMap)));
return ServerResponse.ok().body(BodyInserters.fromValue(Result.success(resultMap)));
}
}

View File

@ -0,0 +1,35 @@
package com.youlai.gateway.handler.swagger;
import lombok.RequiredArgsConstructor;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;
import org.springframework.web.reactive.function.BodyInserters;
import org.springframework.web.reactive.function.server.HandlerFunction;
import org.springframework.web.reactive.function.server.ServerRequest;
import org.springframework.web.reactive.function.server.ServerResponse;
import reactor.core.publisher.Mono;
import springfox.documentation.swagger.web.SwaggerResourcesProvider;
/**
* 聚合各个服务的swagger接口
*
* @author haoxr
* @date 2022/5/17 0:53
*/
@Component
@RequiredArgsConstructor
public class SwaggerResourceHandler implements HandlerFunction<ServerResponse> {
private final SwaggerResourcesProvider swaggerResources;
@Override
public Mono<ServerResponse> handle(ServerRequest request) {
Mono<ServerResponse> responseMono = ServerResponse.ok()
.contentType(MediaType.APPLICATION_JSON)
.body(BodyInserters
.fromValue(swaggerResources.get()));
return responseMono;
}
}

View File

@ -0,0 +1,39 @@
package com.youlai.gateway.handler.swagger;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;
import org.springframework.web.reactive.function.BodyInserters;
import org.springframework.web.reactive.function.server.HandlerFunction;
import org.springframework.web.reactive.function.server.ServerRequest;
import org.springframework.web.reactive.function.server.ServerResponse;
import reactor.core.publisher.Mono;
import springfox.documentation.swagger.web.SecurityConfiguration;
import springfox.documentation.swagger.web.SecurityConfigurationBuilder;
import java.util.Optional;
/**
* 权限处理器
*
* @author haoxr
* @date 2022/5/17
*/
@Component
public class SwaggerSecurityHandler implements HandlerFunction<ServerResponse> {
@Autowired(required = false)
private SecurityConfiguration securityConfiguration;
@Override
public Mono<ServerResponse> handle(ServerRequest request) {
Mono<ServerResponse> responseMono = ServerResponse.ok()
.contentType(MediaType.APPLICATION_JSON)
.body(BodyInserters
.fromValue(Optional.ofNullable(securityConfiguration)
.orElse(SecurityConfigurationBuilder.builder().build())));
return responseMono;
}
}

View File

@ -0,0 +1,41 @@
package com.youlai.gateway.handler.swagger;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;
import org.springframework.web.reactive.function.BodyInserters;
import org.springframework.web.reactive.function.server.HandlerFunction;
import org.springframework.web.reactive.function.server.ServerRequest;
import org.springframework.web.reactive.function.server.ServerResponse;
import reactor.core.publisher.Mono;
import springfox.documentation.swagger.web.UiConfiguration;
import springfox.documentation.swagger.web.UiConfigurationBuilder;
import java.util.Optional;
/**
* UI处理器
*
* @author haoxr
* @date 2022/5/17 0:51
*/
@Component
public class SwaggerUiHandler implements HandlerFunction<ServerResponse> {
@Autowired(required = false)
private UiConfiguration uiConfiguration;
@Override
public Mono<ServerResponse> handle(ServerRequest request) {
Mono<ServerResponse> responseMono = ServerResponse.ok()
.contentType(MediaType.APPLICATION_JSON)
.body(BodyInserters
.fromValue(Optional.ofNullable(uiConfiguration)
.orElse(UiConfigurationBuilder.builder().build())));
return responseMono;
}
}

View File

@ -1,83 +0,0 @@
package com.youlai.gateway.log;
import lombok.Data;
/**
* 请求响应日志实体对象
*
* @author <a href="mailto:xianrui0365@163.com">haoxr</a>
* @date 2022/4/28 16:54
*/
@Data
public class TraceLog {
/**
* 请求路径
*/
private String requestPath;
/**
* 请求方法
*/
private String requestMethod;
/**
* 查询参数
*/
private String queryParams;
/**
* 请求载荷
*/
private String requestBody;
/**
* 响应数据
*/
private String responseBody;
/**
* 请求时间
*/
private String requestTime;
/**
* 响应时间
*/
private String responseTime;
/**
* 执行耗时(毫秒)
*/
private Long executeTime;
public String toRequestString() {
return
"^^^^^^^^请求日志^^^^^^^^: " + requestMethod + ':' + requestPath + '\n' +
"查询参数:" + queryParams + '\n' +
"请求载荷:" + requestBody + '\n' +
"请求时间:" + requestTime;
}
public String toResponseString() {
return
"$$$$$$$$响应日志$$$$$$$$: " + requestMethod + ':' + requestPath + '\n' +
"请求时间:" + requestTime + '\n' +
"响应时间:" + responseTime + '\n' +
"响应数据:" + responseBody + '\n' +
"执行耗时:" + executeTime + "毫秒";
}
@Override
public String toString() {
return "========网关请求响应日志========\n" +
"请求路径:" + requestPath + '\n' +
"请求方法:" + requestMethod + '\n' +
"请求参数:" + requestBody + '\n' +
"响应数据:" + responseBody + '\n' +
"请求时间:" + requestTime + '\n' +
"响应时间:" + responseTime + '\n' +
"执行耗时:" + executeTime + "毫秒";
}
}

View File

@ -1,6 +1,6 @@
package com.youlai.gateway.router;
import com.youlai.gateway.kaptcha.handler.CaptchaHandler;
import com.youlai.gateway.handler.CaptchaHandler;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.MediaType;
@ -10,16 +10,16 @@ import org.springframework.web.reactive.function.server.RouterFunctions;
import org.springframework.web.reactive.function.server.ServerResponse;
/**
* 图片验证码路由
* 验证码路由
*
* @author <a href="mailto:xianrui0365@163.com">haoxr</a>
* @date 2021/10/4
* @author haoxr
* @date 2022/5/16
*/
@Configuration
public class CaptchaRouter {
@Bean
public RouterFunction<ServerResponse> routeFunction(CaptchaHandler captchaHandler) {
public RouterFunction<ServerResponse> captchaRouterFunction(CaptchaHandler captchaHandler) {
return RouterFunctions
.route(RequestPredicates.GET("/captcha")
.and(RequestPredicates.accept(MediaType.TEXT_PLAIN)), captchaHandler::handle);

View File

@ -0,0 +1,46 @@
package com.youlai.gateway.router;
import com.youlai.gateway.handler.swagger.SwaggerResourceHandler;
import com.youlai.gateway.handler.swagger.SwaggerSecurityHandler;
import com.youlai.gateway.handler.swagger.SwaggerUiHandler;
import lombok.RequiredArgsConstructor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.MediaType;
import org.springframework.web.reactive.function.server.RequestPredicates;
import org.springframework.web.reactive.function.server.RouterFunction;
import org.springframework.web.reactive.function.server.RouterFunctions;
import org.springframework.web.reactive.function.server.ServerResponse;
/**
* Swagger路由
*
* @author haoxr
* @date 2022/5/16 16:34
*/
@Configuration
@RequiredArgsConstructor
public class SwaggerRouter {
/**
* 聚合各个服务的swagger接口
*/
private final SwaggerResourceHandler swaggerResourceHandler;
/**
* 权限处理器
*/
private final SwaggerSecurityHandler swaggerSecurityHandler;
/**
* UI处理器
*/
private final SwaggerUiHandler swaggerUiHandler;
@Bean
public RouterFunction<ServerResponse> swaggerRouterFunction() {
return RouterFunctions
.route(RequestPredicates.GET("/swagger-resources/configuration/security").and(RequestPredicates.accept(MediaType.ALL)), swaggerSecurityHandler::handle)
.andRoute(RequestPredicates.GET("/swagger-resources/configuration/ui").and(RequestPredicates.accept(MediaType.ALL)), swaggerUiHandler::handle)
.andRoute(RequestPredicates.GET("/swagger-resources").and(RequestPredicates.accept(MediaType.ALL)), swaggerResourceHandler::handle);
}
}

View File

@ -1,53 +0,0 @@
package com.youlai.gateway.swagger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Mono;
import springfox.documentation.swagger.web.*;
import java.util.Optional;
/**
* @author xianrui
* @Date 2021-02-25 16:34
* @Version 1.0.0
* @ https://gitee.com/xiaoym/swagger-bootstrap-ui-demo/blob/masterknife4j-spring-cloud-gateway/service-doc/src/main/java/com/xiaominfo/swagger/service/doc/handler/SwaggerHandler.java
*/
@RestController
public class SwaggerHandler {
@Autowired(required = false)
private SecurityConfiguration securityConfiguration;
@Autowired(required = false)
private UiConfiguration uiConfiguration;
private final SwaggerResourcesProvider swaggerResources;
@Autowired
public SwaggerHandler(SwaggerResourcesProvider swaggerResources) {
this.swaggerResources = swaggerResources;
}
@GetMapping("/swagger-resources/configuration/security")
public Mono<ResponseEntity<SecurityConfiguration>> securityConfiguration() {
return Mono.just(new ResponseEntity<>(
Optional.ofNullable(securityConfiguration).orElse(SecurityConfigurationBuilder.builder().build()), HttpStatus.OK));
}
@GetMapping("/swagger-resources/configuration/ui")
public Mono<ResponseEntity<UiConfiguration>> uiConfiguration() {
return Mono.just(new ResponseEntity<>(
Optional.ofNullable(uiConfiguration).orElse(UiConfigurationBuilder.builder().build()), HttpStatus.OK));
}
@GetMapping("/swagger-resources")
public Mono<ResponseEntity> swaggerResources() {
return Mono.just((new ResponseEntity<>(swaggerResources.get(), HttpStatus.OK)));
}
}

View File

@ -1,4 +1,4 @@
package com.youlai.gateway.kaptcha;
package com.youlai.gateway.util;
import com.google.code.kaptcha.text.impl.DefaultTextCreator;

View File

@ -14,8 +14,10 @@ import reactor.core.publisher.Mono;
import java.nio.charset.StandardCharsets;
/**
* @Author hxr
* @Date 2021-01-29 13:30
* 异常响应工具类
*
* @Author haoxr
* @Date 2021/01/29 13:30
*/
public class ResponseUtils {