应用开发中会对资源进行大量的CRUD操作,CRUD指创建(Create)、获取(Read)、更新(Update)和销毁(DELETE)。 2000年Roy Fielding博士在他的博士论文“Architectural Styles and the Design of Network-based Software Architectures”《体系结构与基于网络的软件架构设计》中提出了REST。REST Representational State Transfer的缩写(一般中文翻译为表述性状态转移)。在REST中所有东西都被看作资源。每一个资源都有一个URI和它对应。在REST中使用统一接口处理资源。与数据库CRUD操作(Create、Read、Update 和 Delete)一样,可以用POST、GET、PUT和DELETE处理REST资源。
Jersey RESTful 框架是开源的RESTful框架, 实现了JAX-RS (JSR 311 & JSR 339) 规范。它扩展了JAX-RS 参考实现, 提供了更多的特性和工具, 可以进一步地简化 RESTful service 和 client 开发,与Struts类似,它同样可以和hibernate,spring框架整合。
本文使用IDEA+MAVEN+Jersey来开发REST风格的接口(API).
一、实践环境和目标
1、通过MAVEN 来保障Jersey依赖完整
2、开发环境为 IDEA,数据库真实操作,采用模拟方式
4、运行环境为Tomcat
3、通过实践完成REST风格的CRUD操作。
二、工程搭建
1、创建工程
在IDEA里面新建一个Model,选择 Java Enterprise ,SDK采用 java 1.7, 应用服务器为 Tomcat7.应用框架要勾选 Web Application 3.1
Next 后,在Model 名称输入工程名称 RestApi
2、工程配置
工程创建后,还工程框架里面,我们还需要加入MAVEN支持,当然你也可以自己下载Jersey 库,用MAVEN的好处就是依赖的完整性工具本身会自动完成。在工程名称上右键,弹出菜单里面,选择 Add Framework Support:
在新弹出界面上选择 MAVEN,然后点OK确定。
配置Artifacts,完成编译和发布配置。具体做法是,通过Build菜单,打开Build Artifacts->Edit 打开 Artifacts,在Available Elements里面,在自己的MODEL(RestApi)下,选择Maven开始的依赖库,右键,选择Put int /WEB-INF/lib
处理完成后,如下图所示,就配置好了
整体工程结构如下图所示:
三、开发编码
1、配置MAVEN
编辑MAVEN的配置文件POM.xml,代码如下:
<?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.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.study.restful</groupId> <artifactId>RestApi</artifactId> <version>1.0-SNAPSHOT</version> <dependencies> <dependency> <groupId>org.glassfish.jersey.containers</groupId> <artifactId>jersey-container-servlet</artifactId> <version>2.17</version> </dependency> <dependency> <groupId>org.glassfish.jersey.core</groupId> <artifactId>jersey-client</artifactId> <version>2.17</version> </dependency> <dependency> <groupId>org.glassfish.jersey.media</groupId> <artifactId>jersey-media-json-jackson</artifactId> <version>2.17</version> </dependency> </dependencies> </project>编辑后,会提示error,因为没有配置中的内容,执行修正,MAVEN就会自动下载相关的依赖,下载完成后就不会提示error了。
2、配置项目web.xml
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" version="3.1"> <servlet> <servlet-name>JAX-RS Servlet</servlet-name> <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class> <init-param> <param-name>jersey.config.server.provider.packages</param-name> <param-value>com.study.restful</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>JAX-RS Servlet</servlet-name> <url-pattern>/restapi/*</url-pattern> </servlet-mapping> </web-app>这里面的 param-value是com.study.restful 是项目包结构 url-pattern 是指工程发布后,url的路径,以上面代码为例,后面访问地址为: http://localhost:8080/restapi/服务名....
3、编写数据层
数据层包含了 实体,DAO层,CRUD操作,因为CRUD操作涉及具体数据库,一般用hibernate或者mybaits,本工程只是实践REST,所以DAO层的CRUD操作只是模拟。
1)实体
package com.study.restful.entity; import javax.xml.bind.annotation.XmlRootElement; import java.io.Serializable; @XmlRootElement public class User implements Serializable { private static final long serialVersionUID = 1L; private int id; private String name; private String phone; public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getPhone() { return phone; } public void setPhone(String phone) { this.phone = phone; } }创建了一个user实体,含有属性和操作。 注意类名前用@XmlRootElement 注解,可以将实体映射为xml
2)DAO层
package com.study.restful.dao; import com.study.restful.entity.User; public class UserDao { User user; public UserDao() { User user = new User(); user.setId(1); user.setName("solo"); user.setPhone("13799008888"); this.user = user; } public UserDao(User user) { this.user = user; } //CRUD 创建 public void createUser( int id, String name, String phone){ System.out.println("CRUD Opt: 创建一个User"); user.setId(id); user.setName(name); user.setPhone(phone); dbOptCreate(user); } //CRUD 查询 public User readUserByName(String name ){ return dbOptQuery(name); } //CRUD 修改 public void updateUser(int id, String name, String phone){ System.out.println("CRUD Opt: 修改一个User"); user.setId(id); user.setName(name); user.setPhone(phone); dbOptUpdate(user); } //CRUD 删除 public void deleteUser( int id ){ System.out.println("CRUD Opt: 删除一个User"); dbOptDelete(id); } //模拟数据库操作 private void dbOptCreate( User user){ System.out.println("数据库操作,创建成功"); } private void dbOptUpdate( User user){ System.out.println("数据库操作, 修改成功"); } private void dbOptDelete( int id){ System.out.println("数据库操作, 删除成功"); } //模拟数据库操作 private User dbOptQuery( String name){ User user= new User(); //构造一个模拟数据 user.setId(1); user.setName(name); user.setPhone("13988886666"); System.out.println("数据库操作, 查询成功"); return user; } }这里模拟了CRUD操作。
4、编写业务层
业务层,这里就是体现为对外服务接口 UserService,具体看如下类
package com.study.restful; import com.study.restful.dao.UserDao; import com.study.restful.entity.User; import javax.ws.rs.*; import javax.ws.rs.core.MediaType; @Path("/UserService") public class UserService { UserDao userDao = new UserDao(); String msg; @GET @Produces(MediaType.TEXT_PLAIN) public String sayHello() { return "Hello, Service is Runing"; } @GET @Path("/{username}") @Produces("text/plain;charset=UTF-8") public String sayHello2UserByText(@PathParam("username") String username) { return "Hello " + username; } //CRUD @POST @Path("/create/{id}/{username}/{phone}") @Produces( {MediaType.APPLICATION_JSON }) public String createUser( @PathParam("id")int id, @PathParam("username")String name, @PathParam("phone")String phone) { userDao. createUser( id, name, phone); return "Create User:" + id+","+name+","+phone+" Sucessfully!"; } @GET @Path("/get") @Produces( {MediaType.APPLICATION_JSON} ) public User readUserByName(@QueryParam("username") String username) { System.out.println(username); User user = userDao.readUserByName(username); System.out.println(user.getName()); return user; } //@GET 用浏览器是get请求 @PUT @Path("/updateUser/{id}/{username}/{phone}") @Produces(MediaType.APPLICATION_JSON) //修改 public String updateUser(@PathParam("id") int id, @PathParam("username") String name,@PathParam("phone") String phone) { userDao.updateUser( id, name, phone ); return "Update User:" + id+","+name+","+phone+", Run Sucessfully!"; } @DELETE @Path("/deleteUser/{id}") @Produces(MediaType.APPLICATION_JSON) public String deleteUser(@PathParam("id")int id) { userDao.deleteUser(id); return "Delete User:" + id+", Run Sucessfully!"; } }5、发布和运行
前面我们已经配置Artifacts, 现在只要build和运行就可以了
四、调试和测试
1) 使用浏览器测试get方法( 查询)
//CRUD操作, 查找映射http get
http://localhost:8080/restapi/UserService/get?username=solo
因为浏览器http操作是get调用,所以下面操作,需要用工具如postman 或者soapgui 工具来,否则会出现405异常
//CRUD操作, 创建映射http post
http://localhost:8080/restapi/UserService/create/2/solo/13399991111
//CRUD操作, 修改映射http put
http://localhost:8080/restapi/UserService/updateUser/2/solo/13399997777
//CRUD操作, 删除映射http DELETE
http://localhost:8080/restapi/UserService/deleteUser/2
五、补充材料
其他一些RESTful 框架:
Dropwizard
Jersey
Ninja Web Framework
Play Framework
Restlet
Restx
Spark Framework