JAX-RS 2:有限的线程不安全资源的自定义 @Context 注入

一则或许对你有用的小广告

欢迎加入小哈的星球 ,你将获得:专属的项目实战 / Java 学习路线 / 一对一提问 / 学习打卡/ 赠书活动

目前,正在 星球 内带小伙伴们做第一个项目:全栈前后端分离博客项目,采用技术栈 Spring Boot + Mybatis Plus + Vue 3.x + Vite 4手把手,前端 + 后端全栈开发,从 0 到 1 讲解每个功能点开发步骤,1v1 答疑,陪伴式直到项目上线,目前已更新了 204 小节,累计 32w+ 字,讲解图:1416 张,还在持续爆肝中,后续还会上新更多项目,目标是将 Java 领域典型的项目都整上,如秒杀系统、在线商城、IM 即时通讯、权限管理等等,已有 870+ 小伙伴加入,欢迎点击围观

我一直致力于使用 JAX-RS 2 在无状态的 RESTful 接口中包装有状态的 CGI/Perl Web 应用程序。除了与 CGI/Perl Web 应用程序交互的机制(考虑明智地使用 HTTP 客户端和 HTML 抓取),一个具有挑战性的方面是确保对 REST 服务的同时请求不会最终共享 CGI/Perl 应用程序会话。

每个请求都必须为特定的 webapp 用户建立和结束会话;在此期间的任何传入请求都不应与同一用户建立会话。

我最初的想法是自定义 Tomcat 的线程池执行器,以便每个线程都绑定到一个特定的用户。我在这方面取得了进展,但在与记录不足的 tomcat7-maven-plugin 斗争之后放弃了这种方法。此外,考虑到我的自定义 org.apache.catalina.Executor 如何从 标准实现中 大量“借用”,我对在如此低的级别耦合到 Tomcat 持怀疑态度。

我最终确定的方法由以下部分组成:

  • 具有两个子模块的基于 Maven 的 Spring Boot + Jersey 2 项目
    • CGI/Perl 网络应用交互库
    • JAX-RS 网络服务提供围绕该库的 RESTful 接口
  • java.util.concurrent.BlockingQueue 用于管理线程对有限用户 ID 池的访问,以及用于管理队列的自定义 Servlet 过滤器。
  • 自定义注入提供程序 ,负责通过 @Context @Inject 注释将会话注入 JAX-RS 资源。

带有 Jersey 平台的 Maven、Spring Boot 和 JAX-RS 2

这是 JAX-RS 组件的 POM 配置(交互库的父 POM 和 POM 并不令人兴奋或与手头的事情无关)。


 <?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.    apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>com.example.bdkosher/groupId>
        <artifactId>cgi-app-wrapper</artifactId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <artifactId>cgi-app-rest-api</artifactId>
    <packaging>war</packaging>
&lt;properties&gt;
    &lt;spring-boot.version&gt;1.2.4.RELEASE&lt;/spring-boot.version&gt;
    &lt;java.version&gt;1.7&lt;/java.version&gt;
&lt;/properties&gt;

&lt;dependencyManagement&gt;
    &lt;dependencies&gt;
        &lt;dependency&gt;
            &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
            &lt;artifactId&gt;spring-boot-dependencies&lt;/artifactId&gt;
            &lt;version&gt;${spring-boot.version}&lt;/version&gt;
            &lt;type&gt;pom&lt;/type&gt;
            &lt;scope&gt;import&lt;/scope&gt;
        &lt;/dependency&gt;
    &lt;/dependencies&gt;
&lt;/dependencyManagement&gt;

