Vaadin 和 Spring 与 Touchkit。基于servlet和注解?

Vaadin and Spring with Touchkit. servlet and annotation based?

我有一个完全可用的 spring 和基于 spring 引导的 vaadin 应用程序。应用程序 class 现已修改为创建自定义 servlet,因此我可以在项目中同时使用 touchkit 和 spring。

我一直在关注这个 git 项目来执行此操作:git project example

public class SmartenderApplication {

public static void main(String[] args) {
    SpringApplication.run(SmartenderApplication.class, args);
}

@Bean
public VaadinServlet vaadinServlet() {
    return new SpringAwareTouchKitServlet();
}}

我修改了自定义 servlet 以遵循 vaadin 文档以使用 UI 提供程序在 touchkit UI 和浏览器回退 UI 之间进行选择

public class SpringAwareTouchKitServlet extends SpringVaadinServlet {

    TouchKitSettings touchKitSettings;
    MyUIProvider prov = new MyUIProvider();

    @Override
    protected void servletInitialized() throws ServletException {
        super.servletInitialized();
        getService().addSessionInitListener(
                new SessionInitListener() {
                    @Override
                    public void sessionInit(SessionInitEvent event)
                            throws ServiceException {
                        event.getSession().addUIProvider(prov);
                    }
                });

        touchKitSettings = new TouchKitSettings(getService());
    }
}

class MyUIProvider extends UIProvider {
    @Override
    public Class<? extends UI>
    getUIClass(UIClassSelectionEvent event) {
        String ua = event.getRequest()
                .getHeader("user-agent").toLowerCase();
        if (   ua.toLowerCase().contains("ios")) {
            return myTouchkitUI.class;
        } else {
            return myUI.class;
        }
    }
}

当我不调用这部分代码来选择 UI 提供商时,我的应用程序可以正常工作。但它总是会转到触摸套件 UI。 :

    getService().addSessionInitListener(
            new SessionInitListener() {
                @Override
                public void sessionInit(SessionInitEvent event)
                        throws ServiceException {
                    event.getSession().addUIProvider(prov);
                }
            });

我的问题是,虽然它会在 UI class 到 return 之间进行选择,但一旦它开始通过所选的 UI 代码,它就会传回最初通过 spring 自动装配的空对象。当我不选择 UI 而只是选择 touchkit 时,我认为这是有效的,我假设它必须在我的 UI 提供商选择代码中的某处,这会阻止 Spring 功能允许我的 classes to autowire 等?

嗯,UIProvider 应该管理 UI 个实例。此外,由于您正在使用 Spring(启动或不启动),它应该从 Spring 上下文中检索 bean,而不是在需要时自行创建实例:

UIProvider / DefaultUIProvider:

public UI createInstance(UICreateEvent event) {
    try {
        return event.getUIClass().newInstance();
    } catch (InstantiationException e) {
        throw new RuntimeException("Could not instantiate UI class", e);
    } catch (IllegalAccessException e) {
        throw new RuntimeException("Could not access UI class", e);
    }
}

因此,我想说的是,与其扩展简单的 UIProvider (or rather the DefaultUIProvider) you should extend the SpringUIProvider,它会从您的应用程序的 Spring 上下文中检索实例,因此自动魔法将再次开始发生。

SpringUIProvider:

@Override
public UI createInstance(UICreateEvent event) {
    final Class<UIID> key = UIID.class;
    final UIID identifier = new UIID(event);
    CurrentInstance.set(key, identifier);
    try {
        logger.debug(
                "Creating a new UI bean of class [{}] with identifier [{}]",
                event.getUIClass().getCanonicalName(), identifier);
        return webApplicationContext.getBean(event.getUIClass());
    } finally {
        CurrentInstance.set(key, null);
    }
}