当前位置: 首页 > 知识库问答 >
问题:

Spring Boot:RESTful控制器中的多层@服务,适用于许多入站请求

张献
2023-03-14

不确定这是代码审查还是关于Spring Boot如何操作具有许多入站请求的@Service组件的问题。如果这是一个问题,我当然可以在StackExchange中重新发布

  • Spring Boot应用程序
  • 处理列表的RESTful控制器

叙述:本质上,RESTfulendpoint将返回一个列表

我的问题:

  • 这是设计RESTful堆栈的正确方法吗?特别是我们需要的实用程序类...它们应该作为@Service还是作为在数据管理@Service层中使用的POJO类来完成。
  • 在一次有10-100个请求到达RESTfulendpoint的多请求情况下,自定义排序实用程序@Service排序()方法会发生什么?排序()方法是否按顺序为每个请求提供服务?还是在不同的线程中并行?
  • 每个请求是否都使用相同的排序方法,即自定义排序实用程序@Service是一个“单例”,那么排序()方法是如何使用的?
  • 如果ort()方法确实是单一的,如果两个用户同时点击该方法,一个用户是否可能最终得到另一个用户的排序列表?或者Spring Boot只是按顺序或在他们自己的线程中处理入站请求并避免任何混合。

代码片段:为了简洁起见,我删除了大部分代码。

@RestController
@RequestMapping(value = "/search")
@CrossOrigin(origins = "*")
@Slf4j
public class SearchController {

    // @Service for Data handling...
    @Autowired
    private DataManagementService dataManagementService;

    @GetMapping(value="/viewable-documents")
    public SearchResponse getExternallyViewableDocuments(@RequestParam(required = false) Map<String, String> queryParams) {
        logger.debug("getViewableDocuments is called with {}", queryParams);

        SearchResponse searchResponse = new SearchResponse();

        // ENDPOINT : Calls the Data Management handling @Service...
        SearchResponse response = dataManagementService.getDocuments(queryParams);

    }
}

@Service
public class DataManagementServiceImpl implements DataManagementService {

    // CUSTOM SORT UTILITY : Autowired with setter...
    private DocumentSortUtility documentSortUtility;

    @Autowired
    public void setDocumentSortUtility(DocumentSortUtility setValue) {
        this.documentSortUtility = setValue;
    }


    @Override
    public SearchResponse getDocuments(Map<String, String> request) {

        if (request.get("sort") != null && request.get("sort").equals("true")) {

            // SORT : Call the custom sort...
            return serviceImpl.populateResponse(this.documentSortUtility.sort(response));

        } else {
            return serviceImpl.populateResponse(response);
        }
    }
}

@Service
public class DocumentSortUtility {

    public List<DocumentMetadata> sort(List<DocumentMetadata> documentMetadataList) {
        log.debug("Un Sorted:"+documentMetadataList);

        // Do custom sort of documentMetadataList and place in retList...

        log.debug("Sorted:"+retList);   
        return retList;
    }
}

我已在代码中确认,在服务层中没有“共享”可变对象被维护/管理。只有在服务层的方法中才能修改和/或创建对象。

Thx提前。。。


共有1个答案

贡建修
2023-03-14

正如我所看到的,您的困惑基于Spring的单例范围,以及Spring在服务类为单例时如何处理多个请求。

Spring将bean创建并绑定为Singleton对象,除非您使用@Scope注释或与范围相应的注释定义特定范围,例如@SessionScope。您可能已经知道了这一点。

如果您对多个线程上的Singleton对象有模糊不清的地方,这个答案提供了很好的解释。那么,关于你的问题;

  • 这是设计RESTful堆栈的正确方法吗?特别是我们需要的实用程序类,它们应该作为@Service还是作为在数据管理@Service层中使用的POJO类来完成?

是和否。如果您的服务类是单例(必须是)且不可变(无状态),那么这是正确的方法。也就是说,您的服务类不应该有任何可修改的字段。否则,您的服务将导致无法预测的结果。

如果在这个上下文中使用了POJO,那么每次新线程启动时,对象实例化都会初始化新对象,这就引出了第二个问题;

  • 在10-100个请求同时命中RESTfulendpoint的多请求情况下,自定义排序实用程序服务和排序()方法会发生什么情况?方法是否按顺序为每个请求提供服务?还是在不同的线程中并行

