应用开发中会对资源进行大量的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