在 Vaadin 14 (Vaadin Flow) 中呈现 AppLayout 之前,如何在视图中的 BeforeEnterObserver 中重新路由

How can I reroute in BeforeEnterObserver in the view before AppLayout is rendered in Vaadin 14 (Vaadin Flow)

例如让我有:

public class MainView extends AppLayout {
   public MainView() {
      User user = VaadinSession.getAttribute("user");
      if(user.isCheckSomething())
          Span span = new Span("Hello " + user.getFirstname());
   }
}

如果用户尚未登录,这将失败并出现 NPE,因为从会话中获取用户将为空。现在我可以在 if(user.isCheckSomething()) 之前添加一个空检查,但理想情况下,如果用户未登录,我宁愿根本不呈现 AppLayout 。也就是说,我宁愿在视图中失败BeforeEnterObserverpublic void beforeEnter(BeforeEnterEvent event) 方法中,但是 AppLayout 在调用 beforeEnter(...) 方法之前被调用和创建。

换句话说,如果用户未通过视图登录,我如何强制完全跳过 AppLayout 的实例化,从而永远不会构造 AppLayout

根据经验,以任何方式在构造函数中使用 UI 确实不可靠,因为它尚未初始化。

AppLayout 有自己的 afterNavigation 方法,应在 BeforeEnterEvent 之后调用。

public class MainView extends AppLayout {
    @Override
    protected void afterNavigation() {
        super.afterNavigation();
        User user = VaadinSession.getAttribute("user");
        if(user.isCheckSomething())
            Span span = new Span("Hello " + user.getFirstname());
    }

因此在 beforeEnter 方法中,您将重新路由到登录,否则将触发来自父布局的后导航。

@Override
public void beforeEnter(BeforeEnterEvent event) {
    if (!isAuthenticated()) {
        event.rerouteTo(LoginView.class);
    }
}

您可以在每个视图中实施 BeforeEnterObserver 并反复检查用户是否经过身份验证...或者您可以执行一次:

@SpringComponent
public class AuthenticationControl implements VaadinServiceInitListener {
     @Override
    public void serviceInit(ServiceInitEvent event) {
        event.getSource().addUIInitListener(uiEvent -> {
            final UI ui = uiEvent.getUI();
            ui.addBeforeEnterListener(/* do the check here, either with a method reference or create a separate listener class */);
        });
     }
}