我目前有两面旗帜。一个是remoteFlag
,另一个是secondaryFlag
。默认情况下,如果他们想要在我们的应用程序调用时更改它们,则客户可以更改它们。所以可能发生的组合是 -
remoteFlag secondaryFlag
true true
true false
false false
false true
默认情况下,它始终为真。
我应该对我们的服务器进行HTTP调用(所有服务器都是Ubunutu机器)。假设下面是我的服务器,其中完全限定的主机名对应于unix中的hostname -f
。
String hostname1 = hostname1;
String hostname2 = hostname2;
String hostname3 = hostname3;
String hostname4 = hostname4;
我有几个我应该按照以下描述做的案例 -
remoteFlag
和secondaryFlag
两者都是true
,那么我
我应该一个接一个地击中所有上述服务器,直到我们得到
从服务器回复。意思是假设hostname1
已关闭
所以我们不会从那些服务器得到任何响应,它会
抛出异常然后我们将转到hostname2
来获取
相同的数据,但假设如果hostname2
也失效,那么我们就会去
hostname3
获取数据,但假设hostname3
也是
然后我们将转到hostname4
来获取数据。但如果有的话
服务器能够给出响应然后我们将返回
通过做出适当的回应说我们已经得到了数据。
如果没有一台服务器能够回复那么我们
将发出错误回复,说明所有服务器都已关闭。remoteFlag
为true
且secondaryFlag
为false
,则
我们只会转到hostname1
和hostname3
。如果是hostname1
然后我们将转到hostname3
以获得回复。如果两者都有
他们失败了,然后我们会做一个ERROR响应说服务器
落下了。remoteFlag
为false
且secondaryFlag
为false
,则
我们只会去hostname1
,这就是全部。如果hostname1
失效,
那么我们将做出一个ERROR响应,说服务器已关闭。remoteFlag
为false
且secondaryFlag
为true
,则
我们只会转到hostname1
和hostname2
,这就是全部。如果
hostname1
已关闭,然后我们会转到hostname2
获取
响应。如果两者都失效,那么我们将犯一个错误
响应说服务器已关闭。下来我的意思是服务器没有启动,所以这就是他们没有响应的原因。我尝试了其中一个已关闭的服务器,如果我尝试命中该服务器,RestTemplate
会抛出异常。
以下是我的代码到目前为止仅适用于remoteFlag
和secondaryFlag
两者都是真的但是它再次看起来不是很好的代码,因为我只是在下面的代码中重复一下。我不知道如果其中任何一个服务器关闭,我如何继续递归调用服务器。但是,如果其中任何一个已经启动并得到正确的响应,那么通过使用我获得的实际数据进行SUCCESS响应来返回调用。
下面是
public class ClientTask implements Callable<ClientResponse> {
public ClientTask(ClientKey clientKeys) {
this.clientKeys = clientKeys;
}
@Override
public ClientResponse call() throws Exception {
....
boolean remoteFlag = clientKeys.isRemoteFlag();
boolean secondaryFlag = clientKeys.isSecondaryFlag();
RestTemplate restTemplate = new RestTemplate();
String response = null;
...
String hostname1 = hostname1;
String hostname2 = hostname2;
String hostname3 = hostname3;
String hostname4 = hostname4;
// first use case when both are true
if(remoteFlag && secondaryFlag) {
if(hostname1 != null) {
try {
String url = generateURL(hostname1);
response = restTemplate.getForObject(url, String.class);
return new ClientResponse(response, ClientError.NONE, ClientStatus.SUCCESS);
} catch(Exception ex) {
ex.printStackTrace(); // use logger
}
}
// hostname1 is down
if(response == null && hostname2 != null) {
try {
String url = generateURL(hostname2);
response = restTemplate.getForObject(url, String.class);
return new ClientResponse(response, ClientError.NONE, ClientStatus.SUCCESS);
} catch(Exception ex) {
ex.printStackTrace(); // use logger
}
}
// hostname1 and 2 both are down
if(response == null && hostname3 != null) {
try {
String url = generateURL(hostname3);
response = restTemplate.getForObject(url, String.class);
return new ClientResponse(response, ClientError.NONE, ClientStatus.SUCCESS);
} catch(Exception ex) {
ex.printStackTrace(); // use logger
}
}
// hostname1, 2, 3 are down
if(response == null && hostname4 != null) {
try {
String url = generateURL(hostname4);
response = restTemplate.getForObject(url, String.class);
return new ClientResponse(response, ClientError.NONE, ClientStatus.SUCCESS);
} catch(Exception ex) {
ex.printStackTrace(); // use logger
}
}
}
// not sure how to add other use case logic here as well properly
}
/**
* Method to generate the url to hit the servers.
*
*/
private String generateURL(final String hostname) {
StringBuffer url = new StringBuffer();
url.append("http://" + hostname + ":8080/user?userId=" + clientKeys.getUserId() + "&page_id=" + clientKeys.getPageId());
Set<Entry<String, String>> params = clientKeys.getAttributeMap().entrySet();
for(Entry<String, String> e : params){
url.append("&" + e.getKey());
url.append("=" + e.getValue());
}
return url.toString();
}
}
ProblemStatement: -
在上面的代码中,我只是一直在重复内容,不知道在收到响应之前我如何递归地继续调用服务器。以及如何在上面的代码中也适合其他用例。最初我想为其他用例添加相同的if块。然后我认为我的整个代码将填充if if only。
任何想法如何有效地解决这个问题?
答案 0 :(得分:2)
您的代码中有很多样板。只需填写if语句中的主机列表,即可轻松避免它们。然后迭代该列表:
List<String> hostnames = new ArrayList<>();
if(remoteFlag && secondaryFlag) {
hostnames.add(hostname1);
hostnames.add(hostname2);
} else if …
for (String hostname : hostnames) {
if(hostname == null) {
continue;
}
try {
String url = generateURL(hostname1);
response = restTemplate.getForObject(url, String.class);
break;
} catch(Exception ex) {
ex.printStackTrace(); // use logger
}
}
if (response == null) {
// do error handling
}
return new ClientResponse(response, ClientError.NONE, ClientStatus.SUCCESS);
我个人更喜欢另一种解决方案。构建一个表达状态转换并链接这些组件的组件:
public class FallbackCall() {
private String hostname;
private String secondaryHostname;
private FallbackQuery next;
public ClientResponse call(boolean remote, boolean secondary) {
ClientResponse response = getResponse(hostname);
if (response == null && secondary) {
reponse = getResponse(secondaryHostname);
}
if (response == null && remote) {
reponse = next.call(remote, secondary);
}
return response;
}
private ClientResponse getResponse(String hostname) {
// your boiler plate
}
}
答案 1 :(得分:0)
一个想法是将检索提取到另一种方法(甚至可能是“静态”),如此
// I don't recognize your library...
public ClientResponse call(String hostname) throws Exception {
if (hostname == null) {
return null;
}
// You might also make generateURL static
String url = generateURL(hostname);
String response = restTemplate.getForObject(url,
String.class);
if (response == null) { // add more logic here to test your response.
return null;
}
return new ClientResponse(response,
ClientError.NONE, ClientStatus.SUCCESS);
}
然后你可以逐个传递你的网址,直到你得到一个好的回应。像这样,
// String hostname1 = hostname1;
// String hostname2 = hostname2;
// String hostname3 = hostname3;
// String hostname4 = hostname4;
if(remoteFlag && secondaryFlag) {
ClientResponse response = call(hostname1);
// != null is one test. However you test the response is valid.
if (response != null) return response;
response = call(hostname2);
if (response != null) return response;
response = call(hostname3);
if (response != null) return response;
return call(hostname4);
}