RedirectAttributes 不适用于 Spring 5
RedirectAttributes not working with Spring 5
我在 Spring Webflux 应用程序上,我想在我的一个控制器上执行重定向:
@Controller
@RequestMapping(value = "/login")
public class AuthenticationController {
@Autowired
private AuthenticationFacade authenticationFacade;
@GetMapping
public String loginView(final Model model) {
model.addAttribute("authenticationForm", new AuthenticationForm());
return "login";
}
@PostMapping
public Rendering authenticate(@Valid final AuthenticationForm authenticationForm,
final BindingResult bindingResult, final RedirectAttributes redirectAttributes) {
if (!bindingResult.hasErrors()) {
final AccountDto authenticatedAccount =
this.authenticationFacade.authenticate(authenticationForm).block();
if (authenticatedAccount != null) {
return Rendering.redirectTo("/home").build();
}
}
return Rendering.view("login").build();
}
}
我知道 Rendering.redirectTo() 作为 RedirectView 执行重定向。但是,当我在我的控制器方法参数中添加 RedirectAttributes 以提供重定向属性时,出现以下异常:
2017-09-28 18:35:08.084 ERROR 3702 --- [nio-9000-exec-3] o.s.w.s.adapter.HttpWebHandlerAdapter : Failed to handle request
java.lang.IllegalStateException: Failed to invoke handler method with resolved arguments: [0][type=org.springframework.validation.support.BindingAwareConcurrentModel][value={}],[1][type=org.springframework.validation.support.BindingAwareConcurrentModel][value={}] on public java.lang.String fr.auchan.wheatley.front.controller.AuthenticationController.loginView(org.springframework.ui.Model,org.springframework.web.servlet.mvc.support.RedirectAttributes)
at org.springframework.web.reactive.result.method.InvocableHandlerMethod.lambda$invoke[=12=](InvocableHandlerMethod.java:131)
at reactor.core.publisher.MonoFlatMap$FlatMapMain.onNext(MonoFlatMap.java:118)
at reactor.core.publisher.Operators$MonoSubscriber.complete(Operators.java:1010)
at reactor.core.publisher.MonoWhen$WhenCoordinator.signal(MonoWhen.java:246)
at reactor.core.publisher.MonoWhen$WhenInner.onNext(MonoWhen.java:306)
at reactor.core.publisher.FluxPeekFuseable$PeekFuseableSubscriber.onNext(FluxPeekFuseable.java:198)
at reactor.core.publisher.Operators$ScalarSubscription.request(Operators.java:1567)
at reactor.core.publisher.FluxPeekFuseable$PeekFuseableSubscriber.request(FluxPeekFuseable.java:139)
at reactor.core.publisher.MonoWhen$WhenInner.onSubscribe(MonoWhen.java:296)
at reactor.core.publisher.FluxPeekFuseable$PeekFuseableSubscriber.onSubscribe(FluxPeekFuseable.java:173)
at reactor.core.publisher.MonoJust.subscribe(MonoJust.java:54)
at reactor.core.publisher.MonoPeekFuseable.subscribe(MonoPeekFuseable.java:74)
at reactor.core.publisher.Mono.subscribe(Mono.java:2769)
at reactor.core.publisher.MonoWhen$WhenCoordinator.subscribe(MonoWhen.java:177)
at reactor.core.publisher.MonoWhen.subscribe(MonoWhen.java:127)
at reactor.core.publisher.MonoFlatMap.subscribe(MonoFlatMap.java:60)
at reactor.core.publisher.MonoPeekFuseable.subscribe(MonoPeekFuseable.java:74)
at reactor.core.publisher.MonoOnErrorResume.subscribe(MonoOnErrorResume.java:44)
at reactor.core.publisher.MonoDefer.subscribe(MonoDefer.java:52)
at reactor.core.publisher.MonoIgnoreThen$ThenIgnoreMain.drain(MonoIgnoreThen.java:147)
at reactor.core.publisher.MonoIgnoreThen.subscribe(MonoIgnoreThen.java:56)
at reactor.core.publisher.MonoFlatMap$FlatMapMain.onNext(MonoFlatMap.java:148)
at reactor.core.publisher.FluxSwitchIfEmpty$SwitchIfEmptySubscriber.onNext(FluxSwitchIfEmpty.java:67)
at reactor.core.publisher.MonoNext$NextSubscriber.onNext(MonoNext.java:76)
at reactor.core.publisher.FluxConcatMap$ConcatMapImmediate.innerNext(FluxConcatMap.java:270)
at reactor.core.publisher.FluxConcatMap$ConcatMapInner.onNext(FluxConcatMap.java:790)
at reactor.core.publisher.FluxMapFuseable$MapFuseableSubscriber.onNext(FluxMapFuseable.java:115)
at reactor.core.publisher.Operators$ScalarSubscription.request(Operators.java:1567)
at reactor.core.publisher.FluxMapFuseable$MapFuseableSubscriber.request(FluxMapFuseable.java:156)
at reactor.core.publisher.Operators$MultiSubscriptionSubscriber.set(Operators.java:1381)
at reactor.core.publisher.Operators$MultiSubscriptionSubscriber.onSubscribe(Operators.java:1255)
at reactor.core.publisher.FluxMapFuseable$MapFuseableSubscriber.onSubscribe(FluxMapFuseable.java:90)
at reactor.core.publisher.MonoJust.subscribe(MonoJust.java:54)
at reactor.core.publisher.MonoMapFuseable.subscribe(MonoMapFuseable.java:59)
at reactor.core.publisher.Mono.subscribe(Mono.java:2769)
at reactor.core.publisher.FluxConcatMap$ConcatMapImmediate.drain(FluxConcatMap.java:414)
at reactor.core.publisher.FluxConcatMap$ConcatMapImmediate.onSubscribe(FluxConcatMap.java:210)
at reactor.core.publisher.FluxIterable.subscribe(FluxIterable.java:91)
at reactor.core.publisher.FluxIterable.subscribe(FluxIterable.java:55)
at reactor.core.publisher.FluxConcatMap.subscribe(FluxConcatMap.java:121)
at reactor.core.publisher.MonoNext.subscribe(MonoNext.java:40)
at reactor.core.publisher.MonoSwitchIfEmpty.subscribe(MonoSwitchIfEmpty.java:44)
at reactor.core.publisher.MonoFlatMap.subscribe(MonoFlatMap.java:60)
at reactor.core.publisher.MonoFlatMap.subscribe(MonoFlatMap.java:60)
at reactor.core.publisher.MonoOnErrorResume.subscribe(MonoOnErrorResume.java:44)
at reactor.core.publisher.MonoOnErrorResume.subscribe(MonoOnErrorResume.java:44)
at reactor.core.publisher.Mono.subscribe(Mono.java:2769)
at reactor.core.publisher.MonoIgnoreThen$ThenIgnoreMain.drain(MonoIgnoreThen.java:165)
at reactor.core.publisher.MonoIgnoreThen.subscribe(MonoIgnoreThen.java:56)
at reactor.core.publisher.Mono.subscribe(Mono.java:2769)
at org.springframework.http.server.reactive.ServletHttpHandlerAdapter.service(ServletHttpHandlerAdapter.java:116)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:198)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:478)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:140)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:80)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:342)
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:799)
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66)
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:868)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1455)
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Thread.java:745)
这是我的配置:
- Spring 启动 2.0.0.M3(Spring 5.0.0.RC3)。
- Spring Webflux
用Spring5这样提供重定向属性是不可能的吗?有没有其他方法可以做到这一点,或者这是一个错误?
我不完全确定它在 Spring 5 中是如何工作的。但是,从根本上说,当您重定向到另一个 URL 时,它会成为对 HTTP 服务器的新请求。这意味着,服务器需要新重定向请求中的所有必需属性和参数才能访问它。
我认为,这就是您的问题所在,您的控制器期望参数由于使用重定向生成的新请求而丢失。尝试找到一种方法来转发此请求,而不是重定向。这将携带您的终端控制器请求中的所有原始属性。
我不确定我是否能正确理解问题并能说明问题的解决方法。
您正在尝试使用 org.springframework.web.servlet.mvc.support.RedirectAttributes
,一个 Spring MVC class - 在 Spring WebFlux 中。这行不通。
我不知道 WebFlux 中有任何等效项,这可能是一个增强请求。
如答案中所述,RedirectAttributes 等价物目前似乎不存在于 Spring Webflux 中。
我在 Spring 打开了一个 JIRA 以寻求改进,这里是 link 如果有人也有兴趣获得关于这一点的更新:https://jira.spring.io/browse/SPR-16026
我在 Spring Webflux 应用程序上,我想在我的一个控制器上执行重定向:
@Controller
@RequestMapping(value = "/login")
public class AuthenticationController {
@Autowired
private AuthenticationFacade authenticationFacade;
@GetMapping
public String loginView(final Model model) {
model.addAttribute("authenticationForm", new AuthenticationForm());
return "login";
}
@PostMapping
public Rendering authenticate(@Valid final AuthenticationForm authenticationForm,
final BindingResult bindingResult, final RedirectAttributes redirectAttributes) {
if (!bindingResult.hasErrors()) {
final AccountDto authenticatedAccount =
this.authenticationFacade.authenticate(authenticationForm).block();
if (authenticatedAccount != null) {
return Rendering.redirectTo("/home").build();
}
}
return Rendering.view("login").build();
}
}
我知道 Rendering.redirectTo() 作为 RedirectView 执行重定向。但是,当我在我的控制器方法参数中添加 RedirectAttributes 以提供重定向属性时,出现以下异常:
2017-09-28 18:35:08.084 ERROR 3702 --- [nio-9000-exec-3] o.s.w.s.adapter.HttpWebHandlerAdapter : Failed to handle request
java.lang.IllegalStateException: Failed to invoke handler method with resolved arguments: [0][type=org.springframework.validation.support.BindingAwareConcurrentModel][value={}],[1][type=org.springframework.validation.support.BindingAwareConcurrentModel][value={}] on public java.lang.String fr.auchan.wheatley.front.controller.AuthenticationController.loginView(org.springframework.ui.Model,org.springframework.web.servlet.mvc.support.RedirectAttributes)
at org.springframework.web.reactive.result.method.InvocableHandlerMethod.lambda$invoke[=12=](InvocableHandlerMethod.java:131)
at reactor.core.publisher.MonoFlatMap$FlatMapMain.onNext(MonoFlatMap.java:118)
at reactor.core.publisher.Operators$MonoSubscriber.complete(Operators.java:1010)
at reactor.core.publisher.MonoWhen$WhenCoordinator.signal(MonoWhen.java:246)
at reactor.core.publisher.MonoWhen$WhenInner.onNext(MonoWhen.java:306)
at reactor.core.publisher.FluxPeekFuseable$PeekFuseableSubscriber.onNext(FluxPeekFuseable.java:198)
at reactor.core.publisher.Operators$ScalarSubscription.request(Operators.java:1567)
at reactor.core.publisher.FluxPeekFuseable$PeekFuseableSubscriber.request(FluxPeekFuseable.java:139)
at reactor.core.publisher.MonoWhen$WhenInner.onSubscribe(MonoWhen.java:296)
at reactor.core.publisher.FluxPeekFuseable$PeekFuseableSubscriber.onSubscribe(FluxPeekFuseable.java:173)
at reactor.core.publisher.MonoJust.subscribe(MonoJust.java:54)
at reactor.core.publisher.MonoPeekFuseable.subscribe(MonoPeekFuseable.java:74)
at reactor.core.publisher.Mono.subscribe(Mono.java:2769)
at reactor.core.publisher.MonoWhen$WhenCoordinator.subscribe(MonoWhen.java:177)
at reactor.core.publisher.MonoWhen.subscribe(MonoWhen.java:127)
at reactor.core.publisher.MonoFlatMap.subscribe(MonoFlatMap.java:60)
at reactor.core.publisher.MonoPeekFuseable.subscribe(MonoPeekFuseable.java:74)
at reactor.core.publisher.MonoOnErrorResume.subscribe(MonoOnErrorResume.java:44)
at reactor.core.publisher.MonoDefer.subscribe(MonoDefer.java:52)
at reactor.core.publisher.MonoIgnoreThen$ThenIgnoreMain.drain(MonoIgnoreThen.java:147)
at reactor.core.publisher.MonoIgnoreThen.subscribe(MonoIgnoreThen.java:56)
at reactor.core.publisher.MonoFlatMap$FlatMapMain.onNext(MonoFlatMap.java:148)
at reactor.core.publisher.FluxSwitchIfEmpty$SwitchIfEmptySubscriber.onNext(FluxSwitchIfEmpty.java:67)
at reactor.core.publisher.MonoNext$NextSubscriber.onNext(MonoNext.java:76)
at reactor.core.publisher.FluxConcatMap$ConcatMapImmediate.innerNext(FluxConcatMap.java:270)
at reactor.core.publisher.FluxConcatMap$ConcatMapInner.onNext(FluxConcatMap.java:790)
at reactor.core.publisher.FluxMapFuseable$MapFuseableSubscriber.onNext(FluxMapFuseable.java:115)
at reactor.core.publisher.Operators$ScalarSubscription.request(Operators.java:1567)
at reactor.core.publisher.FluxMapFuseable$MapFuseableSubscriber.request(FluxMapFuseable.java:156)
at reactor.core.publisher.Operators$MultiSubscriptionSubscriber.set(Operators.java:1381)
at reactor.core.publisher.Operators$MultiSubscriptionSubscriber.onSubscribe(Operators.java:1255)
at reactor.core.publisher.FluxMapFuseable$MapFuseableSubscriber.onSubscribe(FluxMapFuseable.java:90)
at reactor.core.publisher.MonoJust.subscribe(MonoJust.java:54)
at reactor.core.publisher.MonoMapFuseable.subscribe(MonoMapFuseable.java:59)
at reactor.core.publisher.Mono.subscribe(Mono.java:2769)
at reactor.core.publisher.FluxConcatMap$ConcatMapImmediate.drain(FluxConcatMap.java:414)
at reactor.core.publisher.FluxConcatMap$ConcatMapImmediate.onSubscribe(FluxConcatMap.java:210)
at reactor.core.publisher.FluxIterable.subscribe(FluxIterable.java:91)
at reactor.core.publisher.FluxIterable.subscribe(FluxIterable.java:55)
at reactor.core.publisher.FluxConcatMap.subscribe(FluxConcatMap.java:121)
at reactor.core.publisher.MonoNext.subscribe(MonoNext.java:40)
at reactor.core.publisher.MonoSwitchIfEmpty.subscribe(MonoSwitchIfEmpty.java:44)
at reactor.core.publisher.MonoFlatMap.subscribe(MonoFlatMap.java:60)
at reactor.core.publisher.MonoFlatMap.subscribe(MonoFlatMap.java:60)
at reactor.core.publisher.MonoOnErrorResume.subscribe(MonoOnErrorResume.java:44)
at reactor.core.publisher.MonoOnErrorResume.subscribe(MonoOnErrorResume.java:44)
at reactor.core.publisher.Mono.subscribe(Mono.java:2769)
at reactor.core.publisher.MonoIgnoreThen$ThenIgnoreMain.drain(MonoIgnoreThen.java:165)
at reactor.core.publisher.MonoIgnoreThen.subscribe(MonoIgnoreThen.java:56)
at reactor.core.publisher.Mono.subscribe(Mono.java:2769)
at org.springframework.http.server.reactive.ServletHttpHandlerAdapter.service(ServletHttpHandlerAdapter.java:116)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:198)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:478)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:140)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:80)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:342)
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:799)
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66)
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:868)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1455)
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Thread.java:745)
这是我的配置: - Spring 启动 2.0.0.M3(Spring 5.0.0.RC3)。 - Spring Webflux
用Spring5这样提供重定向属性是不可能的吗?有没有其他方法可以做到这一点,或者这是一个错误?
我不完全确定它在 Spring 5 中是如何工作的。但是,从根本上说,当您重定向到另一个 URL 时,它会成为对 HTTP 服务器的新请求。这意味着,服务器需要新重定向请求中的所有必需属性和参数才能访问它。
我认为,这就是您的问题所在,您的控制器期望参数由于使用重定向生成的新请求而丢失。尝试找到一种方法来转发此请求,而不是重定向。这将携带您的终端控制器请求中的所有原始属性。
我不确定我是否能正确理解问题并能说明问题的解决方法。
您正在尝试使用 org.springframework.web.servlet.mvc.support.RedirectAttributes
,一个 Spring MVC class - 在 Spring WebFlux 中。这行不通。
我不知道 WebFlux 中有任何等效项,这可能是一个增强请求。
如答案中所述,RedirectAttributes 等价物目前似乎不存在于 Spring Webflux 中。
我在 Spring 打开了一个 JIRA 以寻求改进,这里是 link 如果有人也有兴趣获得关于这一点的更新:https://jira.spring.io/browse/SPR-16026