&lt;dependencies&gt;
    &lt;dependency&gt;
        &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
        &lt;artifactId&gt;spring-boot-starter-jersey&lt;/artifactId&gt;
    &lt;/dependency&gt;
    &lt;dependency&gt;
        &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
        &lt;artifactId&gt;spring-boot-starter-web&lt;/artifactId&gt;
        &lt;exclusions&gt;
            &lt;exclusion&gt;
                &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
                &lt;artifactId&gt;spring-boot-starter-tomcat&lt;/artifactId&gt;
            &lt;/exclusion&gt;
        &lt;/exclusions&gt;
    &lt;/dependency&gt;
    &lt;dependency&gt;
        &lt;groupId&gt;${project.groupId}&lt;/groupId&gt;
        &lt;artifactId&gt;cgi-app-interaction-library&lt;/artifactId&gt;
        &lt;version&gt;${project.version}&lt;/version&gt;
    &lt;/dependency&gt;
    &lt;dependency&gt;
        &lt;groupId&gt;commons-collections&lt;/groupId&gt;
        &lt;artifactId&gt;commons-collections&lt;/artifactId&gt;
    &lt;/dependency&gt;
    &lt;dependency&gt;
        &lt;groupId&gt;com.google.guava&lt;/groupId&gt;
        &lt;artifactId&gt;guava&lt;/artifactId&gt;
        &lt;/dependency&gt;
&lt;/dependencies&gt;
&lt;build&gt;
    &lt;finalName&gt;cgiwrapp&lt;/finalName&gt;
    &lt;plugins&gt;
        &lt;plugin&gt;
            &lt;groupId&gt;org.apache.maven.plugins&lt;/groupId&gt;
            &lt;artifactId&gt;maven-war-plugin&lt;/artifactId&gt;
            &lt;version&gt;2.6&lt;/version&gt;
            &lt;configuration&gt;
                &lt;failOnMissingWebXml&gt;false&lt;/failOnMissingWebXml&gt;
            &lt;/configuration&gt;
        &lt;/plugin&gt;
        &lt;plugin&gt;
            &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
            &lt;artifactId&gt;spring-boot-maven-plugin&lt;/artifactId&gt;
            &lt;version&gt;${spring-boot.version}&lt;/version&gt;
        &lt;/plugin&gt;
    &lt;/plugins&gt;
&lt;/build&gt;

</project>

需要强调的重要领域:

  • 因为我有自己的父 POM,所以我使用 dependencyManagement POM 导入 方法来引入 Spring Boot 依赖项。
  • 我将 maven-war-plugin 自定义为不 failOnMissingWebXml 因为我使用注释来配置我的 Servlet 应用程序并且不想创建一个空的 web.xml

我在 src/main/resources/application.properties 文件中定义了我的 CGI/Perl 应用程序用户 ID 池


 <?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.    apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>com.example.bdkosher/groupId>
        <artifactId>cgi-app-wrapper</artifactId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <artifactId>cgi-app-rest-api</artifactId>
    <packaging>war</packaging>
&lt;properties&gt;
    &lt;spring-boot.version&gt;1.2.4.RELEASE&lt;/spring-boot.version&gt;
    &lt;java.version&gt;1.7&lt;/java.version&gt;
&lt;/properties&gt;

&lt;dependencyManagement&gt;
    &lt;dependencies&gt;
        &lt;dependency&gt;
            &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
            &lt;artifactId&gt;spring-boot-dependencies&lt;/artifactId&gt;
            &lt;version&gt;${spring-boot.version}&lt;/version&gt;
            &lt;type&gt;pom&lt;/type&gt;
            &lt;scope&gt;import&lt;/scope&gt;
        &lt;/dependency&gt;
    &lt;/dependencies&gt;
&lt;/dependencyManagement&gt;

&lt;dependencies&gt;
    &lt;dependency&gt;
        &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
        &lt;artifactId&gt;spring-boot-starter-jersey&lt;/artifactId&gt;
    &lt;/dependency&gt;
    &lt;dependency&gt;
        &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
        &lt;artifactId&gt;spring-boot-starter-web&lt;/artifactId&gt;
        &lt;exclusions&gt;
            &lt;exclusion&gt;
                &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
                &lt;artifactId&gt;spring-boot-starter-tomcat&lt;/artifactId&gt;
            &lt;/exclusion&gt;
        &lt;/exclusions&gt;
    &lt;/dependency&gt;
    &lt;dependency&gt;
        &lt;groupId&gt;${project.groupId}&lt;/groupId&gt;
        &lt;artifactId&gt;cgi-app-interaction-library&lt;/artifactId&gt;
        &lt;version&gt;${project.version}&lt;/version&gt;
    &lt;/dependency&gt;
    &lt;dependency&gt;
        &lt;groupId&gt;commons-collections&lt;/groupId&gt;
        &lt;artifactId&gt;commons-collections&lt;/artifactId&gt;
    &lt;/dependency&gt;
    &lt;dependency&gt;
        &lt;groupId&gt;com.google.guava&lt;/groupId&gt;
        &lt;artifactId&gt;guava&lt;/artifactId&gt;
        &lt;/dependency&gt;
