Skip to content

Commit

Permalink
优化 records 类的编码方式
Browse files Browse the repository at this point in the history
  • Loading branch information
vnobo committed Oct 30, 2023
1 parent 9f3f40d commit 9bb4abb
Show file tree
Hide file tree
Showing 5 changed files with 54 additions and 52 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -42,21 +42,19 @@ public class GlobalExceptionHandler {
@ExceptionHandler(ServerWebInputException.class)
public ResponseEntity<ErrorResponse> handleBindException(ServerWebExchange exchange, ServerWebInputException ex) {
List<String> errors = Lists.newArrayList();
// Check if exception is WebExchangeBindException
if (ex instanceof WebExchangeBindException bindException) {
for (ObjectError objectError : bindException.getBindingResult().getAllErrors()) {
errors.add("Error object %s message %s.".formatted(objectError.getObjectName(),
objectError.getDefaultMessage()));
}
} else {
// Add cause and reason to errors list
errors.add("Cause message %s.".formatted(ex.getCause().getMessage()));
errors.add("Exception reason %s".formatted(ex.getReason()));
}
// Log error
log.error("[%s] 请求参数验证失败! 信息: %s".formatted(exchange.getLogPrefix(), errors));
log.error("%s请求参数验证失败! 信息: %s".formatted(exchange.getLogPrefix(), errors));
if (log.isDebugEnabled()) {
log.error("Server error", ex);
log.error("请求参数验证失败", ex);
}
// Return response entity
return ResponseEntity.status(HttpStatus.BAD_REQUEST).contentType(MediaType.APPLICATION_JSON)
Expand Down Expand Up @@ -85,11 +83,11 @@ public ResponseEntity<ErrorResponse> handleFailureException(ServerWebExchange ex
} else {
errors.add(ex.getLocalizedMessage());
}
log.error("[%S] 数据库操作错误! 信息: %S".formatted(exchange.getLogPrefix(), errors));
log.error("%s数据库操作错误! 信息: %S".formatted(exchange.getLogPrefix(), errors));
if (log.isDebugEnabled()) {
log.error("Server error", ex);
log.error("数据库操作错误!", ex);
}
return ResponseEntity.status(HttpStatus.INSUFFICIENT_STORAGE).contentType(MediaType.APPLICATION_JSON)
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).contentType(MediaType.APPLICATION_JSON)
.body(ErrorResponse.of(exchange.getRequest().getId(), exchange.getRequest().getPath().value(),
5070, ex.getMessage(), errors));
}
Expand All @@ -103,11 +101,11 @@ public ResponseEntity<ErrorResponse> handleFailureException(ServerWebExchange ex
*/
@ExceptionHandler(ClientException.class)
public ResponseEntity<ErrorResponse> handleClientException(ServerWebExchange exchange, ClientException ex) {
log.error("[%s] 内部服务访问错误! 信息: %s".formatted(exchange.getLogPrefix(), ex.getMessage()));
log.error("%s内部服务访问错误! 信息: %s".formatted(exchange.getLogPrefix(), ex.getMessage()));
if (log.isDebugEnabled()) {
log.error("Server error", ex);
log.error("内部服务访问错误!", ex);
}
return ResponseEntity.status(HttpStatus.SERVICE_UNAVAILABLE).contentType(MediaType.APPLICATION_JSON)
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).contentType(MediaType.APPLICATION_JSON)
.body(ErrorResponse.of(exchange.getRequest().getId(), exchange.getRequest().getPath().value(),
ex.getCode(), ex.getMessage(), ex.getMsg()));
}
Expand All @@ -121,20 +119,20 @@ public ResponseEntity<ErrorResponse> handleClientException(ServerWebExchange exc
*/
@ExceptionHandler(RestServerException.class)
public ResponseEntity<ErrorResponse> handleRestServerException(ServerWebExchange exchange, RestServerException ex) {
log.error("[%s] 服务器自定义错误. 信息: %s".formatted(exchange.getLogPrefix(), ex.getLocalizedMessage()));
log.error("%s服务器自定义错误! 信息: %s".formatted(exchange.getLogPrefix(), ex.getLocalizedMessage()));
if (log.isDebugEnabled()) {
log.error("Server error", ex);
log.error("服务器自定义错误!", ex);
}
return ResponseEntity.status(HttpStatus.SERVICE_UNAVAILABLE).contentType(MediaType.APPLICATION_JSON)
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).contentType(MediaType.APPLICATION_JSON)
.body(ErrorResponse.of(exchange.getRequest().getId(), exchange.getRequest().getPath().value(),
ex.getCode(), ex.getMessage(), ex.getMsg()));
}

