Java Spring Boot Rest - 如何配置 404 - 找不到资源

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/36733254/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 18:37:37  来源:igfitidea点击:

Spring Boot Rest - How to configure 404 - resource not found

javaspringrestspring-mvcspring-boot

提问by juniorbansal

I got a working spring boot rest service. When the path is wrong it doesn't return anything. No response At all. At the same time it doesn't throw error either. Ideally I expected a 404 not found error.

我得到了一个有效的弹簧靴休息服务。当路径错误时,它不会返回任何内容。完全没有反应。同时它也不会抛出错误。理想情况下,我预计会出现 404 not found 错误。

I got a GlobalErrorHandler

我有一个 GlobalErrorHandler

@ControllerAdvice
public class GlobalErrorHandler extends ResponseEntityExceptionHandler {

}

There is this method in ResponseEntityExceptionHandler

ResponseEntityExceptionHandler 中有这个方法

protected ResponseEntity<Object> handleNoHandlerFoundException(NoHandlerFoundException ex, HttpHeaders headers,
                                                     HttpStatus status, WebRequest request) {

    return handleExceptionInternal(ex, null, headers, status, request);
}

I have marked error.whitelabel.enabled=falsein my properties

我已error.whitelabel.enabled=false在我的属性中标记

What else must I do for this service to throw a 404 not found response back to clients

我还必须为该服务做什么才能将 404 not found 响应返回给客户端

I referred a lot of threads and don't see this trouble faced by anybody.

我提到了很多线程,并没有看到任何人面临这种​​麻烦。

This is my main application class

这是我的主要应用程序类

 @EnableAutoConfiguration // Sprint Boot Auto Configuration
@ComponentScan(basePackages = "com.xxxx")
@EnableJpaRepositories("com.xxxxxxxx") // To segregate MongoDB
                                                        // and JPA repositories.
                                                        // Otherwise not needed.
@EnableSwagger // auto generation of API docs
@SpringBootApplication
@EnableAspectJAutoProxy
@EnableConfigurationProperties

public class Application extends SpringBootServletInitializer {

    private static Class<Application> appClass = Application.class;

    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
        return application.sources(appClass).properties(getProperties());

    }

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }

    @Bean
    public FilterRegistrationBean correlationHeaderFilter() {
        FilterRegistrationBean filterRegBean = new FilterRegistrationBean();
        filterRegBean.setFilter(new CorrelationHeaderFilter());
        filterRegBean.setUrlPatterns(Arrays.asList("/*"));

        return filterRegBean;
    }

    @ConfigurationProperties(prefix = "spring.datasource")
    @Bean
    public DataSource dataSource() {
        return DataSourceBuilder.create().build();
    }

    static Properties getProperties() {
        Properties props = new Properties();
        props.put("spring.config.location", "classpath:/");
        return props;
    }

    @Bean
    public WebMvcConfigurerAdapter webMvcConfigurerAdapter() {
        WebMvcConfigurerAdapter webMvcConfigurerAdapter = new WebMvcConfigurerAdapter() {
            @Override
            public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
                configurer.favorPathExtension(false).favorParameter(true).parameterName("media-type")
                        .ignoreAcceptHeader(false).useJaf(false).defaultContentType(MediaType.APPLICATION_JSON)
                        .mediaType("xml", MediaType.APPLICATION_XML).mediaType("json", MediaType.APPLICATION_JSON);
            }
        };
        return webMvcConfigurerAdapter;
    }

    @Bean
    public RequestMappingHandlerMapping defaultAnnotationHandlerMapping() {
        RequestMappingHandlerMapping bean = new RequestMappingHandlerMapping();
        bean.setUseSuffixPatternMatch(false);
        return bean;
    }
}

回答by Ilya Ovesnov

The solution is pretty easy:

解决方案非常简单:

Firstyou need to implement the controller that will handle all error cases. This controller must have @ControllerAdvice-- required to define @ExceptionHandlerthat apply to all @RequestMappings.

首先,您需要实现将处理所有错误情况的控制器。此控制器必须具有@ControllerAdvice- 要求定义@ExceptionHandler适用于所有@RequestMappings.

@ControllerAdvice
public class ExceptionHandlerController {

    @ExceptionHandler(NoHandlerFoundException.class)
    @ResponseStatus(value= HttpStatus.NOT_FOUND)
    @ResponseBody
    public ErrorResponse requestHandlingNoHandlerFound() {
        return new ErrorResponse("custom_404", "message for 404 error code");
    }
}

Provide exception you want to override response in @ExceptionHandler. NoHandlerFoundExceptionis an exception that will be generated when Spring will not be able to delegate request (404 case). You also can specify Throwableto override any exceptions.

提供您想要覆盖响应的异常@ExceptionHandlerNoHandlerFoundException是当 Spring 无法委托请求(404 情况)时将生成的异常。您还可以指定Throwable覆盖任何异常。

Secondyou need to tell Spring to throw exception in case of 404 (could not resolve handler):

其次,您需要告诉 Spring 在 404 的情况下抛出异常(无法解析处理程序):

@SpringBootApplication
@EnableWebMvc
public class Application {

    public static void main(String[] args) {
        ApplicationContext ctx = SpringApplication.run(Application.class, args);

        DispatcherServlet dispatcherServlet = (DispatcherServlet)ctx.getBean("dispatcherServlet");
        dispatcherServlet.setThrowExceptionIfNoHandlerFound(true);
    }
}

Result when I use non defined URL

当我使用未定义的 URL 时的结果

{
    "errorCode": "custom_404",
    "errorMessage": "message for 404 error code"
}

UPDATE: In case you configure your SpringBoot application using application.propertiesthen you need to add the following properties instead of configuring DispatcherServletin main method (thanks to @mengchengfeng):

更新:如果您使用配置 SpringBoot 应用程序,application.properties则需要添加以下属性而不是DispatcherServlet在 main 方法中配置(感谢@mengchengfeng):

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

回答by Alternatic

I know this is an old question but here is another way to configure the DispatcherServletin code but not in the main class. You can use a separate @Configurationclass:

我知道这是一个老问题,但这是另一种配置DispatcherServlet代码但不在主类中的方法。您可以使用单独的@Configuration类:

@EnableWebMvc
@Configuration
public class ExceptionHandlingConfig {

    @Autowired
    private DispatcherServlet dispatcherServlet;

    @PostConstruct
    private void configureDispatcherServlet() {
        dispatcherServlet.setThrowExceptionIfNoHandlerFound(true);
    }
}

Please not that this does not work without the @EnableWebMvcannotation.

请注意,如果没有@EnableWebMvc注释,这将不起作用。