&lt;/dependencies&gt;
&lt;build&gt;
    &lt;finalName&gt;cgiwrapp&lt;/finalName&gt;
    &lt;plugins&gt;
        &lt;plugin&gt;
            &lt;groupId&gt;org.apache.maven.plugins&lt;/groupId&gt;
            &lt;artifactId&gt;maven-war-plugin&lt;/artifactId&gt;
            &lt;version&gt;2.6&lt;/version&gt;
            &lt;configuration&gt;
                &lt;failOnMissingWebXml&gt;false&lt;/failOnMissingWebXml&gt;
            &lt;/configuration&gt;
        &lt;/plugin&gt;
        &lt;plugin&gt;
            &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
            &lt;artifactId&gt;spring-boot-maven-plugin&lt;/artifactId&gt;
            &lt;version&gt;${spring-boot.version}&lt;/version&gt;
        &lt;/plugin&gt;
    &lt;/plugins&gt;
&lt;/build&gt;

</project>

并创建了一个自定义配置类,用于将这些用户检索为 java.util.Set 以避免多次指定相同用户 ID 时出现问题:


 <?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.    apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>com.example.bdkosher/groupId>
        <artifactId>cgi-app-wrapper</artifactId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <artifactId>cgi-app-rest-api</artifactId>
    <packaging>war</packaging>
&lt;properties&gt;
    &lt;spring-boot.version&gt;1.2.4.RELEASE&lt;/spring-boot.version&gt;
    &lt;java.version&gt;1.7&lt;/java.version&gt;
&lt;/properties&gt;

&lt;dependencyManagement&gt;
    &lt;dependencies&gt;
        &lt;dependency&gt;
            &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
            &lt;artifactId&gt;spring-boot-dependencies&lt;/artifactId&gt;
            &lt;version&gt;${spring-boot.version}&lt;/version&gt;
            &lt;type&gt;pom&lt;/type&gt;
            &lt;scope&gt;import&lt;/scope&gt;
        &lt;/dependency&gt;
    &lt;/dependencies&gt;
&lt;/dependencyManagement&gt;

&lt;dependencies&gt;
    &lt;dependency&gt;
        &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
        &lt;artifactId&gt;spring-boot-starter-jersey&lt;/artifactId&gt;
    &lt;/dependency&gt;
    &lt;dependency&gt;
        &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
        &lt;artifactId&gt;spring-boot-starter-web&lt;/artifactId&gt;
        &lt;exclusions&gt;
            &lt;exclusion&gt;
                &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
                &lt;artifactId&gt;spring-boot-starter-tomcat&lt;/artifactId&gt;
            &lt;/exclusion&gt;
        &lt;/exclusions&gt;
    &lt;/dependency&gt;
    &lt;dependency&gt;
        &lt;groupId&gt;${project.groupId}&lt;/groupId&gt;
        &lt;artifactId&gt;cgi-app-interaction-library&lt;/artifactId&gt;
        &lt;version&gt;${project.version}&lt;/version&gt;
    &lt;/dependency&gt;
    &lt;dependency&gt;
        &lt;groupId&gt;commons-collections&lt;/groupId&gt;
        &lt;artifactId&gt;commons-collections&lt;/artifactId&gt;
    &lt;/dependency&gt;
    &lt;dependency&gt;
        &lt;groupId&gt;com.google.guava&lt;/groupId&gt;
        &lt;artifactId&gt;guava&lt;/artifactId&gt;
        &lt;/dependency&gt;
