我有一个简单的Spring Boot(3.1.2)应用程序,其中定义了@RestController和几个@Getmap(/app/test,/app/test2).

例如:

@GetMapping("/test")
    public TestModel getTestModel() {
        return TestModel.builder()
                .testModelName("The best test model ever!")
                .testModelVersion(1)
                .build();
    }

因此,当我try 使用错误的API路径和Accept头向我的应用程序发送请求时,如下所示:

curl -X GET http://localhost:8080/random/incorrect -H "Accept: yaml"

我收到的不是预期的404 Not Found错误,而是以下异常:

jakarta.servlet.ServletException: Request processing failed: org.springframework.http.InvalidMediaTypeException: Invalid mime type "yaml": does not contain '/'
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1019) ~[spring-webmvc-6.0.11.jar:6.0.11]
    at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:903) ~[spring-webmvc-6.0.11.jar:6.0.11]
    at jakarta.servlet.http.HttpServlet.service(HttpServlet.java:500) ~[jakarta.servlet-api-5.0.0.jar:5.0.0]
    at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:885) ~[spring-webmvc-6.0.11.jar:6.0.11]
    at jakarta.servlet.http.HttpServlet.service(HttpServlet.java:587) ~[jakarta.servlet-api-5.0.0.jar:5.0.0]
    at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:764) ~[jetty-servlet-11.0.15.jar:11.0.15]
    at org.eclipse.jetty.servlet.ServletHandler$ChainEnd.doFilter(ServletHandler.java:1665) ~[jetty-servlet-11.0.15.jar:11.0.15]
    at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100) ~[spring-web-6.0.11.jar:6.0.11]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) ~[spring-web-6.0.11.jar:6.0.11]
    at org.eclipse.jetty.servlet.FilterHolder.doFilter(FilterHolder.java:202) ~[jetty-servlet-11.0.15.jar:11.0.15]
    at org.eclipse.jetty.servlet.ServletHandler$Chain.doFilter(ServletHandler.java:1635) ~[jetty-servlet-11.0.15.jar:11.0.15]
    at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93) ~[spring-web-6.0.11.jar:6.0.11]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) ~[spring-web-6.0.11.jar:6.0.11]
    at org.eclipse.jetty.servlet.FilterHolder.doFilter(FilterHolder.java:202) ~[jetty-servlet-11.0.15.jar:11.0.15]
    at org.eclipse.jetty.servlet.ServletHandler$Chain.doFilter(ServletHandler.java:1635) ~[jetty-servlet-11.0.15.jar:11.0.15]
    at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201) ~[spring-web-6.0.11.jar:6.0.11]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) ~[spring-web-6.0.11.jar:6.0.11]
    at org.eclipse.jetty.servlet.FilterHolder.doFilter(FilterHolder.java:202) ~[jetty-servlet-11.0.15.jar:11.0.15]
    at org.eclipse.jetty.servlet.ServletHandler$Chain.doFilter(ServletHandler.java:1635) ~[jetty-servlet-11.0.15.jar:11.0.15]
    at org.eclipse.jetty.websocket.servlet.WebSocketUpgradeFilter.doFilter(WebSocketUpgradeFilter.java:170) ~[websocket-servlet-11.0.15.jar:11.0.15]
    at org.eclipse.jetty.servlet.FilterHolder.doFilter(FilterHolder.java:202) ~[jetty-servlet-11.0.15.jar:11.0.15]
    at org.eclipse.jetty.servlet.ServletHandler$Chain.doFilter(ServletHandler.java:1635) ~[jetty-servlet-11.0.15.jar:11.0.15]
    at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:527) ~[jetty-servlet-11.0.15.jar:11.0.15]
    at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:131) ~[jetty-server-11.0.15.jar:11.0.15]
    at org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:578) ~[jetty-security-11.0.15.jar:11.0.15]
    at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:122) ~[jetty-server-11.0.15.jar:11.0.15]
    at org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:223) ~[jetty-server-11.0.15.jar:11.0.15]
    at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:1570) ~[jetty-server-11.0.15.jar:11.0.15]
    at org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:221) ~[jetty-server-11.0.15.jar:11.0.15]
    at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1381) ~[jetty-server-11.0.15.jar:11.0.15]
    at org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:176) ~[jetty-server-11.0.15.jar:11.0.15]
    at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:484) ~[jetty-servlet-11.0.15.jar:11.0.15]
    at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:1543) ~[jetty-server-11.0.15.jar:11.0.15]
    at org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:174) ~[jetty-server-11.0.15.jar:11.0.15]
    at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1303) ~[jetty-server-11.0.15.jar:11.0.15]
    at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:129) ~[jetty-server-11.0.15.jar:11.0.15]
    at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:122) ~[jetty-server-11.0.15.jar:11.0.15]
    at org.eclipse.jetty.server.Server.handle(Server.java:563) ~[jetty-server-11.0.15.jar:11.0.15]
    at org.eclipse.jetty.server.HttpChannel.lambda$handle$0(HttpChannel.java:505) ~[jetty-server-11.0.15.jar:11.0.15]
    at org.eclipse.jetty.server.HttpChannel.dispatch(HttpChannel.java:762) ~[jetty-server-11.0.15.jar:11.0.15]
    at org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:497) ~[jetty-server-11.0.15.jar:11.0.15]
    at org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:282) ~[jetty-server-11.0.15.jar:11.0.15]
    at org.eclipse.jetty.io.AbstractConnection$ReadCallback.succeeded(AbstractConnection.java:314) ~[jetty-io-11.0.15.jar:11.0.15]
    at org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:100) ~[jetty-io-11.0.15.jar:11.0.15]
    at org.eclipse.jetty.io.SelectableChannelEndPoint$1.run(SelectableChannelEndPoint.java:53) ~[jetty-io-11.0.15.jar:11.0.15]
    at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:969) ~[jetty-util-11.0.15.jar:11.0.15]
    at org.eclipse.jetty.util.thread.QueuedThreadPool$Runner.doRunJob(QueuedThreadPool.java:1194) ~[jetty-util-11.0.15.jar:11.0.15]
    at org.eclipse.jetty.util.thread.QueuedThreadPool$Runner.run(QueuedThreadPool.java:1149) ~[jetty-util-11.0.15.jar:11.0.15]
    at java.base/java.lang.Thread.run(Thread.java:833) ~[na:na]
