Простой HTTP-сервер на Java
Вы хотите реализовать HTTP-сервер , но не хотите рисковать написанием полноценного HTTP-сервера? Разработка HTTP-сервера с полной функциональностью не является тривиальной задачей. Но у Java есть решение этой проблемы. Java поддерживает встроенный HTTP-сервер. Просто написав 100 строк кода, мы можем разработать несколько приличный HTTP-сервер, который может обрабатывать запросы. Мы также можем использовать его для обработки других HTTP-команд.
HTTPServer
Java SDK предоставляет встроенный сервер под названием HttpServer
. Этот класс относится к пакету com.sun.net
.
Мы можем создать экземпляр сервера следующим образом:
HttpServer server = HttpServer.create(new InetSocketAddress("localhost", 8001), 0);
Приведенная выше строка создает экземпляр HTTPServer
на локальном узле с номером порта 8001. Но есть еще один аргумент со значением 0. Это значение используется для обратной регистрации .
Очередь выполнения запросов
Когда сервер принимает запрос клиента, этот запрос сначала будет поставлен в очередь операционной системой. Позже он будет передан на сервер для обработки запроса. Все эти одновременные запросы будут поставлены в очередь операционной системой. Однако операционная система сама решит, сколько из этих запросов может быть поставлено в очередь в любой данный момент времени. Это значение представляет обратную регистрацию. В нашем примере это значение равно 0, что означает, что мы не ставим в очередь никаких запросов.
Код сервера
Мы собираемся разработать следующий HTTP-сервер:
server.createContext("/test", new MyHttpHandler());
server.setExecutor(threadPoolExecutor);
server.start();
logger.info(" Server started on port 8001");
Мы создали контекст под названием test
. Это не что иное, как корень контекста приложения. Второй параметр - это экземпляр обработчика, который будет обрабатывать HTTP-запросы. Мы рассмотрим этот класс в ближайшее время.
Мы можем использовать исполнителя пула потоков вместе с этим экземпляром сервера. В нашем случае мы создали пул из 10 потоков.
ThreadPoolExecutor threadPoolExecutor = (ThreadPoolExecutor)Executors.newFixedThreadPool(10);
Далее запускаем сервер:
server.start();
С помощью всего трех-четырех строк кода мы создали HTTP-сервер с корневым контекстом, который прослушивает порт!
HTTPHandler
Это интерфейс с вызванным методом handle(..)
. Давайте посмотрим на нашу реализацию этого интерфейса.
private class MyHttpHandler implements HttpHandler {
@Override
public void handle(HttpExchange httpExchange) throws IOException {
String requestParamValue=null;
if("GET".equals(httpExchange.getRequestMethod())) {
requestParamValue = handleGetRequest(httpExchange);
} else if("POST".equals(httpExchange)) {
requestParamValue = handlePostRequest(httpExchange);
}
handleResponse(httpExchange,requestParamValue);
}
private String handleGetRequest(HttpExchange httpExchange) {
return httpExchange.
getRequestURI()
.toString()
.split("\\?")[1]
.split("=")[1];
}
private void handleResponse(HttpExchange httpExchange, String requestParamValue) throws IOException {
OutputStream outputStream = httpExchange.getResponseBody();
StringBuilder htmlBuilder = new StringBuilder();
htmlBuilder.append("").
append("").
append("").
append("Hello ")
.append(requestParamValue)
.append("
")
.append("")
.append("");
// encode HTML content
String htmlResponse = StringEscapeUtils.escapeHtml4(htmlBuilder.toString());
// this line is a must
httpExchange.sendResponseHeaders(200, htmlResponse.length());
outputStream.write(htmlResponse.getBytes());
outputStream.flush();
outputStream.close();
}
}
Это код, который обрабатывает запрос и отправляет ответ клиенту. Запрос и ответ обрабатываются классом HttpExchange
.
Обработка запроса GET
Запрос GET обрабатывается методом handleGETRequest()
. Этот метод, в свою очередь, вызывает метод getRequestURI()
класса HttpExchange
для извлечения значения параметра запроса, содержащегося в URI. Это минимальный метод, который будет обрабатывать только один параметр, присутствующий в запросе. Тем не менее, это может быть изменено для удовлетворения различных требований.
Обработка ответа
Наконец, мы собираемся отправить наш ответ обратно клиенту. Это достигается методом handleResponse(..)
. В этом методе мы получаем выходной поток, вызывая метод getResponseBody()
класса HttpExchange
. Позже мы можем записать содержимое HTML в выходной поток.
Наиболее важным моментом является отправка response header
обратно клиенту. Если вы пропустите это, вы получите сообщение об ошибке в браузере ERR_EMPTY_RESPONSE
.
Если все идет хорошо, вы можете увидеть ответ в браузере запросив URL: http://localhost:8001/test?name=sam