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

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

欢迎加入小哈的星球 ,你将获得:专属的项目实战 / 1v1 提问 / Java 学习路线 / 学习打卡 / 每月赠书 / 社群讨论

  • 新项目:《从零手撸:仿小红书(微服务架构)》 正在持续爆肝中,基于 Spring Cloud Alibaba + Spring Boot 3.x + JDK 17...点击查看项目介绍 ;
  • 《从零手撸:前后端分离博客项目(全栈开发)》 2 期已完结,演示链接: http://116.62.199.48/ ;

截止目前, 星球 内专栏累计输出 63w+ 字,讲解图 2808+ 张,还在持续爆肝中.. 后续还会上新更多项目,目标是将 Java 领域典型的项目都整一波,如秒杀系统, 在线商城, IM 即时通讯,权限管理,Spring Cloud Alibaba 微服务等等,已有 2200+ 小伙伴加入学习 ,欢迎点击围观

我一直致力于使用 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 并将其作为属性存储在 HttpServletRequest 中,以供链中的其他过滤器将来使用。过滤器链返回后,它会替换 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 资源中,使我的服务代码从管理它和保护它免受共享访问的责任中解放出来。

相关文章