diff --git a/src/main/java/com/cisd/tms/common/enums/ErrorCode.java b/src/main/java/com/cisd/tms/common/enums/ErrorCode.java index c0f18d7..64051f6 100644 --- a/src/main/java/com/cisd/tms/common/enums/ErrorCode.java +++ b/src/main/java/com/cisd/tms/common/enums/ErrorCode.java @@ -5,6 +5,7 @@ public enum ErrorCode { UNAUTHORIZED(4010, "未认证或认证失败"), SESSION_INVALID(4011, "会话无效"), FORBIDDEN(4030, "无权限访问"), + NOT_FOUND(4040, "资源不存在"), VALIDATE_FAILED(4001, "参数校验失败"), CONFLICT(4090, "数据冲突"), BIZ_ERROR(5001, "业务处理异常"), diff --git a/src/main/java/com/cisd/tms/common/exception/GlobalExceptionHandler.java b/src/main/java/com/cisd/tms/common/exception/GlobalExceptionHandler.java index 60026ad..1941f42 100644 --- a/src/main/java/com/cisd/tms/common/exception/GlobalExceptionHandler.java +++ b/src/main/java/com/cisd/tms/common/exception/GlobalExceptionHandler.java @@ -14,6 +14,7 @@ import org.springframework.validation.FieldError; import org.springframework.web.bind.MethodArgumentNotValidException; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.RestControllerAdvice; +import org.springframework.web.servlet.resource.NoResourceFoundException; import org.springframework.web.multipart.MaxUploadSizeExceededException; import org.springframework.web.multipart.MultipartException; @@ -79,6 +80,16 @@ public class GlobalExceptionHandler { .withPath(request.getRequestURI())); } + @ExceptionHandler(NoResourceFoundException.class) + public ResponseEntity> handleNoResourceFound(NoResourceFoundException ex, HttpServletRequest request) { + if ("/favicon.ico".equals(request.getRequestURI())) { + return ResponseEntity.noContent().build(); + } + return response(HttpStatus.NOT_FOUND, + ApiResponse.fail(ErrorCode.NOT_FOUND.getCode(), "resource not found") + .withPath(request.getRequestURI())); + } + @ExceptionHandler(Exception.class) public ResponseEntity> handleException(Exception ex, HttpServletRequest request) { log.error("Unhandled exception", ex); diff --git a/src/test/java/com/cisd/tms/common/exception/GlobalExceptionHandlerTest.java b/src/test/java/com/cisd/tms/common/exception/GlobalExceptionHandlerTest.java index 9bf41a8..84c184e 100644 --- a/src/test/java/com/cisd/tms/common/exception/GlobalExceptionHandlerTest.java +++ b/src/test/java/com/cisd/tms/common/exception/GlobalExceptionHandlerTest.java @@ -5,8 +5,10 @@ import com.cisd.tms.common.enums.ErrorCode; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; import org.springframework.http.HttpStatus; +import org.springframework.http.HttpMethod; import org.springframework.http.ResponseEntity; import org.springframework.mock.web.MockHttpServletRequest; +import org.springframework.web.servlet.resource.NoResourceFoundException; import org.springframework.web.multipart.MaxUploadSizeExceededException; import org.springframework.web.multipart.MultipartException; @@ -47,4 +49,36 @@ class GlobalExceptionHandlerTest { Assertions.assertEquals("failed to parse multipart request", response.getBody().getMsg()); Assertions.assertEquals("/api/v1/files/upload", response.getBody().getPath()); } + + @Test + void shouldIgnoreMissingFaviconWithoutErrorBody() { + GlobalExceptionHandler handler = new GlobalExceptionHandler(); + MockHttpServletRequest request = new MockHttpServletRequest("GET", "/favicon.ico"); + + ResponseEntity> response = handler.handleNoResourceFound( + new NoResourceFoundException(HttpMethod.GET, "favicon.ico"), + request + ); + + Assertions.assertEquals(HttpStatus.NO_CONTENT, response.getStatusCode()); + Assertions.assertNull(response.getBody()); + } + + @Test + void shouldHandleMissingStaticResourceAsNotFound() { + GlobalExceptionHandler handler = new GlobalExceptionHandler(); + MockHttpServletRequest request = new MockHttpServletRequest("GET", "/missing.js"); + + ResponseEntity> response = handler.handleNoResourceFound( + new NoResourceFoundException(HttpMethod.GET, "missing.js"), + request + ); + + Assertions.assertEquals(HttpStatus.NOT_FOUND, response.getStatusCode()); + Assertions.assertNotNull(response.getBody()); + Assertions.assertFalse(response.getBody().isSuccess()); + Assertions.assertEquals(ErrorCode.NOT_FOUND.getCode(), response.getBody().getCode()); + Assertions.assertEquals("resource not found", response.getBody().getMsg()); + Assertions.assertEquals("/missing.js", response.getBody().getPath()); + } }