&lt;/dependencies&gt;
&lt;build&gt;
    &lt;finalName&gt;cgiwrapp&lt;/finalName&gt;
    &lt;plugins&gt;
        &lt;plugin&gt;
            &lt;groupId&gt;org.apache.maven.plugins&lt;/groupId&gt;
            &lt;artifactId&gt;maven-war-plugin&lt;/artifactId&gt;
            &lt;version&gt;2.6&lt;/version&gt;
            &lt;configuration&gt;
                &lt;failOnMissingWebXml&gt;false&lt;/failOnMissingWebXml&gt;
            &lt;/configuration&gt;
        &lt;/plugin&gt;
        &lt;plugin&gt;
            &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
            &lt;artifactId&gt;spring-boot-maven-plugin&lt;/artifactId&gt;
            &lt;version&gt;${spring-boot.version}&lt;/version&gt;
        &lt;/plugin&gt;
    &lt;/plugins&gt;
&lt;/build&gt;

</project>

通过将此类标记为 @Component ,我可以依靠 Spring 来管理此配置并将其注入其他 bean。

最后,我使用自定义的 Jersey ResourceConfig 扩展引导了我的 Web 应用程序,并用 Spring Boot 的优点进行了装饰。


 <?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.    apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>com.example.bdkosher/groupId>
        <artifactId>cgi-app-wrapper</artifactId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <artifactId>cgi-app-rest-api</artifactId>
    <packaging>war</packaging>
&lt;properties&gt;
    &lt;spring-boot.version&gt;1.2.4.RELEASE&lt;/spring-boot.version&gt;
    &lt;java.version&gt;1.7&lt;/java.version&gt;
&lt;/properties&gt;

&lt;dependencyManagement&gt;
    &lt;dependencies&gt;
        &lt;dependency&gt;
            &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
            &lt;artifactId&gt;spring-boot-dependencies&lt;/artifactId&gt;
            &lt;version&gt;${spring-boot.version}&lt;/version&gt;
            &lt;type&gt;pom&lt;/type&gt;
            &lt;scope&gt;import&lt;/scope&gt;
        &lt;/dependency&gt;
    &lt;/dependencies&gt;
&lt;/dependencyManagement&gt;

&lt;dependencies&gt;
    &lt;dependency&gt;
        &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
        &lt;artifactId&gt;spring-boot-starter-jersey&lt;/artifactId&gt;
    &lt;/dependency&gt;
    &lt;dependency&gt;
        &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
        &lt;artifactId&gt;spring-boot-starter-web&lt;/artifactId&gt;
        &lt;exclusions&gt;
            &lt;exclusion&gt;
                &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
                &lt;artifactId&gt;spring-boot-starter-tomcat&lt;/artifactId&gt;
            &lt;/exclusion&gt;
        &lt;/exclusions&gt;
    &lt;/dependency&gt;
    &lt;dependency&gt;
        &lt;groupId&gt;${project.groupId}&lt;/groupId&gt;
        &lt;artifactId&gt;cgi-app-interaction-library&lt;/artifactId&gt;
        &lt;version&gt;${project.version}&lt;/version&gt;
    &lt;/dependency&gt;
    &lt;dependency&gt;
        &lt;groupId&gt;commons-collections&lt;/groupId&gt;
        &lt;artifactId&gt;commons-collections&lt;/artifactId&gt;
    &lt;/dependency&gt;
    &lt;dependency&gt;
        &lt;groupId&gt;com.google.guava&lt;/groupId&gt;
        &lt;artifactId&gt;guava&lt;/artifactId&gt;
        &lt;/dependency&gt;
&lt;/dependencies&gt;
&lt;build&gt;
    &lt;finalName&gt;cgiwrapp&lt;/finalName&gt;
    &lt;plugins&gt;
        &lt;plugin&gt;
            &lt;groupId&gt;org.apache.maven.plugins&lt;/groupId&gt;
            &lt;artifactId&gt;maven-war-plugin&lt;/artifactId&gt;
            &lt;version&gt;2.6&lt;/version&gt;
            &lt;configuration&gt;
                &lt;failOnMissingWebXml&gt;false&lt;/failOnMissingWebXml&gt;
            &lt;/configuration&gt;
        &lt;/plugin&gt;
        &lt;plugin&gt;
            &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
            &lt;artifactId&gt;spring-boot-maven-plugin&lt;/artifactId&gt;
            &lt;version&gt;${spring-boot.version}&lt;/version&gt;
        &lt;/plugin&gt;
    &lt;/plugins&gt;
