REST 在 2000 年由 Roy Fielding 在博士论文中提出,他是 HTTP 规范 1.0 和 1.1 版的首席作者之一。
REST 中最重要的概念是资源(resources),使用全球 ID(通常使用 URI)标识。客户端应用程序使用 HTTP 方法(GET/ POST/ PUT/ DELETE)操作资源或资源集。RESTful Web 服务是使用 HTTP 和 REST 原理实现的 Web 服务。通常,RESTful Web 服务应该定义以下方面:
表 1. HTTP 方法操作映射表
方法 | 执行动作 | 示例:http://hostname/{appcontext}/resources/1234 |
---|---|---|
GET | 查看资源 | 查看ID为1234的资源 |
POST | 创建一个资源 | 在下面创建一个子资源 |
PUT | 创建或更新一个资源 | 创建或更新ID为1234的资源 |
DELETE | 删除资源 | 删除ID为1234的资源 |
Jersey is Sun’s production quality reference implementation for JSR 311: JAX-RS: The Java API for RESTful Web Services. Jersey implements support for the annotations defined in JSR-311, making it easy for developers to build RESTful web services with Java and the Java JVM. Jersey also adds additional features not specified by the JSR.
<properties>
<project.build.sourceEncoding>UTF-8project.build.sourceEncoding>
<jersey.version>2.6jersey.version>
<jersey-spring.version>2.23.1jersey-spring.version>
<spring.version>4.2.7.RELEASEspring.version>
<servlet-api-version>3.1.0servlet-api-version>
<logback.version>1.1.1logback.version>
<jcloverslf4j.version>1.7.6jcloverslf4j.version>
properties>
<dependencies>
<dependency>
<groupId>org.glassfish.jersey.extgroupId>
<artifactId>jersey-spring3artifactId>
<version>${jersey-spring.version}version>
<exclusions>
<exclusion>
<groupId>org.springframeworkgroupId>
<artifactId>spring-coreartifactId>
exclusion>
<exclusion>
<groupId>org.springframeworkgroupId>
<artifactId>spring-webartifactId>
exclusion>
<exclusion>
<groupId>org.springframeworkgroupId>
<artifactId>spring-beansartifactId>
exclusion>
exclusions>
dependency>
<dependency>
<groupId>org.glassfish.jersey.containersgroupId>
<artifactId>jersey-container-servletartifactId>
<version>${jersey-spring.version}version>
dependency>
<dependency>
<groupId>org.glassfish.jersey.containersgroupId>
<artifactId>jersey-container-servlet-coreartifactId>
<version>${jersey-spring.version}version>
dependency>
<dependency>
<groupId>org.glassfish.jersey.mediagroupId>
<artifactId>jersey-media-json-jacksonartifactId>
<version>${jersey.version}version>
dependency>
<dependency>
<groupId>org.glassfish.jersey.mediagroupId>
<artifactId>jersey-media-multipartartifactId>
<version>${jersey.version}version>
dependency>
<dependency>
<groupId>org.glassfish.jersey.extgroupId>
<artifactId>jersey-entity-filteringartifactId>
<version>${jersey.version}version>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-coreartifactId>
<version>${spring.version}version>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-contextartifactId>
<version>${spring.version}version>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-webartifactId>
<version>${spring.version}version>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-jdbcartifactId>
<version>${spring.version}version>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-txartifactId>
<version>${spring.version}version>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-testartifactId>
<version>${spring.version}version>
<scope>testscope>
dependency>
<dependency>
<groupId>javax.servletgroupId>
<artifactId>javax.servlet-apiartifactId>
<version>${servlet-api-version}version>
<scope>providedscope>
dependency>
<dependency>
<groupId>ch.qos.logbackgroupId>
<artifactId>logback-classicartifactId>
<version>${logback.version}version>
dependency>
<dependency>
<groupId>org.slf4jgroupId>
<artifactId>jcl-over-slf4jartifactId>
<version>${jcloverslf4j.version}version>
dependency>
<dependency>
<groupId>junitgroupId>
<artifactId>junitartifactId>
<version>4.12version>
<scope>testscope>
dependency>
dependencies>
<web-app>
<display-name>Archetype Created Web Applicationdisplay-name>
<context-param>
<param-name>contextConfigLocationparam-name>
<param-value>classpath:applicationContext.xmlparam-value>
context-param>
<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
listener-class>
listener>
<servlet>
<servlet-name>jersey-serlvetservlet-name>
<servlet-class>
org.glassfish.jersey.servlet.ServletContainer
servlet-class>
<init-param>
<param-name>javax.ws.rs.Applicationparam-name>
<param-value>com.ricky.codelab.jersey.RestJaxRsApplicationparam-value>
init-param>
<load-on-startup>1load-on-startup>
servlet>
<servlet-mapping>
<servlet-name>jersey-serlvetservlet-name>
<url-pattern>/*url-pattern>
servlet-mapping>
web-app>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.1.xsd">
<context:component-scan base-package="com.ricky.codelab.jersey">context:component-scan>
beans>
package com.ricky.codelab.jersey;
import com.ricky.codelab.jersey.resource.UserResource;
import org.glassfish.jersey.jackson.JacksonFeature;
import org.glassfish.jersey.server.ResourceConfig;
import org.glassfish.jersey.server.spring.scope.RequestContextFilter;
/**
* ${DESCRIPTION}
*
* @author Ricky Fung
* @create 2016-07-20 14:15
*/
public class RestJaxRsApplication extends ResourceConfig {
/**
* Register JAX-RS application components.
*/
public RestJaxRsApplication() {
// register application resources
this.register(UserResource.class);
// register filters
register(RequestContextFilter.class);
//register(LoggingResponseFilter.class);
//register(CORSResponseFilter.class);
// register exception mappers
//register(GenericExceptionMapper.class);
//register(AppExceptionMapper.class);
//register(NotFoundExceptionMapper.class);
// register features
register(JacksonFeature.class);
//register(MultiPartFeature.class);
}
}
package com.ricky.codelab.jersey.resource;
import com.ricky.codelab.jersey.domain.User;
import com.ricky.codelab.jersey.service.IUserService;
import org.springframework.beans.factory.annotation.Autowired;
import javax.ws.rs.*;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import java.util.List;
/**
* ${DESCRIPTION}
*
* @author Ricky Fung
* @create 2016-07-20 14:28
*/
@Path("/user")
public class UserResource {
@Autowired
private IUserService userService;
@POST
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.TEXT_HTML })
public Response createUser(User user){
long id = userService.insert(user);
return Response.status(Response.Status.CREATED)// 201
.entity("A new user has been created")
.header("Location",
"http://localhost:8888/user/"
+ String.valueOf(id)).build();
}
@POST
@Consumes({ MediaType.APPLICATION_FORM_URLENCODED })
@Produces({ MediaType.TEXT_HTML })
public Response createUserApplicationFormURLencoded(
@FormParam("name") String name,
@FormParam("age") Integer age) {
User user = new User();
user.setName(name);
user.setAge(age);
long id = userService.insert(user);
return Response
.status(Response.Status.CREATED)// 201
.entity("A new user/resource has been created at /user/"
+ id)
.header("Location",
"http://localhost:8888/user/"
+ String.valueOf(id)).build();
}
//http://localhost:8080/user/1
@GET
@Path("/{id}")
@Produces(MediaType.APPLICATION_JSON)
public User getUserById(@PathParam("id") Long id) {
return userService.findUserById(id);
}
@GET
@Path("/list")
@Produces(MediaType.APPLICATION_JSON)
public List getUserList() {
return userService.getUserList();
}
@GET
@Produces(MediaType.APPLICATION_JSON)
public User getUserByName(@QueryParam("username") String username) {
return userService.findUserByName(username);
}
@PUT
@Path("{id}")
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.TEXT_HTML })
public Response putUserById(@PathParam("id") Long id, User user){
User userById = userService.findUserById(id);
if (userById == null) {
// resource not existent yet, and should be created under the specified URI
long userId = userService.insert(user);
return Response
.status(Response.Status.CREATED)
.entity("A new user has been created AT THE LOCATION you specified")
.header("Location",
"http://localhost:8888/user/"
+ String.valueOf(userId)).build();
} else {
// resource is existent and a full update should occur
userService.update(user);
return Response
.status(Response.Status.OK)
.entity("The user you specified has been fully updated created AT THE LOCATION you specified")
.header("Location",
"http://localhost:8888/user/"
+ String.valueOf(id)).build();
}
}
@DELETE
@Produces({ MediaType.APPLICATION_JSON })
public Response deleteUser() {
userService.delete();
return Response.status(Response.Status.NO_CONTENT)
.entity("All users have been successfully removed").build();
}
@DELETE
@Path("{id}")
@Produces({ MediaType.TEXT_HTML })
public Response deletePodcastById(@PathParam("id") Long id) {
userService.deleteById(id);
return Response.status(Response.Status.NO_CONTENT)
.entity("User successfully removed from database").build();
}
}
其中有几个地方需要强调:
资源类(Resource Class)
资源类是一个简单的 Java 对象 (POJO),可以实现任何接口。这增加了许多好处,比如可重用性和简单。
注解 | 描述 |
---|---|
@Path | URI path |
@GET | |
@POST | |
@PUT | |
@DELETE | |
@HEAD | |
@PathParam | |
@QueryParam | |
@Consumes | |
@Produces | |
@Provider |
Oracle RESTful Web Services Developer’s Guide:https://docs.oracle.com/cd/E19776-01/820-4867/ggnyk/index.html
上述代码均已上传至Github,点此下载