idea 构建spring_以Spring方式构建企业Java应用程序

idea 构建spring

我认为可以说Java EE在Java开发人员中享有很高的声誉。 尽管多年来确实在各个方面都有所改善,甚至将其改名为Eclipse Foundation成为Jakarta EE ,但其苦味仍然相当强烈。 另一方面,我们拥有Spring框架 (或者为了更好地反映现实,一个成熟的Spring平台 ):出色,轻巧,快速,创新和高产的Java EE替代品。 那么,为什么要打扰Java EE ?

我们将通过展示使用大多数Java EE规范构建现代Java应用程序有多么容易来回答这个问题。 成功的关键要素是Eclipse Microprofile : 微服务时代的企业Java。

如此简单,我们将要构建的应用程序就是RESTful Web API来管理人员。 在Java中构建RESTful Web服务的标准方法是使用JAX-RS 2.1 ( JSR-370 )。 因此, CDI 2.0 ( JSR-365 )将负责依赖注入,而JPA 2.0 ( JSR-317 )将涵盖数据访问层。 当然, Bean Validation 2.0 ( JSR-380 )正在帮助我们处理输入验证。

我们将要依赖的唯一非Java EE规范是OpenAPI v3.0 ,它有助于提供RESTful Web API的可用描述。 这样,让我们​​开始使用PersonEntity域模型(将getter和setter省略为不太相关的细节):

@Entity
@Table(name = "people")
public class PersonEntity {@Id @Column(length = 256) private String email;@Column(nullable = false, length = 256, name = "first_name")private String firstName;@Column(nullable = false, length = 256, name = "last_name")private String lastName;@Versionprivate Long version;
}

它只是具有绝对最小的一组属性。 JPA存储库非常简单,并实现了一组典型的CRUD方法。

@ApplicationScoped
@EntityManagerConfig(qualifier = PeopleDb.class)
public class PeopleJpaRepository implements PeopleRepository {@Inject @PeopleDb private EntityManager em;@Override@Transactional(readOnly = true)public Optional<PersonEntity> findByEmail(String email) {final CriteriaBuilder cb = em.getCriteriaBuilder();final CriteriaQuery<PersonEntity> query = cb.createQuery(PersonEntity.class);final Root<PersonEntity> root = query.from(PersonEntity.class);query.where(cb.equal(root.get(PersonEntity_.email), email));try {final PersonEntity entity = em.createQuery(query).getSingleResult();return Optional.of(entity);} catch (final NoResultException ex) {return Optional.empty();}}@Override@Transactionalpublic PersonEntity saveOrUpdate(String email, String firstName, String lastName) {final PersonEntity entity = new PersonEntity(email, firstName, lastName);em.persist(entity);return entity;}@Override@Transactional(readOnly = true)public Collection<PersonEntity> findAll() {final CriteriaBuilder cb = em.getCriteriaBuilder();final CriteriaQuery<PersonEntity> query = cb.createQuery(PersonEntity.class);query.from(PersonEntity.class);return em.createQuery(query).getResultList();}@Override@Transactionalpublic Optional<PersonEntity> deleteByEmail(String email) {return findByEmail(email).map(entity -> {em.remove(entity);return entity;});}
}

事务管理(即@Transactional批注)需要一些解释。 在典型的Java EE应用程序中,容器运行时负责管理事务。 由于我们不想随身携带应用程序容器,而是保持精简,因此我们可以使用EntityManager来启动/提交/回滚事务。 当然可以解决,但会污染样板代码。 可以说,更好的选择是使用Apache DeltaSpike CDI扩展进行声明式事务管理 (这是@Transactional@EntityManagerConfig注释的来源)。 下面的代码段说明了如何进行集成。

@ApplicationScoped
public class PersistenceConfig {@PersistenceUnit(unitName = "peopledb")private EntityManagerFactory entityManagerFactory;@Produces @PeopleDb @TransactionScopedpublic EntityManager create() {return this.entityManagerFactory.createEntityManager();}public void dispose(@Disposes @PeopleDb EntityManager entityManager) {if (entityManager.isOpen()) {entityManager.close();}}
}

