Единый исполняемый модуль для доступа к серверу, подклассы различных типов запросов: как обеспечить уникальность? - PullRequest
0 голосов
/ 24 января 2019

Вот один класс, который предназначен для связи с сервером:

public abstract class AbstractCommunicationChannel implements Runnable {
    static String SERVER_ADDRESS = "http://0.0.0.0";

    private URL url;
    private JSONObject requestObject;
    private JSONObject responseObject;

    AbstractCommunicationChannel(URL url, JSONObject requestObject) {
        this.url = url;
        this.requestObject = requestObject;
    }

    /**
     * This is the general purpose tool for hitting the server and getting a response back.
     */
    public void run() {
        Log.i("requestObject", requestObject.toString());
        try {
            HttpURLConnection httpUrlConnection = (HttpURLConnection) url.openConnection();
            httpUrlConnection.setDoOutput(true);
            httpUrlConnection.setRequestMethod("POST");
            httpUrlConnection.setRequestProperty("Content-Type", "application/json; charset=utf-8");

            OutputStreamWriter outputStreamWriter = new OutputStreamWriter(httpUrlConnection.getOutputStream());
            outputStreamWriter.write(requestObject.toString());
            outputStreamWriter.flush();
            outputStreamWriter.close();
            /* * */
            InputStream inputStream = httpUrlConnection.getInputStream();
            BufferedInputStream bufferedInputStream = new BufferedInputStream(inputStream);
            ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
            int result = bufferedInputStream.read();
            while (result != -1) {
                byteArrayOutputStream.write((byte) result);
                result = bufferedInputStream.read();
            }
            responseObject = new JSONObject(byteArrayOutputStream.toString("UTF-8"));
            httpUrlConnection.disconnect();
        } catch (Exception ignored) {
        }
        processResponse(responseObject);
    }

    protected abstract void processResponse(JSONObject responseObject);
}

Вот пример подкласса, отвечающего за конкретный тип запроса:

public class LoginRequester extends AbstractCommunicationChannel {

    public LoginRequester(String username, String password) throws Exception {
        super(new URL(SERVER_ADDRESS + ":0000/login"),
            new JSONObject().put("username", username).put("password", password));
    }

    @Override
    protected void processResponse(JSONObject responseObject) {
        try {
            if (responseObject.get("result").equals("valid")) {
                StartActivity.accessAccountActivity();
            }

            if (responseObject.get("result").equals("username")) {
                Toast.makeText(StartActivity.startContext, "No such username exists!", Toast.LENGTH_LONG).show();
            }
            if (responseObject.get("result").equals("password")) {
                Toast.makeText(StartActivity.startContext, "Invalid password!", Toast.LENGTH_LONG).show();
            }
        } catch (Exception ignored) {
        }
    }
}

Для контекста, вот еще:

public class CreateRequester extends AbstractCommunicationChannel {

    public CreateRequester(String username, String password) throws Exception {
        super(new URL(SERVER_ADDRESS + ":8080/create"),
            new JSONObject().put("username", username).put("password", password));
    }

    @Override
    protected void processResponse(JSONObject responseObject) {
        try {
            if (responseObject.get("result").equals("success")) {
                StartActivity.accessAccountActivity();

            } else {

                Toast.makeText(StartActivity.startContext, "ERROR!", Toast.LENGTH_LONG).show();
            }
        } catch (Exception ignored) {
        }
    }
}

Что мне нужно, так это то, что существует только один объект, который может отправлять запросы на сервер, поэтому есть ли способ синхронизировать AbstractCommunicationChannel, чтобы гарантировать, что их не может быть два или более, темы общаются с сервером в любое время?

1 Ответ

0 голосов
/ 24 января 2019

Вы можете использовать блокировку уровня класса в абстрактном классе (если вы используете загрузчик одного класса):

Блокировка уровня класса не позволяет нескольким потокам входить в синхронизированный блок во всех доступных экземплярах класса во время выполнения.

Например:

public abstract class AbstractCommunicationChannel implements Runnable {
   private static Object lock = new Object();

    public void run() {
      synchronized(lock){
        Log.i("requestObject", requestObject.toString());
        try {
            HttpURLConnection httpUrlConnection = (HttpURLConnection) url.openConnection();
            httpUrlConnection.setDoOutput(true);
            httpUrlConnection.setRequestMethod("POST");
            httpUrlConnection.setRequestProperty("Content-Type", "application/json; charset=utf-8");

            OutputStreamWriter outputStreamWriter = new OutputStreamWriter(httpUrlConnection.getOutputStream());
            outputStreamWriter.write(requestObject.toString());
            outputStreamWriter.flush();
            outputStreamWriter.close();
            /* * */
            InputStream inputStream = httpUrlConnection.getInputStream();
            BufferedInputStream bufferedInputStream = new BufferedInputStream(inputStream);
            ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
            int result = bufferedInputStream.read();
            while (result != -1) {
                byteArrayOutputStream.write((byte) result);
                result = bufferedInputStream.read();
            }
            responseObject = new JSONObject(byteArrayOutputStream.toString("UTF-8"));
            httpUrlConnection.disconnect();
        } catch (Exception ignored) {
        }
     }
        processResponse(responseObject);
    }
...