Java EE开发系列教程 - Web Service

英文版同步链接:http://www.zxuqian.com/java-ee/java-ee-application-development-restful-web-service.html

Web Service为不同应用程序间传递数据的一种通用协议。REST,全称为Representational State Transfer,是一种数据传输形式,它规定了数据和文件都为能够通过URI访问的资源。此教程将RESTful web service加入到之前的工程中,然后给出生成JSON和XML数据的实例。

项目源代码: https://github.com/zxuqian/Learning-Java-EE-2016/tree/09f7cf7b123e9ed3029841df98db4f5cd42b55c4

创建模块

打开 IntelliJ, 选择 File -> New -> Module... 菜单,在弹出的对话框中选择 Maven, 选择 parentnotebookRoot, 设置 groupIdcom.zxuqianartifactIdnotebookRESTful, 点击 next,确保新创建的模块目录与其他模块在同级目录,否则此模块就会成为其他模块的父模块。点击 finish

src 同级目录创建文件夹结构 WebContent,此文件夹为web工程的根路径,用来存放JSF页面。打包工程时,maven会自动识别此文件夹。最后在此文件夹下创建 WEB-INF 目录,用来存放配置文件。

新模块的 pom.xml



    
        notebookRoot
        com.zxuqian
        0.0.2
        ../notebookRoot/pom.xml
    
    4.0.0
    notebookRESTful
    war

    
        
            
                maven-compiler-plugin
            
            
                maven-war-plugin
                
                    WebContent
                    false
                
            
        
    

    
        
            org.jboss.spec.javax.ws.rs
            jboss-jaxrs-api_2.0_spec
            provided
        

        
            javax.enterprise
            cdi-api
            provided
        

        
            org.jboss.spec.javax.ejb
            jboss-ejb-api_3.2_spec
            provided
        

        
            com.zxuqian
            notebookService
            ejb
        

    




此处引用了新的依赖: org.jboss.spec.javax.ws.rs - 这是JAX-RS规范的JBOSS实现,包含了所有的Web service功能。另外,notebookService 模块也被引用进来,用来添加和获取用户数据供新的RESTful web service模块调用。

编码

notebookRESTful 模块中,创建一个Java类 UserResource 位于 com.zxuqian.notebook.webservice 包中。

@Path("/user")
public class UserResource {

    private static final Logger logger = Logger.getLogger(UserResource.class.getCanonicalName());

    @EJB
    private IUserServiceLocal userService;

    @GET
    @Path("/{id}")
    @Produces({MediaType.APPLICATION_JSON})
    public User getUserById(@PathParam("id") Long id) {

        User user = this.userService.getUserById(id);
        return user;

    }

    @PUT
    @Consumes(MediaType.APPLICATION_JSON)
    public Response createUser(User user) {
        this.userService.addUser(user);

        return Response.ok().build();
    }

    @DELETE
    @Path("/{id}")
    public Response deleteUser(@PathParam("id") Long id) {

        logger.severe("The id is: " + id);

        User user = this.userService.getUserById(id);

        logger.severe("The user is: " + user);

        this.userService.deleteUser(user);

        return Response.ok().build();
    }


}
  • @Path 类级注解定义了访问UserResource的根路径,例如,如果访问Web Service的路径为 http://localhost:8080/notebook-rest,那么访问User资源的URI就会以 http://localhost:8080/notebook-rest/user 开头。 @Path 方法级注解定义了对资源进行操作的具体路径,如果要根据id查询某一特定用户,则相应的URI为 http://localhost:8080/notebook-rest/user/1 ,然后就会匹配到 getUserById 方法。 @Path("/{id}"} 中的{id}为通用匹配符,它会取URI最后一段的值,例如上述URI中的 1,然后它的值会赋给用 @PathParam("id") 参数级注解标记的 id 参数。
  • Web service对资源的操作用HTTP动词来标记,在Web Service中共有7种,常用的为 POST, GET, PUTDELETE,分别用来更新,获取,新增和删除。 Java中使用同名的注解来使用这些动词。
  • @Consume@Produce 分别表示接收什么类型的数据和生成什么样的数据。getUserbyId() 方法生成json格式的数据,而createUser() 方法需要接收 json 类型的数据。
  • 注意,deleteUser() 方法是先根据id查询出user对象然后再删除。但是这样会有问题,因为通过 getUserById() 查询出来的user为detached(脱管)对象,不能直接使用JPA的API进行删除。因而,在 notebookDomain 模块的 deleteUser() 方法第一行添加 user = this.entityManager.merge(user); 来把脱管的对象变为持久对象:
