java - Spring Boot - 处理未找到的静态资源(404)并能够识别异常原因

标签 java spring spring-boot

在我的 Spring Boot 应用程序 (2.3.1.RELEASE) 中,我使用以下方式提供静态资源:

@Configuration
public class StaticResourceConfiguration implements WebMvcConfigurer {
    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/favicon.ico").addResourceLocations("classpath:/static/favicon.ico");
        registry.addResourceHandler("/static/**").addResourceLocations("classpath:/static/");
    }
}

这很好用。但我无法正确管理找不到的静态资源。我希望在发生这种情况时调用自定义处理程序。

在我的应用程序中,我当前的策略是在一个方法中管理所有异常。这是我目前所做的:

@ControllerAdvice
@RestController
public class AppErrorController implements ErrorController {

    @Autowired
    private ErrorAttributes errorAttributes;

    @Override
    public String getErrorPath() {
        return "/error";
    }

    @ExceptionHandler(Exception.class)
    @RequestMapping("/error")
    public ErrorResponse handleError(WebRequest webRequest, HttpServletRequest request, HttpServletResponse response) {

        // Get access to the actual Exception
        Throwable ex = this.errorAttributes.getError(webRequest);

        // Check if it is a 404 exception
        if (ex != null && instanceof NoHandlerFoundException) {
            // Manage the error as a 404!
            // ...
        } else {
            response.setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value());
            ErrorResponse errorResponse = new ErrorResponse("generalError", "An error occured");
            return errorResponse;
        }
    }
}

这很有效,除了一种情况:未找到静态资源时!然后,Spring 由于 @RequestMapping("/error") 调用 handleError 方法,但在这种情况下,this.errorAttributes.getError(webRequest) 返回的异常)null!所以我无法知道它实际上是 404,因此我的代码返回一般 500 错误。

如何处理对不存在的静态资源的请求并能够识别原因,以便返回 404 而不是 500?

编辑:

我在application.properties中使用这些配置:

spring.resources.add-mappings=false
spring.mvc.throw-exception-if-no-handler-found=true

最佳答案

配置请求处理程序,通过将请求转发到 Servlet 容器的“默认”Servlet 来提供静态资源。 DefaultServletHandlerConfigurer

@Configuration
public class StaticResourceConfiguration implements WebMvcConfigurer {

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/favicon.ico").addResourceLocations("/static/favicon.ico");
        registry.addResourceHandler("/static/**").addResourceLocations("/static/");
    }

    @Override
    public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
        configurer.enable();
    }

    @Override
    public void addViewControllers(ViewControllerRegistry registry) {
        registry.addViewController("/").setViewName("forward:/resources/static/index.html");
        registry.addViewController("/error").setViewName("forward:/resources/error/404.html");
        registry.setOrder(Ordered.HIGHEST_PRECEDENCE);
   }
}

或者使用ControllerAdvice。

@Slf4j
@Order(ORDER)
@RestControllerAdvice(annotations = RestController.class)
public class GlobalRestControllerAdvice {

    public static final int ORDER = 0;

    @ResponseStatus(HttpStatus.NOT_FOUND)
    @ExceptionHandler(NotFoundException.class)
    public Map<String, String> handle(NotFoundException e) {
        log.error(e.getMessage(), e);
        Map<String, String> errorAttributes = new HashMap<>();
        errorAttributes.put("code", "NOT_FOUND");
        errorAttributes.put("message", e.getMessage());
        return errorAttributes;
    }
}

@Slf4j
@Order(GlobalRestControllerAdvice.ORDER + 1)
@ControllerAdvice
public class GlobalHtmlControllerAdvice {

    @ResponseStatus(HttpStatus.NOT_FOUND)
    @ExceptionHandler(NotFoundException.class)
    public String handle(NotFoundException e, Model model, HttpServletRequest request) {
        log.error(e.getMessage(), e);
        model.addAttribute("timestamp", LocalDateTime.now());
        model.addAttribute("error", "NOT_FOUND");
        model.addAttribute("path", request.getRequestURI());
        model.addAttribute("message", e.getMessage());
        return "/error/404";
    }
}

ErrorAttributes getError() - 返回:导致错误的异常或 null。

关于java - Spring Boot - 处理未找到的静态资源(404)并能够识别异常原因,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62416027/

相关文章:

java - Android 进行 DELETE Web 服务调用

java - 当检测到类扩展了 Enum 时,如何调用其 valueOf() 方法?

java - 使用局部变量还是全局变量更好

java - 当不再需要时,JVM 是否会将空闲内存返还给操作系统?

java - Spring POST 请求不支持的媒体类型 415

java - 模型 bean 的分层架构和持久性注释?

java - Spring Boot React 在单独的包中

java - url 中的 Spring-boot 位置变量

java - 在 Spring 中传递 Bean 依赖项的最佳方式是什么

hibernate - 交易所需异常 : no transaction is in progress while using JPAItemWriter