如何组织提供REST Web服务的JEE6企业应用程序?

sfr*_*frj 4 java rest design-patterns jax-rs java-ee

从一个月前开始,我正在努力学习宁静的网络服务.现在我练习了语法并理解了概念,我决定创建一个包含EJB,JPA和REST的非常简单的企业应用程序.我正在努力尝试了解组织这种系统的最佳方法.如果有经验的人可以给我一些关于什么是最佳实践的提示,我会非常感激,以及如何解决我当前的问题.

我来告诉你这个形象吧.抱歉,我无法获得更好的分辨率(使用Ctrl +鼠标向上滚动缩放):

在此输入图像描述

正如您所看到的,这是一个非常简单的企业应用程序,它有2个模块.

此应用程序不使用CDI(我希望在没有CDI帮助的情况下实现我的目标)

当某个客户端(任何可互操作的客户端)发送带有某些参数的@GET时,REST服务应将这些参数传递给EJB模块,该模块将在数据库中搜索并发回适当的数据.最后,服务将在JAXB的帮助下自动编组,并将.XML发送回客户端.

我的问题如下:

  • 我得到一个ClassCastException,因为它在EJB模块中的实体与WebModule中的JAXB类不兼容(即使它们的变量是相同的)
  • 我不知道应该如何组织事情,所以前端可以整理和解组这些实体.
  • 应该是实体类在前端与JAXB映射相结合吗?如果那时,就不会真正需要EJB模块.但问题是,我想要EJB模块,因为我经常在那里进行CRUD操作.
  • 将EJB公开为REST Web服务(制作混合)怎么样?你认为这是个好主意吗?它怎么能帮到我?
  • 再次,如果我在Web模块中创建JAXRS + EJB的混合,我将必须在前端创建我的JPA实体,这是我以前从未做过的事情.你认为这是一个好习惯吗?
  • 你有什么建议?使用REST Web服务的企业应用程序的组织方式通常是什么?

bdo*_*han 5

下面是一个JAX-RS服务的示例,该服务作为会话bean实现,使用JPA进行持久化,JAXB用于消息传递.(注意一个EntityManager是注入会话bean的,你为什么要避免这种行为?):

package org.example;

import java.util.List;

import javax.ejb.*;
import javax.persistence.*;
import javax.ws.rs.*;
import javax.ws.rs.core.MediaType;

@Stateless
@LocalBean
@Path("/customers")
public class CustomerService {

    @PersistenceContext(unitName="CustomerService",
                        type=PersistenceContextType.TRANSACTION)
    EntityManager entityManager;

    @POST
    @Consumes(MediaType.APPLICATION_XML)
    public void create(Customer customer) {
        entityManager.persist(customer);
    }

    @GET
    @Produces(MediaType.APPLICATION_XML)
    @Path("{id}")
    public Customer read(@PathParam("id") long id) {
        return entityManager.find(Customer.class, id);
    }

    @PUT
    @Consumes(MediaType.APPLICATION_XML)
    public void update(Customer customer) {
        entityManager.merge(customer);
    }

    @DELETE
    @Path("{id}")
    public void delete(@PathParam("id") long id) {
        Customer customer = read(id);
        if(null != customer) {
            entityManager.remove(customer);
        }
    }

    @GET
    @Produces(MediaType.APPLICATION_XML)
    @Path("findCustomersByCity/{city}")
    public List<Customer> findCustomersByCity(@PathParam("city") String city) {
        Query query = entityManager.createNamedQuery("findCustomersByCity");
        query.setParameter("city", city);
        return query.getResultList();
    }

}
Run Code Online (Sandbox Code Playgroud)

如果要在服务器和客户端使用相同的域对象.然后我将通过XML而不是注释提供JPA映射,以避免客户端上的类路径依赖.

欲获得更多信息


UPDATE

META-INF/persistence.xml中

您可以在persistence.xml文件中指定包含JPA映射的XML文件的链接:

<persistence-unit name="CustomerService" transaction-type="JTA">
    <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
    <jta-data-source>CustomerService</jta-data-source>
    <mapping-file>META-INF/orm.xml</mapping-file>
</persistence-unit>
Run Code Online (Sandbox Code Playgroud)

META-INF/orm.xml中

您将在此文件中添加JPA元数据的XML表示形式.

<?xml version="1.0" encoding="UTF-8"?>
<entity-mappings
    version="2.0"
    xmlns="http://java.sun.com/xml/ns/persistence/orm"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/persistence/orm http://java.sun.com/xml/ns/persistence/orm_2_0.xsd">
    <entity class="org.example.Customer">
         <named-query name="findCustomersByCity">
            <query>SELECT c FROM Customer c WHERE c.address.city = :city</query>
         </named-query>
         <attributes>
            <id name="id"/>
            <basic name="firstName">
                <column name="FIRST_NAME"/>
            </basic>
            <basic name="lastName">
                <column name="LAST_NAME"/>
            </basic>
            <one-to-many name="phoneNumbers" mapped-by="customer">
                <cascade>
                    <cascade-all/>
                </cascade>
            </one-to-many>
            <one-to-one name="address" mapped-by="customer">
                <cascade>
                    <cascade-all/>
                </cascade>
            </one-to-one>
         </attributes>
    </entity>
    <entity class="org.example.Address">
        <attributes>
            <id name="id"/>
            <one-to-one name="customer">
                <primary-key-join-column/>
            </one-to-one>
        </attributes>
    </entity>
    <entity class="org.example.PhoneNumber">
        <table name="PHONE_NUMBER"/>
        <attributes>
            <id name="id"/>
            <many-to-one name="customer">
                <join-column name="ID_CUSTOMER"/>
            </many-to-one>
        </attributes>
    </entity>
</entity-mappings>
Run Code Online (Sandbox Code Playgroud)

欲获得更多信息