太棒了,最难的部分已经过去了! 接下来是人员 数据传输对象和服务层。

public class Person {@NotNull private String email;@NotNull private String firstName;@NotNull private String lastName;
}

老实说,为了使示例应用程序尽可能小,我们可以完全跳过服务层,直接进入存储库。 但这通常不是一个很好的做法,因此无论如何让我们介绍PeopleServiceImpl

@ApplicationScoped
public class PeopleServiceImpl implements PeopleService {@Inject private PeopleRepository repository;@Overridepublic Optional<Person> findByEmail(String email) {return repository.findByEmail(email).map(this::toPerson);}@Overridepublic Person add(Person person) {return toPerson(repository.saveOrUpdate(person.getEmail(), person.getFirstName(), person.getLastName()));}@Overridepublic Collection<Person> getAll() {return repository.findAll().stream().map(this::toPerson).collect(Collectors.toList());}@Overridepublic Optional<Person> remove(String email) {return repository.deleteByEmail(email).map(this::toPerson);}private Person toPerson(PersonEntity entity) {return new Person(entity.getEmail(), entity.getFirstName(), entity.getLastName());}
}

剩下的唯一部分是JAX-RS应用程序和资源的定义。

@Dependent
@ApplicationPath("api")
@OpenAPIDefinition(info = @Info(title = "People Management Web APIs", version = "1.0.0", license = @License(name = "Apache License", url = "https://www.apache.org/licenses/LICENSE-2.0"))
)
public class PeopleApplication extends Application {
}

不多说,可能就这么简单。 不过, JAX-RS资源实现更加有趣( OpenAPI注释占据了大部分位置)。

@ApplicationScoped
@Path( "/people" ) 
@Tag(name = "people")
public class PeopleResource {@Inject private PeopleService service;@Produces(MediaType.APPLICATION_JSON)@GET@Operation(description = "List all people", responses = {@ApiResponse(content = @Content(array = @ArraySchema(schema = @Schema(implementation = Person.class))),responseCode = "200")})public Collection<Person> getPeople() {return service.getAll();}@Produces(MediaType.APPLICATION_JSON)@Path("/{email}")@GET@Operation(description = "Find person by e-mail", responses = {@ApiResponse(content = @Content(schema = @Schema(implementation = Person.class)), responseCode = "200"),@ApiResponse(responseCode = "404", description = "Person with such e-mail doesn't exists")})public Person findPerson(@Parameter(description = "E-Mail address to lookup for", required = true) @PathParam("email") final String email) {return service.findByEmail(email).orElseThrow(() -> new NotFoundException("Person with such e-mail doesn't exists"));}@Consumes(MediaType.APPLICATION_JSON)@Produces(MediaType.APPLICATION_JSON)@POST@Operation(description = "Create new person",requestBody = @RequestBody(content = @Content(schema = @Schema(implementation = Person.class)),), responses = {@ApiResponse(content = @Content(schema = @Schema(implementation = Person.class)),headers = @Header(name = "Location"),responseCode = "201"),@ApiResponse(responseCode = "409", description = "Person with such e-mail already exists")})public Response addPerson(@Context final UriInfo uriInfo,@Parameter(description = "Person", required = true) @Valid Person payload) {final Person person = service.add(payload);return Response.created(uriInfo.getRequestUriBuilder().path(person.getEmail()).build()).entity(person).build();}@Path("/{email}")@DELETE@Operation(description = "Delete existing person",responses = {@ApiResponse(responseCode = "204",description = "Person has been deleted"),@ApiResponse(responseCode = "404", description = "Person with such e-mail doesn't exists")})public Response deletePerson(@Parameter(description = "E-Mail address to lookup for", required = true ) @PathParam("email") final String email) {return service.remove(email).map(r -> Response.noContent().build()).orElseThrow(() -> new NotFoundException("Person with such e-mail doesn't exists"));}
}