&lt;/build&gt;

</project>

在构造函数中,我将我希望注入的 AppSession 实例绑定到我将用来注入它们的工厂类,即创造性地命名的 AppSessionInjectionFactory

AppSession 类是 CGI/Perl 应用程序交互库的入口点。除了以下事实之外,它的代码与主题无关

  • 每个 AppSession 实例都绑定到一个特定的、珍贵的用户 ID 字符串。
  • AppSession 实现了 java.lang.AutoCloseable 接口。这允许它在 try-with-resources 块中使用,并通知 API 用户这是必须关闭的资源。

Servlet过滤器

我想专门管理 AppSessionInjectionFactory 中的 BlockingQueue,但遇到了范围问题。

也就是说,Jersey 的默认行为是为每次注入创建一个新的工厂实例。我尝试更改绑定的范围并将我的整体绑定策略更改为 bindFactory(new AppSessionInjectionFactory()).to(AppSession.class) (请注意我如何创建单个实例而不是使用类文字提供 bindFactory 方法)。在这两种情况下,我都无法让 Spring 将 AppConfig bean 注入 AppSessionInjectionFactory 中。因此,我决定使用 Servlet Filter,我知道它只会被实例化一次。这是过滤器的代码,在我看来,这是应用程序中最有趣的部分。


 <?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.    apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>com.example.bdkosher/groupId>
        <artifactId>cgi-app-wrapper</artifactId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <artifactId>cgi-app-rest-api</artifactId>
    <packaging>war</packaging>
&lt;properties&gt;
    &lt;spring-boot.version&gt;1.2.4.RELEASE&lt;/spring-boot.version&gt;
    &lt;java.version&gt;1.7&lt;/java.version&gt;
&lt;/properties&gt;

&lt;dependencyManagement&gt;
    &lt;dependencies&gt;
        &lt;dependency&gt;
            &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
            &lt;artifactId&gt;spring-boot-dependencies&lt;/artifactId&gt;
            &lt;version&gt;${spring-boot.version}&lt;/version&gt;
            &lt;type&gt;pom&lt;/type&gt;
            &lt;scope&gt;import&lt;/scope&gt;
        &lt;/dependency&gt;
    &lt;/dependencies&gt;
&lt;/dependencyManagement&gt;

&lt;dependencies&gt;
    &lt;dependency&gt;
        &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
        &lt;artifactId&gt;spring-boot-starter-jersey&lt;/artifactId&gt;
    &lt;/dependency&gt;
    &lt;dependency&gt;
        &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
        &lt;artifactId&gt;spring-boot-starter-web&lt;/artifactId&gt;
        &lt;exclusions&gt;
            &lt;exclusion&gt;
                &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
                &lt;artifactId&gt;spring-boot-starter-tomcat&lt;/artifactId&gt;
            &lt;/exclusion&gt;
        &lt;/exclusions&gt;
    &lt;/dependency&gt;
    &lt;dependency&gt;
        &lt;groupId&gt;${project.groupId}&lt;/groupId&gt;
        &lt;artifactId&gt;cgi-app-interaction-library&lt;/artifactId&gt;
        &lt;version&gt;${project.version}&lt;/version&gt;
    &lt;/dependency&gt;
    &lt;dependency&gt;
        &lt;groupId&gt;commons-collections&lt;/groupId&gt;
        &lt;artifactId&gt;commons-collections&lt;/artifactId&gt;
    &lt;/dependency&gt;
    &lt;dependency&gt;
        &lt;groupId&gt;com.google.guava&lt;/groupId&gt;
        &lt;artifactId&gt;guava&lt;/artifactId&gt;
        &lt;/dependency&gt;
