大型网站如何做别名,注册个公司大概要多少钱,wordpress主题首页文件夹,修改wordpress数据库域名城镇中有一个名为Micronaut的新微服务框架。 在本文中#xff0c;我将从Java EE / Jakarta EE的角度讨论如何冒险使用Micronaut框架。 我是Java EE开发人员#xff0c;因此使用诸如Eclipse MicroProfile之类的解决方案开发微服务更接近我的专业知识#xff0c;但是Micronaut… 城镇中有一个名为Micronaut的新微服务框架。 在本文中我将从Java EE / Jakarta EE的角度讨论如何冒险使用Micronaut框架。 我是Java EE开发人员因此使用诸如Eclipse MicroProfile之类的解决方案开发微服务更接近我的专业知识但是Micronaut吸引了我的注意力因为它具有以下功能 –使用JavaGroovy或Kotlin开发 –易于通过Spock或JUnit进行测试..完全集成的测试 –嵌入式服务器和编译时HTTP客户端 –易于打包的Docker –快速启动时间低内存消耗 –完全反应 作为内心的企业开发人员我的第一个想法通常是数据库因为我编写的大多数应用程序都使用RDBMS。 我发现将Micronaut与RDBMS一起使用的示例数量很少因此我认为为该用例创建另一个示例可能对我有用。 在此示例中我使用PostgreSQL。 但是大多数其他RDBMS也受支持。 本文无意对安装Micronaut或利用所有许多Micronaut功能进行完整说明。 相反它是那些希望开始使用带有关系数据库的Micronaut的入门指南……尤其适合那些具有Java EE / Jakarta EE背景的人。 在我的特殊情况下我对快速完善可测试可扩展和高效的微服务感兴趣。 尽管我可以使用MicroProfile或标准Java EE做到这一点但我认为学习新知识并具有使用Groovy或Kotlin的能力将很有趣。 我还想将Java EE / Jakarta EE放在上面……所以我正在使用JPA来处理数据。 许多Micronaut示例都使用Groovy和GORM来实现持久性……但是我可能不会在我的任何应用程序中使用它。 该示例是使用Apache NetBeans 9.0和Micronaut随附的命令行界面CLI开发的 。 此特定示例是针对Micronaut 1.0.0.M4编写的。 在这种情况下我保持简单只使用一个基本数据库表在PostgreSQL数据库中进行持久化。 首先我通过发出以下命令利用CLI创建了一个应用程序 mn create-app org.acme.books --features hibernate-jpa,jdbc-tomcat 这只是在名为“ books”的目录中为我的应用程序创建了一个框架Application.java主类将放置在org.acme.books包中。 默认情况下应用程序支持一些基本功能但是在这种情况下我添加了对Tomcat连接池的支持。 通过Java Persistence APIJPA创建数据库连接时将利用此功能。 默认应用程序也会在支持Gradle构建系统的情况下生成。 因此将创建一个build.gradle即将在其中进行依赖项管理的文件。 请注意也可以使用Apache Maven构建系统来生成应用程序但是在Micronaut 1.0.0.M4下运行Maven项目时遇到了问题因此在这个示例中我坚持使用Gradle。 如果使用Apache NetBeans 9.0则可以安装“ Groovy and Grails”和“ Gradle”插件当前在NetBeans 8.2插件中心提供以提供打开项目的支持。 一旦完成就可以在NetBeans中打开项目并开始开发。 安装插件并在Apache NetBeans中打开项目后完整的项目结构应如下图所示 为了提供对PostgreSQL数据库的支持我在build.gradle中添加了依赖项 compile group: org.postgresql, name: postgresql, version: 42.2.5 接下来我打开了application.yml文件并为该应用程序添加了数据源。 这是替换传统Java EE应用程序中的persistence.xml的文件。 另外通过此文件添加了JPA支持指示哪个包包括实体类以及Hibernate的配置。 端口8080也已设置因为默认情况下Micronaut将选择一个随机端口来启动服务器。 application.xml的完整资源如下 micronaut:application:name: books#Uncomment to set server portserver:port: 8080---datasources:default:url: jdbc:postgresql://localhost/postgresusername: postgrespassword: yourpassworddriverClassName: org.postgresql.DriverconnectionTimeout: 4000jpa:default:packages-to-scan:- org.acme.domainproperties:hibernate:hbm2ddl:auto: updateshow_sql: true 现在配置已不复存在我可以开始有趣的部分了……开发。 在此示例中我创建了一项基本服务该服务允许用户在BOOK表中创建读取更新或删除记录。 org.acme包中自动生成的Application类用于启动服务。 package org.acme;import io.micronaut.runtime.Micronaut;public class Application {public static void main(String[] args) {Micronaut.run(Application.class);}} 要开始开发请在应用程序中创建两个用于组织源代码的软件包。 首先创建org.acme.domain它将包含实体类。 接下来创建org.acme.book其中将包含实现类。 在org.acme.domain包中创建一个Book.java类它将是包含数据库标准JPA映射的实体类。 在这种情况下请注意我将java.time.LocalDate用于日期字段并将数据库序列生成器用于主键填充。 来源如下 package org.acme.domain;import java.time.LocalDate;import javax.persistence.Column;import javax.persistence.Entity;import javax.persistence.GeneratedValue;import javax.persistence.GenerationType;import javax.persistence.Id;import javax.persistence.SequenceGenerator;import javax.persistence.Table;import javax.validation.constraints.NotNull;/*** JPA Mappings for the BOOK database table.*/EntityTable(nameBOOK)public class Book {IdGeneratedValue(strategyGenerationType.SEQUENCE,generatorbook_generator)SequenceGenerator(namebook_generator,sequenceNamebook_s, allocationSize1)private Long id;Column(namePUBLISH_DATE)NotNullprivate LocalDate publishDate;Column(nameTITLE)NotNullprivate String title;Column(nameAUTHOR_FIRST)NotNullprivate String authorFirst;Column(nameAUTHOR_LAST)NotNullprivate String authorLast;private Long pages;public Book(){}public Book(NotNull Long id, NotNull LocalDate publishDate, NotNull String title, String authorFirst, String authorLast, Long pages){this.id id;this.publishDate publishDate;this.title title;this.authorFirst authorFirst;this.authorLast authorLast;this.pages pages;}public Book(NotNull LocalDate publishDate, NotNull String title, String authorFirst, String authorLast, Long pages){this.publishDate publishDate;this.title title;this.authorFirst authorFirst;this.authorLast authorLast;this.pages pages;}/*** return the id*/public Long getId() {return id;}/*** param id the id to set*/public void setId(Long id) {this.id id;}/*** return the publishDate*/public LocalDate getPublishDate() {return publishDate;}/*** param publishDate the publishDate to set*/public void setPublishDate(LocalDate publishDate) {this.publishDate publishDate;}/*** return the title*/public String getTitle() {return title;}/*** param title the title to set*/public void setTitle(String title) {this.title title;}/*** return the authorFirst*/public String getAuthorFirst() {return authorFirst;}/*** param authorFirst the authorFirst to set*/public void setAuthorFirst(String authorFirst) {this.authorFirst authorFirst;}/*** return the authorLast*/public String getAuthorLast() {return authorLast;}/*** param authorLast the authorLast to set*/public void setAuthorLast(String authorLast) {this.authorLast authorLast;}/*** return the pages*/public Long getPages() {return pages;}/*** param pages the pages to set*/public void setPages(Long pages) {this.pages pages;}Overridepublic String toString() {return Book{ id id , publishDate publishDate \ , title title \ , authorFirst authorFirst \ , authorLast authorLast \ , pages pages };}} 在Micronaut应用程序中需要将HTTP请求和响应封装在Serializable类中进行处理因此生成一些简单的“纯旧Java对象”POJO来封装将在数据库操作中使用的数据是有意义的。 在同一个org.acme.domain包中我创建了两个此类BookSaveOperation.java和BookUpdateOperation.java。 这些类将定义将数据从HTTP请求传递到控制器类所需的字段。 BookSaveOperation.java的源如下有关完整源请参见GitHub存储库 package org.acme.domain;import java.time.LocalDate;import javax.validation.constraints.NotBlank;import javax.validation.constraints.NotNull;/**** author Josh Juneau*/public class BookSaveOperation implements java.io.Serializable {NotNullprivate LocalDate publishDate;NotNullNotBlankprivate String title;NotNullNotBlankprivate String authorFirst;NotNullNotBlankprivate String authorLast;private Long pages;public BookSaveOperation(){}public BookSaveOperation(LocalDate publishDate, String title,String authorFirst, String authorLast, Long pages){this.publishDate publishDate;this.title title;this.authorFirst authorFirst;this.authorLast authorLast;this.pages pages;}// ...// getters and setters// ...} 应用程序业务逻辑发生在一个类中该类非常类似于EJB或DAO实现并且该类必须实现定义了每个业务逻辑方法的接口。 在这种情况下我创建了一个接口org.acme.book.BookRepository.java并定义了一些标准的操作方法 package org.acme.book;import java.time.LocalDate;import java.util.List;import java.util.Optional;import org.acme.domain.Book;/****/public interface BookRepository {Book save(LocalDate publishDate, String title, String authorFirst, String authorLast, Long pages);OptionalBook findById(Long id);void deleteById(Long id);ListBook findAll();int update(Long id, LocalDate publishDate, String title, String authorFirst, String authorLast, Long pages);} 接下来在名为org.acme.book.BookRepositoryImpl.java的类中实现该接口并注释为Singleton。 由于这是将实现业务逻辑的类因此请注入一个PersistenceContext该持久性上下文提供将用于执行数据库操作的JPA EntityManager。 只需实现BookRepository界面中概述的每个操作并使用Transactionalio.micronaut.spring.tx.annotation.Transactional进行标记就意味着仅对那些不会修改任何数据的方法进行只读。 BookRepositoryImpl.java的源如下 package org.acme.book;import io.micronaut.configuration.hibernate.jpa.scope.CurrentSession;import io.micronaut.spring.tx.annotation.Transactional;import java.time.LocalDate;import java.util.List;import java.util.Optional;import javax.inject.Singleton;import javax.persistence.EntityManager;import javax.persistence.PersistenceContext;import org.acme.domain.Book;/*** Business logic for the service.*/Singletonpublic class BookRepositoryImpl implements BookRepository {PersistenceContextprivate EntityManager entityManager;public BookRepositoryImpl(CurrentSession EntityManager entityManager) {this.entityManager entityManager;}OverrideTransactionalpublic Book save(LocalDate publishDate, String title, String authorFirst, String authorLast, Long pages) {Book book new Book(publishDate, title, authorFirst, authorLast, pages);entityManager.persist(book);return book;}OverrideTransactional(readOnly true)public OptionalBook findById(Long id) {return Optional.ofNullable(entityManager.find(Book.class, id));}Transactional(readOnly true)public ListBook findAll() {return entityManager.createQuery(SELECT b FROM Book b, Book.class).getResultList();}OverrideTransactionalpublic int update(Long id, LocalDate publishDate, String title, String authorFirst, String authorLast, Long pages) {return entityManager.createQuery(UPDATE Book b SET publishDate :publishDate, title :title, authorFirst :authorFirst, authorLast :authorLast, pages :pages where id :id).setParameter(publishDate, publishDate).setParameter(title, title).setParameter(authorFirst, authorFirst).setParameter(authorLast, authorLast).setParameter(pages, pages).setParameter(id, id).executeUpdate();}OverrideTransactionalpublic void deleteById(Long id) {findById(id).ifPresent(book - entityManager.remove(book));}} 为了从Java EE角度解释Micronaut应用程序基础结构我将比较该实现与一个简单的JAX-RS应用程序。 Micronaut利用io.micronaut.http.annotation.Controller类来执行服务的请求-响应处理。 这非常类似于JAX-RS控制器类但有一些细微的差异。 这让我想起了Eclipse Krazo项目或Java EE的MVC 1.0。 例如Micronaut而不是使用JAX-RS注释javax.ws.rs.GETjavax.ws.rs.POST或javax.ws.rs.Path注释方法而是使用io.micronaut.http.annotation.Get和io.micronaut.http.annotation.Post等。 每个方法的URI路径都可以通过 Get Post Put Delete批注直接声明。 每个控制器类将实现服务的功能并处理请求-响应生命周期。 通过Inject批注或构造函数注入将用于持久性的业务逻辑包含在BookRepositoryImpl类中注入到控制器类中。 在此示例的源代码中使用了构造函数注入。 package org.acme.book;import org.acme.domain.Book;import io.micronaut.http.HttpHeaders;import io.micronaut.http.HttpResponse;import io.micronaut.http.annotation.Body;import io.micronaut.http.annotation.Controller;import io.micronaut.http.annotation.Delete;import io.micronaut.http.annotation.Get;import io.micronaut.http.annotation.Post;import io.micronaut.http.annotation.Put;import io.micronaut.validation.Validated;import javax.validation.Valid;import java.net.URI;import java.util.List;import org.acme.domain.BookSaveOperation;import org.acme.domain.BookUpdateOperation;ValidatedController(/books)public class BookController {protected final BookRepository bookRepository;public BookController(BookRepository bookRepository) {this.bookRepository bookRepository;}Get(/)public ListBook list() {return bookRepository.findAll();}Put(/)public HttpResponse update(Body Valid BookUpdateOperation operation) {bookRepository.update(operation.getId(), operation.getPublishDate(),operation.getTitle(), operation.getAuthorFirst(), operation.getAuthorLast(), operation.getPages());return HttpResponse.noContent().header(HttpHeaders.LOCATION, location(operation.getId()).getPath());}Get(/{id})Book show(Long id) {return bookRepository.findById(id).orElse(null);}Delete(/{id})HttpResponse delete(Long id) {bookRepository.deleteById(id);return HttpResponse.noContent();}Post(/)HttpResponseBook save(Body Valid BookSaveOperation operation) {Book book bookRepository.save(operation.getPublishDate(), operation.getTitle(),operation.getAuthorFirst(), operation.getAuthorLast(), operation.getPages());return HttpResponse.created(book).headers(headers - headers.location(location(book)));}protected URI location(Book book) {return location(book.getId());}protected URI location(Long id) {return URI.create(/books/ id);}}测试应用 Micronaut可以使用Spock或JUnit以及嵌入式服务器轻松进行测试从而可以轻松地为每个控制器创建测试。 在这种情况下我利用JUnit来测试应用程序。 我在名为org.acme.BookControllerTest的项目的测试文件夹内创建了一个测试类。 package org.acme;import io.micronaut.context.ApplicationContext;import io.micronaut.core.type.Argument;import io.micronaut.http.HttpHeaders;import io.micronaut.http.HttpRequest;import io.micronaut.http.HttpResponse;import io.micronaut.http.HttpStatus;import io.micronaut.http.client.HttpClient;import io.micronaut.runtime.server.EmbeddedServer;import java.time.LocalDate;import java.util.ArrayList;import java.util.List;import org.acme.domain.Book;import org.acme.domain.BookSaveOperation;import org.acme.domain.BookUpdateOperation;import org.junit.AfterClass;import static org.junit.Assert.assertEquals;import org.junit.BeforeClass;import org.junit.Test;/*** Test cases for BookController*/public class BookControllerTest {private static EmbeddedServer server;private static HttpClient client;private Book book;HttpRequest request;HttpResponse response;Long id;ListLong bookIds new ArrayList();BeforeClasspublic static void setupServer() {server ApplicationContext.run(EmbeddedServer.class);client server.getApplicationContext().createBean(HttpClient.class, server.getURL());}AfterClasspublic static void stopServer() {if (server ! null) {server.stop();}if (client ! null) {client.stop();}}Testpublic void testInsertBooks() {request HttpRequest.POST(/books, new BookSaveOperation(LocalDate.now(), Java EE 8 Recipes, Josh, Juneau, new Long(750)));response client.toBlocking().exchange(request);assertEquals(HttpStatus.CREATED, response.getStatus());request HttpRequest.POST(/books, new BookSaveOperation(LocalDate.now(), Java 9 Recipes, Josh, Juneau, new Long(600)));response client.toBlocking().exchange(request);id entityId(response, /books/);assertEquals(HttpStatus.CREATED, response.getStatus());}Testpublic void testBookRetrieve() {request HttpRequest.GET(/books);ListBook books client.toBlocking().retrieve(request, Argument.of(List.class, Book.class));// Populate a book instance for laterfor(Book b:books){book b;}assertEquals(2, books.size());}Testpublic void testBookOperations() {request HttpRequest.GET(/books);ListBook books client.toBlocking().retrieve(request, Argument.of(List.class, Book.class));// Populate a book instance for laterfor(Book b:books){book b;}request HttpRequest.PUT(/books/, new BookUpdateOperation(book.getId(),book.getPublishDate(),Java 10 Recipes,book.getAuthorFirst(),book.getAuthorLast(),book.getPages()));response client.toBlocking().exchange(request);assertEquals(HttpStatus.NO_CONTENT, response.getStatus());request HttpRequest.GET(/books/ book.getId());book client.toBlocking().retrieve(request, Book.class);assertEquals(Java 10 Recipes, book.getTitle());testDelete();}public void testDelete(){request HttpRequest.GET(/books);ListBook books client.toBlocking().retrieve(request, Argument.of(List.class, Book.class));// Populate a book instance for laterfor(Book b:books){request HttpRequest.DELETE(/books/ b.getId());response client.toBlocking().exchange(request);assertEquals(HttpStatus.NO_CONTENT, response.getStatus());}}Long entityId(HttpResponse response, String path) {String value response.header(HttpHeaders.LOCATION);if (value null) {return null;}int index value.indexOf(path);if (index ! -1) {return Long.valueOf(value.substring(index path.length()));}return null;}}考试逻辑导论 在运行BeforeClass的方法中将创建HTTP服务器和客户端。 同样当测试完成执行时将调用用AfterClass注释的方法如果服务器正在运行它将停止服务器。 在textInsertBooks方法中通过将填充了数据的新BookSaveOperation对象传递给可通过Post命名的“ / books”路径访问的服务来创建两个新的书记录。 在这种情况下将调用控制器方法BookController.save。 看一下save方法您可以看到该方法只是将BookSaveOperation的内容传递给BookRepository.save业务方法利用该接口从而持久化对象。 最后返回HttpResponse。 testBookRetrieve方法调用包含Get名称的“ / books”路径上可用的服务。 依次调用BookController.list方法该方法在BookRepository上执行findAll返回Book对象的List。 testBookOperations方法负责对记录进行更新。 首先从BookController中检索Book对象的列表然后通过使用要更新的内容填充BookUpdateOperation对象通过BookController.update方法更新其中一本书。 **请记住BookSaveOperation.java和BookUpdateOperation.java对象只是用于移动数据的POJO。 最后调用testDelete方法该方法遍历Book对象的List通过对“ / books”路径的服务调用来调用BookController.delete方法并调用指定为Delete的方法。 要执行测试只需在NetBeans中右键单击该项目并选择“ Test”或使用命令行使用以下命令来调用 ./gradlew test 如果尚未创建数据库表则将为您生成该表。 请注意您可能需要根据环境修改application.yml中的数据库配置。 运行服务 Micronaut是独立的允许使用基于Netty构建的嵌入式服务器执行服务。 可以通过右键单击Apache NetBeans中的项目并选择“运行”来完成。 您也可以转到命令行并使用以下命令进行调用 ./gradlew run 您应该在终端或Apache NetBeans输出面板的输出中看到托管服务器的URL。 摘要 作为Java EE开发人员我不得不说Micronaut确实有不同的开发方法。 它与Spring Boot或Grails并没有太大区别但又有足够的区别以至于我花了一些时间找到解决方法。 最后我发现它是一个易于使用的框架它具有快速开发服务或计划任务的巨大潜力同时仍然利用Java EE / Jakarta EE的一些概念。 我还没有使用很多功能例如通过Micronaut框架创建计划任务以及使用Groovy或Kotlin而不是Java进行开发。 我希望在以后的文章中继续介绍对有兴趣开始Micronaut之旅的Java EE和Jakarta EE开发人员的更多信息。 GitHub项目https://github.com/juneau001/micronaut-books 翻译自: https://www.javacodegeeks.com/2018/09/micronaut-for-java-ee-jakarta-ee-developers.html