至此,我们完成了! 但是,我们如何将所有这些部件组装并连接在一起? 这是Microprofile进入舞台的时间。 有很多实现可供选择,本文中将使用的是Project Hammock 。 我们唯一要做的就是指定我们要使用的CDI 2.0 , JAX-RS 2.1和JPA 2.0实现,它们分别转换为Weld , Apache CXF和OpenJPA (通过Project Hammock依赖关系表示)。 让我们看一下Apache Maven pom.xml文件。

<properties><deltaspike.version>1.8.1</deltaspike.version><hammock.version>2.1</hammock.version>
</properties><dependencies><dependency><groupId>org.apache.deltaspike.modules</groupId><artifactId>deltaspike-jpa-module-api</artifactId><version>${deltaspike.version}</version><scope>compile</scope></dependency><dependency><groupId>org.apache.deltaspike.modules</groupId><artifactId>deltaspike-jpa-module-impl</artifactId><version>${deltaspike.version}</version><scope>runtime</scope></dependency><dependency><groupId>ws.ament.hammock</groupId><artifactId>dist-microprofile</artifactId><version>${hammock.version}</version></dependency><dependency><groupId>ws.ament.hammock</groupId><artifactId>jpa-openjpa</artifactId><version>${hammock.version}</version></dependency><dependency><groupId>ws.ament.hammock</groupId><artifactId>util-beanvalidation</artifactId><version>${hammock.version}</version></dependency><dependency><groupId>ws.ament.hammock</groupId><artifactId>util-flyway</artifactId><version>${hammock.version}</version></dependency><dependency><groupId>ws.ament.hammock</groupId><artifactId>swagger</artifactId><version>${hammock.version}</version></dependency>
</dependencies>

事不宜迟,让我们立即构建并运行该应用程序(如果您好奇应用程序正在使用什么关系数据存储,则它是H2 ,并且内存中配置了数据库)。

> mvn clean package
> java -jar target/eclipse-microprofile-hammock-0.0.1-SNAPSHOT-capsule.jar

确保我们的人员管理RESTful Web API正常运行的最佳方法是向其发送几个请求:

>  curl -X POST http://localhost:10900/api/people -H "Content-Type: application\json" \-d '{"email": "a@b.com", "firstName": "John", "lastName": "Smith"}'HTTP/1.1 201 Created
Location: http://localhost:10900/api/people/a@b.com
Content-Type: application/json{"firstName":"John",""lastName":"Smith","email":"a@b.com"
}

如何确保Bean验证正常工作呢? 要触发该请求,让我们发送部分准备好的请求。

>  curl  --X POST http://localhost:10900/api/people -H "Content-Type: application\json" \-d '{"firstName": "John", "lastName": "Smith"}'HTTP/1.1 400 Bad Request
Content-Length: 0

您还可以在http:// localhost:10900 / index.html?url = http:// localhost:10900 / api / openapi.json上获得OpenAPI规范和预先捆绑的Swagger UI分发。

Java应用

到目前为止,到目前为止还算不错,但实际上我们还没有谈论过测试应用程序。 假设要增加一个人,要进行集成测试有多难? 事实证明,围绕测试Java EE应用程序的框架有了很大的改进。 特别是,使用Arquillian测试框架(以及最受欢迎的JUnit和REST Assured )非常容易完成。 一个真实的例子值得一千个单词。

@RunWith(Arquillian.class)
@EnableRandomWebServerPort
public class PeopleApiTest {@ArquillianResource private URI uri;@Deploymentpublic static JavaArchive createArchive() {return ShrinkWrap.create(JavaArchive.class).addClasses(PeopleResource.class, PeopleApplication.class).addClasses(PeopleServiceImpl.class, PeopleJpaRepository.class, PersistenceConfig.class).addPackages(true, "org.apache.deltaspike");}@Testpublic void shouldAddNewPerson() throws Exception {final Person person = new Person("a@b.com", "John", "Smith");given().contentType(ContentType.JSON).body(person).post(uri + "/api/people").then().assertThat().statusCode(201).body("email", equalTo("a@b.com")).body("firstName", equalTo("John")).body("lastName", equalTo("Smith"));}
}

