编程语言
首页 > 编程语言> > java – 当唯一部分在循环/ try-catch中时避免重复代码

java – 当唯一部分在循环/ try-catch中时避免重复代码

作者:互联网

我有一个类有两个方法,有很多重复的代码但是唯一的位在整个事件的中间.根据我的研究,我认为我应该做“执行周围方法”模式,但我找不到我可以遵循的资源,因为他们似乎都使用我无法复制的代码.

我有两种方法,apiPost和apiGet,我已粘贴在下面.我已经将这些方法的独特部分包装在一起,注释显示了唯一部分的开始和结束位置:

/**
 * 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
     * https://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
     * https://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());
        }
    }

我可以使用“执行周围方法”模式来保存代码重复吗?如果是这样,有人可以帮我弄清楚如何重构这段代码来使用它.如果这是错误的方式,那么有人会提出一个明智的替代方案吗?

解决方法:

可以通过将“唯一”代码提取到特殊工作者中来完成.更具体地说,例如,您可以使用lambda表达式:

public String apiPost(String urlString, String payload) {
    return commonMethod(urlString, payload, (connection) -> {
        // UNIQUE CODE START
        prepareConnection(connection, POST);
        OutputStreamWriter writer = new OutputStreamWriter(connection.getOutputStream(), "UTF-8");
        writer.write(payload);
        writer.close();
        // UNIQUE CODE END
    });
}

interface ConnectionWorker {
    void run(HttpURLConnection connection) throws IOException;
}

public String commonMethod(String urlString, String payload, ConnectionWorker worker) {
    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();

            worker.run(connection);

            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();
}

更新:如果你不能使用java 8和lambda,你总是可以切换到创建匿名类:

    return commonMethod(urlString, payload, new ConnectionWorker() {
        @Override
        public void run(HttpURLConnection connection) throws IOException {
            // UNIQUE CODE START
            CallHandler.this.prepareConnection(connection, POST);
            OutputStreamWriter writer = new OutputStreamWriter(connection.getOutputStream(), "UTF-8");
            writer.write(payload);
            writer.close();
            // UNIQUE CODE END
        }
    }); 

标签:java,code-duplication
来源: https://codeday.me/bug/20190608/1199533.html