&lt;/dependencies&gt;
&lt;build&gt;
    &lt;finalName&gt;cgiwrapp&lt;/finalName&gt;
    &lt;plugins&gt;
        &lt;plugin&gt;
            &lt;groupId&gt;org.apache.maven.plugins&lt;/groupId&gt;
            &lt;artifactId&gt;maven-war-plugin&lt;/artifactId&gt;
            &lt;version&gt;2.6&lt;/version&gt;
            &lt;configuration&gt;
                &lt;failOnMissingWebXml&gt;false&lt;/failOnMissingWebXml&gt;
            &lt;/configuration&gt;
        &lt;/plugin&gt;
        &lt;plugin&gt;
            &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
            &lt;artifactId&gt;spring-boot-maven-plugin&lt;/artifactId&gt;
            &lt;version&gt;${spring-boot.version}&lt;/version&gt;
        &lt;/plugin&gt;
    &lt;/plugins&gt;
&lt;/build&gt;

</project>

doFilter 方法尝试从 BlockingQueue 中获取用户 ID。如果没有可用的用户 ID,它将阻塞,直到将用户 ID 放回池中。获得用户 ID 后,它将实例化 AppSession 并将其存储在 Servlet Request 属性中,以供链中的其他过滤器将来使用。过滤器链返回后,它会替换 BlockingQueue 中的用户 ID。

定制注塑厂

最后一部分是工厂本身,它使请求属性绑定的 AppSession 可用于我们的 JAX-RS 资源。

这个类的代码非常简单。唯一棘手的部分是将类注释为请求范围,以便它可以在实例化时用当前的 HttpServletRequest 注入。


 <?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.    apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>com.example.bdkosher/groupId>
        <artifactId>cgi-app-wrapper</artifactId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <artifactId>cgi-app-rest-api</artifactId>
    <packaging>war</packaging>
&lt;properties&gt;
    &lt;spring-boot.version&gt;1.2.4.RELEASE&lt;/spring-boot.version&gt;
    &lt;java.version&gt;1.7&lt;/java.version&gt;
&lt;/properties&gt;

&lt;dependencyManagement&gt;
    &lt;dependencies&gt;
        &lt;dependency&gt;
            &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
            &lt;artifactId&gt;spring-boot-dependencies&lt;/artifactId&gt;
            &lt;version&gt;${spring-boot.version}&lt;/version&gt;
            &lt;type&gt;pom&lt;/type&gt;
            &lt;scope&gt;import&lt;/scope&gt;
        &lt;/dependency&gt;
    &lt;/dependencies&gt;
&lt;/dependencyManagement&gt;

&lt;dependencies&gt;
    &lt;dependency&gt;
        &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
        &lt;artifactId&gt;spring-boot-starter-jersey&lt;/artifactId&gt;
    &lt;/dependency&gt;
    &lt;dependency&gt;
        &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
        &lt;artifactId&gt;spring-boot-starter-web&lt;/artifactId&gt;
        &lt;exclusions&gt;
            &lt;exclusion&gt;
                &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
                &lt;artifactId&gt;spring-boot-starter-tomcat&lt;/artifactId&gt;
            &lt;/exclusion&gt;
        &lt;/exclusions&gt;
    &lt;/dependency&gt;
    &lt;dependency&gt;
        &lt;groupId&gt;${project.groupId}&lt;/groupId&gt;
        &lt;artifactId&gt;cgi-app-interaction-library&lt;/artifactId&gt;
        &lt;version&gt;${project.version}&lt;/version&gt;
    &lt;/dependency&gt;
    &lt;dependency&gt;
        &lt;groupId&gt;commons-collections&lt;/groupId&gt;
        &lt;artifactId&gt;commons-collections&lt;/artifactId&gt;
    &lt;/dependency&gt;
    &lt;dependency&gt;
        &lt;groupId&gt;com.google.guava&lt;/groupId&gt;
        &lt;artifactId&gt;guava&lt;/artifactId&gt;
        &lt;/dependency&gt;
&lt;/dependencies&gt;
&lt;build&gt;
    &lt;finalName&gt;cgiwrapp&lt;/finalName&gt;
    &lt;plugins&gt;
        &lt;plugin&gt;
            &lt;groupId&gt;org.apache.maven.plugins&lt;/groupId&gt;
            &lt;artifactId&gt;maven-war-plugin&lt;/artifactId&gt;
            &lt;version&gt;2.6&lt;/version&gt;
            &lt;configuration&gt;
                &lt;failOnMissingWebXml&gt;false&lt;/failOnMissingWebXml&gt;
            &lt;/configuration&gt;
        &lt;/plugin&gt;
        &lt;plugin&gt;
            &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
            &lt;artifactId&gt;spring-boot-maven-plugin&lt;/artifactId&gt;
            &lt;version&gt;${spring-boot.version}&lt;/version&gt;
        &lt;/plugin&gt;
    &lt;/plugins&gt;
