我应该在哪个层、Dao 或服务中解析 Rest 客户端响应? [关闭]

Posted

技术标签:

【中文标题】我应该在哪个层、Dao 或服务中解析 Rest 客户端响应? [关闭]【英文标题】:In Which Layer, Dao or Service, Should I Parse a Rest Client Response? [closed] 【发布时间】:2020-11-22 07:13:26 【问题描述】:

我有自己的服务调用第三方 rest 服务,该服务返回基于文本的响应。此基于文本的响应不是正确的服务响应,需要解析内容和错误。出于讨论的目的,假设第 3 方休息服务不能更改。

鉴于这些情况,我想知道是否应该将该解析连接到应用程序的 dao 层或服务层。我知道服务层应该包含您的所有业务逻辑,但我觉得如果我不这样做在我泄漏的 Dao 层中进行解析。在这种情况下,是否可以在 dao 中包含用于解析/转换的逻辑,还是应该在服务层中完成?

感谢任何建议。

public void MyDao 

     private RestTemplate restTemplate;
     private ResponseParser responseParser;

     public myDao(RestTemplate restTemplate, ResponseParser responsePaser)
          this.restTemplate = restTemplate;
          this.responseParser = responseParser;
     

     public MyResponse sendRequest(MyRequest myRequest)
         ResponseEntity<String> responeEntity = restTemplate.exchange(...);
         String body = responseEntity.getBody();
         return responseParser.parse(body);
    

public void MyDao 

     private RestTemplate restTemplate;

     public myDao(RestTemplate restTemplate, ResponseParser responsePaser)
          this.restTemplate = restTemplate;
     

     public String sendRequest(MyRequest myRequest)
         ResponseEntity<String> responeEntity = restTemplate.exchange(...);
         return responseEntity.getBody();
    


public void MyService 

     private MyDao myDao;
     private ResponseParser responseParser;

     public myDao(MyDao myDao, ResponseParser responsePaser)
         this.myDao = myDao; 
         this.responseParser = responseParser;
     

     public MyObject process(MyRequest myRequest)
         String response = myDao.sendRequest(myRequest)
         return responseParser.parse(response);
    

【问题讨论】:

对您问题的每一个答案肯定都是基于与个人程序员偏好相关的意见。因此,在我看来,由于单一职责原则,单独的解析逻辑更好。 对于 SRP,它声明一个类应该只有一个改变的理由。我会说在 dao 中包含解析是可以的,因为如果其余响应的格式发生变化,您将需要更改它的解析方式。因此它们本质上是耦合的,不是吗? 【参考方案1】:

严格来说,Dao 层用于管理包含在持久性机制中的信息,例如:数据库、LDAP 等。因此,当您处理外部端点时,在服务中“包含”该功能是一种更广泛使用的方法。

回答您的问题,第一个选项更好。

    您将所需的业务逻辑包含在知道外部端点返回的格式/信息的类中。

    使用上述类的外部类将管理一个众所周知的对象(而不是原始字符串值)

    可以在您的 Dao 类中更好地管理外部端点中的某些类型的升级(例如响应格式的更改),而不会影响使用它的其他类。

【讨论】:

“DAO”代表“数据访问对象”。如果拥有数据的系统碰巧是通过 HTTP 而不是 JDBC 访问的,这不会改变关系的性质,使用 RestTemplate 的 DAO 与使用 JdbcTemplate 的 DAO 一样合理。 我自己和我的一位导师对此有过几次“好脾气”的争论哈哈。我倾向于同意医生的观点,即它属于服务或更好的是它自己的 RestClient 类。我相信这是因为严格来说,DAO 定义确实适用于“持久性”机制,并且这个特定的休息服务不会持久化任何东西,只是解析并返回响应。现在,如果我调用一个有 crud 操作的 rest 服务,那么我会说它属于 DAO。我想这一切都归结为你想要解释规则的严格程度。【参考方案2】:

这是我对设计的看法和看法。

DAO 是一种抽象持久性操作的模式,应仅用于处理持久性操作。 DAO 模式有助于从客户端的数据源中抽象出持久性机制/操作或数据访问操作,并且设计遵循 SRP,从而轻松过渡到新的持久性类型。而你的持久化机制/数据源的变化,停留在 DAO 层,而不是服务层。 服务层负责处理和计算数据上的业务操作。它使用 DAO/Repository/Client 来获取操作所需的数据。

考虑到以上几点,以下是我对现有设计的看法以及我将如何做。

DAO,正如上面提到的 chrylis,是一个数据访问对象,无论数据是从数据库中还是通过 HTTP 获取都无关紧要。 Oracle 关于 J2EE 模式的article 内容如下:

使用数据访问对象 (DAO) 来抽象和封装对数据源的所有访问。 DAO 管理与数据源的连接以获取和存储数据。

它进一步写道:数据源可以是像 RDBMS 这样的持久存储,像 B2B 交换这样的外部服务,像 LDAP 数据库这样的存储库,或者通过以下方式访问的业务服务CORBA Internet Inter-ORB 协议 (IIOP) 或低级套接字

考虑到这些,我会从 DAO 进行调用,解析响应并将业务对象发送到服务。 考虑到 SRP,服务不应该知道通过 HTTP 进行的调用/进行的 db 调用/从平面文件中读取。它应该知道的是,一旦我对数据进行查询,我就会从 DAO 中取回一个包含所需数据的对象。 如果服务负责解析,如果明天数据源发生变化并且您拥有原位数据怎么办。所以现在你的 DAO 发生了变化,因为它现在与 DB 对话,而不是发出 HTTP 请求。你不能再返回一个字符串表示。您需要一个数据映射器并将某种对象表示发回,这意味着您的服务类也发生了变化。因此,数据源的一次更改,不仅会更改您在 DAO 中的代码,还会涉及业务层,这会破坏 SRP。 这么说,不是长期开发,也不是软件工程背景(我理解数据访问对象只能来自数据存储,但感谢 chrylis 的评论让我阅读更多并思考数据之间的区别-源和数据存储),我总是更喜欢将其命名为 Client -> RestClient 并进行调用并将我的数据库操作保留到 DAO/Repo。原因是,明天很容易阅读。一看类名,就很容易理解它在做什么或该类可能正在处理什么样的操作。

所以,是的,调用和解析应该发生在 DAO/Client 中。

【讨论】:

【参考方案3】:

我的意见是放在 DAO 层。因为解析不是业务功能。此外,DAO 层用于访问来自 DB 或其他第三方实体的数据。因此,在我看来,从 DAO 层返回时以正确的 POJO 格式保存数据是很有意义的。

【讨论】:

以上是关于我应该在哪个层、Dao 或服务中解析 Rest 客户端响应? [关闭]的主要内容,如果未能解决你的问题,请参考以下文章

域、DAO 和服务层

mybatis怎么知道dao层调用了实体.xml里面哪个方法

从另一个服务调用服务 vs dao

DAO 层应该如何实现?一张表 DAO 还是多表 DAO?

ssh 集成框架 dao层 如何使用session

带有休眠的 DAO 和服务层