引言
提到 RestFul ,很容易联想到 Spring 框架,如果你在此之前没有接触过 Spring 框架,建议先点击 传送门 了解一下如何通过 Spring 快速构建一个 Restful Web 服务。
今天我们主要通过另一个轻量级的框架— Jersey
整合 Spring 来构建一个 Restful 服务。 Jersey 是一个用于构建 Restful Web 服务的一个开源框架。是 JAX-RS 规范的一种具体实现。
Maven 依赖
首先引入 Jersey
相关的依赖:1
2
3
4
5
6
7
8
9
10<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-container-servlet</artifactId>
<version>3.0.1</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-json-jackson</artifactId>
<version>3.0.1</version>
</dependency>
如果要整合 Spring 框架的话,我们还需要引入 jersey-spring4
依赖:
1 | <!-- 整合spring --> |
Web 配置
接下来,我们需要建立一个 Web 项目来进行 Servlet 配置,使用 Spring 的 WebApplicationInitializer 。1
2
3
4
5
6
7
8
9
10
11 (Ordered.HIGHEST_PRECEDENCE)
public class ApplicationInitializer implements WebApplicationInitializer {
public void onStartup(javax.servlet.ServletContext servletContext) {
AnnotationConfigWebApplicationContext context
= new AnnotationConfigWebApplicationContext();
servletContext.addListener(new ContextLoaderListener(context));
servletContext.setInitParameter("contextConfigLocation", "com.example.server");
}
}
这里添加 @Order(Ordered.HIGHEST_PRECEDENCE)
注解的作用是确保 WebApplicationInitializer 在 Jersey-Spring 默认初始化程序之前执行。
使用 Jersey JAX-RS 服务
资源表示类
1 |
|
当仅需要 XML 支持(除了JSON)时,才需要引入 @XmlRootElement 这一类的 JAXB 注解,
实现服务
现在我们通过 JAX-RS 注解来构建一个 RESTful Web 服务:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29"/employees") (
public class EmployeeResource {
private EmployeeRepository employeeRepository;
"/{id}") (
({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
public Employee getEmployee(@PathParam("id") int id) {
return employeeRepository.getEmployee(id);
}
({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
public Response addEmployee(
Employee employee, @Context UriInfo uriInfo) {
employeeRepository.addEmployee(new Employee(employee.getId(),
employee.getFirstName(), employee.getLastName(),
employee.getAge()));
return Response.status(Response.Status.CREATED.getStatusCode())
.header(
"Location",
String.format("%s/%s",uriInfo.getAbsolutePath().toString(),
employee.getId())).build();
}
}
@Path
注解表示服务请求路由,我们也可以将变量嵌入到请求路由中,如代码中的 {id}
。如果需要获取该变量值,可以通过 @PathParam
注解。
@GET
, @PUT
, @POST
, @DELETE
和 @HEAD
标识请求 HTTP 的方式。
@Produces
表示响应的数据类型,在示例中,我们已将其配置为根据HTTP请求头为 (Acceptapplication/json 或 application/xml) 的值返回JSON或XML。
@Consumes
定义服务可用的 MIME 类型,具体的数据类型取决于请求头 Content-Type(application/json或application/xml)。
@Context
注解用于将信息注入类字段,bean属性或方法参数。在示例中,我们使用它来注入 UriInfo
。我们还可以使用它来注入 ServletConfig , ServletContext , HttpServletRequest 和 HttpServletResponse 。
使用 ExceptionMapper
ExceptionMapper
可以帮助我们拦截异常并将适当的HTTP响应代码返回给客户端。在以下示例中,如果抛出 EmployeeNotFound 异常,则返回 HTTP 响应代码 404 :
1
2
3
4
5
6
7
8
public class NotFoundExceptionHandler
implements ExceptionMapper<EmployeeNotFound> {
public Response toResponse(EmployeeNotFound ex) {
return Response.status(Response.Status.NOT_FOUND).build();
}
}
管理资源类
最后,让我们根据应用程序路径连接所有服务实现类和异常映射:1
2
3
4
5
6
7
8
9
10"/resources") (
public class RestConfig extends Application {
public Set<Class<?>> getClasses() {
return new HashSet<Class<?>>(
Arrays.asList(
EmployeeResource.class,
NotFoundExceptionHandler.class,
AlreadyExistsExceptionHandler.class));
}
}
API 测试
1 | public class JerseyApiLiveTest { |
总结
本文介绍了 Jersey
框架并开发了一个简单的 API 。我们引入 Spring
用于依赖关系注入功能。还看到了 ExceptionMapper 的使用。
...
...
Copyright by @maybelence.