Java 如何在我的HttpClient执行人中遵循单一责任原则?

Java 如何在我的HttpClient执行人中遵循单一责任原则?,java,spring,oop,resttemplate,Java,Spring,Oop,Resttemplate,我使用as我的HttpClient执行URL,服务器将返回一个json字符串作为响应。客户将通过传递包含userId的DataKey对象来调用此库 使用给定的userId,我将找出我可以点击哪些机器来获取数据,然后将这些机器存储在LinkedList中,以便按顺序执行它们 之后,我将检查第一个主机名是否在阻止列表中。如果它不在阻止列表中,那么我将使用列表中的第一个主机名创建一个URL并执行它,如果响应成功,则返回响应。但是假设第一个主机名在阻止列表中,那么我将尝试获取列表中的第二个主机名,生成

我使用as我的
HttpClient
执行URL,服务器将返回一个json字符串作为响应。客户将通过传递包含
userId
DataKey
对象来调用此库

  • 使用给定的
    userId
    ,我将找出我可以点击哪些机器来获取数据,然后将这些机器存储在
    LinkedList
    中,以便按顺序执行它们
  • 之后,我将检查第一个主机名是否在阻止列表中。如果它不在阻止列表中,那么我将使用列表中的第一个主机名创建一个URL并执行它,如果响应成功,则返回响应。但是假设第一个主机名在阻止列表中,那么我将尝试获取列表中的第二个主机名,生成url并执行它,因此基本上,在生成url之前,首先找到不在阻止列表中的主机名
  • 现在,假设我们选择了第一个不在阻止列表中的主机名,并执行了URL,但不知何故服务器关闭或没有响应,那么我将执行列表中的第二个主机名,并继续执行,直到您获得成功响应但要确保它们也不在阻止列表中,因此我们需要遵循上述要点。
  • 如果所有服务器都关闭或在阻止列表中,那么我可以简单地记录并返回服务不可用的错误
下面是我的DataClient类,客户将调用该类,并将
DataKey
对象传递给
getData
方法

public class DataClient implements Client {

    private RestTemplate restTemplate = new RestTemplate(new HttpComponentsClientHttpRequestFactory());
    private ExecutorService service = Executors.newFixedThreadPool(15);

    public Future<DataResponse> getData(DataKey key) {
        DataExecutorTask task = new DataExecutorTask(key, restTemplate);
        Future<DataResponse> future = service.submit(task);

        return future;
    }
}
为了检查是否有任何服务器在阻止列表中,我使用以下命令-

ShardMappings.isBlockHost(hostname);
如果服务器关闭或在阻止列表中,我将返回
SERVICE\u UNAVAILABLE
,根据
response==null
检查,不确定这是否正确。

我想我根本没有遵循单一责任原则。 有人能举一个例子说明什么是使用SRP原则的最佳方法吗

经过深思熟虑,我能够像下面给出的那样提取hosts类,但不确定在我上面的
DataExecutorTask
类中使用它的最佳方式是什么。

公共类主机{
private final LinkedList hostsnames=new LinkedList();
公共主机(最终列表主机){
checkNotNull(主机,“主机不能为null”);
this.hostsnames.addAll(主机);
}
公共可选getNextAvailableHostname(){
而(!hostsnames.isEmpty()){
String firstHostname=hostsnames.removeFirst();
如果(!ClientUtils.isEmpty(firstHostname)和&!ShardMappings.isBlockHost(firstHostname)){
返回可选的.of(firstHostname);
}
}
返回可选的。缺席();
}
公共布尔值为空(){
返回hostsnames.isEmpty();
}
}

您的担忧是正确的。首先,让我们看看原始数据执行器是做什么的:

First, it is getting list of hostnames
Next, it loops through every hostnames that do the following things:
    It checks whether the hostname is valid to send request.
    If not valid: skip. 
    Else continue.
        Generate the URL based on hostname
        Send the request
        Translate the request response to domain response
        Handle exceptions
If the hostnames is empty, generate an empty response
Return response
现在,我们可以做些什么来遵循SRP?正如我所看到的,我们可以把这些行动分成若干组。我看到的是,这些操作可以分为:

HostnameValidator:        checks whether the hostname is valid to send request
--------------
HostnameRequestSender:    Generate the URL
                          Send the request
--------------
HttpToDataResponse:       Translate the request response to domain response
--------------
HostnameExceptionHandler: Handle exceptions
HostnameValidator:        checks whether the hostname is valid to send request
--------------
ValidHostnameData:        Getting list of hostnames
                          Loops through every hostnames that do the following things:
                              Checks whether the hostname is valid to send request
                              If not valid: remove hostname
                              Else: Generate the URL based on hostname
--------------
HostnameRequestSender:    Send the request
--------------
HttpToDataResponse:       Translate the request response to domain response
--------------
HostnameExceptionHandler: Handle exceptions
也就是说,一种分离操作并遵循SRP的方法。还有其他方法,例如简化操作:

First, it is getting list of hostnames
If the hostnames is empty, generate an empty response
Next, it loops through every hostnames that do the following things:
    It checks whether the hostname is valid to send request
    If not valid: remove hostname
    Else: Generate the URL based on hostname
Next, it loops through every valid hostnames that do the following things:
    Send the request
    Translate the request response to domain response
    Handle exceptions
Return response
然后还可以将其分为:

HostnameValidator:        checks whether the hostname is valid to send request
--------------
HostnameRequestSender:    Generate the URL
                          Send the request
--------------
HttpToDataResponse:       Translate the request response to domain response
--------------
HostnameExceptionHandler: Handle exceptions
HostnameValidator:        checks whether the hostname is valid to send request
--------------
ValidHostnameData:        Getting list of hostnames
                          Loops through every hostnames that do the following things:
                              Checks whether the hostname is valid to send request
                              If not valid: remove hostname
                              Else: Generate the URL based on hostname
--------------
HostnameRequestSender:    Send the request
--------------
HttpToDataResponse:       Translate the request response to domain response
--------------
HostnameExceptionHandler: Handle exceptions

当然,还有其他的方法。我将实现细节留白,因为有很多方法可以实现它。

Offtopic:在Spring中使用模板的优势是什么?@PantaRhei RestTemplate是HttpClient上的一个方便的包装器。它只是简化和抽象了一些最常见的用例和代码。
HostnameValidator:        checks whether the hostname is valid to send request
--------------
ValidHostnameData:        Getting list of hostnames
                          Loops through every hostnames that do the following things:
                              Checks whether the hostname is valid to send request
                              If not valid: remove hostname
                              Else: Generate the URL based on hostname
--------------
HostnameRequestSender:    Send the request
--------------
HttpToDataResponse:       Translate the request response to domain response
--------------
HostnameExceptionHandler: Handle exceptions