API REST con Jersey e Spring

REST Top

Ho appena annunciato il nuovo corso Learn Spring , incentrato sui fondamenti di Spring 5 e Spring Boot 2:

>> SCOPRI IL CORSO

1. Panoramica

Jersey è un framework open source per lo sviluppo di servizi Web RESTful. Serve come implementazione di riferimento di JAX-RS.

In questo articolo esploreremo la creazione di un servizio Web RESTful utilizzando Jersey 2 . Inoltre, useremo la Dependency Injection (DI) di Spring con la configurazione Java.

2. Dipendenze di Maven

Cominciamo aggiungendo le dipendenze al pom.xml :

 org.glassfish.jersey.containers jersey-container-servlet 2.26   org.glassfish.jersey.media jersey-media-json-jackson 2.26 

Inoltre, per l'integrazione di Spring dobbiamo aggiungere la dipendenza jersey-spring4 :

 org.glassfish.jersey.ext jersey-spring4 2.26 

L'ultima versione di queste dipendenze è disponibile in jersey-container-servlet, jersey-media-json-jackson e jersey-spring4.

3. Configurazione Web

Successivamente, abbiamo bisogno di impostare un progetto web per fare la configurazione Servlet. Per questo, useremo WebApplicationInitializer di Spring :

@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"); } }

Qui stiamo aggiungendo l' annotazione @Order (Ordered.HIGHEST_PRECEDENCE) per assicurarci che il nostro inizializzatore venga eseguito prima dell'inizializzatore predefinito Jersey-Spring.

4. Un servizio che utilizza Jersey JAX-RS

4.1. Classe di rappresentazione delle risorse

Usiamo una classe di rappresentazione della risorsa di esempio:

@XmlRootElement public class Employee { private int id; private String firstName; // standard getters and setters }

Tieni presente che le annotazioni JAXB come @XmlRootElement sono richieste solo se è necessario il supporto XML (oltre a JSON).

4.2. Implementazione del servizio

Vediamo ora come possiamo utilizzare le annotazioni JAX-RS per creare servizi web RESTful:

@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(); } }

L' annotazione @Path fornisce il percorso URI relativo al servizio. Possiamo anche incorporare variabili nella sintassi dell'URI, come mostra la variabile {id} . Quindi, le variabili verranno sostituite in fase di esecuzione. Per ottenere il valore della variabile possiamo utilizzare l' annotazione @PathParam .

@GET , @PUT , @POST, @DELETE e @HEAD definiscono il metodo HTTP della richiesta , che verrà elaborato dai metodi annotati.

L' annotazione @Produces definisce il tipo di risposta dell'endpoint (tipo di supporto MIME). Nel nostro esempio, l'abbiamo configurato per restituire JSON o XML a seconda del valore dell'intestazione HTTP Accept ( application / json o application / xml ).

D'altra parte, l' annotazione @Consumes definisce i tipi di media MIME che il servizio può utilizzare. Nel nostro esempio, il servizio può utilizzare JSON o XML a seconda dell'intestazione HTTP Content-Type ( application / json o application / xml ).

L' annotazione @Context viene utilizzata per iniettare informazioni in un campo di classe, una proprietà del bean o un parametro del metodo. Nel nostro esempio, lo stiamo usando per iniettare UriInfo . Possiamo anche usarlo per iniettare ServletConfig , ServletContext , HttpServletRequest e HttpServletResponse.

5. Utilizzo di ExceptionMapper

ExceptionMapper ci consente di intercettare le eccezioni e restituire il codice di risposta HTTP appropriato al client. Nell'esempio seguente, viene restituito il codice di risposta HTTP 404 se viene generata l'eccezione EmployeeNotFound :

@Provider public class NotFoundExceptionHandler implements ExceptionMapper { public Response toResponse(EmployeeNotFound ex) { return Response.status(Response.Status.NOT_FOUND).build(); } }

6. Gestione delle classi di risorse

Infine, colleghiamo tutte le classi di implementazione del servizio e i mappatori di eccezioni su un percorso dell'applicazione:

@ApplicationPath("/resources") public class RestConfig extends Application { public Set
    
      getClasses() { return new HashSet
     
      ( Arrays.asList( EmployeeResource.class, NotFoundExceptionHandler.class, AlreadyExistsExceptionHandler.class)); } }
     
    

7. Test API

Proviamo ora le API con alcuni test dal vivo:

public class JerseyApiLiveTest { private static final String SERVICE_URL = "//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. Conclusione

In questo articolo abbiamo introdotto il framework Jersey e sviluppato una semplice API. Abbiamo utilizzato le funzionalità di Spring for Dependency Injection. Abbiamo anche visto l'uso di ExceptionMapper .

Come sempre, il codice sorgente completo è disponibile in questo progetto Github.

REST fondo

Ho appena annunciato il nuovo corso Learn Spring , incentrato sui fondamenti di Spring 5 e Spring Boot 2:

>> SCOPRI IL CORSO