当我将组件添加到Vaadin的组件(如TabSheet或Tree)时,添加的组件将被缓存。当用户单击选项卡(或树节点)时,如果它包含db数据,它将显示陈旧的数据,而不是反映最新的db状态。
我想知道是否有办法确保加载最新的数据?
我通过定义自定义接口来解决这个问题:
public interface Reloadable {
void reload();
}每个组件都实现了这个可重加载的接口,例如:
@SpringComponent
public class TeachersView extends VerticalLayout implements Reloadable, Serializable {
@Inject
private TeacherDao teacherDao;
private final static int PAGESIZE = 10;
private MTable<Teacher> mTable = new MTable<>(Teacher.class);
@PostConstruct
public void init() {
// mTable settings skip here
reload();
addComponent(mTable);
}
@Override
public void reload() {
mTable.setBeans(new SortableLazyList<>(
sortablePagingProvider ,
() -> (int) teacherDao.count() ,
PAGESIZE
));
}
private SortableLazyList.SortablePagingProvider<Teacher> sortablePagingProvider =
(firstRow, asc, sortProperty) -> {
return teacherDao.findAll(
new PageRequest(
firstRow / PAGESIZE, PAGESIZE,
asc ? Sort.Direction.ASC : Sort.Direction.DESC,
sortProperty == null ? "id" : sortProperty
)
).getContent();
};
}这个视图被注入到UI类中:
@SpringUI(path = "/ui")
@Theme("valo")
public class VaadinUI extends UI {
@Inject
private TeacherDao teacherDao;
@Inject
private TeachersView teachersView;
@Override
protected void init(VaadinRequest vaadinRequest) {
Panel panel = new Panel("Admin Panel");
HorizontalSplitPanel splitPanel = new HorizontalSplitPanel();
splitPanel.setSplitPosition(15, Unit.PERCENTAGE);
panel.setContent(splitPanel);
Tree tree = new Tree("Menu");
splitPanel.setFirstComponent(tree);
Label home = new Label("Home");
Map<String, Component> map = new HashMap<>();
map.put("Teachers", teachersView);
map.put("Home", home);
map.forEach((k, v) -> tree.addItem(k));
tree.addItemClickListener(event -> {
Component view = map.get(event.getItemId());
if (view instanceof Reloadable) {
((Reloadable) view).reload();
}
splitPanel.setSecondComponent(view);
});
splitPanel.setSecondComponent(home);
setContent(panel);
} // init()
}注意tree.addItemClickListener,我必须检查每个组件是否实现了Reloadable,如果为真,则调用它。
起作用了。但我不知道这是否是标准的实现这一目标的方式?我认为这应该是一个常见的场景,应该有类似于内置接口的组件来实现,比如onRender (但我找不到)。我错过什么了吗?
谢谢。
发布于 2016-03-10 11:40:14
首先,我将建议您可能已经看到的关于Spring & Vaadin的本教程,但是我将在几个地方引用它,我认为它是Vaadin & Spring集成的一个好起点。
第二,出于好奇,你为什么要用树来构建菜单?
在提供的示例中,您似乎在对某些视图特性(已经是以Vaadin提供 )之间的导航进行建模,并且由于您使用的是春天,所以Vaadin 春天 & 弹簧靴扩展使在视图之间定义和导航变得非常容易。然后,您可以在各自的enter()方法中为每个视图定义一些特定的行为。我使用Vaadin仪表板演示作为对以下更改的灵感:
@SpringView(name = TeachersView.NAME)
public class TeachersView extends VerticalLayout implements View {
public static final String NAME = "Teachers";
private Label title = new Label("Teachers view");
@PostConstruct
void init() {
addComponent(title);
}
@Override
public void enter(ViewChangeListener.ViewChangeEvent event) {
// recreate or reload stuff here
title.setValue("Teachers view reloaded @ " + new Date());
}
}@SpringView(name = HomeView.NAME)
public class HomeView extends VerticalLayout implements View {
public static final String NAME = "";
@PostConstruct
void init() {
addComponent(new Label("Home"));
}
@Override
public void enter(ViewChangeListener.ViewChangeEvent event) {
// meh, nothing special to do here
}
}public class SpringVaadinUI extends UI {
@Autowired
private SpringViewProvider viewProvider;
@Override
protected void init(VaadinRequest vaadinRequest) {
addStyleName(ValoTheme.UI_WITH_MENU);
Panel panel = new Panel("Admin Panel");
HorizontalSplitPanel splitPanel = new HorizontalSplitPanel();
splitPanel.setSplitPosition(15, Unit.PERCENTAGE);
panel.setContent(splitPanel);
VerticalLayout navigationBar = new VerticalLayout();
navigationBar.setPrimaryStyleName(ValoTheme.MENU_ROOT);
navigationBar.addComponent(createNavigationButton("Home", FontAwesome.HOME, HomeView.NAME));
navigationBar.addComponent(createNavigationButton("Teachers", FontAwesome.GROUP, TeachersView.NAME));
splitPanel.setFirstComponent(navigationBar);
CssLayout navigationDisplay = new CssLayout();
splitPanel.setSecondComponent(navigationDisplay);
Navigator navigator = new Navigator(this, navigationDisplay);
navigator.addProvider(viewProvider);
setContent(panel);
}
private Button createNavigationButton(String caption, FontAwesome icon, final String viewName) {
Button button = new Button(caption, icon);
button.setPrimaryStyleName(ValoTheme.MENU_ITEM);
button.addStyleName(ValoTheme.BUTTON_SMALL);
button.addStyleName(ValoTheme.BUTTON_BORDERLESS);
button.addClickListener(event -> getUI().getNavigator().navigateTo(viewName));
return button;
}
}其结果类似于:

如果由于某种原因不能或不想使用导航器,那么您的解决方案看起来很好。尽管如此,无论您选择使用哪种解决方案,您都应该知道默认情况下 Spring创建了单身汉。除了一些UI之外,您可能应该将组件更改为原型,这样每次都会得到一个新实例。否则,所有用户在访问应用程序时都会得到相同的实例,我认为您不希望发生这种情况。
https://stackoverflow.com/questions/35908702
复制相似问题