无描述符的Jersey Servlet容器在Servlet 3.x容器中作为过滤器运行 [英] Descriptor-less Jersey servlet container run as filter in Servlet 3.x container

查看:224
本文介绍了无描述符的Jersey Servlet容器在Servlet 3.x容器中作为过滤器运行的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

是否有一种方法可以在Servlet 3.x容器中以javax.servlet.Filter的身份运行不含描述符的Jersey servlet容器(2.x)?我需要与服务一起提供静态资源,因此需要使用jersey.config.servlet.filter.forwardOn404jersey.config.servlet.filter.staticContentRegex,它们仅在根据Javadoc作为过滤器运行时有效

Is there a way to run the Jersey servlet container (2.x) descriptor-less as a javax.servlet.Filter in a Servlet 3.x container? I need to serve static resources alongside my services and therefore need to use jersey.config.servlet.filter.forwardOn404 or jersey.config.servlet.filter.staticContentRegex which only work when run as a filter according to Javadoc

该属性仅在Jersey servlet容器配置为以javax.servlet.Filter运行时适用,否则该属性将被忽略.

The property is only applicable when Jersey servlet container is configured to run as a javax.servlet.Filter, otherwise this property will be ignored.

我想完全摆脱web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee 
            http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
    version="3.1">
    <display-name>My-Webservice</display-name>

    <filter>
        <filter-name>Jersey Filter</filter-name>
        <filter-class>org.glassfish.jersey.servlet.ServletContainer</filter-class>
        <init-param>
            <param-name>javax.ws.rs.Application</param-name>
            <param-value>com.foo.webservices.MyApplication</param-value>
        </init-param>
    </filter>
</web-app>

并将所有内容保存在我的自定义Application

and have everything in my custom Applicationclass

@ApplicationPath(value = "/")
public class MyApplication extends ResourceConfig
{    
    public MyApplication()
    {
        packages("com.foo.webservices.services");
        property(ServletProperties.FILTER_FORWARD_ON_404, true);
    }
}

官方文档( https://jersey.java. net/documentation/latest/deployment.html#deployment.servlet.3 )并没有说明有关过滤器的任何信息.

The official documentation (https://jersey.java.net/documentation/latest/deployment.html#deployment.servlet.3) doesn't state anything about filters unfortunately.

推荐答案

它是可能的,但是不像设置一些配置属性那样简单.如果您对它的实际工作方式有所了解,将会有所帮助.在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存储库

这篇关于无描述符的Jersey Servlet容器在Servlet 3.x容器中作为过滤器运行的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