如何修复我的 Spring Boot WebClient 请求。我收到消息,因为它是 supposd 但随后我收到 400 Bad Request
How do I fix my Spring Boot WebClient request. I receive the message as it is supposd but then I get an 400 Bad Request
我正在尝试对 musicbrainz 发出 WebClient 请求,但不明白我缺少什么。
我使用 resttemplate 成功了,但是当我尝试 WebClient 时,我成功了,但也失败了。
我正在使用 Spring Boot v2.5.0 并且启动它没有问题。
我的控制器如下所示:
@RestController
public class MashupController {
@Autowired
private MashupService service;
@GetMapping("/{mbid}")
public Artist artistInfo(@PathVariable String mbid){
Artist artist = new Artist();
artist.setMbid(mbid);
//MusicBrainz
ArtistDetails artistDetailsResponse = MusicBrainzService.getArtistDetails(mbid);
return artist;
}
这只是第一部分,足以显示错误。
我有一个 ArtistDetails class 如下:
@JsonIgnoreProperties(ignoreUnknown = true)
public class ArtistDetails {
private String id;
private String name;
private List<Relation> relations;
@JsonProperty("release-groups")
private List<ReleaseGroup> releaseGroups;
... getters / setters
}
我尝试了不同的设置并试图找到任何解决方案,但我迷路了。
我的服务 class 如下所示:
public class MusicBrainzService {
public static ArtistDetails getArtistDetails(String mbid){
WebClient wc = WebClient.create("http://musicbrainz.org");
ArtistDetails artistResponse = wc
.get()
.uri("/ws/2/artist/".concat(mbid).concat("?&fmt=json&inc=url-rels+release-groups"))
.retrieve()
// .onStatus(HttpStatus::is4xxClientError, response -> {
// System.out.println("4xx error");
// return Mono.error(new RuntimeException("4xx"));
// })
// .onStatus(HttpStatus::is5xxServerError, response -> {
// System.out.println("5xx error");
// return Mono.error(new RuntimeException("5xx"));
// })
.bodyToMono(ArtistDetails.class)
// .retry()
// .retryWhen(Retry.fixedDelay(3, Duration.ofMillis(1000)))
.block();
return artistResponse;
}
}
我也试过像下面这样添加 ClientHttpConnector。
private static ClientHttpConnector connector() {
return new
ReactorClientHttpConnector(HttpClient.create(ConnectionProvider.newConnection()));
}
正如我所写的那样,我仍然收到 json 的回复,但我也收到了
回复:
{"mbid":"5b11f4ce-a62d-471e-81fc-a69a8278c7da","description":null,"albums":[{"id":"fe317a1e-4339-4c45-86f4-229c33aa27ad","title":"Fully Illustrated Book & Interview Disc","image":null},{"id":"f1afec0b-26dd-3db5-9aa1-c91229a74a24","title":"Bleach","image":null},{"id":"1b022e01-4da6-387b-8658-8678046e4cef","title":"Nevermind","image":null},{"id":"2a0981fb-9593-3019-864b-ce934d97a16e","title":"In Utero","image":null},{"id":"01cf1391-141b-3c87-8650-45ade6e59070","title":"Incesticide","image":null},{"id":"5ab32af4-c62e-3cbf-aa8c-c761581d3b94","title":"Nirvana","image":null},{"id":"d4d28ec1-220a-327c-93c5-ae006be43598","title":"With the Lights Out","image":null},{"id":"e9674d41-d94b-344a-89f5-734736853d5f","title":"Sliver: The Best of the Box","image":null},{"id":"5cc5dc44-8860-462e-8aa5-2cf9b71af237","title":"ICON","image":null},{"id":"95563c6a-92e5-456c-9f86-6fe2ff1d148e","title":"2 for 1: Incesticide / In Utero","image":null},{"id":"55fca0ec-17ed-4860-b700-ef366574aa42","title":"Live! Tonight! Sold Out!!","image":null},{"id":"249e7835-5c39-3a10-b15b-e2d3470fb40c","title":"From the Muddy Banks of the Wishkah","image":null},{"id":"fb3770f6-83fb-32b7-85c4-1f522a92287e","title":"MTV Unplugged in New York","image":null},{"id":"48f5d526-0fa6-4ca6-ac59-9b2cf9ef464f","title":"Live at Reading","image":null},{"id":"e0372c5a-1750-46ec-8f1b-4b76df1fe8e7","title":"Live at the Paramount","image":null},{"id":"c171986d-83d9-4659-9644-ce9dc2b30836","title":"Live and Loud","image":null},{"id":"603761e1-7d54-41d3-b56b-f012a449f163","title":"Complete Live On KAOS FM 1987","image":null},{"id":"04f53329-d0d0-3b0d-856a-1e2cbcde0e69","title":"Love Buzz","image":null},{"id":"c01d417b-0e34-3723-9ebe-87de4620080c","title":"Sliver","image":null},{"id":"8c22577f-aaea-3973-9d27-20731751e088","title":"Candy / Molly’s Lips","image":null},{"id":"40f18565-ab15-3a93-8a9a-4ed6be9a112e","title":"Here She Comes Now / Venus in Furs","image":null},{"id":"03345972-d2f8-36bb-b49a-03a9ceccb7a7","title":"Smells Like Teen Spirit","image":null},{"id":"6970c348-86ce-3902-bee3-d2ebabc2643d","title":"Come as You Are","image":null},{"id":"be95ba52-8a66-3769-82ad-b5024e993ad7","title":"Lithium","image":null},{"id":"5d8050da-e5c9-3a1b-9e39-0a73620218c0","title":"In Bloom","image":null}]}
错误信息:
2021-05-25 19:49:32.445 ERROR 708 --- [nio-8080-exec-2] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.web.reactive.function.client.WebClientResponseException$BadRequest: 400 Bad Request from GET http://musicbrainz.org/ws/2/artist/favicon.ico?fmt=json&inc=url-rels+release-groups] with root cause
Stack trace:
at org.springframework.web.reactive.function.client.WebClientResponseException.create(WebClientResponseException.java:196) ~[spring-webflux-5.3.7.jar:5.3.7]
at org.springframework.web.reactive.function.client.DefaultClientResponse.lambda$createException(DefaultClientResponse.java:213) ~[spring-webflux-5.3.7.jar:5.3.7]
at reactor.core.publisher.FluxMap$MapSubscriber.onNext(FluxMap.java:106) ~[reactor-core-3.4.6.jar:3.4.6]
at reactor.core.publisher.FluxOnErrorResume$ResumeSubscriber.onNext(FluxOnErrorResume.java:79) ~[reactor-core-3.4.6.jar:3.4.6]
at reactor.core.publisher.FluxDefaultIfEmpty$DefaultIfEmptySubscriber.onNext(FluxDefaultIfEmpty.java:100) ~[reactor-core-3.4.6.jar:3.4.6]
at reactor.core.publisher.FluxMapFuseable$MapFuseableSubscriber.onNext(FluxMapFuseable.java:127) ~[reactor-core-3.4.6.jar:3.4.6]
at reactor.core.publisher.FluxContextWrite$ContextWriteSubscriber.onNext(FluxContextWrite.java:107) ~[reactor-core-3.4.6.jar:3.4.6]
at reactor.core.publisher.FluxMapFuseable$MapFuseableConditionalSubscriber.onNext(FluxMapFuseable.java:295) ~[reactor-core-3.4.6.jar:3.4.6]
at reactor.core.publisher.FluxFilterFuseable$FilterFuseableConditionalSubscriber.onNext(FluxFilterFuseable.java:337) ~[reactor-core-3.4.6.jar:3.4.6]
at reactor.core.publisher.Operators$MonoSubscriber.complete(Operators.java:1815) ~[reactor-core-3.4.6.jar:3.4.6]
at reactor.core.publisher.MonoCollect$CollectSubscriber.onComplete(MonoCollect.java:159) ~[reactor-core-3.4.6.jar:3.4.6]
at reactor.core.publisher.FluxMap$MapSubscriber.onComplete(FluxMap.java:142) ~[reactor-core-3.4.6.jar:3.4.6]
at reactor.core.publisher.FluxPeek$PeekSubscriber.onComplete(FluxPeek.java:259) ~[reactor-core-3.4.6.jar:3.4.6]
at reactor.core.publisher.FluxMap$MapSubscriber.onComplete(FluxMap.java:142) ~[reactor-core-3.4.6.jar:3.4.6]
at reactor.netty.channel.FluxReceive.onInboundComplete(FluxReceive.java:401) ~[reactor-netty-core-1.0.7.jar:1.0.7]
at reactor.netty.channel.ChannelOperations.onInboundComplete(ChannelOperations.java:416) ~[reactor-netty-core-1.0.7.jar:1.0.7]
at reactor.netty.channel.ChannelOperations.terminate(ChannelOperations.java:470) ~[reactor-netty-core-1.0.7.jar:1.0.7]
at reactor.netty.http.client.HttpClientOperations.onInboundNext(HttpClientOperations.java:685) ~[reactor-netty-http-1.0.7.jar:1.0.7]
at reactor.netty.channel.ChannelOperationsHandler.channelRead(ChannelOperationsHandler.java:94) ~[reactor-netty-core-1.0.7.jar:1.0.7]
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379) ~[netty-transport-4.1.65.Final.jar:4.1.65.Final]
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365) ~[netty-transport-4.1.65.Final.jar:4.1.65.Final]
at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357) ~[netty-transport-4.1.65.Final.jar:4.1.65.Final]
at io.netty.handler.codec.MessageToMessageDecoder.channelRead(MessageToMessageDecoder.java:103) ~[netty-codec-4.1.65.Final.jar:4.1.65.Final]
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379) ~[netty-transport-4.1.65.Final.jar:4.1.65.Final]
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365) ~[netty-transport-4.1.65.Final.jar:4.1.65.Final]
at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357) ~[netty-transport-4.1.65.Final.jar:4.1.65.Final]
at io.netty.channel.CombinedChannelDuplexHandler$DelegatingChannelHandlerContext.fireChannelRead(CombinedChannelDuplexHandler.java:436) ~[netty-transport-4.1.65.Final.jar:4.1.65.Final]
at io.netty.handler.codec.ByteToMessageDecoder.fireChannelRead(ByteToMessageDecoder.java:324) ~[netty-codec-4.1.65.Final.jar:4.1.65.Final]
at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:296) ~[netty-codec-4.1.65.Final.jar:4.1.65.Final]
at io.netty.channel.CombinedChannelDuplexHandler.channelRead(CombinedChannelDuplexHandler.java:251) ~[netty-transport-4.1.65.Final.jar:4.1.65.Final]
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379) ~[netty-transport-4.1.65.Final.jar:4.1.65.Final]
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365) ~[netty-transport-4.1.65.Final.jar:4.1.65.Final]
at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357) ~[netty-transport-4.1.65.Final.jar:4.1.65.Final]
at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1410) ~[netty-transport-4.1.65.Final.jar:4.1.65.Final]
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379) ~[netty-transport-4.1.65.Final.jar:4.1.65.Final]
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365) ~[netty-transport-4.1.65.Final.jar:4.1.65.Final]
at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:919) ~[netty-transport-4.1.65.Final.jar:4.1.65.Final]
at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:166) ~[netty-transport-4.1.65.Final.jar:4.1.65.Final]
at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:719) ~[netty-transport-4.1.65.Final.jar:4.1.65.Final]
at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:655) ~[netty-transport-4.1.65.Final.jar:4.1.65.Final]
at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:581) ~[netty-transport-4.1.65.Final.jar:4.1.65.Final]
at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:493) ~[netty-transport-4.1.65.Final.jar:4.1.65.Final]
at io.netty.util.concurrent.SingleThreadEventExecutor.run(SingleThreadEventExecutor.java:989) ~[netty-common-4.1.65.Final.jar:4.1.65.Final]
at io.netty.util.internal.ThreadExecutorMap.run(ThreadExecutorMap.java:74) ~[netty-common-4.1.65.Final.jar:4.1.65.Final]
at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30) ~[netty-common-4.1.65.Final.jar:4.1.65.Final]
at java.base/java.lang.Thread.run(Thread.java:830) ~[na:na]
Suppressed: java.lang.Exception: #block terminated with an error
at reactor.core.publisher.BlockingSingleSubscriber.blockingGet(BlockingSingleSubscriber.java:99) ~[reactor-core-3.4.6.jar:3.4.6]
at reactor.core.publisher.Mono.block(Mono.java:1703) ~[reactor-core-3.4.6.jar:3.4.6]
at com.test.mashupmusicservice.service.MusicBrainzService.getArtistDetails(MusicBrainzService.java:45) ~[classes/:na]
at com.test.mashupmusicservice.controller.MashupController.artistInfo(MashupController.java:30) ~[classes/:na]
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:na]
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
at java.base/java.lang.reflect.Method.invoke(Method.java:567) ~[na:na]
at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:197) ~[spring-web-5.3.7.jar:5.3.7]
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:141) ~[spring-web-5.3.7.jar:5.3.7]
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:106) ~[spring-webmvc-5.3.7.jar:5.3.7]
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:894) ~[spring-webmvc-5.3.7.jar:5.3.7]
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:808) ~[spring-webmvc-5.3.7.jar:5.3.7]
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87) ~[spring-webmvc-5.3.7.jar:5.3.7]
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1063) ~[spring-webmvc-5.3.7.jar:5.3.7]
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:963) ~[spring-webmvc-5.3.7.jar:5.3.7]
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006) ~[spring-webmvc-5.3.7.jar:5.3.7]
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:898) ~[spring-webmvc-5.3.7.jar:5.3.7]
at javax.servlet.http.HttpServlet.service(HttpServlet.java:626) ~[tomcat-embed-core-9.0.46.jar:4.0.FR]
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883) ~[spring-webmvc-5.3.7.jar:5.3.7]
at javax.servlet.http.HttpServlet.service(HttpServlet.java:733) ~[tomcat-embed-core-9.0.46.jar:4.0.FR]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:227) ~[tomcat-embed-core-9.0.46.jar:9.0.46]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) ~[tomcat-embed-core-9.0.46.jar:9.0.46]
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53) ~[tomcat-embed-websocket-9.0.46.jar:9.0.46]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189) ~[tomcat-embed-core-9.0.46.jar:9.0.46]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) ~[tomcat-embed-core-9.0.46.jar:9.0.46]
at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100) ~[spring-web-5.3.7.jar:5.3.7]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.3.7.jar:5.3.7]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189) ~[tomcat-embed-core-9.0.46.jar:9.0.46]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) ~[tomcat-embed-core-9.0.46.jar:9.0.46]
at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93) ~[spring-web-5.3.7.jar:5.3.7]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.3.7.jar:5.3.7]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189) ~[tomcat-embed-core-9.0.46.jar:9.0.46]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) ~[tomcat-embed-core-9.0.46.jar:9.0.46]
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201) ~[spring-web-5.3.7.jar:5.3.7]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.3.7.jar:5.3.7]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189) ~[tomcat-embed-core-9.0.46.jar:9.0.46]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) ~[tomcat-embed-core-9.0.46.jar:9.0.46]
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:202) ~[tomcat-embed-core-9.0.46.jar:9.0.46]
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:97) ~[tomcat-embed-core-9.0.46.jar:9.0.46]
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:542) ~[tomcat-embed-core-9.0.46.jar:9.0.46]
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:143) ~[tomcat-embed-core-9.0.46.jar:9.0.46]
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92) ~[tomcat-embed-core-9.0.46.jar:9.0.46]
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:78) ~[tomcat-embed-core-9.0.46.jar:9.0.46]
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:357) ~[tomcat-embed-core-9.0.46.jar:9.0.46]
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:374) ~[tomcat-embed-core-9.0.46.jar:9.0.46]
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65) ~[tomcat-embed-core-9.0.46.jar:9.0.46]
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:893) ~[tomcat-embed-core-9.0.46.jar:9.0.46]
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1707) ~[tomcat-embed-core-9.0.46.jar:9.0.46]
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) ~[tomcat-embed-core-9.0.46.jar:9.0.46]
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128) ~[na:na]
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628) ~[na:na]
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) ~[tomcat-embed-core-9.0.46.jar:9.0.46]
at java.base/java.lang.Thread.run(Thread.java:830) ~[na:na]
org.springframework.web.reactive.function.client.WebClientResponseException$BadRequest: 400 Bad Request from GET http://musicbrainz.org/ws/2/artist/favicon.ico?fmt=json&inc=url-rels+release-groups
at org.springframework.web.reactive.function.client.WebClientResponseException.create(WebClientResponseException.java:196) ~[spring-webflux-5.3.7.jar:5.3.7]
Suppressed: reactor.core.publisher.FluxOnAssembly$OnAssemblyException:
Error has been observed at the following site(s):
|_ checkpoint ⇢ 400 from GET http://musicbrainz.org/ws/2/artist/favicon.ico?fmt=json&inc=url-rels+release-groups [DefaultWebClient]
使用:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
Java11
错误堆栈告诉我“.block()”周围有问题,但我还没有找到任何解决方案。有人可以帮助我吗?
问题是:
- 您(内部基于 GUI 的浏览器)请求
http[s]://<yourhost>:<yourport>[/your-app]/favicon.ico
- 您的
@GetMapping("/{mbid}")
(@PathVariable
在上下文根)也覆盖(任何默认 spring-web)favicon.ico
处理,这导致 mbid == "favico.ico"
和报告的 issue/behavior.
为了克服这个问题,我们可以:
使用 REST-/not 基于 GUI 的浏览器/curl。 (这是相当严格的!)
(似乎更好)省略你的控制器和(任何spring默认)静态资源处理的冲突:
通过覆盖(为此引入一个额外的控制器)@GetMapping("/favicon.ico")
(https://www.baeldung.com/spring-boot-favicon#gracefully-disable-favicon)
(首选) 将控制器的请求路径更改为更明确的内容! :-)(例如 @GetMapping("/artist/{mbid}/info")
)
我正在尝试对 musicbrainz 发出 WebClient 请求,但不明白我缺少什么。 我使用 resttemplate 成功了,但是当我尝试 WebClient 时,我成功了,但也失败了。
我正在使用 Spring Boot v2.5.0 并且启动它没有问题。
我的控制器如下所示:
@RestController public class MashupController {
@Autowired
private MashupService service;
@GetMapping("/{mbid}")
public Artist artistInfo(@PathVariable String mbid){
Artist artist = new Artist();
artist.setMbid(mbid);
//MusicBrainz
ArtistDetails artistDetailsResponse = MusicBrainzService.getArtistDetails(mbid);
return artist;
}
这只是第一部分,足以显示错误。
我有一个 ArtistDetails class 如下:
@JsonIgnoreProperties(ignoreUnknown = true)
public class ArtistDetails {
private String id;
private String name;
private List<Relation> relations;
@JsonProperty("release-groups")
private List<ReleaseGroup> releaseGroups;
... getters / setters
}
我尝试了不同的设置并试图找到任何解决方案,但我迷路了。
我的服务 class 如下所示:
public class MusicBrainzService {
public static ArtistDetails getArtistDetails(String mbid){
WebClient wc = WebClient.create("http://musicbrainz.org");
ArtistDetails artistResponse = wc
.get()
.uri("/ws/2/artist/".concat(mbid).concat("?&fmt=json&inc=url-rels+release-groups"))
.retrieve()
// .onStatus(HttpStatus::is4xxClientError, response -> {
// System.out.println("4xx error");
// return Mono.error(new RuntimeException("4xx"));
// })
// .onStatus(HttpStatus::is5xxServerError, response -> {
// System.out.println("5xx error");
// return Mono.error(new RuntimeException("5xx"));
// })
.bodyToMono(ArtistDetails.class)
// .retry()
// .retryWhen(Retry.fixedDelay(3, Duration.ofMillis(1000)))
.block();
return artistResponse;
}
}
我也试过像下面这样添加 ClientHttpConnector。
private static ClientHttpConnector connector() {
return new
ReactorClientHttpConnector(HttpClient.create(ConnectionProvider.newConnection()));
}
正如我所写的那样,我仍然收到 json 的回复,但我也收到了
回复:
{"mbid":"5b11f4ce-a62d-471e-81fc-a69a8278c7da","description":null,"albums":[{"id":"fe317a1e-4339-4c45-86f4-229c33aa27ad","title":"Fully Illustrated Book & Interview Disc","image":null},{"id":"f1afec0b-26dd-3db5-9aa1-c91229a74a24","title":"Bleach","image":null},{"id":"1b022e01-4da6-387b-8658-8678046e4cef","title":"Nevermind","image":null},{"id":"2a0981fb-9593-3019-864b-ce934d97a16e","title":"In Utero","image":null},{"id":"01cf1391-141b-3c87-8650-45ade6e59070","title":"Incesticide","image":null},{"id":"5ab32af4-c62e-3cbf-aa8c-c761581d3b94","title":"Nirvana","image":null},{"id":"d4d28ec1-220a-327c-93c5-ae006be43598","title":"With the Lights Out","image":null},{"id":"e9674d41-d94b-344a-89f5-734736853d5f","title":"Sliver: The Best of the Box","image":null},{"id":"5cc5dc44-8860-462e-8aa5-2cf9b71af237","title":"ICON","image":null},{"id":"95563c6a-92e5-456c-9f86-6fe2ff1d148e","title":"2 for 1: Incesticide / In Utero","image":null},{"id":"55fca0ec-17ed-4860-b700-ef366574aa42","title":"Live! Tonight! Sold Out!!","image":null},{"id":"249e7835-5c39-3a10-b15b-e2d3470fb40c","title":"From the Muddy Banks of the Wishkah","image":null},{"id":"fb3770f6-83fb-32b7-85c4-1f522a92287e","title":"MTV Unplugged in New York","image":null},{"id":"48f5d526-0fa6-4ca6-ac59-9b2cf9ef464f","title":"Live at Reading","image":null},{"id":"e0372c5a-1750-46ec-8f1b-4b76df1fe8e7","title":"Live at the Paramount","image":null},{"id":"c171986d-83d9-4659-9644-ce9dc2b30836","title":"Live and Loud","image":null},{"id":"603761e1-7d54-41d3-b56b-f012a449f163","title":"Complete Live On KAOS FM 1987","image":null},{"id":"04f53329-d0d0-3b0d-856a-1e2cbcde0e69","title":"Love Buzz","image":null},{"id":"c01d417b-0e34-3723-9ebe-87de4620080c","title":"Sliver","image":null},{"id":"8c22577f-aaea-3973-9d27-20731751e088","title":"Candy / Molly’s Lips","image":null},{"id":"40f18565-ab15-3a93-8a9a-4ed6be9a112e","title":"Here She Comes Now / Venus in Furs","image":null},{"id":"03345972-d2f8-36bb-b49a-03a9ceccb7a7","title":"Smells Like Teen Spirit","image":null},{"id":"6970c348-86ce-3902-bee3-d2ebabc2643d","title":"Come as You Are","image":null},{"id":"be95ba52-8a66-3769-82ad-b5024e993ad7","title":"Lithium","image":null},{"id":"5d8050da-e5c9-3a1b-9e39-0a73620218c0","title":"In Bloom","image":null}]}
错误信息:
2021-05-25 19:49:32.445 ERROR 708 --- [nio-8080-exec-2] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.web.reactive.function.client.WebClientResponseException$BadRequest: 400 Bad Request from GET http://musicbrainz.org/ws/2/artist/favicon.ico?fmt=json&inc=url-rels+release-groups] with root cause
Stack trace:
at org.springframework.web.reactive.function.client.WebClientResponseException.create(WebClientResponseException.java:196) ~[spring-webflux-5.3.7.jar:5.3.7]
at org.springframework.web.reactive.function.client.DefaultClientResponse.lambda$createException(DefaultClientResponse.java:213) ~[spring-webflux-5.3.7.jar:5.3.7]
at reactor.core.publisher.FluxMap$MapSubscriber.onNext(FluxMap.java:106) ~[reactor-core-3.4.6.jar:3.4.6]
at reactor.core.publisher.FluxOnErrorResume$ResumeSubscriber.onNext(FluxOnErrorResume.java:79) ~[reactor-core-3.4.6.jar:3.4.6]
at reactor.core.publisher.FluxDefaultIfEmpty$DefaultIfEmptySubscriber.onNext(FluxDefaultIfEmpty.java:100) ~[reactor-core-3.4.6.jar:3.4.6]
at reactor.core.publisher.FluxMapFuseable$MapFuseableSubscriber.onNext(FluxMapFuseable.java:127) ~[reactor-core-3.4.6.jar:3.4.6]
at reactor.core.publisher.FluxContextWrite$ContextWriteSubscriber.onNext(FluxContextWrite.java:107) ~[reactor-core-3.4.6.jar:3.4.6]
at reactor.core.publisher.FluxMapFuseable$MapFuseableConditionalSubscriber.onNext(FluxMapFuseable.java:295) ~[reactor-core-3.4.6.jar:3.4.6]
at reactor.core.publisher.FluxFilterFuseable$FilterFuseableConditionalSubscriber.onNext(FluxFilterFuseable.java:337) ~[reactor-core-3.4.6.jar:3.4.6]
at reactor.core.publisher.Operators$MonoSubscriber.complete(Operators.java:1815) ~[reactor-core-3.4.6.jar:3.4.6]
at reactor.core.publisher.MonoCollect$CollectSubscriber.onComplete(MonoCollect.java:159) ~[reactor-core-3.4.6.jar:3.4.6]
at reactor.core.publisher.FluxMap$MapSubscriber.onComplete(FluxMap.java:142) ~[reactor-core-3.4.6.jar:3.4.6]
at reactor.core.publisher.FluxPeek$PeekSubscriber.onComplete(FluxPeek.java:259) ~[reactor-core-3.4.6.jar:3.4.6]
at reactor.core.publisher.FluxMap$MapSubscriber.onComplete(FluxMap.java:142) ~[reactor-core-3.4.6.jar:3.4.6]
at reactor.netty.channel.FluxReceive.onInboundComplete(FluxReceive.java:401) ~[reactor-netty-core-1.0.7.jar:1.0.7]
at reactor.netty.channel.ChannelOperations.onInboundComplete(ChannelOperations.java:416) ~[reactor-netty-core-1.0.7.jar:1.0.7]
at reactor.netty.channel.ChannelOperations.terminate(ChannelOperations.java:470) ~[reactor-netty-core-1.0.7.jar:1.0.7]
at reactor.netty.http.client.HttpClientOperations.onInboundNext(HttpClientOperations.java:685) ~[reactor-netty-http-1.0.7.jar:1.0.7]
at reactor.netty.channel.ChannelOperationsHandler.channelRead(ChannelOperationsHandler.java:94) ~[reactor-netty-core-1.0.7.jar:1.0.7]
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379) ~[netty-transport-4.1.65.Final.jar:4.1.65.Final]
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365) ~[netty-transport-4.1.65.Final.jar:4.1.65.Final]
at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357) ~[netty-transport-4.1.65.Final.jar:4.1.65.Final]
at io.netty.handler.codec.MessageToMessageDecoder.channelRead(MessageToMessageDecoder.java:103) ~[netty-codec-4.1.65.Final.jar:4.1.65.Final]
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379) ~[netty-transport-4.1.65.Final.jar:4.1.65.Final]
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365) ~[netty-transport-4.1.65.Final.jar:4.1.65.Final]
at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357) ~[netty-transport-4.1.65.Final.jar:4.1.65.Final]
at io.netty.channel.CombinedChannelDuplexHandler$DelegatingChannelHandlerContext.fireChannelRead(CombinedChannelDuplexHandler.java:436) ~[netty-transport-4.1.65.Final.jar:4.1.65.Final]
at io.netty.handler.codec.ByteToMessageDecoder.fireChannelRead(ByteToMessageDecoder.java:324) ~[netty-codec-4.1.65.Final.jar:4.1.65.Final]
at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:296) ~[netty-codec-4.1.65.Final.jar:4.1.65.Final]
at io.netty.channel.CombinedChannelDuplexHandler.channelRead(CombinedChannelDuplexHandler.java:251) ~[netty-transport-4.1.65.Final.jar:4.1.65.Final]
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379) ~[netty-transport-4.1.65.Final.jar:4.1.65.Final]
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365) ~[netty-transport-4.1.65.Final.jar:4.1.65.Final]
at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357) ~[netty-transport-4.1.65.Final.jar:4.1.65.Final]
at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1410) ~[netty-transport-4.1.65.Final.jar:4.1.65.Final]
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379) ~[netty-transport-4.1.65.Final.jar:4.1.65.Final]
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365) ~[netty-transport-4.1.65.Final.jar:4.1.65.Final]
at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:919) ~[netty-transport-4.1.65.Final.jar:4.1.65.Final]
at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:166) ~[netty-transport-4.1.65.Final.jar:4.1.65.Final]
at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:719) ~[netty-transport-4.1.65.Final.jar:4.1.65.Final]
at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:655) ~[netty-transport-4.1.65.Final.jar:4.1.65.Final]
at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:581) ~[netty-transport-4.1.65.Final.jar:4.1.65.Final]
at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:493) ~[netty-transport-4.1.65.Final.jar:4.1.65.Final]
at io.netty.util.concurrent.SingleThreadEventExecutor.run(SingleThreadEventExecutor.java:989) ~[netty-common-4.1.65.Final.jar:4.1.65.Final]
at io.netty.util.internal.ThreadExecutorMap.run(ThreadExecutorMap.java:74) ~[netty-common-4.1.65.Final.jar:4.1.65.Final]
at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30) ~[netty-common-4.1.65.Final.jar:4.1.65.Final]
at java.base/java.lang.Thread.run(Thread.java:830) ~[na:na]
Suppressed: java.lang.Exception: #block terminated with an error
at reactor.core.publisher.BlockingSingleSubscriber.blockingGet(BlockingSingleSubscriber.java:99) ~[reactor-core-3.4.6.jar:3.4.6]
at reactor.core.publisher.Mono.block(Mono.java:1703) ~[reactor-core-3.4.6.jar:3.4.6]
at com.test.mashupmusicservice.service.MusicBrainzService.getArtistDetails(MusicBrainzService.java:45) ~[classes/:na]
at com.test.mashupmusicservice.controller.MashupController.artistInfo(MashupController.java:30) ~[classes/:na]
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:na]
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
at java.base/java.lang.reflect.Method.invoke(Method.java:567) ~[na:na]
at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:197) ~[spring-web-5.3.7.jar:5.3.7]
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:141) ~[spring-web-5.3.7.jar:5.3.7]
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:106) ~[spring-webmvc-5.3.7.jar:5.3.7]
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:894) ~[spring-webmvc-5.3.7.jar:5.3.7]
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:808) ~[spring-webmvc-5.3.7.jar:5.3.7]
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87) ~[spring-webmvc-5.3.7.jar:5.3.7]
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1063) ~[spring-webmvc-5.3.7.jar:5.3.7]
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:963) ~[spring-webmvc-5.3.7.jar:5.3.7]
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006) ~[spring-webmvc-5.3.7.jar:5.3.7]
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:898) ~[spring-webmvc-5.3.7.jar:5.3.7]
at javax.servlet.http.HttpServlet.service(HttpServlet.java:626) ~[tomcat-embed-core-9.0.46.jar:4.0.FR]
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883) ~[spring-webmvc-5.3.7.jar:5.3.7]
at javax.servlet.http.HttpServlet.service(HttpServlet.java:733) ~[tomcat-embed-core-9.0.46.jar:4.0.FR]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:227) ~[tomcat-embed-core-9.0.46.jar:9.0.46]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) ~[tomcat-embed-core-9.0.46.jar:9.0.46]
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53) ~[tomcat-embed-websocket-9.0.46.jar:9.0.46]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189) ~[tomcat-embed-core-9.0.46.jar:9.0.46]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) ~[tomcat-embed-core-9.0.46.jar:9.0.46]
at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100) ~[spring-web-5.3.7.jar:5.3.7]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.3.7.jar:5.3.7]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189) ~[tomcat-embed-core-9.0.46.jar:9.0.46]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) ~[tomcat-embed-core-9.0.46.jar:9.0.46]
at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93) ~[spring-web-5.3.7.jar:5.3.7]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.3.7.jar:5.3.7]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189) ~[tomcat-embed-core-9.0.46.jar:9.0.46]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) ~[tomcat-embed-core-9.0.46.jar:9.0.46]
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201) ~[spring-web-5.3.7.jar:5.3.7]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.3.7.jar:5.3.7]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189) ~[tomcat-embed-core-9.0.46.jar:9.0.46]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) ~[tomcat-embed-core-9.0.46.jar:9.0.46]
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:202) ~[tomcat-embed-core-9.0.46.jar:9.0.46]
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:97) ~[tomcat-embed-core-9.0.46.jar:9.0.46]
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:542) ~[tomcat-embed-core-9.0.46.jar:9.0.46]
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:143) ~[tomcat-embed-core-9.0.46.jar:9.0.46]
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92) ~[tomcat-embed-core-9.0.46.jar:9.0.46]
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:78) ~[tomcat-embed-core-9.0.46.jar:9.0.46]
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:357) ~[tomcat-embed-core-9.0.46.jar:9.0.46]
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:374) ~[tomcat-embed-core-9.0.46.jar:9.0.46]
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65) ~[tomcat-embed-core-9.0.46.jar:9.0.46]
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:893) ~[tomcat-embed-core-9.0.46.jar:9.0.46]
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1707) ~[tomcat-embed-core-9.0.46.jar:9.0.46]
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) ~[tomcat-embed-core-9.0.46.jar:9.0.46]
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128) ~[na:na]
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628) ~[na:na]
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) ~[tomcat-embed-core-9.0.46.jar:9.0.46]
at java.base/java.lang.Thread.run(Thread.java:830) ~[na:na]
org.springframework.web.reactive.function.client.WebClientResponseException$BadRequest: 400 Bad Request from GET http://musicbrainz.org/ws/2/artist/favicon.ico?fmt=json&inc=url-rels+release-groups
at org.springframework.web.reactive.function.client.WebClientResponseException.create(WebClientResponseException.java:196) ~[spring-webflux-5.3.7.jar:5.3.7]
Suppressed: reactor.core.publisher.FluxOnAssembly$OnAssemblyException:
Error has been observed at the following site(s):
|_ checkpoint ⇢ 400 from GET http://musicbrainz.org/ws/2/artist/favicon.ico?fmt=json&inc=url-rels+release-groups [DefaultWebClient]
使用:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
Java11
错误堆栈告诉我“.block()”周围有问题,但我还没有找到任何解决方案。有人可以帮助我吗?
问题是:
- 您(内部基于 GUI 的浏览器)请求
http[s]://<yourhost>:<yourport>[/your-app]/favicon.ico
- 您的
@GetMapping("/{mbid}")
(@PathVariable
在上下文根)也覆盖(任何默认 spring-web)favicon.ico
处理,这导致mbid == "favico.ico"
和报告的 issue/behavior.
为了克服这个问题,我们可以:
使用 REST-/not 基于 GUI 的浏览器/curl。 (这是相当严格的!)
(似乎更好)省略你的控制器和(任何spring默认)静态资源处理的冲突:
通过覆盖(为此引入一个额外的控制器)
@GetMapping("/favicon.ico")
(https://www.baeldung.com/spring-boot-favicon#gracefully-disable-favicon)(首选) 将控制器的请求路径更改为更明确的内容! :-)(例如
@GetMapping("/artist/{mbid}/info")
)