jersey的简单使用原理(jersey1.15版本)

本文介绍了jersey1.15版本的简单使用和原理,通过web.xml配置及源码解析,揭示了如何通过Filter拦截请求。在web.xml中声明的servlet在初始化过程中,通过MatrixServlet、Filter的注册过程,展示了jersey如何在请求到达时进行拦截,为请求处理提供预处理功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

来到新公司,看了一下框架,使用了一个jersey的RESTful的API,之前听都没听过,也不知道是个什么鸟东东,抽空看了一下他的简单使用方法和原理,记录一下。

一、web.xml配置

<servlet>
        <servlet-name>JerseyServlet</servlet-name>
        <servlet-class>
            com.xxx.servlet.MatrixServlet
        </servlet-class>
        <init-param>
            <param-name>com.sun.jersey.spi.container.ContainerRequestFilters</param-name>
            <param-value>com.xxx.InternalAuthResourceFilter</param-value>
        </init-param>
        <init-param>
            <param-name>com.sun.jersey.spi.container.ResourceFilters</param-name>
            <param-value>com.xxx.RoleApiResourceFilterFactor</param-value>
        </init-param>
</servlet>
<servlet-mapping>
        <servlet-name>JerseyServlet</servlet-name>
        <url-pattern>/*</url-pattern>
</servlet-mapping>

二、源码解析

1、首先在web.xml中声明一个servlet,然后在这个servlet中初始化了两个Filter。我们都知道Filter是拦截请求的,那么问题来了,这两个Filter不是显示的初始声明在web.xml中的,那么他们是怎么起到拦截请求的作用的呢。
进入到MatrixServlet中发现他的继承关系是这样的:
在这里插入图片描述
2、首先我们都知道,servlet要是实现javax.servlet接口,web容器在初始化servlet的时候都会调用次接口的init()方法。我们在MatrixServlet中重写它的init()方法:

/**
     * Initiate the Web component.
     *
     * @param webConfig the Web configuration.
     *
     * @throws javax.servlet.ServletException in case of an initialization failure
     */
    protected void init(WebConfig webConfig) throws ServletException {
        webComponent = (app == null)
                ? new InternalWebComponent()
                : new InternalWebComponent(app);
        webComponent.init(webConfig);
    }

3、在init()方法中调用一下webComponent.init(webConfig)方法初始化web容器。进入到对应方法内,代码如下:

/**
     * Initiate the Web component.
     *
     * @param webConfig the Web configuration.
     * @throws javax.servlet.ServletException in case of any initialization error
     */
    public void init(WebConfig webConfig) throws ServletException {
        config = webConfig;

        if (resourceConfig == null)
            resourceConfig = createResourceConfig(config);

        if (config.getConfigType() == WebConfig.ConfigType.FilterConfig &&
                resourceConfig.getFeature(ServletContainer.FEATURE_FILTER_FORWARD_ON_404)) {
            useSetStatusOn404 = true;
        }

        load();

        Object o = resourceConfig.getProperties().get(
                ResourceConfig.PROPERTY_CONTAINER_NOTIFIER);
        if (o instanceof List) {
            List list = (List) o;
            for (Object elem : list) {
                if (elem instanceof ContainerNotifier) {
                    ContainerNotifier crf = (ContainerNotifier) elem;
                    crf.addListener(this);
                }
            }
        } else if (o instanceof ContainerNotifier) {
            ContainerNotifier crf = (ContainerNotifier) o;
            crf.addListener(this);
        }
    }

4、我们发现其中都是根据加载到的config进行容器配置,此文的目的是找到两个Filter是怎么注册到容器中的,所以相关配置就不讨论了。我们发现此方法中有一个load()方法,进入到load()方法,代码如下:

/**
     * Load the Web application. This will create, configure and initiate
     * the web application.
     */
    public void load() {
        WebApplication _application = create();
        configure(config, resourceConfig, _application);
        initiate(resourceConfig, _application);
        application = _application;
    }

5、发现是进行WebApplication的创建和配置,其中有一步initiate(resourceConfig, _application),进入到此方法内,代码如下:

/**
     * Initiate the {@link WebApplication}.
     * <p/>
     * This method will be called once at initiation and for
     * each reload of the Web application.
     * <p/>
     * An inheriting class may override this method to initiate the
     * Web application with different parameters.
     *
     * @param rc the Resource configuration
     * @param wa the Web application
     */
    protected void initiate(ResourceConfig rc, WebApplication wa) {
        wa.initiate(rc);
    }

6、继续进入代码:

@Override
public void initiate(final ResourceConfig rc, final IoCComponentProviderFactory _provider) {
    Errors.processWithErrors(new Errors.Closure<Void>() {
        @Override
        public Void f() {
            Errors.setReportMissingDependentFieldOrMethod(false);
            _initiate(rc, _provider);
            return null;
        }
    });
}

7、发现调用的是另一个_initiate(rc, _provider)方法,此方法有点长,几百行,所以只列出需要的部分代码,在1252行有这样一句代码:

filterFactory.init(resourceConfig);

8、进入到此方法:

public void init(ResourceConfig resourceConfig) {
	  // Initiate request filters
	   requestFilters.addAll(
	       getFilters(ContainerRequestFilter.class,resourceConfig.getContainerRequestFilters())
	   );
	
	   requestFilters.addAll(providerServices.getServices(ContainerRequestFilter.class));
	
	   // Initiate response filters
	   responseFilters.addAll(
	       getFilters(ContainerResponseFilter.class, resourceConfig.getContainerResponseFilters())
	   );
	
	   responseFilters.addAll(providerServices.getServices(ContainerResponseFilter.class));
	
	   // Initiate resource filter factories
	   resourceFilterFactories.addAll(
	       getFilters(ResourceFilterFactory.class, resourceConfig.getResourceFilterFactories())
	   );
	   
	   resourceFilterFactories.addAll(providerServices.getServices(ResourceFilterFactory.class));
	   resourceFilterFactories.add(new AnnotationResourceFilterFactory(this));
}

9、其中有两句:

requestFilters.addAll(getFilters(ContainerRequestFilter.class,resourceConfig.getContainerRequestFilters()));
resourceFilterFactories.addAll(getFilters(ResourceFilterFactory.class, resourceConfig.getResourceFilterFactories()));

10、而两个方法中对应的第二个参数继续点进去会发现:

public static final String PROPERTY_CONTAINER_REQUEST_FILTERS = 
            "com.sun.jersey.spi.container.ContainerRequestFilters";
public List getContainerRequestFilters() {
        return getFilterList(PROPERTY_CONTAINER_REQUEST_FILTERS);
}
public static final String PROPERTY_RESOURCE_FILTER_FACTORIES =
            "com.sun.jersey.spi.container.ResourceFilters";
public List getResourceFilterFactories() {
        return getFilterList(PROPERTY_RESOURCE_FILTER_FACTORIES);
}

11、获取的就是我们在web.xml中配置的两个Filter,所以当请求来到服务器的时候,就会被这两个Filter拦截,进而就可以在这两个自定义Filter的filter()方法中实现我们对请求的校验等操作。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值