当10-100或数千个或多个请求到达endpoint时,如果您使用了POJO,它还会创建数千个额外的对象,这些对象会不必要地污染堆,因为我们可以使用服务注释使用一个单例对象。因为,singleton对象是不可变的(不会通过方法调用保持任何更改),并且在多个线程之间共享,能够同时执行,而不会对结果产生任何副作用。

如果ort()发生在内存中并随后返回排序结果,它会在线程的执行中独立执行。

  • 每个请求是否都使用相同的排序方法,即自定义排序实用程序@Service是一个“单例”,那么排序()方法是如何使用的?

Singleton并不意味着它的函数不能共享,除非它们是专门的同步。在您的情况下,我相信这个ort()方法不是同步的。因此,在每个线程上单独执行ort()方法没有问题(没有差异,因为我们的singleton对象是无状态/不可变的)。

  • 如果ort()方法真正是单一的,如果两个用户同时命中该方法,一个用户是否可能最终得到另一个用户的排序List?或者Spring Boot只是按顺序或在他们自己的线程中处理入站请求并避免任何混合。

你知道,Spring boot是基于Java EE的。因此,基本上它使用了javax。servlet。ServletContext类实例来处理这个请求和响应流,以及Java EE中的所有其他类都参与了这个过程,我们看不到Spring的巧妙设计。但流程是一样的。简而言之,每个请求都有单独的线程绑定到它,而那些请求线程永远不会混淆。线程涉及整个过程,直到响应被调度到客户端。

你有没有注意到,除了特殊情况,我们不会手动创建线程?这是因为,Java EE生态系统代表我们管理这些线程。

所以,您的问题的答案是,不,sort()不会执行一次,也永远不会有一个请求的结果最终出现在另一个请求的响应对象中,无论有多少用户同时发出请求。这个答案还提供了关于这些请求-响应机制如何在下面工作的精彩解释。

 类似资料:
  • 我对AWS和serverless相当陌生,到目前为止,我一直在使用lambda函数和层。 我们有两项服务: lambda1.yml λ2.yml 当我使用'sls deploy--config lambda1'部署lambda1时。yml’,该层被上传并成功分配给lambda1函数。 但是,当我使用“sls deploy--config lambda2”部署lambda2时。yml’,无服务器上传

  • 或者也许有另一种方法。 OBS.我现在不打算让游戏运行在服务器上对付作弊者。因为这将对我的安装程序中的服务器cpu造成很大的负载。

  • 问题内容: 我有一个简单的Angular JS场景。我在一个视图中显示了一个专家列表,该列表包含编辑专家的操作,该操作将在另一视图中完成。这些视图来自服务器,并且不在一个文件中。它们不会一起加载。 在服务器上的另一个文件中,我有: 我的控制器是: 但是,任何数据都不会显示在编辑表单中。我使用Batarang检查了范围,但不会显示对象。 问题似乎是我在一个控制器上使用了两个(可能有两个以上)视图。但

  • Navicat 提供“服务器监控”提供来查看已选择的服务器的属性。从菜单栏选择“工具”->“服务器监控”并选择你想要的服务器类型。 【注意】仅适用于 MySQL、Oracle、PostgreSQL、SQL Server 、MariaDB 和 MongoDB。 进程列表 此选项卡以列表显示所有已选择的服务器的进程。进程列表提供以下的信息。它是根据你所选择的数据库类型而定。 在设置连接时提供的服务器名

  • Navicat 提供“服务器监控”提供来查看已选择的服务器的属性。从菜单栏选择“工具”->“服务器监控”并选择你想要的服务器类型。 【注意】仅适用于 MySQL、Oracle、PostgreSQL、SQL Server、MariaDB 和 MongoDB。 进程列表 此选项卡以列表显示所有已选择的服务器的进程。进程列表提供以下的信息。它是根据你所选择的数据库类型而定。 在设置连接时提供的服务器名。

  • Navicat 提供“服务器监控”提供来查看已选择的服务器的属性。从菜单栏选择“工具”->“服务器监控”并选择你想要的服务器类型。 【注意】仅适用于 MySQL、Oracle、PostgreSQL、SQL Server、MariaDB 和 MongoDB。 进程列表 此选项卡以列表显示所有已选择的服务器的进程。进程列表提供以下的信息。它是根据你所选择的数据库类型而定。 在设置连接时提供的服务器名。