Простой 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(..) . Давайте посмотрим на нашу реализацию этого интерфейса.
«). append(«Hello «) .append(requestParamValue) .append(«
Клиент-сервер на Java
Это первое приложение в односторонней связи. В случае односторонней связи клиент отправляет на сервер, но сервер не отправляет обратно клиенту. При двусторонней связи клиент отправляет на сервер, а сервер отправляет обратно клиенту.
Всего в приложении TCP / IP 4 варианта.
| APPLICATION NUMBER | FUNCTIONALITY |
|---|---|
| 1st application | Client to server communication (one-way) |
| 2nd application | Server to client communication (one-way) |
| 3rd application | Server sends file contents to client (two-way, non-continuous) |
| 4th application | Chat program (two-way, continuous) |
1-е Приложение клиент-сервер
Приложение состоит из двух программ. Клиентская программа, работающая на стороне клиента, и серверная программа, работающая на стороне сервера. Клиентская программа WishesClient.java отправляет серверу наилучшие пожелания, а серверная программа WishesServer.java получает сообщение и печатает на своем терминале (мониторе).
Клиентская программа – WishesClient.java
import java.net.Socket; import java.io.OutputStream; import java.io.DataOutputStream; public class WishesClient < public static void main(String args[]) throws Exception < Socket sock = new Socket("127.0.0.1", 5000); String message1 = "Accept Best Wishes, Serverji"; OutputStream ostream = sock.getOutputStream(); DataOutputStream dos = new DataOutputStream(ostream); dos.writeBytes(message1); dos.close(); ostream.close(); sock.close(); >> Socket sock = new Socket ("127.0.0.1", 5000);
Конструктор класса Socket принимает два параметра – строку, IP-адрес сервера и целое число, номер порта на сервере, к которому клиент хотел бы подключиться. 127.0.0.1 – это адрес по умолчанию локальной системы в компьютерных сетях.
OutputStream ostream = sock.getOutputStream ();
Метод getOutputStream() класса Socket возвращает объект OutputStream, здесь объект является ostream. Это отправная точка всего общения (программы). Здесь сокет связан с потоками. Потоки способствуют передаче данных.
DataOutputStream dos = new DataOutputStream (ostream); dos.writeBytes (message1);
OutputStream является абстрактным классом; он не может быть использован напрямую. В приведенном выше коде он связан с конкретным классом DataOutputStream. Метод writeBytes() объекта DataOutputStream принимает строковое сообщение и передает его в Socket. Теперь клиентский сокет отправляется на другой сокет на сервере. Когда работа закончится, закройте потоки и сокет. Он освобождает дескрипторы (ссылки), связанные с системными ресурсами.
Ниже приведены исключения в вышеприведенной программе, создаваемые конструктором и различными методами.
- Socket(“127.0.0.1”, 5000) выдает UnknownHostException
- getOutputStream() генерирует IOException
- writeBytes (message1) выдает IOException
- Все методы close() выдают IOException
- Серверная программа – WishesServer.java
import java.net.ServerSocket; import java.net.Socket; import java.io.InputStream; import java.io.DataInputStream; public class WishesServer < public static void main(String args[]) throws Exception < ServerSocket sersock = new ServerSocket(5000); System.out.println("server is ready"); // message to know the server is running Socket sock = sersock.accept(); InputStream istream = sock.getInputStream(); DataInputStream dstream = new DataInputStream(istream); String message2 = dstream.readLine(); System.out.println(message2); dstream .close(); istream.close(); sock.close(); sersock.close(); >>
ServerSocket sersock = новый ServerSocket (5000);
У сервера есть два задания: одно, как и ожидалось, должно связываться, а другое связывает соединение с номером порта 5000. Для связи он использует Socket, а для привязки – ServerSocket.
Связывание – это не что иное, как выделение номера порта клиенту так долго, как ему хотелось бы; Между тем, если какой-либо другой клиент запрашивает номер порта 5000, он не должен выделяться сервером. Когда клиент отключается, порт освобождается и может быть предоставлен другому клиенту сервером.
Socket sock = sersock.accept ();
accept() – это метод класса ServerSocket, используемый сервером для привязки соединения по номеру порта 5000, запрошенного клиентом.
InputStream istream = sock.getInputStream();
Метод getInputStream() объекта Socket возвращает объект InputStream, и это отправная точка серверной программы. Сервер использует входной поток при получении сообщения.
DataInputStream dstream = new DataInputStream (istream);
Поскольку InputStream является абстрактным классом, его нельзя использовать напрямую. Он связан с конкретным классом DataInputStream.
String message2 = dstream.readLine();
Метод readLine() объекта DataInputStream читает строку сообщения из сокета и возвращает ее. Это сообщение печатается на консоли.
Примечание. При компиляции этой программы вы получаете предупреждение из-за метода readLine() объекта DataInutStream; но программа выполняется. Чтобы избежать этого предупреждения, в следующей программе используется BufferedReader.
Выполнение клиентских и серверных программ
В одной системе, чтобы действовать как клиент и сервер, откройте два шDOS и обработайте одно как клиент, а другой – как сервер. Из одного приглашения DOS сначала запустите серверную программу, а из другого приглашения DOS запустите клиентскую программу. Вы получаете вывод при запросе сервера DOS.
Это приложение и следующее – только односторонняя связь, отправляющая или получающая. Но второй набор (после следующего) приложений является двусторонним, когда клиент и сервер могут отправлять и получать (оба). Для тестирования на выделенных серверах, можно обратиться сюда https://www.mixtelecom.ru/arenda-serverov.html
Для лучшего понимания вопрос-ответ из пакета java.lang.
Сколько существует типов внутренних классов?
Ответ: 4 типа.
Что такое файлы JAR?
Ответ: JAR-файл – это заархивированный файл, сжатый JVM.
Как преобразовать строку в форму типа данных?
Ответ: Преобразование строки в тип данных – байтовое, короткое, целое, длинное, плавающее, двойное, символьное и логическое.
Как преобразовать объект в строку?
Ответ: Объект в строку – toString()
Как сравнить два объекта?
Ответ: Сравнение объектов – hashCode() & equals()
Средняя оценка 3.1 / 5. Количество голосов: 16
Спасибо, помогите другим — напишите комментарий, добавьте информации к статье.
Или поделись статьей
Видим, что вы не нашли ответ на свой вопрос.
Помогите улучшить статью.
Напишите комментарий, что можно добавить к статье, какой информации не хватает.
Как быстро создать свой java сервер? [закрыт]
Закрыт. Этот вопрос необходимо уточнить или дополнить подробностями. Ответы на него в данный момент не принимаются.
Хотите улучшить этот вопрос? Добавьте больше подробностей и уточните проблему, отредактировав это сообщение.
Закрыт 2 года назад .
Есть ли что нибудь простое для начинающего
Отслеживать
Alexander Yanchuk
задан 16 дек 2020 в 14:04
Alexander Yanchuk Alexander Yanchuk
19 3 3 бронзовых знака
Что это, статья? Здесь, как правило, задают вопросы, а не пишут статьи. Впрочем, вы можете оформить свой вопрос в виде QA — только перенесите ту часть, которая содержит ответ, в ответ
16 дек 2020 в 14:28
Позже отметьте свой ответ как верный(если не будет других, которые вам больше понравятся). Для этого нужно нажать на галочку напротив ответа. Но если я не ошибаюсь, то новичкам доступно принятие своего ответа, только спустя 3 дня после публикации (могу ошибаться).
16 дек 2020 в 14:46
Понятно теперь, почему у русскоязычной версии вашего сайта такой низкий рейтинг. Этот вопрос очень популярен в англоязычных ресурсах. А ваших модераторов он не интересует. Пока. Здесь больше не пишу.
17 дек 2020 в 11:16
1 ответ 1
Сортировка: Сброс на вариант по умолчанию
Иногда необходимо сделать простой HTTP java сервер, который отвечает на GET и POST запросы используя MySql базу данных и не тратить время на разворачивание Tomcat или ему подобного громоздкого ПО.
На базе предлагаемых абстрактных классов получается очень эффективный(каждый запрос обрабатывается в отдельном потоке) сервер, на базе которого некоторое время назад был создан Биддер, который побил все рекорды скорости на электронных биржах по торговле контекстной рекламой. Хочу поделиться как это можно сделать:
Сначала нужно скачать jar библиотеку по этой ссылке и включить ее в свой проект. Затем создать класс с main методом и унаследовать его от YaaServer класса
import com.yaa.server.YaaServer; public class MyServer extends YaaServer < public static void main(String[] args) < // TODO Auto-generated method stub >>
Абстрактный класс YaaServer потребует генерирование нескольких методов и конструктора. Позволим ему это сделать:
import java.io.IOException; import java.sql.Connection; import com.yaa.server.YaaServer; import com.yaa.server.YaaServlet; public class MyServer extends YaaServer < public MyServer(int port) throws IOException < super(port); // TODO Auto-generated constructor stub >public static void main(String[] args) < // TODO Auto-generated method stub >@Override protected Connection getConnection() < // TODO Auto-generated method stub return null; >@Override protected Class getServletClass(int arg0) < // TODO Auto-generated method stub return null; >@Override protected String getServletContext(int arg0) < // TODO Auto-generated method stub return null; >@Override protected int howManyServlets() < // TODO Auto-generated method stub return 0; >@Override protected boolean isLog() < // TODO Auto-generated method stub return false; >@Override protected String setServerName() < // TODO Auto-generated method stub return null; >>
Осталось совсем немного. Вставляем в main new MyServer(8080).start(); и получаем:
public static void main(String[] args) < try < new MyServer(8080).start(); >catch (IOException e) < // TODO Auto-generated catch block e.printStackTrace(); >>
Наш сервер почти готов. Дадим ему имя в методе setServerName()
protected String setServerName()
и запустим. В консоли увидим сообщение:
My First javaServer Server started. Listening for connections on port : 8080 .
Совершенно верно ваш сервер слушает порт 8080 на вашем компьютере. Осталось совсем чуть чуть. Нужно заполнить этот сервер обработчиками HTTP запросов.
Создадим обработчик GET запроса, который обрабатывает личные данные пользователя имя и возраст. В адресной строке браузера такой запрос будет выглядеть так:
http://localhost:8080/myserver?name=Иван&age=19
Сейчас на этот запрос браузер выведет 404 Not Found. Посмотрим, что он выведет потом. Итак:
1. В методе howManyServlets() — количество обработчиков, ставим return 1 ;
2. в методе getServletContext меняем return
protected String getServletContext(int i) < return new String[] < "/myserver" >[i]; >
Это означает, что к нашему обработчику будет идти обращение по контексту /myserver , смотрите строку запроса из браузера;
3. Меняем getServletClass следующим образом:
protected Class getServletClass(int i) < return new Class[] < Myservlet.class >[i]; >
Этим мы указываем, что по контексту /myserver будет обработчик в классе с именем Myservlet .
Eclipse (или какая там у вас ide) Требует создать этот класс. Создаем и наследуем его от YaaServlet. Разрешаем генерацию абстрактных методов и конструктора и получаем:
import java.sql.Connection; import java.util.Map; import com.yaa.server.YaaServlet; public class Myservlet extends YaaServlet < public Myservlet(Connection conn, Mapget_request, String post_request) < super(conn, get_request, post_request); // TODO Auto-generated constructor stub >@Override protected String getResponcse() < // TODO Auto-generated method stub return null; >>
conn — это коннектор к базе MySql, мы его пока не используем;
get_request — GET параметры в виде HashMap коллекции;
post_request — строка POST запроса.
Осталось написать ответ на GET запрос:
protected String getResponcse()
Теперь перезапускаем сервер и повторяем наш запрос из браузера. Если мы все сделали правильно, то в браузере увидим:
Привет Иван! Твой возраст 19 лет.
Обработку POST запроса предлагаю вам сделать самостоятельно. В этом примере мы не подключали базу данных. Чтобы это сделать необходимо в методе getConnection() сервера поставить подключение драйвера. Примерно так return conn = DriverManager.getConnection(«jdbc:mysql://. «);
Кстати в обработчике не надо закрывать базу — не пишите conn.close() .
Как написать сервер на java
Архитектура современных приложений состоит из отдельных модулей, как показано на рисунке выше. Эти модули часто называют Frontend и Backend. Frontend – это модуль, который отвечает за юзер-интерфейс и логику, которые предоставляется приложением при использовании. Так, например когда мы заходим в соцсети через браузер, мы взаимодействуем именно с FrontEnd-модулем приложения. То, как отображаются наши посты в виде сторисов или карточек, сообщения и другие активности реализуются именно в FrontEnd-модуле. А все данные, которые мы видим, хранятся и обрабатываются в Backend или серверной части приложения. Эти модули обмениваются между собой посредством разных архитектурных стилей: REST, GRPC и форматов сообщений – JSON и XML.
В этой статье мы напишем примитивную серверную часть социальной сети с использованием Spring Boot, запустим свой сервер, рассмотрим разные типы HTTP запросов и их применение.
Необходимое требование к читателю: умение писать на Java и базовые знания Spring Framework. Данная статья познакомит вас со Spring Boot и даст базовые понятия данного фреймворка.
☕ Подтянуть свои знания по Java вы можете на нашем телеграм-канале «Библиотека Java для собеса»
Инициализация проекта
Чтобы создать Spring Boot проект, перейдем на страницу https://start.spring.io/ и выберем необходимые зависимости: в нашем случае Spring Web. Чтобы запустить проект, необходима минимальная версия Java 17. Скачиваем проект и открываем в любом IDE (в моем случае – Intellij Idea)

Spring Web – зависимость, которая предоставляет контейнер сервлетов Apache Tomcat (является дефолтным веб-сервером). Проще говоря, сервлеты – это классы, которые обрабатывают все входящие запросы.
Открываем проект и запускаем.

Мы видим, что проект запустился и готов обрабатывать запросы на порту 8080 – Tomcat started on port(s): 8080 (http) .
Теперь создадим свой первый класс – GreetingController . Controller-классы ответственны за обработку входящих запросов и возвращают ответ.
Чтобы сделать наш класс Controller , достаточно прописать аннотацию @RestController . @RequestMapping указывает, по какому пути будет находиться определённый ресурс или выполняться логика.

Если отправить запрос по адресу http://localhost:8080/ , мы получим ошибку, т. к. по этому пути не определены логика обработки запроса и ресурсы.
☕ Интересные задачи по Java для практики можно найти на нашем телеграм-канале «Библиотека задач по Java»
Request Params
При отправке запросов мы часто используем переменные в запросе, чтобы передавать дополнительную информацию или же делать запросы гибкими. Параметр в запросе передаётся в конце адреса ( =url ) сервера и указывается после вопросительного знака ( =? ).
Например, http://localhost:8080/greet?name=Alice . Параметр запроса является = name cо значением = Alice .
Чтобы обрабатывать переменную запроса, используется аннотация @RequestParam . Параметры запроса могут быть опциональными или же обязательными. @RequestParam(«name») означает следующее: взять ту переменную из запроса, название которого равно name .

Вдобавок, запрос может содержать несколько параметров.
Например, http://localhost:8080/greet/full?name=John&surname=Smith . Параметры выделяются знаком & . В этом запросе два параметра: name=John и surname=Smith .
Чтобы обработать каждый параметр запроса, нужно пометить каждую переменную @RequestParam .

Path Variable
PathVariable по применению похож на @Request Param . @PathVariable также является параметром запроса, но используются внутри адреса запроса. Например,
RequestParam – http://localhost:8080/greet/full?name=John&surname=Smith
PathVariable – http://localhost:8080/greet/John . В этом случае John является PathVariable.
В запросе можно указывать несколько PathVariable, как и в случае RequestParam

Запрос с двумя параметризованными PathVariable.

HTTP-методы
Когда мы говорим о запросах, мы также подразумеваем HTTP-метод, который используется при отправке этого запроса. Каждый запрос представляет собой некий HTTP-метод. Например, когда мы переходим в браузере по адресу http://localhost:8080/greet/John/Smith , наш браузер отправляет GET-запрос на сервер.
Большая часть информационных систем обмениваются данными посредством HTTP-методов. Основными HTTP-методами являются – POST , GET , PUT , DELETE . Эти четыре запроса также называют CRUD-запросами.
- POST-метод – используется при создании новых ресурсов или данных. Например, когда мы загружаем новые посты в соцсетях, чаще всего используется POST-запросы. POST-запрос может иметь тело запроса.
- GET-метод – используется при получении данных. Например, при открытии любого веб-приложения, отправляется именно GET-запрос для получения данных и отображения их на странице. GET-запрос не имеет тела запроса.
- PUT-метод – используется для обновления данных, а также может иметь тело запроса, как и POST.
- DELETE-метод – используется для удаления данных.
Реализация основных методов
Давайте создадим сущности и реализуем методы, чтобы наш сервер принимал все четыре запроса. Для этого создадим сущности User и Post , и будем проводить операции над ними.
Для простоты User имеет только два поля: username и список постов posts , а сущность Post имеет поле description и imageUrl .

GET-запрос: получение пользователей

PUT-запрос: обновление списка постов пользователя

DELETE-запрос: удаление пользователя по username

В этой статье мы рассмотрели архитектуру современных web-приложений, а также написали свою серверную часть приложения, получив поверхностные знания по Spring Boot , HTTP запросы и параметры запросов.
Ссылка на репозиторий
Исходный код можно найти по ссылке.
Материалы по теме
- ☕ Сертификаты и тренинги для Java-разработчика
- ☕️ Дорожная карта Java-разработчика в 2023 году: путь с нуля до первой работы
