我正在使用SpringBoot(1.5.6.RELEASE)和Vaadin(8.1.4)创建一个Web应用程序。
我有一个Vaadin View,这是我注释的enter
方法:
@SpringView(name = UserListViewVaadinInit.VIEW_NAME, ui = { WebUI.class })
public class UserListViewVaadinInit extends VerticalLayout implements View {
[...]
@Override
@PreAuthorize("hasRole('ROLE_admin')")
public void enter(ViewChangeEvent event) {
// trigger the presenter to fill the view with data
eventBus.publish(this, new ViewEnteredEvent(event));
}
}
这部分工作正常:当没有ROLE_admin
权限的用户尝试访问视图时,会抛出AccessDeniedException
。
当抛出异常时,我希望将用户重定向到HomeView
(我稍后会添加一个正确的AccessDeniedView
)。所以我尝试了以下内容:
@SpringUI(path = WebUI.PATH)
public class WebUI extends UI {
@Override
protected void init(VaadinRequest request) {
setErrorHandler(event -> {
if (event.getThrowable() instanceof AccessDeniedException) {
getNavigator().navigateTo(HomeView.VIEW_NAME);
}
});
// do some other initialization stuff
[...]
}
[...]
}
ErrorHandler
被正确触发,但navigateTo
抛出异常(只有相关部分):
java.lang.IllegalArgumentException:类没有SpringView注释或别名 在org.springframework.util.Assert.notNull(Assert.java:134)〜[spring-core-4.3.10.RELEASE.jar:4.3.10.RELEASE] 在com.vaadin.spring.navigator.SpringViewProvider.isViewValidForCurrentUI(SpringViewProvider.java:363)〜[vaadin-spring-2.0.1.jar:2.0.1] 在com.vaadin.spring.navigator.SpringViewProvider.getAllViewsForCurrentUI(SpringViewProvider.java:231)〜[vaadin-spring-2.0.1.jar:2.0.1] 在com.vaadin.spring.navigator.SpringViewProvider.getAllowedViewsForCurrentUI(SpringViewProvider.java:250)~ [vaadin-spring-2.0.1.jar:2.0.1] 在com.vaadin.spring.navigator.SpringViewProvider.getViewName(SpringViewProvider.java:307)〜[vaadin-spring-2.0.1.jar:2.0.1] 在com.vaadin.navigator.Navigator.getViewProvider(Navigator.java:1145)〜[vaadin-server-8.1.5.jar:8.1.5] 在com.vaadin.navigator.Navigator.navigateTo(Navigator.java:534)〜[vaadin-server-8.1.5.jar:8.1.5] 在de.teamsped.webapp.ui.WebUI.lambda $ init $ a1d28b15 $ 1(WebUI.java:57)〜[main /:na]
我们来看看isViewValidForCurrentUI
:
protected boolean isViewValidForCurrentUI(ViewInfo viewInfo) {
String beanName = viewInfo.getBeanName();
try {
final Class<?> type = getWebApplicationContext().getType(beanName);
Assert.isAssignable(View.class, type,
"bean did not implement View interface");
final UI currentUI = UI.getCurrent();
final SpringView annotation = AnnotatedElementUtils.findMergedAnnotation(type, SpringView.class);
Assert.notNull(annotation,
"class did not have a SpringView annotation or an alias for it");
[...]
}
我调查过,getWebApplicationContext().getType(beanName);
(beanName
为userListViewVaadinInit
)似乎返回了一个没有必要SpringView
注释的代理对象。
知道为什么会这样,以及如何解决它?
修改 HomeView:
@ViewScope
@SpringView(name = HomeView.VIEW_NAME, ui={WebUI.class})
public class HomeView extends VerticalLayout implements View {
public static final String VIEW_NAME = "home";
Label label = new Label("Home");
@PostConstruct
void init() {
this.addComponent(label);
}
@Override
public void enter(ViewChangeEvent event) {
// the view is constructed in the init() method()
}
}