public void deleteUser(User user) {
        user = this.entityManager.merge(user);
        this.entityManager.remove(user);

}

UserResource 中各个方法中的代码都很简单明了,无非查询和添加数据,然后返回HTTP响应码。Response.ok() 返回 200 表示成功。当然更正确的做法应该在 @PUT 方法中返回 201 并返回新创建的资源的URI。

JAXB

JAXB 是Java XML绑定API,可以把普通Java对象(POJO)自动映射为XML或者JSON。使用此API需要转换 notebookDomain 模块中的User 类为JAXB类。只需要简单的添加一个类级注解 @XmlRootElement 即可,所有的成员变量的名字将作为XML的标签或JSON的key。

User.java

@Entity
// 'from' unexpected error. Add JPA facet by project structure, then specify the persistent.xml and provider.
@NamedQuery(name = "getAllUsersQuery", query = "from User u")
@XmlRootElement
public class User implements Serializable {

配置模块

现在,在 WebContent/WEB-INF 文件夹下创建 web.xml 文件,内容为:




  
    javax.ws.rs.core.Application
    /*
  


javax.ws.rs.core.Application 是负责映射URL到Web Service资源的servlet。/* 代表所有访问此模块的URL都会映射到web serivce资源的URI。

最后在 notebookEAR 模块中的 pom.xml 文件中配置web service模块的上下文路径(此处为关键代码,全文请参考github源码):


      com.zxuqian
      notebookRESTful
      /notebook-rest

运行程序

notebookRoot 模块执行Maven install 然后在 notebookEAR 模块中执行 wildfly:run 来启动wildfly server并部署EAR文件。

这里我用了一个叫 Postman 的工具来测试Web Service,可在这里下载: https://www.getpostman.com/ 打开后工具界面如下:

Java EE开发系列教程 - Web Service_第1张图片
image.png

在工具右侧,可选择HTTP动词,输入Web Service URI,定义HTTP headers。然后点击 Send 就会发起HTTP请求到Web Service。 例如访问id为 1 的用户,可以看到返回的JSON数据(为了测试目的,用户的密码明文返回到了这里,在生产环境中应坚决避免)。

新增一个用户:

Java EE开发系列教程 - Web Service_第2张图片
image.png

选择 PUT 方式。 然后在 Body 选项中选择 JSON(application/JSON) 作为content type(橙色部分)。 可以直接copy从GET中返回的JSON结构,然后删除 id 属性,并修改其他属性为新的用户数据,然后点击 Send。成功之后就会看到 Status 显示为 200

可以从数据库中验证结果:

Java EE开发系列教程 - Web Service_第3张图片
image.png

可以看到,数据库中多了一条id为 5 的用户数据。

删除用户:

Java EE开发系列教程 - Web Service_第4张图片
image.png

选择 DELETE 方式,按图指定URI,然后点击 Send 按钮。 成功后可在数据库中查询结果:

Java EE开发系列教程 - Web Service_第5张图片
image.png

最后,如果把 UserResource 类中的 getUserById() 方法的注解 @Produces 改成 APPLICATION_XML 就会产生 XML 格式的数据:

Java EE开发系列教程 - Web Service_第6张图片
image.png

有关Web Service的基本知识就介绍到这里,如果有问题,欢迎留言评论!

你可能感兴趣的:(Java EE开发系列教程 - Web Service)