日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > java >内容正文

java

用Spring构建企业Java应用程序

發布時間:2024/3/26 java 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 用Spring构建企业Java应用程序 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

來源:SpringForAll社區

通過在本教程中構建一個簡單的RESTful web API,了解關于使用Java EE和Spring框架構建企業Java應用程序的更多信息。

我認為可以說Java EE在Java開發人員中獲得了相當壞的名聲。盡管多年來,它確實在各個方面都有所改善,甚至從Eclipse Foundation變成了JakartaEE,但它的苦味仍然相當強烈。另一方面,我們有Spring Framework(或者更好地反映現實,一個成熟的Spring Platform),這是一個出色的、輕量級的、快速的、創新的、高生產力的Java EE替代品。那么,為什么要為Java EE費心呢?我們將通過展示使用大多數Java EE規范構建現代Java應用程序是多么容易來回答這個問題。在這方面取得成功的關鍵因素是Eclipse Microprofile:J2EE的微服務時代。我們將要構建的應用程序是用于管理人員的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;

  • ? ?@Version

  • ? ?private 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

  • ? ?@Transactional

  • ? ?public 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

  • ? ?@Transactional

  • ? ?public Optional<PersonEntity> deleteByEmail(String email) {

  • ? ? ? ?return findByEmail(email)

  • ? ? ? ? ? ?.map(entity -> {

  • ? ? ? ? ? ? ? ?em.remove(entity);

  • ? ? ? ? ? ? ? ?return entity;

  • ? ? ? ? ? ?});

  • ? ?}

  • }

  • 事務管理(即@Transactionalannotation)需要一些解釋。在典型的Java EE應用程序中,容器運行時負責管理事務。由于我們不想裝載應用程序容器,而是保持精簡,所以我們可以使用EntityManager來啟動/提交/回滾事務。這當然是可行的,但它也會用樣板污染代碼。可以說,更好的選擇是使用Apache DeltaSpikeCDI擴展用于聲明性事務管理(這是@Transactional和@EntityManagerConfig注釋的來源)。下面的代碼片段說明了如何集成它。

  • @ApplicationScoped

  • public class PersistenceConfig {

  • ? ?@PersistenceUnit(unitName = "peopledb")

  • ? ?private EntityManagerFactory entityManagerFactory;

  • ? ?@Produces @PeopleDb @TransactionScoped

  • ? ?public EntityManager create() {

  • ? ? ? ?return this.entityManagerFactory.createEntityManager();

  • ? ?}

  • ? ?public void dispose(@Disposes @PeopleDb EntityManager entityManager) {

  • ? ? ? ?if (entityManager.isOpen()) {

  • ? ? ? ? ? ?entityManager.close();

  • ? ? ? ?}

  • ? ?}

  • }

  • 太棒了——最難的部分已經過去了!接下來是person數據傳輸對象和服務層。

  • 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;

  • ? ?@Override

  • ? ?public Optional<Person> findByEmail(String email) {

  • ? ? ? ?return repository

  • ? ? ? ? ? ?.findByEmail(email)

  • ? ? ? ? ? ?.map(this::toPerson);

  • ? ?}

  • ? ?@Override

  • ? ?public Person add(Person person) {

  • ? ? ? ?return toPerson(repository.saveOrUpdate(person.getEmail(), person.getFirstName(), person.getLastName()));

  • ? ?}

  • ? ?@Override

  • ? ?public Collection<Person> getAll() {

  • ? ? ? ?return repository

  • ? ? ? ? ? ?.findAll()

  • ? ? ? ? ? ?.stream()

  • ? ? ? ? ? ?.map(this::toPerson)

  • ? ? ? ? ? ?.collect(Collectors.toList());

  • ? ?}

  • ? ?@Override

  • ? ?public 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 Mavenpom.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>

  • 在沒有進一步的ado的情況下,讓我們立即構建和運行應用程序(如果您想知道應用程序使用的是什么關系數據存儲,那么它是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: applicationjson"

  • ? ? -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 Validation 工作正常?為了觸發它,讓我們發送部分準備好的請求。

  • > ?curl ?--X POST http://localhost:10900/api/people -H "Content-Type: applicationjson"

  • ? ? -d '{"firstName": "John", "lastName": "Smith"}'

  • HTTP/1.1 400 Bad Request

  • Content-Length: 0

  • OpenAPI規范和預捆綁的Swagger UI發行版也可以通過http://localhost:10900/index.html?url=http://localhost:10900/api/openapi.json獲得。到目前為止,一切都很好,但公平地說,我們根本沒有談到測試我們的應用程序。要為添加一個person的場景設計出集成測試有多難呢?事實證明,圍繞Java EE應用程序測試的框架已經有了很大的改進。特別是,使用Arquillian測試框架(以及受歡迎的JUnit和REST Assured)非常容易完成。一個真實的例子抵得上千言萬語。

  • @RunWith(Arquillian.class)

  • @EnableRandomWebServerPort

  • public class PeopleApiTest {

  • ? ?@ArquillianResource private URI uri;

  • ? ?@Deployment

  • ? ?public 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");

  • ? ?}

  • ? ?@Test

  • ? ?public 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的方式!事實上,與Spring的相似之處并非巧合,因為它很有啟發性,很有啟發性,而且無疑將繼續激勵Java EE生態系統中的創新。未來如何?我認為,無論對于雅加達EE還是Eclipse Microprofile來說,都是光明的。后者剛剛接近2.0版本,提供了大量新的規范,這些規范旨在滿足微服務體系結構的需求。目睹這些轉變真是太棒了。項目的完整源代碼可以在GitHub上找到。

    原文鏈接:https://dzone.com/articles/building-enterprise-java-applications-the-spring-w

    作者:Andriy Redko

    譯者:xieed


    ·END·

    ?近期熱文:

    • 深入聊一聊 Spring AOP 實現機制

    • Spring Cloud Stream 學習小清單

    • 在一臺Mac上不同平臺同時使用多個Git賬號

    • Git 版本控制之 GitFlow

    • 徹底搞懂 Git-Rebase

    • 我說分布式事務之最大努力通知型事務

    • 我說分布式事務之TCC

    • 不可錯過的CMS學習筆記

    • 在生產中使用Java 11:需要了解的重要事項

    • 可能是最全面的G1學習筆記


    看完,趕緊點個“好看”鴨

    點鴨點鴨

    ↓↓↓↓

    總結

    以上是生活随笔為你收集整理的用Spring构建企业Java应用程序的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。