Skip to content

Commit

Permalink
🔧 fix: 修复日志记录错误和请求-响应处理逻辑
Browse files Browse the repository at this point in the history
  • Loading branch information
vnobo committed May 21, 2024
1 parent a3ff508 commit f72cbf4
Show file tree
Hide file tree
Showing 8 changed files with 137 additions and 176 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,7 @@
import com.google.common.collect.Lists;
import com.platform.boot.commons.exception.RestServerException;
import io.r2dbc.spi.R2dbcException;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import lombok.extern.log4j.Log4j2;
import org.springframework.dao.DataAccessException;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
Expand All @@ -22,14 +21,12 @@
/**
* @author <a href="https://github.com/vnobo">Alex bob</a>
*/
@Log4j2
@ControllerAdvice
public class GlobalExceptionHandler {

private static final Log log = LogFactory.getLog(GlobalExceptionHandler.class);

@ExceptionHandler(ServerWebInputException.class)
public ResponseEntity<ErrorResponse> handleBindException(ServerWebExchange exchange, ServerWebInputException ex) {
List<String> errors = Lists.newArrayList();
List<String> errors = Lists.newArrayList(ex.getReason());
if (ex instanceof WebExchangeBindException bindException) {
for (ObjectError objectError : bindException.getBindingResult().getAllErrors()) {
errors.add("Error field: %s, msg: %s.".formatted(objectError.getObjectName(),
Expand All @@ -49,11 +46,11 @@ public ResponseEntity<ErrorResponse> handleBindException(ServerWebExchange excha

@ExceptionHandler({DataAccessException.class, R2dbcException.class})
public ResponseEntity<ErrorResponse> handleFailureException(ServerWebExchange exchange, RuntimeException ex) {
List<String> errors = Lists.newArrayList();
List<String> errors = Lists.newArrayList("Database exec exception!");
if (ex instanceof R2dbcException r2dbcException) {
errors.add(r2dbcException.getMessage());
errors.add(r2dbcException.getSql());
errors.add(r2dbcException.getSqlState());
errors.add(r2dbcException.getMessage());
} else if (ex instanceof BadSqlGrammarException grammarException) {
errors.add(grammarException.getMessage());
errors.add(grammarException.getSql());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,50 +33,39 @@ protected <T> Flux<T> queryWithCache(Object key, Query query, Class<T> entityCla

protected <T> Flux<T> queryWithCache(Object key, String sql,
Map<String, Object> bindParams, Class<T> entityClass) {
// 构建数据库执行规范
var executeSpec = this.databaseClient.sql(() -> sql);
executeSpec = executeSpec.bindValues(bindParams);
// 执行查询并映射结果
Flux<T> source = executeSpec
.map((row, rowMetadata) -> this.r2dbcConverter.read(entityClass, row, rowMetadata))
.all();
// 调用带有缓存的查询方法

return queryWithCache(key, source);
}

protected <T> Flux<T> queryWithCache(Object key, Flux<T> sourceFlux) {
// 根据key生成缓存Key
String cacheKey = key + ":data";
// 从缓存中获取数据,若不存在则使用ArrayList创建新集合
Collection<T> cacheData = this.cache.get(cacheKey, ArrayList::new);
assert cacheData != null;

// 将源Flux的数据添加到缓存数据集合,并在其完成时将更新后的数据放入缓存
Flux<T> source = sourceFlux
.doOnNext(cacheData::add)
.doAfterTerminate(() -> BeanUtils.cachePut(this.cache, cacheKey, cacheData));

// 如果缓存数据不为空,则直接返回缓存数据流;否则,当数据流为空时切换为从源Flux获取数据
return Flux.fromIterable(ObjectUtils.isEmpty(cacheData) ? Collections.emptyList() : cacheData)
.switchIfEmpty(Flux.defer(() -> source));
}

protected <T> Mono<Long> countWithCache(Object key, Query query, Class<T> entityClass) {
// 通过查询条件,从数据库中计算记录数
Mono<Long> source = this.entityTemplate.count(query, entityClass);
// 将计算结果缓存起来,并返回缓存的结果
return countWithCache(key, source);
}

protected Mono<Long> countWithCache(Object key, String sql, Map<String, Object> bindParams) {
// 构建执行规范,设置SQL语句并绑定参数
var executeSpec = this.databaseClient.sql(() -> sql);
executeSpec = executeSpec.bindValues(bindParams);

// 执行查询并仅获取第一个结果的行数
Mono<Long> source = executeSpec.mapValue(Long.class).first();

// 使用给定的键和查询结果源对结果进行缓存
return countWithCache(key, source);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,13 +30,6 @@ public void afterPropertiesSet() {
@Component
@WritingConverter
public static class JsonToNodeWriteConverter implements Converter<JsonNode, Json> {

/**
* Convert JsonNode to Json
*
* @param source JsonNode
* @return Json
*/
@Override
public Json convert(@NonNull JsonNode source) {
return Json.of(source.toString());
Expand All @@ -46,13 +39,6 @@ public Json convert(@NonNull JsonNode source) {
@Component
@ReadingConverter
public static class JsonToNodeReadConverter implements Converter<Json, JsonNode> {

/**
* Convert Json to JsonNode
*
* @param source Json
* @return JsonNode
*/
@Override
public JsonNode convert(@NonNull Json source) {
try {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,6 @@ public void afterPropertiesSet() {
@Component
@WritingConverter
public static class UserAuditorWriteConverter implements Converter<UserAuditor, String> {
/**
* Converts a UserAuditor object to a string.
*
* @param source the UserAuditor object to convert
* @return the username of the UserAuditor object
*/
@Override
public String convert(@NonNull UserAuditor source) {
return source.code();
Expand All @@ -40,13 +34,6 @@ public String convert(@NonNull UserAuditor source) {
@Component
@ReadingConverter
public static class UserAuditorReadConverter implements Converter<String, UserAuditor> {

/**
* Converts a string to a UserAuditor object.
*
* @param source the string to convert
* @return a UserAuditor object with the given username
*/
@Override
public UserAuditor convert(@NonNull String source) {
return UserAuditor.withCode(source);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,7 @@
import com.platform.boot.commons.ErrorResponse;
import com.platform.boot.commons.utils.ContextUtils;
import com.platform.boot.security.oauth2.Oauth2SuccessHandler;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import lombok.extern.log4j.Log4j2;
import org.springframework.boot.autoconfigure.security.reactive.PathRequest;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
Expand Down Expand Up @@ -113,32 +112,46 @@ public Mono<MatchResult> matches(ServerWebExchange exchange) {
}
}

@Log4j2
static class CustomServerAuthenticationEntryPoint extends HttpBasicServerAuthenticationEntryPoint {
private static final Log log = LogFactory.getLog(CustomServerAuthenticationEntryPoint.class);

private static final String X_REQUESTED_WITH = "X-Requested-With";
private static final String XML_HTTP_REQUEST = "XMLHttpRequest";

@Override
public Mono<Void> commence(ServerWebExchange exchange, AuthenticationException e) {
String xRequestedWith = "X-Requested-With";
String xmlHttpRequest = "XMLHttpRequest";
ServerHttpRequest request = exchange.getRequest();
String requestedWith = request.getHeaders().getFirst(xRequestedWith);

log.error("认证失败! 信息: %s".formatted(e.getMessage()));

if (requestedWith != null && requestedWith.contains(xmlHttpRequest)) {
var response = exchange.getResponse();
response.setStatusCode(HttpStatus.UNAUTHORIZED);
response.getHeaders().setContentType(MediaType.APPLICATION_JSON);
ErrorResponse errorResponse = ErrorResponse.of(request.getId(), request.getPath().value(),
4010, "认证失败,检查你的用户名,密码是否正确或安全密钥是否过期!", List.of(e.getMessage()));
var body = ContextUtils.objectToBytes(errorResponse);
var dataBufferFactory = response.bufferFactory();
var bodyBuffer = dataBufferFactory.wrap(body);
return response.writeAndFlushWith(Flux.just(bodyBuffer).windowUntilChanged())
.doOnError((error) -> DataBufferUtils.release(bodyBuffer));
String requestedWith = request.getHeaders().getFirst(X_REQUESTED_WITH);

log.error("认证失败! 信息: {}", e.getMessage());
if (isXmlHttpRequest(requestedWith)) {
return handleXmlHttpRequestFailure(exchange, e);
}
return super.commence(exchange, e);
}

private boolean isXmlHttpRequest(String requestedWith) {
return requestedWith != null && requestedWith.contains(XML_HTTP_REQUEST);
}

private Mono<Void> handleXmlHttpRequestFailure(ServerWebExchange exchange, AuthenticationException e) {
var response = exchange.getResponse();
response.setStatusCode(HttpStatus.UNAUTHORIZED);
response.getHeaders().setContentType(MediaType.APPLICATION_JSON);

ErrorResponse errorResponse = createErrorResponse(exchange, e);
var body = ContextUtils.objectToBytes(errorResponse);
var dataBufferFactory = response.bufferFactory();
var bodyBuffer = dataBufferFactory.wrap(body);

return response.writeAndFlushWith(Flux.just(bodyBuffer).windowUntilChanged())
.doOnError((error) -> DataBufferUtils.release(bodyBuffer));
}

private ErrorResponse createErrorResponse(ServerWebExchange exchange, AuthenticationException e) {
return ErrorResponse.of(exchange.getRequest().getId(), exchange.getRequest().getPath().value(),
401, "认证失败,检查你的用户名,密码是否正确或安全密钥是否过期!", List.of(e.getMessage()));
}

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
public class SessionConfiguration {

public final static String HEADER_SESSION_ID_NAME = "X-Auth-Token";
public static final String HEADER_REQUESTED_WITH_NAME = "X-Requested-With";
public final static String HEADER_REQUESTED_WITH_NAME = "X-Requested-With";

@Bean
@Primary
Expand Down
Loading

0 comments on commit f72cbf4

Please sign in to comment.