Vaadin Flow的Beverage Buddy App(源码https://vaadin.com/start/lts/simple-ui)的持久

请教这个vaadin10demo的持久化问题,源码里的假数据采用静态的方式,被业务类调用,然后我想使用springdatajpa+herbernate的方式对数据进行持久化,发现很难初始化时注入数据,因为交给spring管理的对象依赖注入时,不能是静态的,这该怎么处理?

你是指在app启动时存入一些初始数据吗?

** Zhang ZhiKe:**
你是指在app启动时存入一些初始数据吗?

你好,是的,Demo里本来是假数据,我改成存储在mysql中,那么app启动时渲染界面肯定需要从数据库查询传入数据,v10初始化界面都是空参构造,我怎么传入数据呢

应该是在WEB容器启动后,你的应用被浏览器打开之前就要完成存储初始数据吧。
注册一个VaadinServiceInitListenner,实现serviceInit,在那里就可以存储你的初始数据了。
你反正用的是Spring Data JPA,那就用可以用JpaRepository存数据,还不用写SQL,连Session都不用取。

要是你用的是Spring Boot,你就写一个InitialBean,在bean里完成初始数据的持久化。

** Zhang ZhiKe:**
应该是在WEB容器启动后,你的应用被浏览器打开之前就要完成存储初始数据吧。
注册一个VaadinServiceInitListenner,实现serviceInit,在那里就可以存储你的初始数据了。
你反正用的是Spring Data JPA,那就用可以用JpaRepository存数据,还不用写SQL,连Session都不用取。

要是你用的是Spring Boot,你就写一个InitialBean,在bean里完成初始数据的持久化。

应该是照老兄指导的这思路来传入数据,我试了一下,还是没传成功,是不是注册的方式不对,我就在原来的基础上implement VaadinServiceInitListenner,
然后重写了init方法,还缺哪一步,希望指导一下

@Route(value = "categories", layout = MainLayout.class)
@PageTitle("Categories List")
public class CategoriesList extends VerticalLayout implements VaadinServiceInitListener {

    @Autowired
    private CategoryService categoryService;

    @Autowired
    private ReviewService reviewService;

    private final TextField searchField = new TextField("", "Search categories");
    private final H2 header = new H2("Categories");
    private final Grid<Category> grid = new Grid<>();
    private CategoryEditorDialog form;

    public CategoriesList() {

    }

    @Override
    public void serviceInit(ServiceInitEvent event) {
        form = new CategoryEditorDialog(
                this::saveCategory, this::deleteCategory, this.categoryService, reviewService);
        initView();
        addSearchBar();
        addContent();
        updateView(categoryService);
    }

Bill Li:

** Zhang ZhiKe:**
应该是在WEB容器启动后,你的应用被浏览器打开之前就要完成存储初始数据吧。
注册一个VaadinServiceInitListenner,实现serviceInit,在那里就可以存储你的初始数据了。
你反正用的是Spring Data JPA,那就用可以用JpaRepository存数据,还不用写SQL,连Session都不用取。

要是你用的是Spring Boot,你就写一个InitialBean,在bean里完成初始数据的持久化。

应该是照老兄指导的这思路来传入数据,我试了一下,还是没传成功,是不是注册的方式不对,我就在原来的基础上implement VaadinServiceInitListenner,
然后重写了init方法,还缺哪一步,希望指导一下

@Route(value = "categories", layout = MainLayout.class)
@PageTitle("Categories List")
public class CategoriesList extends VerticalLayout implements VaadinServiceInitListener {

    @Autowired
    private CategoryService categoryService;

    @Autowired
    private ReviewService reviewService;

    private final TextField searchField = new TextField("", "Search categories");
    private final H2 header = new H2("Categories");
    private final Grid<Category> grid = new Grid<>();
    private CategoryEditorDialog form;

    public CategoriesList() {

    }

    @Override
    public void serviceInit(ServiceInitEvent event) {
        form = new CategoryEditorDialog(
                this::saveCategory, this::deleteCategory, this.categoryService, reviewService);
        initView();
        addSearchBar();
        addContent();
        updateView(categoryService);
    }

这个是导航类,是不是需要在这边发布事件

@HtmlImport("frontend://styles/shared-styles.html")
@Viewport("width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes")
//@Component("mainLayout")
public class MainLayout extends Div
        implements RouterLayout, PageConfigurator {


    public MainLayout() {
        H2 title = new H2("Beverage Buddy");
        title.addClassName("main-layout__title");

        RouterLink reviews = new RouterLink(null, ReviewsList.class);
        reviews.add(new Icon(VaadinIcon.LIST), new Text("Reviews"));
        reviews.addClassName("main-layout__nav-item");
        // Only show as active for the exact URL, but not for sub paths
        reviews.setHighlightCondition(HighlightConditions.sameLocation());

        RouterLink categories = new RouterLink(null, CategoriesList.class);
        categories.add(new Icon(VaadinIcon.ARCHIVES), new Text("Categories"));
        categories.addClassName("main-layout__nav-item");

        Div navigation = new Div(reviews, categories);
        navigation.addClassName("main-layout__nav");

        Div header = new Div(title, navigation);
        header.addClassName("main-layout__header");
        add(header);

        addClassName("main-layout");
    }

    @Override
    public void configurePage(InitialPageSettings settings) {
        settings.addMetaTag("apple-mobile-web-app-capable", "yes");
        settings.addMetaTag("apple-mobile-web-app-status-bar-style", "black");
    }
}

还不是VaadinServiceInitService,是这个:
https://vaadin.com/docs/v13/flow/advanced/tutorial-flow-runtime-configuration.html

@WebServlet(
        urlPatterns = "/*",
        initParams = {
                @WebInitParam(name = "frontend.url.es6", value = "http://mydomain.com/es6/"),
                @WebInitParam(name = "frontend.url.es5", value = "http://mydomain.com/es5/") }
)
@VaadinServletConfiguration(productionMode = false)
public class MyInitServlet extends VaadinServlet {
    @Override
    protected void servletInitialized() throws ServletException {
        super.servletInitialized();
        System.out.println("Do Some Thing");
    }
}

Do Some Thing你就开始存数据了。。。

@WebServlet(urlPatterns = "/*", name = "MyUIServlet", asyncSupported = true)
	@VaadinServletConfiguration(ui = MainUI.class, productionMode = false)
	public static class MyUIServlet extends VaadinServlet {

		/**
		 * 
		 */
		private static final long serialVersionUID = 1L;
	}

一般vaadin的MainUI都要extends VaadinServlet ,这个Demo里的mainlayout怎么没继承,也能打开界面啊

** Zhang ZhiKe:**
还不是VaadinServiceInitService,是这个:
https://vaadin.com/docs/v13/flow/advanced/tutorial-flow-runtime-configuration.html

@WebServlet(
        urlPatterns = "/*",
        initParams = {
                @WebInitParam(name = "frontend.url.es6", value = "http://mydomain.com/es6/"),
                @WebInitParam(name = "frontend.url.es5", value = "http://mydomain.com/es5/") }
)
@VaadinServletConfiguration(productionMode = false)
public class MyInitServlet extends VaadinServlet {
    @Override
    protected void servletInitialized() throws ServletException {
        super.servletInitialized();
        System.out.println("Do Some Thing");
    }
}

Do Some Thing你就开始存数据了。。。

老兄,我发现了更简单的方法,在视图入口类直接带参注入,就能在app一启动的时候传入数据了,下面是代码

@HtmlImport("frontend://styles/shared-styles.html")
@Viewport("width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes")
public class MainLayout extends Div
        implements RouterLayout, PageConfigurator {

    public MainLayout(@Autowired CategoryService categoryService, @Autowired ReviewService reviewService) {
        H2 title = new H2("Beverage Buddy");
        title.addClassName("main-layout__title");

        RouterLink reviews = new RouterLink(null, ReviewsList.class);
        reviews.add(new Icon(VaadinIcon.LIST), new Text("Reviews"));
        reviews.addClassName("main-layout__nav-item");
        // Only show as active for the exact URL, but not for sub paths
        reviews.setHighlightCondition(HighlightConditions.sameLocation());

        RouterLink categories = new RouterLink(null, CategoriesList.class);
        categories.add(new Icon(VaadinIcon.ARCHIVES), new Text("Categories"));
        categories.addClassName("main-layout__nav-item");

        Div navigation = new Div(reviews, categories);
        navigation.addClassName("main-layout__nav");

        Div header = new Div(title, navigation);
        header.addClassName("main-layout__header");
        add(header);

        addClassName("main-layout");
    }


@Route(value = "categories", layout = MainLayout.class)
@PageTitle("Categories List")
@UIScope
public class CategoriesList extends VerticalLayout {

    private CategoryService categoryService;

    private ReviewService reviewService;

    private final TextField searchField = new TextField("", "Search categories");
    private final H2 header = new H2("Categories");
    private final Grid<Category> grid = new Grid<>();
    private CategoryEditorDialog form;

    public CategoriesList(@Autowired CategoryService categoryService,@Autowired ReviewService reviewService) {
        this.categoryService = categoryService;
        this.reviewService = reviewService;
        form = new CategoryEditorDialog("category",
                this::saveCategory, this::deleteCategory,this.categoryService);
        initView();
        addSearchBar();
        addContent();
        updateView(categoryService);
    }

    private void initView() {
        addClassName("categories-list");
        setDefaultHorizontalComponentAlignment(Alignment.STRETCH);
    }

Bill Li:

** Zhang ZhiKe:**
还不是VaadinServiceInitService,是这个:
https://vaadin.com/docs/v13/flow/advanced/tutorial-flow-runtime-configuration.html

@WebServlet(
        urlPatterns = "/*",
        initParams = {
                @WebInitParam(name = "frontend.url.es6", value = "http://mydomain.com/es6/"),
                @WebInitParam(name = "frontend.url.es5", value = "http://mydomain.com/es5/") }
)
@VaadinServletConfiguration(productionMode = false)
public class MyInitServlet extends VaadinServlet {
    @Override
    protected void servletInitialized() throws ServletException {
        super.servletInitialized();
        System.out.println("Do Some Thing");
    }
}

Do Some Thing你就开始存数据了。。。

老兄,我发现了更简单的方法,在视图入口类直接带参注入,就能在app一启动的时候传入数据了,下面是代码

@HtmlImport("frontend://styles/shared-styles.html")
@Viewport("width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes")
public class MainLayout extends Div
        implements RouterLayout, PageConfigurator {

    public MainLayout(@Autowired CategoryService categoryService, @Autowired ReviewService reviewService) {
        H2 title = new H2("Beverage Buddy");
        title.addClassName("main-layout__title");

        RouterLink reviews = new RouterLink(null, ReviewsList.class);
        reviews.add(new Icon(VaadinIcon.LIST), new Text("Reviews"));
        reviews.addClassName("main-layout__nav-item");
        // Only show as active for the exact URL, but not for sub paths
        reviews.setHighlightCondition(HighlightConditions.sameLocation());

        RouterLink categories = new RouterLink(null, CategoriesList.class);
        categories.add(new Icon(VaadinIcon.ARCHIVES), new Text("Categories"));
        categories.addClassName("main-layout__nav-item");

        Div navigation = new Div(reviews, categories);
        navigation.addClassName("main-layout__nav");

        Div header = new Div(title, navigation);
        header.addClassName("main-layout__header");
        add(header);

        addClassName("main-layout");
    }


@Route(value = "categories", layout = MainLayout.class)
@PageTitle("Categories List")
@UIScope
public class CategoriesList extends VerticalLayout {

    private CategoryService categoryService;

    private ReviewService reviewService;

    private final TextField searchField = new TextField("", "Search categories");
    private final H2 header = new H2("Categories");
    private final Grid<Category> grid = new Grid<>();
    private CategoryEditorDialog form;

    public CategoriesList(@Autowired CategoryService categoryService,@Autowired ReviewService reviewService) {
        this.categoryService = categoryService;
        this.reviewService = reviewService;
        form = new CategoryEditorDialog("category",
                this::saveCategory, this::deleteCategory,this.categoryService);
        initView();
        addSearchBar();
        addContent();
        updateView(categoryService);
    }

    private void initView() {
        addClassName("categories-list");
        setDefaultHorizontalComponentAlignment(Alignment.STRETCH);
    }

666
不过初始化数据的存放,我个人比较喜欢在容器启动时在相关的地方进行

注册一个VaadinServiceInitListenner,实现serviceInit,在那里就可以存储你的初始数据了。 你反正用的是Spring Data JPA,那就用可以用JpaRepository存数据,还不用写SQL,连Session都不用取。
[teatv download]
(https://teatv.ltd/)
[hellodear.in]
(https://hellodear.in)