太神奇了,不是吗? 它实际上是一个很大的乐趣,以发展现代的Java EE应用程序,可能有人会说了, 春节的方式! 实际上,与Spring的相似之处并非偶然,因为它令人鼓舞,正在鼓舞,而且无疑将继续激发Java EE生态系统中的许多创新。

未来如何? 我认为,对于Jakarta EE和Eclipse Microprofile来说 , 绝对是光明的。 后者刚刚推出了2.0版 ,其中包含大量新规范,旨在满足微服务架构的需求。 见证这些转变的发生真是太棒了。

该项目的完整资源可在Github上找到 。

翻译自: https://www.javacodegeeks.com/2018/11/building-java-applications-spring-way.html

idea 构建spring

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/333179.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

入门案例Maven搭建SpringBoot工程

一、引入依赖 <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0"xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation"http://maven.apache.org/POM/4.…

Linux 命令之 passwd -- 修改用户账号密码

文章目录简介相关文件常用选项参考示例修改当前登陆的账户密码修改其他用户密码读取标准输入的值&#xff0c;设置成指定用户的密码锁定密码不允许用户修改解除锁定密码&#xff0c;允许用户修改下次登陆强制改密码清除登录密码。清除之后登录时无需密码&#xff0c;风险极大&a…

自动化测试特定区域滑动_自动化用户特定实体的访问控制

自动化测试特定区域滑动实际上&#xff0c;每个Web应用程序都应该有多个用户&#xff0c;并且每个用户都有一些数据-帖子&#xff0c;文档&#xff0c;消息等等。 最明显的事情是保护这些实体免遭非这些资源合法所有者的用户获取。 不幸的是&#xff0c;这不是最容易的事情。 …

Linux 命令之 usermod -- 用于修改用户的基本信息

文章目录命令介绍常用选项参考示例设置用户默认使用的shell类型将不能登录的用户改成可以登录的限定用户不能 shell 登录&#xff0c;只能 ftp修改用户的主目录更改用户的名称锁定用户的密码解锁用户的密码将用户添加到指定用户组命令介绍 usermod 命令用于修改用户的基本信息…

使用IDEA的Spring Initializr创建SpringBoot工程