Caused by: org.springframework.http.InvalidMediaTypeException: Invalid mime type "yaml": does not contain '/'
    at org.springframework.http.MediaType.parseMediaType(MediaType.java:742) ~[spring-web-6.0.11.jar:6.0.11]
    at org.springframework.http.MediaType.parseMediaTypes(MediaType.java:768) ~[spring-web-6.0.11.jar:6.0.11]
    at org.springframework.boot.autoconfigure.web.servlet.WelcomePageHandlerMapping.getAcceptedMediaTypes(WelcomePageHandlerMapping.java:82) ~[spring-boot-autoconfigure-3.1.2.jar:3.1.2]
    at org.springframework.boot.autoconfigure.web.servlet.WelcomePageHandlerMapping.isHtmlTextAccepted(WelcomePageHandlerMapping.java:71) ~[spring-boot-autoconfigure-3.1.2.jar:3.1.2]
    at org.springframework.boot.autoconfigure.web.servlet.WelcomePageHandlerMapping.getHandlerInternal(WelcomePageHandlerMapping.java:67) ~[spring-boot-autoconfigure-3.1.2.jar:3.1.2]
    at org.springframework.web.servlet.handler.AbstractHandlerMapping.getHandler(AbstractHandlerMapping.java:505) ~[spring-webmvc-6.0.11.jar:6.0.11]
    at org.springframework.web.servlet.DispatcherServlet.getHandler(DispatcherServlet.java:1275) ~[spring-webmvc-6.0.11.jar:6.0.11]
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1057) ~[spring-webmvc-6.0.11.jar:6.0.11]
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:974) ~[spring-webmvc-6.0.11.jar:6.0.11]
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1011) ~[spring-webmvc-6.0.11.jar:6.0.11]
    ... 48 common frames omitted

正如我所看到的那样,WelcomePageHandlerMapping号被叫停了.所以我的问题是:为什么调用这个处理程序而不是立即返回404错误?

我试图在文档中找到一些信息,但我没有运气.

推荐答案

当接收到请求时,Spring MVC会按顺序调用所有注册的处理程序映射,直到为请求提供处理程序为止.

WelcomePageHandlerMapping是在RequestMappingHandlerMapping之后排序的,因此只有在没有与请求匹配的@RequestMapping时才会调用WelcomePageHandlerMapping.

当调用WelcomePageHandlerMapping时,它必须确定它是否可以为传入请求提供处理程序.确定它是否可以这样做的一部分是判断请求是否会接受text/html响应.此判断是在判断路径是否匹配之前完成的,因此无论请求的路径如何,无效的Accept标头都会导致问题.

Java相关问答推荐

将linkedHashMap扩展到Java中的POJO类

强制Mockito返回null而不是emtpy list

Spring boot:Bean和动态扩展器

H2弹簧靴试验跌落台

如何在运行时动态创建表(使用Java、JPA、SprringBoot)

我的Spring Boot测试显示&IlLegalStateException:无法加载某事的ApplicationContext.

使用Jackson库反序列化json

SpringBoot:在条件{Variable}.isBlank/{Variable}.isEmpty不起作用的情况下进行路径变量验证

Java泛型类方法的静态返回类型是否被类型擦除?

Java 11 HttpCookie.parse在解析包含JSON的Cookie时引发IlLegalArgumentException

为什么我不能建立输入/输出流?Java ServerSocket

在线程Java中调用Interrupt()之后调用Join()

在Oracle中调用输出参数在索引处缺少IN或OUT参数的函数

无法在IntStream上应用Collectors.groupingBy

为什么使用lo索引来解决二进制搜索问题不同于使用hi索引?

如何使用带有可选参数的类生成器?

如何通过gradle命令行从build.gradle获得Java targetCompatibility

OpenJDK20:JEP434:Foreign Function&;内存API(第二次预览)

如何用Micrometer&;斯普肯

为什么 Random() 的行为不符合预期?