1. 概述
Jersey 是一個開源框架,用於開發 RESTful Web 服務。它作為 JAX-RS 的參考實現。
在本文中,我們將探索使用 Jersey 2 創建 RESTful Web 服務。 此外,我們還將使用 Spring 的依賴注入 (DI) 與 Java 配置。
2. Maven 依賴項
首先,讓我們為 pom.xml 添加依賴項:
org.glassfish.jersey.containers
jersey-container-servlet
2.26
org.glassfish.jersey.media
jersey-media-json-jackson
2.26
此外,為了進行 Spring 集成,我們需要添加 jersey-spring4 依賴項:
org.glassfish.jersey.ext
jersey-spring4
2.26
這些依賴項的最新版本可以在 jersey-container-servlet、jersey-media-json-jackson 和 jersey-spring4。
3. Web 配置
接下來,我們需要設置一個 Web 項目來進行 Servlet 配置。為此,我們將使用 Spring 的 WebApplicationInitializer:@Order(Ordered.HIGHEST_PRECEDENCE)
public class ApplicationInitializer
implements WebApplicationInitializer {
@Override
public void onStartup(ServletContext servletContext)
throws ServletException {
AnnotationConfigWebApplicationContext context
= new AnnotationConfigWebApplicationContext();
servletContext.addListener(new ContextLoaderListener(context));
servletContext.setInitParameter(
"contextConfigLocation", "com.baeldung.server");
}
}
在這裏,我們添加了 @Order(Ordered.HIGHEST_PRECEDENCE) 註解,以確保我們的初始化器在 Jersey-Spring 默認初始化器之前執行。
4. 一種使用 Jersey JAX-RS 的服務
4.1. 資源表示類
讓我們使用一個示例資源表示類:
@XmlRootElement
public class Employee {
private int id;
private String firstName;
// 標準的 getter 和 setter
}
請注意,JAXB 註解如 @XmlRootElement 僅在需要 XML 支持(除了 JSON)時才需要。
4.2. 服務實現
現在讓我們看看如何使用 JAX-RS 註解來創建 RESTful Web 服務:
@Path("/employees")
public class EmployeeResource {
@Autowired
private EmployeeRepository employeeRepository;
@GET
@Path("/{id}")
@Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
public Employee getEmployee(@PathParam("id") int id) {
return employeeRepository.getEmployee(id);
}
@POST
@Consumes({ 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 註解提供服務到相對 URI 路徑。 我們可以將變量嵌入到 URI 語法中,如 {id} 變量所示。 然後,變量將在運行時進行替換。 要獲取變量的值,可以使用 @PathParam 註解。
@GET, @PUT, @POST, @DELETE 和 @HEAD 定義請求的 HTTP 方法,這些方法將由註釋的方法處理。
@Produces 註解定義端點的響應類型(MIME 媒體類型)。 在我們的示例中,我們已將其配置為根據 HTTP 標頭 Accept(application/json 或 application/xml)的值返回 JSON 或 XML。
另一方面,@Consumes 註解定義服務可以消耗的 MIME 媒體類型。 在我們的示例中,服務可以消耗 JSON 或 XML,具體取決於 HTTP 標頭 Content-Type(application/json 或 application/xml)。
@Context 註解用於在類字段、Bean 屬性或方法參數中注入信息。 在我們的示例中,我們使用它來注入 UriInfo。 還可以使用它來注入 ServletConfig、ServletContext、HttpServletRequest 和 HttpServletResponse。
5. 使用 ExceptionMapper
ExceptionMapper 允許我們攔截異常並向客户端返回適當的 HTTP 響應代碼。 在下面的示例中,如果拋出 EmployeeNotFound 異常,則返回 HTTP 響應代碼 404:
@Provider
public class NotFoundExceptionHandler
implements ExceptionMapper<EmployeeNotFound> {
public Response toResponse(EmployeeNotFound ex) {
return Response.status(Response.Status.NOT_FOUND).build();
}
}
6. 管理資源類
最後,讓我們將所有服務實現類和異常映射器與應用程序路徑連接起來:@ApplicationPath("/resources")
public class RestConfig extends Application {
public Set<Class<?>> getClasses() {
return new HashSet<Class<?>>(
Arrays.asList(
EmployeeResource.class,
NotFoundExceptionHandler.class,
AlreadyExistsExceptionHandler.class));
}
}
7. API 測試
現在我們來使用一些實時測試來測試 API:
public class JerseyApiLiveTest {
private static final String SERVICE_URL
= "http://localhost:8082/spring-jersey/resources/employees";
@Test
public void givenGetAllEmployees_whenCorrectRequest_thenResponseCodeSuccess()
throws ClientProtocolException, IOException {
HttpUriRequest request = new HttpGet(SERVICE_URL);
HttpResponse httpResponse = HttpClientBuilder
.create()
.build()
.execute(request);
assertEquals(httpResponse
.getStatusLine()
.getStatusCode(), HttpStatus.SC_OK);
}
}
8. 結論
在本文中,我們介紹了 Jersey 框架並開發了一個簡單的 API。我們使用了 Spring 的依賴注入功能。我們還看到了 ExceptionMapper 的使用。