Bouw een REST API met Spring en Java Config

REST Top

Ik heb zojuist het nieuwe aangekondigd Leer de lente natuurlijk, gericht op de basisprincipes van Spring 5 en Spring Boot 2:

>> BEKIJK DE CURSUS

1. Overzicht

Dit artikel laat zien hoe stel REST in het voorjaar in - de controller en HTTP-responscodes, configuratie van payload-rangschikking en inhoudsonderhandeling.

2. REST in het voorjaar begrijpen

Het Spring-framework ondersteunt twee manieren om RESTful-services te maken:

  • MVC gebruiken met ModelAndView
  • met behulp van HTTP-berichtconverters

De ModelAndView aanpak is ouder en veel beter gedocumenteerd, maar ook meer uitgebreid en configuratie zwaar. Het probeert het REST-paradigma in het oude model te brengen, wat niet zonder problemen is. Het Spring-team begreep dit en bood eersteklas REST-ondersteuning vanaf Spring 3.0.

De nieuwe aanpak, gebaseerd op HttpMessageConverter en annotaties, is veel lichter en gemakkelijker te implementeren. De configuratie is minimaal en biedt redelijke standaardinstellingen voor wat u van een RESTful-service zou verwachten.

3. De Java-configuratie

@Configuration @EnableWebMvc openbare klasse Webconfiguratie {//}

De nieuwe @EnableWebMvc annotatie heeft een aantal nuttige dingen - specifiek, in het geval van REST, detecteert het het bestaan ​​van Jackson en JAXB 2 op het klassenpad en maakt en registreert automatisch standaard JSON- en XML-converters. De functionaliteit van de annotatie is gelijk aan de XML-versie:

Dit is een snelkoppeling en hoewel het in veel situaties nuttig kan zijn, is het niet perfect. Als er een complexere configuratie nodig is, verwijdert u de annotatie en breidt u deze uit WebMvcConfigurationSupport direct.

3.1. Spring Boot gebruiken

Als we de @SpringBootApplication annotatie en de lente-webmvc bibliotheek is op het klassenpad, dan is de @EnableWebMvc annotatie wordt automatisch toegevoegd met een standaard autoconfiguratie.

We kunnen nog steeds MVC-functionaliteit aan deze configuratie toevoegen door het WebMvcConfigurer interface op een @Configuratie geannoteerde klasse. We kunnen ook een WebMvcRegistrationsAdapter instantie om onze eigen te voorzien RequestMappingHandlerMapping, RequestMappingHandlerAdapter, of ExceptionHandlerExceptionResolver implementaties.

Ten slotte, als we de MVC-functies van Spring Boot willen negeren en een aangepaste configuratie willen declareren, kunnen we dit doen door de @EnableWebMvc annotatie.

4. Testen van de lente-context

Vanaf Spring 3.1 krijgen we eersteklas testondersteuning voor @Configuratie klassen:

@RunWith (SpringJUnit4ClassRunner.class) @ContextConfiguration (classes = {WebConfig.class, PersistenceConfig.class}, loader = AnnotationConfigContextLoader.class) public class SpringContextIntegrationTest {@Test public void contextLoad }s () {

We specificeren de Java-configuratieklassen met de @ContextConfiguration annotatie. De nieuwe AnnotationConfigContextLoader laadt de bean-definities van de @Configuratie klassen.

Merk op dat de Webconfiguratie configuratieklasse is niet opgenomen in de test omdat deze moet worden uitgevoerd in een Servlet-context, die niet is opgegeven.

4.1. Spring Boot gebruiken

Spring Boot biedt verschillende annotaties om de Spring in te stellen ApplicationContext voor onze tests op een meer intuïtieve manier.

We kunnen slechts een bepaald deel van de applicatieconfiguratie laden, of we kunnen het hele opstartproces van de context simuleren.

We kunnen bijvoorbeeld de @BuienRadarNL annotatie als we willen dat de volledige context wordt gemaakt zonder de server te starten.

Met dat op zijn plaats, kunnen we vervolgens de @AutoConfigureMockMvc om een MockMvc instantie en verzend HTTP-verzoeken:

@RunWith (SpringRunner.class) @SpringBootTest @AutoConfigureMockMvc openbare klasse FooControllerAppIntegrationTest {@Autowired privé MockMvc mockMvc; @Test public void whenTestApp_thenEmptyResponse () gooit Uitzondering {this.mockMvc.perform (get ("/ foos") .andExpect (status (). IsOk ()) .andExpect (...);}}

Om te voorkomen dat we de hele context creëren en alleen onze MVC-controllers testen, kunnen we @WebMvcTest:

@RunWith (SpringRunner.class) @WebMvcTest (FooController.class) openbare klasse FooControllerWebLayerIntegrationTest {@Autowired private MockMvc mockMvc; @MockBean privé IFooService-service; @Test () public void whenTestMvcController_thenRetrieveExpectedResult () gooit uitzondering {// ... this.mockMvc.perform (get ("/ foos") .andExpect (...);}}

We kunnen gedetailleerde informatie over dit onderwerp vinden in ons artikel ‘Testen in Spring Boot '.

5. De verantwoordelijke

De @RestController is het centrale artefact in de volledige weblaag van de RESTful API. Voor het doel van dit bericht is de controller een eenvoudige REST-bron aan het modelleren - Foo:

@RestController @RequestMapping ("/ foos") klasse FooController {@Autowired privé IFooService-service; @GetMapping openbare lijst findAll () {retourneer service.findAll (); } @GetMapping (waarde = "/ {id}") openbare Foo findById (@PathVariable ("id") Lange id) {retourneer RestPreconditions.checkFound (service.findById (id)); } @PostMapping @ResponseStatus (HttpStatus.CREATED) openbaar Lang maken (@RequestBody Foo-bron) {Preconditions.checkNotNull (bron); return service.create (bron); } @PutMapping (value = "/ {id}") @ResponseStatus (HttpStatus.OK) openbare ongeldige update (@PathVariable ("id") Lange id, @RequestBody Foo-bron) {Preconditions.checkNotNull (bron); RestPreconditions.checkNotNull (service.getById (resource.getId ())); service.update (bron); } @DeleteMapping (waarde = "/ {id}") @ResponseStatus (HttpStatus.OK) openbare ongeldige verwijdering (@PathVariable ("id") Lange id) {service.deleteById (id); }}

Het is je misschien opgevallen dat ik een eenvoudige Guava-stijl gebruik RestPreconditions nut:

openbare klasse RestPreconditions {openbare statische T checkFound (T-resource) {if (resource == null) {gooi nieuwe MyResourceNotFoundException (); } bron teruggeven; }}

De implementatie van de controller is niet openbaar - dit is omdat dit niet nodig is.

Meestal is de controller de laatste in de keten van afhankelijkheden. Het ontvangt HTTP-verzoeken van de Spring front-controller (het DispatcherServlet) en delegeert ze eenvoudig door naar een servicelaag. Als er geen use-case is waarbij de controller moet worden geïnjecteerd of gemanipuleerd via een directe referentie, dan verklaar ik deze liever niet als openbaar.

De aanvraagtoewijzingen zijn eenvoudig. Zoals bij elke controller, is de actual waarde van de mapping, evenals de HTTP-methode, bepalen de doelmethode voor het verzoek. @RequestBody bindt de parameters van de methode aan de body van het HTTP-verzoek, terwijl @ResponseBody doet hetzelfde voor het antwoord en het retourtype.

De @RestController is een afkorting om zowel de @ResponseBody en de @Controller annotaties in onze klas.

Ze zorgen er ook voor dat de resource met de juiste HTTP-converter wordt gerangschikt en gedemarkeerd. Er vindt onderhandeling over de inhoud plaats om te kiezen welke van de actieve converters wordt gebruikt, voornamelijk op basis van de Aanvaarden header, hoewel andere HTTP-headers ook kunnen worden gebruikt om de weergave te bepalen.

6. Het in kaart brengen van de HTTP-antwoordcodes

De statuscodes van de HTTP-respons zijn een van de belangrijkste onderdelen van de REST-service en het onderwerp kan snel erg gecompliceerd worden. Het juist krijgen van deze punten kan de service maken of breken.

6.1. Niet-toegewezen verzoeken

Als Spring MVC een verzoek ontvangt dat geen toewijzing heeft, beschouwt het het verzoek als niet toegestaan ​​en retourneert het een 405-METHODE NIET TOEGESTAAN naar de client.

Het is ook een goede gewoonte om de Toestaan HTTP-header bij het retourneren van een 405 aan de klant, om te specificeren welke bewerkingen zijn toegestaan. Dit is het standaardgedrag van Spring MVC en vereist geen aanvullende configuratie.

6.2. Geldige toegewezen verzoeken

Voor elk verzoek dat wel een toewijzing heeft, beschouwt Spring MVC het verzoek als geldig en antwoordt met 200 OK als er geen andere statuscode anders is gespecificeerd.

Het is daarom dat de controller anders verklaart @ResponseStatus voor de creëren, bijwerken en verwijderen acties maar niet voor krijgen, die inderdaad de standaard 200 OK zou moeten retourneren.

6.3. Clientfout

In het geval van een clientfout worden aangepaste uitzonderingen gedefinieerd en toegewezen aan de juiste foutcodes.

Door simpelweg deze uitzonderingen uit een van de lagen van de weblaag te gooien, zorgt Spring ervoor dat de bijbehorende statuscode op de HTTP-reactie wordt toegewezen:

@ResponseStatus (HttpStatus.BAD_REQUEST) openbare klasse BadRequestException breidt RuntimeException uit {//} @ResponseStatus (HttpStatus.NOT_FOUND) openbare klasse ResourceNotFoundException breidt RuntimeException uit {//}

Deze uitzonderingen maken deel uit van de REST API en mogen als zodanig alleen worden gebruikt in de juiste lagen die overeenkomen met REST; als er bijvoorbeeld een DAO / DAL-laag bestaat, mag deze de uitzonderingen niet rechtstreeks gebruiken.

Merk ook op dat dit geen gecontroleerde uitzonderingen zijn, maar runtime-uitzonderingen - in lijn met de Spring-praktijken en idiomen.

6.4. Gebruik makend van @BuienRadarNL

Een andere optie om aangepaste uitzonderingen op specifieke statuscodes toe te wijzen, is door de @BuienRadarNL annotatie in de controller. Het probleem met die benadering is dat de annotatie alleen van toepassing is op de controller waarin deze is gedefinieerd. Dit betekent dat we in elke controller afzonderlijk moeten declareren.

Er zijn natuurlijk meer manieren om fouten in zowel Spring als Spring Boot af te handelen die meer flexibiliteit bieden.

7. Extra afhankelijkheden van Maven

Naast de lente-webmvc afhankelijkheid vereist voor de standaard webapplicatie, moeten we content marshalling en unmarshalling instellen voor de REST API:

  com.fasterxml.jackson.core jackson-databind 2.9.8 javax.xml.bind jaxb-api 2.3.1 runtime 

Dit zijn de bibliotheken die worden gebruikt om de weergave van de REST-bron naar JSON of XML te converteren.

7.1. Spring Boot gebruiken

Als we JSON-geformatteerde bronnen willen ophalen, biedt Spring Boot ondersteuning voor verschillende bibliotheken, namelijk Jackson, Gson en JSON-B.

Autoconfiguratie wordt uitgevoerd door gewoon een van de toewijzingsbibliotheken in het klassenpad op te nemen.

Als we een webapplicatie ontwikkelen, we zullen gewoon de spring-boot-starter-web afhankelijkheid en vertrouw erop om alle noodzakelijke artefacten voor ons project op te nemen:

 org.springframework.boot spring-boot-starter-web 2.1.2.RELEASE 

Spring Boot gebruikt standaard Jackson.

Als we onze bronnen in XML-indeling willen serialiseren, moeten we de Jackson XML-extensie (jackson-dataformat-xml) naar onze afhankelijkheden, of terugvallen op de JAXB-implementatie (standaard geleverd in de JDK) door de @XmlRootElement annotatie op onze bron.

8. Conclusie

Deze tutorial illustreert hoe je een REST-service implementeert en configureert met behulp van Spring en Java-gebaseerde configuratie.

In de volgende artikelen van de serie zal ik me concentreren op de vindbaarheid van de API, geavanceerde inhoudsonderhandelingen en het werken met aanvullende weergaven van een Bron.

Alle code van dit artikel is beschikbaar op Github. Dit is een op Maven gebaseerd project, dus het zou gemakkelijk moeten kunnen worden geïmporteerd en uitgevoerd zoals het is.

REST onder

Ik heb zojuist het nieuwe aangekondigd Leer de lente natuurlijk, gericht op de basisprincipes van Spring 5 en Spring Boot 2:

>> BEKIJK DE CURSUS

$config[zx-auto] not found$config[zx-overlay] not found