一、创建步骤 二、创建完成后的界面 三、controller package com.william.day01_springboot_initializr.controller;import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController;/*** author &#xff1…

Linux系统下MySQL的导入数据的命令语句Load Data InFile的用法详解

文章目录语法格式LOW_PRIORITYCONCURRENTLOCALREPLACE 或 IGNOREPARTITIONCHARACTER SET对导入文件的字段进行格式描述指定行的起始符号和终止符号IGNORE number LINES指定数据表的列名获取表达式的值存储到指定的列中开启/关闭功能参考示例示例一示例二示例三示例四示例五错误…

认证令牌_Java应用程序的简单令牌认证

认证令牌“我喜欢编写身份验证和授权代码。” 〜从来没有Web开发人员。 厌倦了一次又一次地建立相同的登录屏幕&#xff1f; 尝试使用Okta API进行托管身份验证&#xff0c;授权和多因素身份验证。 JSON Web令牌已Swift成为保护Web应用程序安全的标准&#xff0c;并取代了Cook…

SpringBoot配置文件与配置类的属性映射方式

一、在pom文件中加入依赖 目录结构 在实体类中会出现错误&#xff0c;然后点击这个网址会有需要的依赖 网址&#xff1a; https://docs.spring.io/spring-boot/docs/2.1.6.RELEASE/reference/html/configuration-metadata.html#configuration-metadata-annotation-processor 引…

Linux 命令之 groupadd -- 新建用户群组

文章目录命令简介常用选项参考示例创建新的用户组创建系统用户组扩展知识命令简介 用于创建一个新的工作组&#xff0c;新工作组的信息将被添加到 /etc/group 文件中。 /etc/group 文件存储着系统所有的用户组信息&#xff0c;文件中每一行描述一个用户组信息&#xff0c;格式…

java获得电脑性能_Java:使用SingletonStream获得性能

java获得电脑性能仅具有一个元素的Java流有时会在应用程序中造成不必要的开销。 了解如何使用SingletonStream对象并为其中某些流获得十倍的性能&#xff0c;并了解如何同时简化代码。 背景 Java 8中的Stream库是迄今为止Java语言最强大的功能之一。 一旦您开始了解它的多功能…

SpringBoot与MyBatis技术集成

一 、创建project步骤 目录结构 pom依赖 <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0" xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation"ht…

Linux 命令之 deluser -- 删除用户

文章目录命令简介常用选项参考示例删除普通用户将用户从用户组中删除删除用户的所有文件命令简介 deluser 命令用于删除用户。将一个用户从一个组中删除&#xff08;即退出用户组&#xff09;&#xff0c;大家都推荐用 usermod&#xff0c;其实 deluser 才是正解。deluser 的选…

ubuntu安装jdk语句_JDK 12:实际中的切换语句/表达式

ubuntu安装jdk语句我的上一篇文章“ 玩JDK 12的Switch表达式 ”讨论了使用JDK 12 Early Access Builds尝试JEP 325 switch 表达式和语句的过程&#xff0c;并提供了一个简单的示例。 这篇文章使用相同的JDK 12 Early Access Build 10来演示switch表达式和增强的switch语句的不同…

SpringBoot JPA

一、创建步骤 二、目录结构 三、application.properties配置datasource spring.datasource.driver-class-namecom.mysql.cj.jdbc.Driver spring.datasource.usernameroot spring.datasource.passwordroot spring.datasource.urljdbc:mysql://localhost/springboot?userUnicod…

Linux 命令之 userdel -- 用于删除给定的用户以及与用户相关的文件

文章目录命令简介常用选项参考示例删除用户命令简介 userdel 命令用于删除指定的用户及与该用户相关的文件&#xff0c;英文全称即“user delete”。在 Debian 上&#xff0c;我们通常会使用 deluser 命令。 其实 userdel 命令实际上是修改了系统的用户账号文件 /etc/passwd、…

RestTemplate入门案例

一、创建步骤注意事项 二、目录结构 三、RestTemplateApplication层 package com.william;import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.annotation.Bean; …

java 示例_功能Java示例 第5部分–将I / O移到外部

java 示例这是称为“ Functional Java by Example”的系列文章的第5部分。 在上一部分中&#xff0c;我们停止了对文档的变异&#xff0c;并返回了数据的副本。 现在&#xff0c;我们需要移走一些I / O。 如果您是第一次来&#xff0c;最好是从头开始阅读。 它有助于了解我们…

Linux 命令之 groupdel -- 删除指定的用户组

命令介绍 groupdel 命令用于删除指定的工作组&#xff0c;本命令要修改的系统文件包括 /ect/group 和 /ect/gshadow。若该群组中仍包括某些用户&#xff0c;则必须先删除这些用户后&#xff0c;方能删除群组。 参考示例 删除指定用户组 删除 linuxcool 工作组&#xff1a; …

模拟微服务业务场景

一、创建步骤 模拟开发过程中的服务间关系。抽象出来&#xff0c;开发中的微服务之间的关系是生产者和消费者关系。 总目标&#xff1a;模拟一个最简单的服务调用场景&#xff0c;场景中保护微服务提供者(Producer)和微服务调用者(Consumer)&#xff0c;方便后面使用微服务架…

Linux 命令之 groupmod -- 更改群组识别码或名称

文章目录命令介绍常用选项参考示例命令介绍 groupmod 命令用于更改群组的识别码或名称时。不过大家还是要注意&#xff0c;用户名不要随意修改&#xff0c;组名和 GID 也不要随意修改&#xff0c;因为非常容易导致管理员逻辑混乱。如果非要修改用户名或组名&#xff0c;则建议…