问题描述
例如让我有:
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
。也就是说,我宁愿在视图中失败BeforeEnterObserver
在 public 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 方法中,您将重新路由以登录,否则将触发来自父布局的 after 导航。
@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 */);
});
}
}