最近遇到一个重定向的问题困扰了很久,百度也找不到合适的解决方案!!
一 、问题描述使用的技术:springboot(2.6.x) + springcloud gateway(3.1.x);
1、请求后台controller,通过service层进行一些列业务处理后,最终重定向到指定的页面显示数据;这里贴一下测试代码的demo
// 允许跨域访问
@CrossOrigin(origins = "*", maxAge = 7200)
@RequestMapping(value = "/test/request", method = RequestMethod.POST)
public String demo1(@RequestBody Map params)
throws IOException {
System.out.println("接收到的报文信息:" + params );
//TODO 业务处理代码略......
String targetUrl = "redirect:http://www.baidu.com";
return targetUrl;
}
2、但重定向失败,提示了下面的报错问题
ERROR 17580 --- [nio-8080-exec-2] a.w.r.e.AbstractErrorWebExceptionHandler : [54db0557] 500 Server Error for HTTP POST "/request/test/request" java.lang.IllegalStateException: Could not resolve view with name 'redirect:http://www.baidu.com'. at org.springframework.web.reactive.result.view.ViewResolutionResultHandler.lambda$resolveViews$3(ViewResolutionResultHandler.java:278) ~[spring-webflux-5.3.15.jar:5.3.15] Suppressed: reactor.core.publisher.FluxOnAssembly$OnAssemblyException: Error has been observed at the following site(s): *__checkpoint ⇢ Handler com.example.spring263.ApiRedirectController#demo1(Map) [DispatcherHandler] *__checkpoint ⇢ org.springframework.cloud.gateway.filter.WeightCalculatorWebFilter [DefaultWebFilterChain] *__checkpoint ⇢ HTTP POST "/request/test/request" [ExceptionHandlingWebHandler]二、分析原因
1、根据上述的报错,断点ViewResolutionResultHandler的278行,对应的方法;如下
private Mono> resolveViews(String viewName, Locale locale) { return Flux.fromIterable(getViewResolvers()) .concatMap(resolver -> resolver.resolveViewName(viewName, locale)) .collectList() .map(views -> { if (views.isEmpty()) { throw new IllegalStateException( "Could not resolve view with name '" + viewName + "'."); } views.addAll(getDefaultViews()); return views; }); }
发现是因为getViewResolvers() 没有找到视图解析器导致,无法解析redirect关键字导致无法跳转到指定的地址上;
那么到底为什么没有get到视图解析器呢?启动springboot工程的时候没加载到容器??
网上搜罗了一通,什么baidu啊,bing啊,stackoverflow啊,都没找到相对满意的答案,心累…
还是看看官方文档吧,好像看英文又有点头大,还是硬着头皮啃一下吧,毕竟有翻译工具;
传送门:https://docs.spring.io/spring-framework/docs/5.3.15/reference/html/web-reactive.html#spring-webflux
好了发现一个相关的问题:如图
redirect关键字需要**UrlBasedViewResolver**及其子类才能解析;
上面导致无法重定向的原因是因为无法找到视图解析器(viewResolver)而报错Could not resolve view with name 'redirect:http://www.baidu.com';那我在启动的时候加一个是不是就可以了呢??那怎么加啊???
接着往下看吧。
首先我们的定义的重定向的controller类不能基于@RestController 注解,必需是@Controller 注解
接着就添加一个config去初始化我们的viewResolver相关配置,自定义一个config类然后实现WebFluxConfigurer接口,再重写接口里的方法就可以做相应的操作了。
加载一个视图解析器,那就找找这个WebFluxConfigurer有没有对应的方法。
WebFluxConfigurer的方法如下:
default void configureViewResolvers(ViewResolverRegistry registry) {
}
最终写的配置类如下:
@Configuration
@EnableWebFlux
public class WebConfig implements WebFluxConfigurer {
@Override
public void configureViewResolvers(ViewResolverRegistry registry) {
System.out.println("加载了WebFlux");
ViewResolver viewResolver = new UrlBasedViewResolver();
registry.viewResolver(viewResolver);
}
}
温馨提示:配置类必需的注解**@Configuration**及**@EnableWebFlux**
因为上面官网说了,需要UrlBasedViewResolver识别redirect指令,所以就用了UrlBasedViewResolver;
重启应用验证一下这个config配置类是否解决重定向问题!!!!!!
果然已经不报错,且跳转到百度首页了。再断点看看刚刚ViewResolutionResultHandler的resolveViews方法,是否有我们添加的UrlBasedViewResolver;
显然是它。
这个方法可以解决重定向的问题,但会不会引起其他问题,需要去到每个人的代码实践里,我自己分析我们的项目,目前是没什么影响的。
至于更深层的原因,欢迎大神评论区告诉我。。。。。



