且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

无描述符的Jersey Servlet容器在Servlet 3.x容器中作为过滤器运行

更新时间:2023-12-03 13:50:16

它是可能的,但是不像设置一些配置属性那样简单.如果您对它的实际工作方式有所了解,将会有所帮助.在Servlet 3.x中,引入了ServletContainerInitializer,我们可以实现该ServletContainerInitializer以动态地加载servlet(在此处进一步讨论) .泽西岛具有其使用的实现.但是它遵循JAX-RS,JAX-RS指出应将应用程序作为servlet加载.因此,泽西岛(Jersey)没有提供任何解决方案.

It's possible, but not gonna be as easy as just setting some config property. It would help if you understand a little about how it actually works. With Servlet 3.x, introduced a ServletContainerInitializer that we can implement to load servlets dynamically (this is discussed further here). Jersey has an implementation that it uses. But it follows the JAX-RS which says that the application should be loaded as a servlet. So Jersey doesn't doesn't offer any way around this.

我们可以编写我们自己的ServletContainerInitializer,也可以只使用泽西岛的.泽西岛(Jersey)有一个我们可以实现的SerletContainerProvider.我们需要自己注册servlet过滤器.实现看起来像这样

We could write our own ServletContainerInitializer or we can just tap into Jersey's. Jersey has a SerletContainerProvider we can implement. We would need to register the servlet filter ourselves. The implementation would look something like this

@Override
public void preInit(ServletContext context, Set<Class<?>> classes) throws ServletException {
    final Class<? extends Application> applicationCls = getApplicationClass(classes);
    if (applicationCls != null) {
        final ApplicationPath appPath = applicationCls.getAnnotation(ApplicationPath.class);
        if (appPath == null) {
            LOGGER.warning("Application class is not annotated with ApplicationPath");
            return;
        }
        final String mapping = createMappingPath(appPath);
        addFilter(context, applicationCls, classes, mapping);
        // to stop Jersey servlet initializer from trying to register another servlet
        classes.remove(applicationCls);
    }
}

private static void addFilter(ServletContext context, Class<? extends Application> cls,
                              Set<Class<?>> classes, String mapping) {
    final ResourceConfig resourceConfig = ResourceConfig.forApplicationClass(cls, classes);
    final ServletContainer filter = new ServletContainer(resourceConfig);
    final FilterRegistration.Dynamic registration = context.addFilter(cls.getName(), filter);
    registration.addMappingForUrlPatterns(null, true, mapping);
    registration.setAsyncSupported(true);
}

实施后,我们需要创建一个文件

Once we have our implementation, we need to create a file

META-INF/services/org.glassfish.jersey.servlet.internal.spi.ServletContainerProvider

应位于类路径的根目录.该文件的内容应该是我们实施的完全限定名称.

Which should be at the root of the class path. The contents of that file should be the fully qualified name of our implementation.

您可以在此 GitHub存储库