Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/312.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 复杂Spring框架服务层_Java_Multithreading_Spring_Spring Mvc_Architecture - Fatal编程技术网

Java 复杂Spring框架服务层

Java 复杂Spring框架服务层,java,multithreading,spring,spring-mvc,architecture,Java,Multithreading,Spring,Spring Mvc,Architecture,该帖子的编辑短版: 没有足够的观点,所以我总结一下问题: 我的架构是完全无状态和异步的,前端向RESTAPI发出请求,然后长时间轮询响应。这个RESTAPI将请求排队到消息队列中,每个请求都由后端出列和处理 我希望这个后端遵循“传统”的Spring@Service接口和ServiceImpl方法,但是由于我的操作方式,这有点困难 一个线程将请求(生产者)出列,生成一个新线程(消费者),然后处理该线程中的所有请求,该线程随后将发送回“响应池”,在那里进行轮询。该请求可能需要使用多个@Service

该帖子的编辑短版:

没有足够的观点,所以我总结一下问题:

我的架构是完全无状态和异步的,前端向RESTAPI发出请求,然后长时间轮询响应。这个RESTAPI将请求排队到消息队列中,每个请求都由后端出列和处理

我希望这个后端遵循“传统”的Spring@Service接口和ServiceImpl方法,但是由于我的操作方式,这有点困难

一个线程将请求(生产者)出列,生成一个新线程(消费者),然后处理该线程中的所有请求,该线程随后将发送回“响应池”,在那里进行轮询。该请求可能需要使用多个@Service并合并每个@Service的响应,甚至可能两次合并同一个@Service

你会怎么做?有关更多信息,请查看下面的说明

原始长帖子:

我有一个大型应用程序,有3层,如下所示:

  • 前端(SpringMVC):视图和控制器,“模型”是对中间件中RESTAPI的异步请求,首先将请求排队,然后长时间轮询以获得答案
  • 中间件(SpringMVC):RESTAPI。两个主要功能:从前端接收请求并将其排队,从后端接收答复并将其存储在响应缓存中,直到前端检索到为止
  • 后端(Spring单机版应用程序):生产者/消费者模式,一个生产者退出申请,并为每个申请创建一个原型消费者。使用者实现了InitializingBean,因此它是这样的:初始化,初始化许多自动连接的字段,然后执行afterPropertiesSet,并设置许多依赖于请求的字段
  • 我还有一个HibernateDaos存储库层,它对数据库进行所有查询

    我缺少一个正确构建的服务层,这就是这个问题的全部内容

    让我再解释一下上下文。我现在拥有的就像一个只有221个函数的巨大服务(消费者的文件很长),一个请求可能需要调用其中的几个函数,每个函数的结果都被合并到DTO列表中,之后前端会收到这些DTO

    我想将这一个也是唯一的服务拆分为几个,在逻辑上与“it's”对应的存储库相匹配,但是我遇到了以下问题:

    记住这一点:

    • 一个请愿书有许多动作,一个动作是对服务功能的调用
    • 每个消费者都是一个单一且唯一的线程
    • 每次使用者线程启动时,都会启动一个事务,并在返回之前提交该事务,除非回滚
    • 我需要在同一线程和事务中执行该请愿书的所有服务
    • 当使用者运行afterPropertiesSet时,特定于该请求的多个字段由始终发送的一些参数初始化
    有了一个好的服务层,我想完成:

    • 我不想总是为请求的每个服务初始化所有这些参数,我希望它们是请求/线程的全局参数,但是,我不想将它们作为参数传递给所有函数
    • 我想懒洋洋地初始化新服务,只有在需要的时候,当它被初始化时,我想设置我上面提到的所有参数。每个服务都需要是请愿书的原型,但是我觉得如果需要在同一请愿书中初始化它两次(在一个请愿书中对同一服务执行两个操作),即我希望它的行为像一个“请求”范围,但是,它不是一个请求,因为它不是基于Web的,它是一个新线程,在请求解队列时由生产者初始化
    我在考虑为每个消费者创建一个原型ServicesFactory,该原型使用消费者中设置的所有参数AfterProperties进行初始化,在这个ServicesFactory中,所有可能的服务都声明为类字段,当请求特定服务时,如果其字段为null,则初始化该服务,如果不为null,则设置所有字段,返回相同的实例。这种方法的问题在于,我发现我正在失去对所有服务的依赖注入。我一直在读关于也许这是一条路要走,但我真的无法抓住它。它需要消费者的所有参数,并且每个消费者都需要一个唯一的ServiceFactoryBean,这一事实确实令人困惑

    有什么想法吗


    感谢

    第2点和第3点需要更多的重新组织,更愿意检查“中间件”和(Spring独立应用程序):生产者/消费者模式的“Spring集成”实际上是为了解决这2点,如果您同时执行2个或更多操作,请使用发布/订阅,另一点是您使用REST的原因“中间件”是由另一个应用程序而不是您的前端公开的这些“中间件”服务,在这种情况下,您可以使用“内容协商”将此部分集成到您的Spring MVC前端应用程序中,否则,如果您要使用“Spring集成”“您将找到多种通信方式。

    根据描述,我认为这不是使用原型作用域的好例子,在这种情况下,理想的作用域似乎是
    线程作用域

    作为一种解决方案,最简单的方法是使所有服务
    都是单例的。然后,使用者从入站队列读取请求并开始处理

    其中一个服务也是
    singleton
    ,并被注入到所有需要的服务中,我们称之为
    requestscopedservice

    此服务在内部使用,它是类型为的变量的线程范围的保持器
    public class PetitionContext {
        ... just a POJO, getters and setters etc. 
    }
    
    @Service
    public class PetitionScopedService {
    
        private ThreadLocal<PetitionContext> = new ThreadLocal<PetitionContext>();
    
    
        public doSomethingPetitionSpecific() {
            ... uses the petition context ...
        }
    }
    
    @Service
    public class SomeOtherService {
    
        @Autowired
        private PetitionScopedService petitionService;
    
        ... use petition service that is a singleton with thread scoped internal state, effectivelly thread scoped ...
    }