&lt;/build&gt;

</project>

回报

现在我们已经解决了所有这些麻烦以确保没有两个请求线程共享同一个 AppSession 实例,让我们实际看一下 JAX-RS 资源示例。


 <?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.    apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>com.example.bdkosher/groupId>
        <artifactId>cgi-app-wrapper</artifactId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <artifactId>cgi-app-rest-api</artifactId>
    <packaging>war</packaging>
&lt;properties&gt;
    &lt;spring-boot.version&gt;1.2.4.RELEASE&lt;/spring-boot.version&gt;
    &lt;java.version&gt;1.7&lt;/java.version&gt;
&lt;/properties&gt;

&lt;dependencyManagement&gt;
    &lt;dependencies&gt;
        &lt;dependency&gt;
            &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
            &lt;artifactId&gt;spring-boot-dependencies&lt;/artifactId&gt;
            &lt;version&gt;${spring-boot.version}&lt;/version&gt;
            &lt;type&gt;pom&lt;/type&gt;
            &lt;scope&gt;import&lt;/scope&gt;
        &lt;/dependency&gt;
    &lt;/dependencies&gt;
&lt;/dependencyManagement&gt;

&lt;dependencies&gt;
    &lt;dependency&gt;
        &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
        &lt;artifactId&gt;spring-boot-starter-jersey&lt;/artifactId&gt;
    &lt;/dependency&gt;
    &lt;dependency&gt;
        &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
        &lt;artifactId&gt;spring-boot-starter-web&lt;/artifactId&gt;
        &lt;exclusions&gt;
            &lt;exclusion&gt;
                &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
                &lt;artifactId&gt;spring-boot-starter-tomcat&lt;/artifactId&gt;
            &lt;/exclusion&gt;
        &lt;/exclusions&gt;
    &lt;/dependency&gt;
    &lt;dependency&gt;
        &lt;groupId&gt;${project.groupId}&lt;/groupId&gt;
        &lt;artifactId&gt;cgi-app-interaction-library&lt;/artifactId&gt;
        &lt;version&gt;${project.version}&lt;/version&gt;
    &lt;/dependency&gt;
    &lt;dependency&gt;
        &lt;groupId&gt;commons-collections&lt;/groupId&gt;
        &lt;artifactId&gt;commons-collections&lt;/artifactId&gt;
    &lt;/dependency&gt;
    &lt;dependency&gt;
        &lt;groupId&gt;com.google.guava&lt;/groupId&gt;
        &lt;artifactId&gt;guava&lt;/artifactId&gt;
        &lt;/dependency&gt;
&lt;/dependencies&gt;
&lt;build&gt;
    &lt;finalName&gt;cgiwrapp&lt;/finalName&gt;
    &lt;plugins&gt;
        &lt;plugin&gt;
            &lt;groupId&gt;org.apache.maven.plugins&lt;/groupId&gt;
            &lt;artifactId&gt;maven-war-plugin&lt;/artifactId&gt;
            &lt;version&gt;2.6&lt;/version&gt;
            &lt;configuration&gt;
                &lt;failOnMissingWebXml&gt;false&lt;/failOnMissingWebXml&gt;
            &lt;/configuration&gt;
        &lt;/plugin&gt;
        &lt;plugin&gt;
            &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
            &lt;artifactId&gt;spring-boot-maven-plugin&lt;/artifactId&gt;
            &lt;version&gt;${spring-boot.version}&lt;/version&gt;
        &lt;/plugin&gt;
    &lt;/plugins&gt;
&lt;/build&gt;

</project>

在实际应用程序中,我正在与 AppSession 对象的更有用的方法进行交互。但这个简单的示例说明了主要目标:我已将我有限的资源注入到我的 JAX-RS 资源中,使我的服务代码免于管理它并保护它免受其他请求线程的共享访问的责任。