From ef2b82d6052f2a363e5fecd44e4e13325424e319 Mon Sep 17 00:00:00 2001
From: lbw <wangiegie@163.com>
Date: Sun, 7 Jan 2024 13:51:33 +0800
Subject: [PATCH] =?UTF-8?q?:zap:=20=E4=BC=98=E5=8C=96=20[Spring=20Boot=203?=
 =?UTF-8?q?.2.0]=20404=20Not=20Found=20behavior=20#38733?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 pig-common/pig-common-feign/pom.xml           |  97 +++++------
 .../handle/GlobalBizExceptionHandler.java     | 154 ++++++++++--------
 2 files changed, 139 insertions(+), 112 deletions(-)

diff --git a/pig-common/pig-common-feign/pom.xml b/pig-common/pig-common-feign/pom.xml
index cde961353..6ce9eb1c5 100755
--- a/pig-common/pig-common-feign/pom.xml
+++ b/pig-common/pig-common-feign/pom.xml
@@ -16,52 +16,57 @@
   -->
 
 <project xmlns="http://maven.apache.org/POM/4.0.0"
-		 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-		 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
-	<parent>
-		<groupId>com.pig4cloud</groupId>
-		<artifactId>pig-common</artifactId>
-		<version>3.7.3</version>
-	</parent>
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <parent>
+        <groupId>com.pig4cloud</groupId>
+        <artifactId>pig-common</artifactId>
+        <version>3.7.3</version>
+    </parent>
 
-	<modelVersion>4.0.0</modelVersion>
-	<packaging>jar</packaging>
-	<artifactId>pig-common-feign</artifactId>
-	<description>feign-sentinel服务降级熔断、限流组件</description>
+    <modelVersion>4.0.0</modelVersion>
+    <packaging>jar</packaging>
+    <artifactId>pig-common-feign</artifactId>
+    <description>feign-sentinel服务降级熔断、限流组件</description>
 
-	<dependencies>
-		<dependency>
-			<groupId>com.pig4cloud</groupId>
-			<artifactId>pig-common-core</artifactId>
-		</dependency>
-		<dependency>
-			<groupId>com.alibaba.cloud</groupId>
-			<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
-		</dependency>
-		<!--feign 依赖-->
-		<dependency>
-			<groupId>org.springframework.cloud</groupId>
-			<artifactId>spring-cloud-starter-openfeign</artifactId>
-		</dependency>
-		<!-- okhttp 扩展 -->
-		<dependency>
-			<groupId>io.github.openfeign</groupId>
-			<artifactId>feign-okhttp</artifactId>
-		</dependency>
-		<!-- LB 扩展 -->
-		<dependency>
-			<groupId>org.springframework.cloud</groupId>
-			<artifactId>spring-cloud-starter-loadbalancer</artifactId>
-		</dependency>
-		<!--caffeine 替换LB 默认缓存实现-->
-		<dependency>
-			<groupId>com.github.ben-manes.caffeine</groupId>
-			<artifactId>caffeine</artifactId>
-		</dependency>
-		<!--oauth server 依赖-->
-		<dependency>
-			<groupId>org.springframework.security</groupId>
-			<artifactId>spring-security-core</artifactId>
-		</dependency>
-	</dependencies>
+    <dependencies>
+        <dependency>
+            <groupId>com.pig4cloud</groupId>
+            <artifactId>pig-common-core</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.alibaba.cloud</groupId>
+            <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
+        </dependency>
+        <!--feign 依赖-->
+        <dependency>
+            <groupId>org.springframework.cloud</groupId>
+            <artifactId>spring-cloud-starter-openfeign</artifactId>
+        </dependency>
+        <!-- okhttp 扩展 -->
+        <dependency>
+            <groupId>io.github.openfeign</groupId>
+            <artifactId>feign-okhttp</artifactId>
+        </dependency>
+        <!-- LB 扩展 -->
+        <dependency>
+            <groupId>org.springframework.cloud</groupId>
+            <artifactId>spring-cloud-starter-loadbalancer</artifactId>
+        </dependency>
+        <!--caffeine 替换LB 默认缓存实现-->
+        <dependency>
+            <groupId>com.github.ben-manes.caffeine</groupId>
+            <artifactId>caffeine</artifactId>
+        </dependency>
+        <!--oauth server 依赖-->
+        <dependency>
+            <groupId>org.springframework.security</groupId>
+            <artifactId>spring-security-core</artifactId>
+        </dependency>
+        <!-- 异常枚举 -->
+        <dependency>
+            <groupId>org.springframework</groupId>
+            <artifactId>spring-webmvc</artifactId>
+        </dependency>
+    </dependencies>
 </project>
