The introduction
When it comes to RestFul, it’s easy to think of the Spring framework, and if you haven’t worked with it before, it’s recommended to click on the portal to learn how to quickly build a RestFul Web service using Spring.
Today we are building a Restful service by integrating Spring with Jersey, another lightweight framework. Jersey is an open source framework for building Restful Web services. Is a concrete implementation of the JAX-RS specification.
Maven rely on
First we introduce jersey-related dependencies:
<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>
Copy the code
To integrate the Spring framework, we also need to introduce jersey-Spring 4 dependencies:
<! -- Integrate spring -->
<dependency>
<groupId>org.glassfish.jersey.ext</groupId>
<artifactId>jersey-spring4</artifactId>
<version>3.0.0 - M6</version>
</dependency>
Copy the code
Web configuration
Next, we need to create a Web project for the Servlet configuration, use the Spring WebApplicationInitializer.
@Order(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"); }}Copy the code
Here add @ Order (Ordered HIGHEST_PRECEDENCE) the role of annotation is to ensure that the WebApplicationInitializer in Jersey – Spring before the default initialization program execution.
Use the Jersey JAX-RS service
Resource representation class
@XmlRootElement
public class Employee {
private int id;
private String firstName;
public int getId(a) {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getFirstName(a) {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName; }}Copy the code
JAXB annotations like @XMLRootelement need to be introduced when only XML support is required (other than JSON),
Implementation services
Now let’s build a RESTful Web service using JAX-RS annotations:
@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(); }}Copy the code
The @path annotation represents the service request route. We can also embed variables in the request route, such as {id} in the code. If you need to get the value of this variable, you can annotate it with @pathParam.
@get, @PUT, @post, @delete, and @head indicate how HTTP requests are made.
Produces represents the data type of the response, which in our example we have configured to return JSON or XML based on the HTTP request header (Acceptapplication/ JSON or Application/XML).
@Consumes defines the MIME types that are available for services. The data types depend on the content-type (application/ JSON or Application/XML) of the request header.
The @context annotation is used to inject information into a class field, bean property, or method parameter. In the example, we use it to inject UriInfo. We can also use it to inject ServletConfig, ServletContext, HttpServletRequest, and HttpServletResponse.
Using ExceptionMapper
ExceptionMapper helps us intercept exceptions and return the appropriate HTTP response code to the client. In the following example, HTTP response code 404 is returned if the EmployeeNotFound exception is thrown:
@Provider
public class NotFoundExceptionHandler
implements ExceptionMapper<EmployeeNotFound> {
public Response toResponse(EmployeeNotFound ex) {
returnResponse.status(Response.Status.NOT_FOUND).build(); }}Copy the code
Managing Resource Classes
Finally, let’s connect all service implementation classes and exception mappings according to the application path:
@ApplicationPath("/resources")
public class RestConfig extends Application {
publicSet<Class<? >> getClasses() {return new HashSet<Class<?>>(
Arrays.asList(
EmployeeResource.class,
NotFoundExceptionHandler.class,
AlreadyExistsExceptionHandler.class));
}
}
Copy the code
The API test
public class JerseyApiLiveTest {
private static final String SERVICE_URL
= "http://localhost:8082/spring-jersey/resources/employees";
@Test
public void givenGetAllEmployees_whenCorrectRequest_thenResponseCodeSuccess(a)
throws ClientProtocolException, IOException {
HttpUriRequest request = newHttpGet(SERVICE_URL); HttpResponse httpResponse = HttpClientBuilder .create() .build() .execute(request); assertEquals(httpResponse .getStatusLine() .getStatusCode(), HttpStatus.SC_OK); }}Copy the code
conclusion
This article introduced the Jersey framework and developed a simple API. We introduced Spring for dependency injection. We also saw the use of ExceptionMapper.