1. Обзор
С ростом популярности микросервисной архитектуры и разработки облачных приложений растет потребность в быстром и легком сервере приложений.
В этом вводном руководстве мы рассмотрим платформу Open Liberty для создания и использования веб-службы RESTful. Мы также рассмотрим несколько основных функций, которые он предоставляет.
2. Открытая свобода
Open Liberty — это открытый фреймворк для экосистемы Java, позволяющий разрабатывать микросервисы с использованием возможностей платформ Eclipse MicroProfile и Jakarta EE .
Это гибкая, быстрая и легкая среда выполнения Java, которая кажется многообещающей для разработки облачных микросервисов.
Платформа позволяет нам настраивать только те функции, которые нужны нашему приложению, что приводит к меньшему объему памяти при запуске. Кроме того, его можно развернуть на любой облачной платформе с использованием таких контейнеров, как Docker и Kubernetes .
Он поддерживает быструю разработку за счет перезагрузки кода в реальном времени для быстрой итерации.
3. Создайте и запустите
Во-первых, мы создадим простой проект на основе Maven с именем open-liberty,
а затем добавим в pom.xml последнюю версию
плагина Liberty -maven-plugin
: ``
<plugin>
<groupId>io.openliberty.tools</groupId>
<artifactId>liberty-maven-plugin</artifactId>
<version>3.3-M3</version>
</plugin>
Или мы можем добавить последнюю зависимость Maven openliberty-runtime
в качестве альтернативы Liberty -maven-plugin
:
<dependency>
<groupId>io.openliberty</groupId>
<artifactId>openliberty-runtime</artifactId>
<version>20.0.0.1</version>
<type>zip</type>
</dependency>
Точно так же мы можем добавить последнюю зависимость Gradle в build.gradle
:
dependencies {
libertyRuntime group: 'io.openliberty', name: 'openliberty-runtime', version: '20.0.0.1'
}
Затем мы добавим последние зависимости jakarta.jakartaee-web-api
и microprofile
Maven:
<dependency>
<groupId>jakarta.platform</groupId>
<artifactId>jakarta.jakartaee-web-api</artifactId>
<version>8.0.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.eclipse.microprofile</groupId>
<artifactId>microprofile</artifactId>
<version>3.2</version>
<type>pom</type>
<scope>provided</scope>
</dependency>
Затем давайте добавим свойства HTTP-порта по умолчанию в pom.xml
:
<properties>
<liberty.var.default.http.port>9080</liberty.var.default.http.port>
<liberty.var.default.https.port>9443</liberty.var.default.https.port>
</properties>
Далее мы создадим файл server.xml в каталоге
src/main/liberty/config
:
<server description="ForEach Open Liberty server">
<featureManager>
<feature>mpHealth-2.0</feature>
</featureManager>
<webApplication location="open-liberty.war" contextRoot="/" />
<httpEndpoint host="*" httpPort="${default.http.port}"
httpsPort="${default.https.port}" id="defaultHttpEndpoint" />
</server>
Здесь мы добавили функцию mpHealth-2.0
для проверки работоспособности приложения.
Вот и все основные настройки. Давайте запустим команду Maven для первой компиляции файлов:
mvn clean package
Наконец, давайте запустим сервер с помощью предоставленной Liberty команды Maven:
mvn liberty:dev
Вуаля! Наше приложение запущено и будет доступно по адресу localhost:9080
:
Кроме того, мы можем получить доступ к состоянию приложения по адресу localhost:9080/health
:
{"checks":[],"status":"UP"}
Команда Liberty :dev
запускает сервер Open Liberty в режиме разработки , который выполняет горячую перезагрузку любых изменений, внесенных в код или конфигурацию, без перезапуска сервера.
Точно так же доступна команда Liberty:Run для запуска сервера в производственном режиме.
Кроме того, мы можем использовать Liberty:Start-Server
и Liberty:
Stop-Server
для запуска/остановки сервера в фоновом режиме .
``
4. Сервлет
Чтобы использовать сервлеты в приложении, мы добавим функцию servlet-4.0 в
server.xml
:
<featureManager>
...
<feature>servlet-4.0</feature>
</featureManager>
Добавьте последнюю зависимость Maven servlet-4.0
, если используете зависимость Maven openliberty-runtime
в pom.xml
:
<dependency>
<groupId>io.openliberty.features</groupId>
<artifactId>servlet-4.0</artifactId>
<version>20.0.0.1</version>
<type>esa</type>
</dependency>
Однако, если мы используем плагин Liberty-maven-plugin
, в этом нет необходимости.
Затем мы создадим класс AppServlet
, расширяющий класс HttpServlet
:
@WebServlet(urlPatterns="/app")
public class AppServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String htmlOutput = "<html><h2>Hello! Welcome to Open Liberty</h2></html>";
response.getWriter().append(htmlOutput);
}
}
Здесь мы добавили аннотацию @WebServlet
, которая сделает AppServlet
доступным по указанному шаблону URL.
Давайте получим доступ к сервлету по адресу localhost:9080/app
:
**
**
5. Создайте веб-службу RESTful
Во-первых, давайте добавим функцию jaxrs-2.1
в server.xml
:
<featureManager>
...
<feature>jaxrs-2.1</feature>
</featureManager>
Затем мы
создадим класс ApiApplication
, который предоставляет конечные точки для веб-службы RESTful:
@ApplicationPath("/api")
public class ApiApplication extends Application {
}
Здесь мы использовали аннотацию @ApplicationPath
для пути URL.
Затем давайте создадим класс Person
, обслуживающий модель:
public class Person {
private String username;
private String email;
// getters and setters
// constructors
}
Далее мы создадим класс PersonResource
для определения сопоставлений HTTP:
@RequestScoped
@Path("persons")
public class PersonResource {
@GET
@Produces(MediaType.APPLICATION_JSON)
public List<Person> getAllPersons() {
return Arrays.asList(new Person(1, "normanlewis", "normanlewis@email.com"));
}
}
Здесь мы добавили метод getAllPersons
для сопоставления GET с конечной точкой /api/persons
. Итак, веб-служба RESTful готова, и команда Liberty:dev
будет загружать изменения «на лету».
Давайте получим доступ к веб-службе /api/persons
RESTful с помощью запроса curl GET:
curl --request GET --url http://localhost:9080/api/persons
Затем мы получим в ответ массив JSON:
[{"id":1, "username":"normanlewis", "email":"normanlewis@email.com"}]
Точно так же мы можем добавить сопоставление POST, создав метод addPerson
:
@POST
@Consumes(MediaType.APPLICATION_JSON)
public Response addPerson(Person person) {
String respMessage = "Person " + person.getUsername() + " received successfully.";
return Response.status(Response.Status.CREATED).entity(respMessage).build();
}
Теперь мы можем вызвать конечную точку с помощью POST-запроса curl:
curl --request POST --url http://localhost:9080/api/persons \
--header 'content-type: application/json' \
--data '{"username": "normanlewis", "email": "normanlewis@email.com"}'
Ответ будет выглядеть так:
Person normanlewis received successfully.
6. Настойчивость
6.1. Конфигурация
Давайте добавим поддержку постоянства в наши веб-сервисы RESTful.
Во-первых, мы добавим зависимость derby
Maven к pom.xml
:
<dependency>
<groupId>org.apache.derby</groupId>
<artifactId>derby</artifactId>
<version>10.14.2.0</version>
</dependency>
Затем мы добавим в server.xml несколько функций, таких как jpa -
2.2
, jsonp-1.1
и cdi-2.0
: ``
<featureManager>
...
<feature>jpa-2.2</feature>
<feature>jsonp-1.1</feature>
<feature>cdi-2.0</feature>
</featureManager>
Здесь функция jsonp-1.1
предоставляет Java API для обработки JSON, а функция cdi-2.0
обрабатывает области действия и внедрение зависимостей.
Далее мы создадим файл persistence.xml
в каталоге src/main/resources/META-INF
:
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.2"
xmlns="http://xmlns.jcp.org/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence
http://xmlns.jcp.org/xml/ns/persistence/persistence_2_2.xsd">
<persistence-unit name="jpa-unit" transaction-type="JTA">
<jta-data-source>jdbc/jpadatasource</jta-data-source>
<properties>
<property name="eclipselink.ddl-generation" value="create-tables"/>
<property name="eclipselink.ddl-generation.output-mode" value="both" />
</properties>
</persistence-unit>
</persistence>
Здесь мы использовали генерацию EclipseLink DDL для автоматического создания нашей схемы базы данных. Мы также можем использовать другие альтернативы, такие как Hibernate.
Затем добавим конфигурацию источника данных
в server.xml
:
<library id="derbyJDBCLib">
<fileset dir="${shared.resource.dir}" includes="derby*.jar"/>
</library>
<dataSource id="jpadatasource" jndiName="jdbc/jpadatasource">
<jdbcDriver libraryRef="derbyJDBCLib" />
<properties.derby.embedded databaseName="libertyDB" createDatabase="create" />
</dataSource>
Обратите внимание, что jndiName
имеет ту же ссылку на тег jta-data-source
в файле persistence.xml.
6.2. Сущность и DAO
Затем мы добавим аннотацию @Entity
и идентификатор в наш класс Person :
@Entity
public class Person {
@GeneratedValue(strategy = GenerationType.AUTO)
@Id
private int id;
private String username;
private String email;
// getters and setters
}
Далее создадим класс PersonDao
, который будет взаимодействовать с базой данных с помощью экземпляра EntityManager :
@RequestScoped
public class PersonDao {
@PersistenceContext(name = "jpa-unit")
private EntityManager em;
public Person createPerson(Person person) {
em.persist(person);
return person;
}
public Person readPerson(int personId) {
return em.find(Person.class, personId);
}
}
Обратите внимание, что @PersistenceContext
определяет ту же ссылку на тег persistence-unit в файле
persistence.xml
.
Теперь мы добавим зависимость PersonDao в класс
PersonResource
:
@RequestScoped
@Path("person")
public class PersonResource {
@Inject
private PersonDao personDao;
// ...
}
Здесь мы использовали аннотацию @Inject
, предоставляемую функцией CDI.
Наконец, мы обновим метод addPerson класса
PersonResource
, чтобы сохранить объект Person :
@POST
@Consumes(MediaType.APPLICATION_JSON)
@Transactional
public Response addPerson(Person person) {
personDao.createPerson(person);
String respMessage = "Person #" + person.getId() + " created successfully.";
return Response.status(Response.Status.CREATED).entity(respMessage).build();
}
Здесь метод addPerson снабжен аннотацией
@Transactional
для управления транзакциями управляемых компонентов CDI.
Давайте вызовем конечную точку уже обсуждавшимся POST-запросом curl:
curl --request POST --url http://localhost:9080/api/persons \
--header 'content-type: application/json' \
--data '{"username": "normanlewis", "email": "normanlewis@email.com"}'
Затем мы получим текстовый ответ:
Person #1 created successfully.
Точно так же давайте добавим метод getPerson
с отображением GET для получения объекта Person :
@GET
@Path("{id}")
@Produces(MediaType.APPLICATION_JSON)
@Transactional
public Person getPerson(@PathParam("id") int id) {
Person person = personDao.readPerson(id);
return person;
}
Давайте вызовем конечную точку с помощью запроса curl GET:
curl --request GET --url http://localhost:9080/api/persons/1
Затем мы получим объект Person
в качестве ответа JSON:
{"email":"normanlewis@email.com","id":1,"username":"normanlewis"}
7. Использование веб-службы RESTful с использованием
JSON-B
Во-первых, мы включим возможность прямой сериализации и десериализации моделей, добавив функцию jsonb-1.0
в server.xml
:
<featureManager>
...
<feature>jsonb-1.0</feature>
</featureManager>
Затем создадим класс RestConsumer с методом
потребленияWithJsonb
:
public class RestConsumer {
public static String consumeWithJsonb(String targetUrl) {
Client client = ClientBuilder.newClient();
Response response = client.target(targetUrl).request().get();
String result = response.readEntity(String.class);
response.close();
client.close();
return result;
}
}
Здесь мы использовали класс ClientBuilder
для запроса конечных точек веб-службы RESTful.
Наконец, давайте напишем модульный тест для использования веб-службы /api/person
RESTful и проверки ответа:
@Test
public void whenConsumeWithJsonb_thenGetPerson() {
String url = "http://localhost:9080/api/persons/1";
String result = RestConsumer.consumeWithJsonb(url);
Person person = JsonbBuilder.create().fromJson(result, Person.class);
assertEquals(1, person.getId());
assertEquals("normanlewis", person.getUsername());
assertEquals("normanlewis@email.com", person.getEmail());
}
Здесь мы использовали класс JsonbBuilder
для анализа ответа String
в объекте Person .
Кроме того, мы можем использовать MicroProfile Rest Client, добавив функцию mpRestClient-1.3
для использования веб-служб RESTful . Он предоставляет интерфейс RestClientBuilder
для запроса конечных точек веб-службы RESTful.
8. Заключение
В этой статье мы рассмотрели платформу Open Liberty — быструю и легкую среду выполнения Java, которая предоставляет все функции платформ Eclipse MicroProfile и Jakarta EE.
Для начала мы создали веб-службу RESTful с использованием JAX-RS. Затем мы включили постоянство, используя такие функции, как JPA и CDI.
Наконец, мы использовали веб-службу RESTful с использованием JSON-B.
Как обычно, все реализации кода доступны на GitHub .