Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions .idea/libraries/gson_2_9_0.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions java-kanban.iml
Original file line number Diff line number Diff line change
Expand Up @@ -24,5 +24,6 @@
<SOURCES />
</library>
</orderEntry>
<orderEntry type="library" name="gson-2.9.0" level="project" />
</component>
</module>
7 changes: 7 additions & 0 deletions src/ru/yandex/javacourse/exceptions/NotFoundException.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package ru.yandex.javacourse.exceptions;

public class NotFoundException extends RuntimeException {
public NotFoundException(String message) {
super(message);
}
}
19 changes: 19 additions & 0 deletions src/ru/yandex/javacourse/http/HttpStatusCode.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package ru.yandex.javacourse.http;

public enum HttpStatusCode {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

хорошее решение вынести статус коды в енам. лайк!

OK(200),
CREATED(201),
NOT_FOUND(404),
NOT_ACCEPTABLE(406),
INTERNAL_SERVER_ERROR(500);

final int code;

HttpStatusCode(int code) {
this.code = code;
}

public int getCode() {
return code;
}
}
92 changes: 92 additions & 0 deletions src/ru/yandex/javacourse/http/HttpTaskServer.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
package ru.yandex.javacourse.http;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.sun.net.httpserver.HttpServer;
import ru.yandex.javacourse.http.adapter.DurationTypeAdapter;
import ru.yandex.javacourse.http.adapter.LocalDateTimeTypeAdapter;
import ru.yandex.javacourse.http.handler.*;
import ru.yandex.javacourse.model.Epic;
import ru.yandex.javacourse.model.Subtask;
import ru.yandex.javacourse.model.Task;
import ru.yandex.javacourse.service.Managers;
import ru.yandex.javacourse.service.TaskManager;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.time.Duration;
import java.time.LocalDateTime;

public class HttpTaskServer {
private final int port;
private final TaskManager taskManager;
private HttpServer httpServer;
private static Gson gson = new GsonBuilder()
.setPrettyPrinting()
.serializeNulls()
.registerTypeAdapter(LocalDateTime.class, new LocalDateTimeTypeAdapter())
.registerTypeAdapter(Duration.class, new DurationTypeAdapter())
.create();

public HttpTaskServer() {
taskManager = Managers.getDefault();
port = 8080;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

порт даже можно было вынести в константу, но твое решение корректно также

gson = new GsonBuilder()
.setPrettyPrinting()
.serializeNulls()
.registerTypeAdapter(LocalDateTime.class, new LocalDateTimeTypeAdapter())
.registerTypeAdapter(Duration.class, new DurationTypeAdapter())
.create();
}

public HttpTaskServer(TaskManager taskManager) {
this.taskManager = taskManager;
port = 8080;
}

public HttpTaskServer(TaskManager taskManager, int port) {
this.taskManager = taskManager;
this.port = port;
}

public static Gson getGson() {
return gson;
}

public static void main(String[] args) throws IOException {
HttpTaskServer httpTaskServer = new HttpTaskServer();
httpTaskServer.start();
httpTaskServer.taskManager.addTask(new Task("Звонок бабушке",
"Позвонить, чтобы узнать новости"));
httpTaskServer.taskManager.addTask(new Task("Стирка",
"Постирать белые вещи"));

Epic epic1 = httpTaskServer.taskManager.addEpic(new Epic("Сделать домашнее задание",
"Задание для 6 спринта"));
httpTaskServer.taskManager.addSubtask(new Subtask("Изучить теорию",
"Прочитать теорию на сайте", epic1.getId()));
httpTaskServer.taskManager.addSubtask(new Subtask("Освоить тренажёр",
"Выполнить все задания", epic1.getId()));
httpTaskServer.taskManager.addSubtask(new Subtask("Прослушать вебинар",
"Подключиться на вебинар в среду", epic1.getId()));

//httpTaskServer.stop();

}

public void start() throws IOException {
httpServer = HttpServer.create(new InetSocketAddress(port), 0);
httpServer.createContext("/tasks", new TaskHandler(taskManager, gson));
httpServer.createContext("/subtasks", new SubtaskHandler(taskManager, gson));
httpServer.createContext("/epics", new EpicHandler(taskManager, gson));
httpServer.createContext("/history", new HistoryHandler(taskManager, gson));
httpServer.createContext("/prioritized", new PrioritizedHandler(taskManager, gson));
httpServer.start();
System.out.println("HTTP-сервер запущен на " + port + " порту!");
}

public void stop() {
httpServer.stop(1);
System.out.println("HTTP-сервер остановлен на " + port + " порту!");
}
}
33 changes: 33 additions & 0 deletions src/ru/yandex/javacourse/http/adapter/DurationTypeAdapter.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package ru.yandex.javacourse.http.adapter;

import com.google.gson.TypeAdapter;
import com.google.gson.stream.JsonReader;
import com.google.gson.stream.JsonWriter;

import java.io.IOException;
import java.time.Duration;