@ExceptionHandler(Exception.class)
public ResponseEntity<ErrorResponse> handleException(ServerWebExchange exchange, Exception ex) {
log.error("[%s] 服务器自定义错误. 信息: %s".formatted(exchange.getLogPrefix(), ex.getLocalizedMessage()));
log.error("%s服务器未知错误! 信息: %s".formatted(exchange.getLogPrefix(), ex.getLocalizedMessage()));
if (log.isDebugEnabled()) {
log.error("Server error", ex);
log.error("服务器未知错误!", ex);
}
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).contentType(MediaType.APPLICATION_JSON)
.body(ErrorResponse.of(exchange.getRequest().getId(), exchange.getRequest().getPath().value(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,12 @@
import org.springframework.beans.BeanUtils;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.http.HttpHeaders;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.security.core.context.ReactiveSecurityContextHolder;
import org.springframework.stereotype.Component;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

Expand All @@ -21,6 +24,7 @@
import java.lang.reflect.InvocationTargetException;
import java.util.Arrays;
import java.util.Map;
import java.util.Objects;
import java.util.StringJoiner;

/**
Expand All @@ -29,6 +33,21 @@
@Log4j2
@Component
public final class ContextUtils implements Serializable {
private static final String[] IP_HEADER_CANDIDATES = {
"X-Forwarded-For",
"X-Real-IP",
"Proxy-Client-IP",
"WL-Proxy-Client-IP",
"HTTP_X_FORWARDED_FOR",
"HTTP_X_FORWARDED",
"HTTP_X_CLUSTER_CLIENT_IP",
"HTTP_CLIENT_IP",
"HTTP_FORWARDED_FOR",
"HTTP_FORWARDED",
"HTTP_VIA",
"REMOTE_ADDR"
};

public final static String CSRF_TOKEN_CONTEXT = "CSRF_TOKEN_CONTEXT";
public final static String SECURITY_AUTH_TOKEN_HEADER = "X-Auth-Token";
public static ObjectMapper OBJECT_MAPPER;
Expand All @@ -41,6 +60,18 @@ public final class ContextUtils implements Serializable {
ContextUtils.USERS_SERVICE = usersService;
}

public static String getClientIpAddress(ServerHttpRequest httpRequest) {
HttpHeaders headers = httpRequest.getHeaders();
for (String header : IP_HEADER_CANDIDATES) {
String ipList = headers.getFirst(header);
if (ipList != null && !ipList.isEmpty() && !"unknown".equalsIgnoreCase(ipList)) {
String[] ipArray = StringUtils.commaDelimitedListToStringArray(ipList);
return ipArray[0];
}
}
return Objects.requireNonNull(httpRequest.getRemoteAddress()).getAddress().getHostAddress();
}

public static StringJoiner cacheKey(Object... objects) {
// Convert objects to a map using ObjectMapper
StringJoiner keyBuilder = new StringJoiner("&");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
import java.util.Optional;
import java.util.function.Function;

import static com.platform.boot.commons.utils.ContextUtils.getClientIpAddress;
import static org.springframework.security.web.server.csrf.CsrfWebFilter.DEFAULT_CSRF_MATCHER;

/**
Expand Down Expand Up @@ -228,7 +229,7 @@ private Mono<Void> cacheFilterChain(ServerWebExchange exchange, WebFilterChain c
HandlerStrategies.withDefaults().messageReaders());
return serverRequest.bodyToMono(String.class).doOnNext((objectValue) -> {
Object previousCachedBody = exchange.getAttributes().put(CACHED_REQUEST_BODY_ATTR, objectValue);
log.debug("[%s]Cache request body: %s".formatted(exchange.getLogPrefix(), previousCachedBody));
log.debug("%sCache request body: %s".formatted(exchange.getLogPrefix(), previousCachedBody));
});
}).then(Mono.defer(() -> {
ServerHttpRequest cachedRequest = exchange.getAttribute(CACHED_SERVER_HTTP_REQUEST_DECORATOR_ATTR);
Expand Down Expand Up @@ -257,6 +258,9 @@ private void logRequest(ServerWebExchange exchange, SecurityDetails userDetails)

ObjectNode contentNode = ContextUtils.OBJECT_MAPPER.createObjectNode();
contentNode.putPOJO("requestHeaders", request.getHeaders());
contentNode.putPOJO("requestAddress", getClientIpAddress(request));
contentNode.putPOJO("requestCookies", request.getCookies());
contentNode.putPOJO("requestQueryParams", request.getQueryParams());
contentNode.set("requestBody", readRequestBody(exchange));

contentNode.putPOJO("responseHeaders", response.getHeaders());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,42 +23,23 @@ public class TenantsService extends AbstractDatabase {
private final TenantsRepository tenantsRepository;
private final TenantMembersRepository membersRepository;

/**
* @param request 租户请求对象
* @param pageable 分页参数对象
* @return 包含租户信息的Flux对象
*/
public Flux<Tenant> search(TenantRequest request, Pageable pageable) {
var cacheKey = ContextUtils.cacheKey(request, pageable);
// 使用Java 17中的var关键字,类型推断更加简洁
var query = Query.query(request.toCriteria()).with(pageable);
// 使用Java 17中的新方法of,避免使用Tuple2
return super.queryWithCache(cacheKey, query, Tenant.class).flatMap(ContextUtils::userAuditorSerializable);
}

/**
* @param request 租户请求对象
* @param pageable 分页参数对象
* @return 包含租户信息的Mono对象
*/
public Mono<Page<Tenant>> page(TenantRequest request, Pageable pageable) {
var tenantsMono = this.search(request, pageable).collectList();

var cacheKey = ContextUtils.cacheKey(request);
Query query = Query.query(request.toCriteria());
// 使用Java 17中的var关键字,类型推断更加简洁
var tenantsMono = this.search(request, pageable).collectList();
var countMono = this.countWithCache(cacheKey, query, Tenant.class);
// 使用Java 17中的新方法ofTuple,避免使用Tuple2

return Mono.zip(tenantsMono, countMono)
.map(tuple2 -> new PageImpl<>(tuple2.getT1(), pageable, tuple2.getT2())); // 强制类型转换
.map(tuple2 -> new PageImpl<>(tuple2.getT1(), pageable, tuple2.getT2()));
}

/**
* 对租户进行操作,根据请求参数中的租户编码查找租户,如果找到则更新租户信息,否则创建新租户。
* 操作完成后清空缓存。
*
* @param request 租户请求参数
* @return Mono<Tenant> 返回操作后的租户信息
*/
public Mono<Tenant> operate(TenantRequest request) {
var tenantMono = this.tenantsRepository.findByCode(request.getCode())
.defaultIfEmpty(request.toTenant());
Expand All @@ -69,24 +50,12 @@ public Mono<Tenant> operate(TenantRequest request) {
return tenantMono.doAfterTerminate(() -> this.cache.clear());
}

/**
* Deletes a tenant.
*
* @param request the tenant request
* @return a Mono of void
*/
public Mono<Void> delete(TenantRequest request) {
return Flux.concatDelayError(
this.tenantsRepository.delete(request.toTenant()),
this.membersRepository.deleteByTenantCode(request.getCode())).then();
}

/**
* Saves a tenant.
*
* @param tenant the tenant to be saved
* @return a Mono of Tenant
*/
public Mono<Tenant> save(Tenant tenant) {
if (tenant.isNew()) {
return this.tenantsRepository.save(tenant);
Expand Down
2 changes: 1 addition & 1 deletion boot/platform/src/main/resources/application.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ server:

spring:
main.keep-alive: true
application.name: platform
application.name: plate
webflux.format:
time: HH:mm:ss
date-time: yyyy-MM-dd HH:mm:ss
Expand Down

0 comments on commit 9bb4abb

Please sign in to comment.