【问题标题】:How to setup a RequestHandler for images with VaadinServlet如何使用 VaadinServlet 为图像设置 RequestHandler
【发布时间】:2015-07-18 04:02:15
【问题描述】:

我希望有一个RequestHandler 能够在myDomain/images/id8938748.jpg 上动态创建图像,同时通过标准VaadinServlet 处理所有其他流量。为此,我知道我需要将RequestHandler 放入VaadinServlet 作为explained here,方法是:

public class MyCustomServlet extends VaadinServlet 
{
        @Override
        protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException 
        {
            getService().addSessionInitListener(new SessionInitListener() 
            {
                @Override
                public void sessionInit(SessionInitEvent event) throws ServiceException 
                {
                    event.getSession().addRequestHandler(myCustomRequestHandlerForImages);
                }
            });
        }
}

我的问题是如何注册新的MyCustomServlet?我在web.xml 中查看了它,但我似乎无法做到正确。

我的RequestHandler 很简单:

@Override
public boolean handleRequest(VaadinSession session, VaadinRequest request, VaadinResponse response) throws IOException 
{
    System.out.println("Test it's being called");
}

对于web.xml,我有:

<servlet>
    <servlet-name>MyCustomVaadinServlet</servlet-name>
    <servlet-class>
        com.test.MyCustomVaadinServlet
    </servlet-class>
</servlet>

<servlet-mapping>
    <servlet-name>MyCustomVaadinServlet</servlet-name>
    <url-pattern>/images/*</url-pattern>
</servlet-mapping>

然后我在 UI 代码中定义了另一个 Servlet 并带有注释:

public class MyUI extends UI
{
  @WebServlet(value = "/*", asyncSupported = true)
  @VaadinServletConfiguration(productionMode = false, ui = MyUI.class, widgetset = "com.MyWidgetSet")
    public static class Servlet extends VaadinServlet 
  {
  }
  ...
}

当我调用域本身时,一切都按预期工作,我的 Vaadin 应用程序也能正常工作。但是当我调用 domain/images 或 domain/images/randomText 时,我得到一个空页面,并且不会输出 System.out.println 语句。基本上不会调用RequestHandler

我也尝试过映射到/images/*/app/* 之类的方法,但这并没有什么区别...

【问题讨论】:

    标签: javascript java jakarta-ee vaadin vaadin7


    【解决方案1】:

    如果您使用 Image 组件在您的 Vaadin UI 中显示这些图像,您可以使用 Resource。有几种可用的资源实现:

    • ThemeResource:将您的文件(例如图像)添加到您的主题中并使用它来引用图像。
    • ÈxternalResource:URL 上的文件。
    • ClassResource:类路径中的一个文件,Vaadin servlet 将该文件提供给浏览器。
    • FileResource:服务器文件系统上的一个文件。 Vaadin servlet 将文件提供给浏览器。
    • StreamResource:从InputStream 生成文件。 Vaadin servlet 将文件提供给浏览器。

      Image image = new Image();
      image.setSource(new ThemeResource("path/is/relative/to/the/theme/folder.png"));
      

    一个有效的替代方法是创建一个常规的 servlet 来生成和提供文件。然后,您不能再将 Vaadin Servlet 映射到上下文根。然后您可以使用 ExternalResource 来引用您的 Vaadin 代码中的文件:

    Image image = new Image();
    image.setSource(new ExternalResource("/images/id8938748.jpg"));
    

    您的 servlet 映射如下所示:

    <servlet-mapping>
      <servlet-name>MyImageServlet</servlet-name>
      <url-pattern>/images/*</url-pattern>
    </servlet-mapping>
    
    <servlet-mapping>
      <servlet-name>MyVaadinServlet</servlet-name>
      <url-pattern>/ui/*</url-pattern>
    </servlet-mapping>
    
    <servlet-mapping>
      <servlet-name>MyVaadinServlet</servlet-name>
      <url-pattern>/VAADIN/*</url-pattern>
    </servlet-mapping>
    

    【讨论】:

    • 我正在尝试直接链接图像而不是在 UI 中。内部的 UI 非常简单。我想在 Vaadin 中执行此操作,以便我可以利用会话管理(您只能看到您的图像)并因此使用相同的会话身份验证。现在我确实尝试按照您的建议使用 servlet 映射来执行此操作,但它对我不起作用。我试图删除通配符并执行 /images/* 和 /app/* (最后一行问题)但这没有用。请求处理程序从未被调用...
    • @StephaneGrenier 从同一个war文件部署的Servlet共享同一个HttpSession,因此可以用来存储用户信息。
    • 这正是我想使用 Servlet 的原因;)
    【解决方案2】:

    我认为不是正确的唯一解决方案是创建另一个 UI 类,这样:

    public class MyImagesUI extends UI 
    {
        @WebServlet(value = "/images/*", asyncSupported = true)
        @VaadinServletConfiguration(productionMode = false, ui = MyImagesUI.class, widgetset = "com.MyWidgetset")
        public static class Servlet extends VaadinServlet 
        {
        }
    
        @Override
        protected void init(VaadinRequest request) 
        {
            VaadinSession.getCurrent().addRequestHandler(new RequestHandler() 
            {
                @Override
                public boolean handleRequest(VaadinSession session, VaadinRequest request, VaadinResponse response) throws IOException 
                {
                    System.out.println("Test output");
                }
            });
        }
    }
    

    此代码确实有效,并将输出显示到控制台。从那里我可以response.setContentType("...") 并按照我的需要做,它也能正常工作。

    现在我的理解是,这不是“正确的方式”,正确的方式是通过Servlet,但同时这确实很有效。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-06-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-09-02
      • 1970-01-01
      相关资源
      最近更新 更多