public class DurationTypeAdapter extends TypeAdapter<Duration> {
@Override
public void write(JsonWriter jsonWriter, Duration duration) throws IOException {
if (duration == null) {
jsonWriter.nullValue();
} else {
jsonWriter.value(String.valueOf(duration.toMinutes()));
}
}

@Override
public Duration read(JsonReader jsonReader) throws IOException {
try {
String value = jsonReader.nextString();
if (value == null || value.equals("null")) {
return null;
}
return Duration.ofMinutes(Long.parseLong(value));
} catch (Exception e) {
jsonReader.nextNull();
return null;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

да корректно. но увлекаться возвратами null нужно очень аккуратно так как это может привести к скрытым багам npe

}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package ru.yandex.javacourse.http.adapter;

import com.google.gson.TypeAdapter;
import com.google.gson.stream.JsonReader;
import com.google.gson.stream.JsonWriter;

import java.io.IOException;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;

public class LocalDateTimeTypeAdapter extends TypeAdapter<LocalDateTime> {
private final DateTimeFormatter timeFormatter = DateTimeFormatter.ofPattern("dd.MM.yyyy HH:mm:ss");

@Override
public void write(JsonWriter jsonWriter, LocalDateTime localDateTime) throws IOException {
if (localDateTime == null) {
jsonWriter.nullValue();
} else {
jsonWriter.value(localDateTime.format(timeFormatter));
}
}

@Override
public LocalDateTime read(JsonReader jsonReader) throws IOException {
try {
String value = jsonReader.nextString();
if (value == null || value.equals("null")) {
return null;
}
return LocalDateTime.parse(value, timeFormatter);
} catch (Exception exception) {
jsonReader.nextNull();
return null;
}
}
}
96 changes: 96 additions & 0 deletions src/ru/yandex/javacourse/http/handler/BaseHttpHandler.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
package ru.yandex.javacourse.http.handler;

import com.google.gson.Gson;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import com.sun.net.httpserver.HttpExchange;
import com.sun.net.httpserver.HttpHandler;
import ru.yandex.javacourse.http.HttpStatusCode;
import ru.yandex.javacourse.service.TaskManager;

import java.io.IOException;
import java.io.OutputStream;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.Optional;

abstract class BaseHttpHandler implements HttpHandler {
private static final Charset DEFAULT_CHARSET = StandardCharsets.UTF_8;
protected TaskManager taskManager;
protected Gson gson;

protected BaseHttpHandler(TaskManager taskManager, Gson gson) {
this.taskManager = taskManager;
this.gson = gson;
}

/**
* Основной метод, который обрабатывает входящий запрос
*/
@Override
public abstract void handle(HttpExchange exchange) throws IOException;

/**
* Отправляет ответ от сервера клиенту с указанным кодом.
* Используется для отправки 200 и 201 ответов
*/
protected void sendText(HttpExchange exchange, String response, int responseCode) {
try (OutputStream outputStream = exchange.getResponseBody()) {
exchange.getResponseHeaders().add("Content-Type", "application/json;charset=utf-8");
exchange.sendResponseHeaders(responseCode, 0);
outputStream.write(response.getBytes(DEFAULT_CHARSET));
} catch (IOException exception) {
System.out.println("Возникла проблема при отправке ответа выполнения метода");
}
}

/**
* Отправляет ответ от сервера клиенту с кодом 404.
* Используется для отправки сообщения о том, что элемент не найден
*/
protected void sendNotFound(HttpExchange exchange, String response) {
try (OutputStream outputStream = exchange.getResponseBody()) {
exchange.getResponseHeaders().add("Content-Type", "application/json;charset=utf-8");
exchange.sendResponseHeaders(HttpStatusCode.NOT_FOUND.getCode(), 0);
outputStream.write(response.getBytes(DEFAULT_CHARSET));
} catch (IOException exception) {
System.out.println("Возникла проблема при отправке ответа о том, что элемент не найден");
}
}

/**
* Отправляет ответ от сервера клиенту с кодом 406.
* Используется для отправки сообщения о том, что элемент пересекается с уже существующими
*/
protected void sendHasInteractions(HttpExchange exchange, String response) {
try (OutputStream outputStream = exchange.getResponseBody()) {
exchange.getResponseHeaders().add("Content-Type", "application/json;charset=utf-8");
exchange.sendResponseHeaders(HttpStatusCode.NOT_ACCEPTABLE.getCode(), 0);
outputStream.write(response.getBytes(DEFAULT_CHARSET));
} catch (IOException exception) {
System.out.println("Возникла проблема при отправке ответа о том, что объект пересекается с существующим");
}
}

/**
* Возвращает Id задачи из запроса
*/
public Optional<Integer> getIdFromRequestBody(String requestBody) {
JsonElement jsonElement = JsonParser.parseString(requestBody);

if (!jsonElement.isJsonObject()) {
System.out.println("Невозможно получить номер задачи. Проверьте корректность запроса");
return Optional.empty();
}

JsonObject jsonObject = jsonElement.getAsJsonObject();
JsonElement idElement = jsonObject.get("id");

if (idElement == null || idElement.getAsInt() == 0) {
return Optional.empty();
}

return Optional.of(idElement.getAsInt());
}
}
Loading