diff --git a/pig-common/pig-common-feign/src/main/java/com/pig4cloud/pig/common/feign/sentinel/handle/GlobalBizExceptionHandler.java b/pig-common/pig-common-feign/src/main/java/com/pig4cloud/pig/common/feign/sentinel/handle/GlobalBizExceptionHandler.java
index 3dccbf3c8..da465e01e 100644
--- a/pig-common/pig-common-feign/src/main/java/com/pig4cloud/pig/common/feign/sentinel/handle/GlobalBizExceptionHandler.java
+++ b/pig-common/pig-common-feign/src/main/java/com/pig4cloud/pig/common/feign/sentinel/handle/GlobalBizExceptionHandler.java
@@ -31,6 +31,7 @@
 import org.springframework.web.bind.annotation.ExceptionHandler;
 import org.springframework.web.bind.annotation.ResponseStatus;
 import org.springframework.web.bind.annotation.RestControllerAdvice;
+import org.springframework.web.servlet.resource.NoResourceFoundException;
 
 import java.util.List;
 
@@ -48,76 +49,97 @@
 @ConditionalOnExpression("!'${security.oauth2.client.clientId}'.isEmpty()")
 public class GlobalBizExceptionHandler {
 
-	/**
-	 * 全局异常.
-	 * @param e the e
-	 * @return R
-	 */
-	@ExceptionHandler(Exception.class)
-	@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
-	public R handleGlobalException(Exception e) {
-		log.error("全局异常信息 ex={}", e.getMessage(), e);
+    /**
+     * 全局异常.
+     *
+     * @param e the e
+     * @return R
+     */
+    @ExceptionHandler(Exception.class)
+    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
+    public R handleGlobalException(Exception e) {
+        log.error("全局异常信息 ex={}", e.getMessage(), e);
 
-		// 业务异常交由 sentinel 记录
-		Tracer.trace(e);
-		return R.failed(e.getLocalizedMessage());
-	}
+        // 业务异常交由 sentinel 记录
+        Tracer.trace(e);
+        return R.failed(e.getLocalizedMessage());
+    }
 
-	/**
-	 * 处理业务校验过程中碰到的非法参数异常 该异常基本由{@link org.springframework.util.Assert}抛出
-	 * @see Assert#hasLength(String, String)
-	 * @see Assert#hasText(String, String)
-	 * @see Assert#isTrue(boolean, String)
-	 * @see Assert#isNull(Object, String)
-	 * @see Assert#notNull(Object, String)
-	 * @param exception 参数校验异常
-	 * @return API返回结果对象包装后的错误输出结果
-	 */
-	@ExceptionHandler(IllegalArgumentException.class)
-	@ResponseStatus(HttpStatus.OK)
-	public R handleIllegalArgumentException(IllegalArgumentException exception) {
-		log.error("非法参数,ex = {}", exception.getMessage(), exception);
-		return R.failed(exception.getMessage());
-	}
+    /**
+     * 处理业务校验过程中碰到的非法参数异常 该异常基本由{@link org.springframework.util.Assert}抛出
+     *
+     * @param exception 参数校验异常
+     * @return API返回结果对象包装后的错误输出结果
+     * @see Assert#hasLength(String, String)
+     * @see Assert#hasText(String, String)
+     * @see Assert#isTrue(boolean, String)
+     * @see Assert#isNull(Object, String)
+     * @see Assert#notNull(Object, String)
+     */
+    @ExceptionHandler(IllegalArgumentException.class)
+    @ResponseStatus(HttpStatus.OK)
+    public R handleIllegalArgumentException(IllegalArgumentException exception) {
+        log.error("非法参数,ex = {}", exception.getMessage(), exception);
+        return R.failed(exception.getMessage());
+    }
 
-	/**
-	 * AccessDeniedException
-	 * @param e the e
-	 * @return R
-	 */
-	@ExceptionHandler(AccessDeniedException.class)
-	@ResponseStatus(HttpStatus.FORBIDDEN)
-	public R handleAccessDeniedException(AccessDeniedException e) {
-		String msg = SpringSecurityMessageSource.getAccessor()
-			.getMessage("AbstractAccessDecisionManager.accessDenied", e.getMessage());
-		log.warn("拒绝授权异常信息 ex={}", msg);
-		return R.failed(e.getLocalizedMessage());
-	}
+    /**
+     * AccessDeniedException
+     *
+     * @param e the e
+     * @return R
+     */
+    @ExceptionHandler(AccessDeniedException.class)
+    @ResponseStatus(HttpStatus.FORBIDDEN)
+    public R handleAccessDeniedException(AccessDeniedException e) {
+        String msg = SpringSecurityMessageSource.getAccessor()
+                .getMessage("AbstractAccessDecisionManager.accessDenied", e.getMessage());
+        log.warn("拒绝授权异常信息 ex={}", msg);
+        return R.failed(e.getLocalizedMessage());
+    }
 
-	/**
-	 * validation Exception
-	 * @param exception
-	 * @return R
-	 */
-	@ExceptionHandler({ MethodArgumentNotValidException.class })
-	@ResponseStatus(HttpStatus.BAD_REQUEST)
-	public R handleBodyValidException(MethodArgumentNotValidException exception) {
-		List<FieldError> fieldErrors = exception.getBindingResult().getFieldErrors();
-		log.warn("参数绑定异常,ex = {}", fieldErrors.get(0).getDefaultMessage());
-		return R.failed(String.format("%s %s", fieldErrors.get(0).getField(), fieldErrors.get(0).getDefaultMessage()));
-	}
+    /**
+     * validation Exception
+     *
+     * @param exception
+     * @return R
+     */
+    @ExceptionHandler({MethodArgumentNotValidException.class})
+    @ResponseStatus(HttpStatus.BAD_REQUEST)
+    public R handleBodyValidException(MethodArgumentNotValidException exception) {
+        List<FieldError> fieldErrors = exception.getBindingResult().getFieldErrors();
+        log.warn("参数绑定异常,ex = {}", fieldErrors.get(0).getDefaultMessage());
+        return R.failed(String.format("%s %s", fieldErrors.get(0).getField(), fieldErrors.get(0).getDefaultMessage()));
+    }
+
+    /**
+     * validation Exception (以form-data形式传参)
+     *
+     * @param exception
+     * @return R
+     */
+    @ExceptionHandler({BindException.class})
+    @ResponseStatus(HttpStatus.BAD_REQUEST)
+    public R bindExceptionHandler(BindException exception) {
+        List<FieldError> fieldErrors = exception.getBindingResult().getFieldErrors();
+        log.warn("参数绑定异常,ex = {}", fieldErrors.get(0).getDefaultMessage());
+        return R.failed(fieldErrors.get(0).getDefaultMessage());
+    }
+
+    /**
+     * 保持和低版本请求路径不存在的行为一致
+     * <p>
+     * <a href="https://github.com/spring-projects/spring-boot/issues/38733">[Spring Boot 3.2.0] 404 Not Found behavior #38733</a>
+     *
+     * @param exception
+     * @return R
+     */
+    @ExceptionHandler({NoResourceFoundException.class})
+    @ResponseStatus(HttpStatus.NOT_FOUND)
+    public R bindExceptionHandler(NoResourceFoundException exception) {
+        log.debug("请求路径 404 {}", exception.getMessage());
+        return R.failed(exception.getMessage());
+    }
 
-	/**
-	 * validation Exception (以form-data形式传参)
-	 * @param exception
-	 * @return R
-	 */
-	@ExceptionHandler({ BindException.class })
-	@ResponseStatus(HttpStatus.BAD_REQUEST)
-	public R bindExceptionHandler(BindException exception) {
-		List<FieldError> fieldErrors = exception.getBindingResult().getFieldErrors();
-		log.warn("参数绑定异常,ex = {}", fieldErrors.get(0).getDefaultMessage());
-		return R.failed(fieldErrors.get(0).getDefaultMessage());
-	}
 
 }