Ich habe eine Klasse, die zwei Methoden hat, die viel doppelten Code haben, aber das Bit, das einzigartig ist, ist in der Mitte der ganzen Sache. Aus meiner Forschung sollte ich das Muster "Execute around method" machen, aber ich kann keine Ressource finden, der ich folgen kann, da sie Code verwenden, den ich nicht replizieren kann.Vermeidung von doppelten Code, wenn das eindeutige Teil innerhalb einer Schleife ist/try-catch
Ich habe zwei Methoden, apiPost und apiGet, die ich unten eingefügt habe. Ich habe die einzigartigen Teile dieser Methoden mit Kommentaren gewickelt zeigen, wo die einzigartige Abschnitt beginnt und endet:
/**
* Class that handles authorising the connection and handles posting and getting data
*
* @version %I%, %G%
* @since 1.0
*/
public class CallHandler {
private static PropertyLoader props = PropertyLoader.getInstance();
final static int MAX = props.getPropertyAsInteger(props.MAX_REQUESTS);
private final Logger log = LoggerFactory.getLogger(CallHandler.class);
private final static String POST = "POST";
private final static String GET = "GET";
/**
* Makes a POST call to the API URL provided and returns the JSON response as a string
* http://stackoverflow.com/questions/15570656/how-to-send-request-payload-to-rest-api-in-java
*
* @param urlString the API URL to send the data to, as a string
* @param payload the serialised JSON payload string
* @return and value returned as a JSON string, ready to be deserialised
*/
public String apiPost(String urlString, String payload) {
boolean keepGoing = true;
int tries = 0;
String line;
StringBuilder jsonString = new StringBuilder();
log.debug("Making API Call: {}", urlString);
while (keepGoing && tries < MAX) {
tries++;
try {
URL url = new URL(urlString);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
// UNIQUE CODE START
prepareConnection(connection, POST);
OutputStreamWriter writer = new OutputStreamWriter(connection.getOutputStream(), "UTF-8");
writer.write(payload);
writer.close();
// UNIQUE CODE END
BufferedReader br = new BufferedReader(new InputStreamReader(connection.getInputStream()));
while ((line = br.readLine()) != null) {
jsonString.append(line);
}
br.close();
connection.disconnect();
keepGoing = false;
} catch (Exception e) {
log.warn("Try #{}. Error posting: {}", tries, e.getMessage());
log.warn("Pausing for 1 second then trying again...");
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException f) {
log.warn("Sleeping has been interrupted: {}", f.getMessage());
}
}
}
return jsonString.toString();
}
/**
* Makes a GET call to the API URL provided and returns the JSON response as a string
* http://stackoverflow.com/questions/2793150/using-java-net-urlconnection-to-fire-and-handle-http-requests
*
* @param urlString the API URL to request the data from, as a string
* @return the json response as a string, ready to be deserialised
*/
public String apiGet(String urlString) {
boolean keepGoing = true;
int tries = 0;
String line;
StringBuilder jsonString = new StringBuilder();
log.debug("Making API Call: {}", urlString);
while (keepGoing && tries < MAX) {
tries++;
try {
URL url = new URL(urlString);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
// UNIQUE CODE START
prepareConnection(connection, GET);
connection.connect();
// UNIQUE CODE END
BufferedReader br = new BufferedReader(new InputStreamReader(connection.getInputStream()));
while ((line = br.readLine()) != null) {
jsonString.append(line);
}
br.close();
connection.disconnect();
keepGoing = false;
} catch (Exception e) {
log.warn("Try #{}. Error getting from API: {}", tries, e.getMessage());
log.warn("Pausing for 1 second then trying again...");
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException f) {
log.warn("Sleeping has been interrupted: {}", f.getMessage());
}
}
}
return jsonString.toString();
}
/**
* Prepares the HTTP Url connection depending on whether this is a POST or GET call
*
* @param connection the connection to prepare
* @param method whether the call is a POST or GET call
*/
private void prepareConnection(HttpURLConnection connection, String method) {
String charset = "UTF-8";
try {
connection.setRequestMethod(method);
if (method.equals(GET)) {
connection.setRequestProperty("Accept-Charset", charset);
} else if (method.equals(POST)) {
connection.setDoInput(true);
connection.setDoOutput(true);
connection.setRequestProperty("Content-Type", "application/json; charset=" + charset);
}
connection.setRequestProperty("Accept", "application/json");
connection.setRequestProperty("Authorization", "Bearer " + apiKey);
} catch (Exception e) {
log.error("Error preparing HTTP URL connection: {}", e.getMessage());
throw new RuntimeException(e.getMessage());
}
}
Kann ich die „Execute um Methode“ Muster hier auf Code-Duplizierung zu retten? Wenn ja, könnte mir jemand helfen, herauszufinden, wie ich diesen Code umgestalten kann, um ihn zu nutzen. Wenn dies der falsche Weg ist, könnte jemand eine kluge Alternative vorschlagen?
Vielen Dank für die Antwort @Andremoniy Ich denke, ich beginne es zu verstehen (obwohl ich etwas über Lambda lesen muss). Gibt es sowieso ohne Lambda dies zu tun, da ich für die Google App Engine entwickle und ich glaube nicht, dass es Java 8 unterstützt: S – SBmore
@SBmore Yep, sicher, schau dir mein Edit an, du kannst anonyme Klasse verwenden – Andremoniy
Danke So viel @Andremoniy, das hat sehr geholfen und ich habe viel gelernt. – SBmore