Bonenvalidatie in Jersey

1. Overzicht

In deze tutorial gaan we kijken naar Bean Validation met behulp van het open source framework Jersey.

Zoals we al hebben gezien in eerdere artikelen, Jersey is een open source framework voor het ontwikkelen van RESTful Web Services. We kunnen meer informatie over Jersey krijgen in onze inleiding over het maken van een API met Jersey en Spring.

2. Bonenvalidatie in Jersey

Validatie is het proces waarbij wordt gecontroleerd of sommige gegevens voldoen aan een of meer vooraf gedefinieerde beperkingen. Het is natuurlijk een veel voorkomende use-case in de meeste toepassingen.

Het Java Bean Validation-framework (JSR-380) is de de facto standaard geworden voor het afhandelen van dit soort bewerkingen in Java. Raadpleeg onze vorige tutorial om de basisprincipes van Java Bean Validation samen te vatten.

Jersey bevat een uitbreidingsmodule om Bean Validation te ondersteunen. Om deze mogelijkheid in onze applicatie te gebruiken, moeten we deze eerst configureren. In de volgende sectie zullen we zien hoe we onze applicatie kunnen configureren.

3. Applicatie-instellingen

Laten we nu voortbouwen op het eenvoudige Fruit API-voorbeeld uit het uitstekende Jersey MVC Support-artikel.

3.1. Afhankelijkheden van Maven

Laten we allereerst de Bean Validation-afhankelijkheid toevoegen aan onze pom.xml:

 org.glassfish.jersey.ext jersey-bean-validation 2.27 

We kunnen de nieuwste versie krijgen van Maven Central.

3.2. Configureren van de server

In Jersey registreren we normaal gesproken de extensiefunctie die we willen gebruiken in onze aangepaste resourceconfiguratieklasse.

Voor de bean-validatie-extensie is deze registratie echter niet nodig. Gelukkig is dit een van de weinige extensies die het Jersey-framework automatisch registreert.

Ten slotte, om validatiefouten naar de klant te sturen we voegen een servereigenschap toe aan onze aangepaste bronconfiguratie:

openbare ViewApplicationConfig () {pakketten ("com.baeldung.jersey.server"); eigenschap (ServerProperties.BV_SEND_ERROR_IN_RESPONSE, true); } 

4. Validatie van JAX-RS-bronmethoden

In dit gedeelte leggen we twee verschillende manieren uit om invoerparameters te valideren met behulp van constraint-annotaties:

  • Met behulp van ingebouwde API-beperkingen voor Bean Validation
  • Een aangepaste beperking en validator maken

4.1. Gebruik van ingebouwde constraint-annotaties

Laten we beginnen met de ingebouwde annotaties met beperkingen:

@POST @Path ("/ create") @Consumes (MediaType.APPLICATION_FORM_URLENCODED) public void createFruit (@NotNull (message = "Fruitnaam mag niet null zijn") @FormParam ("name") Stringnaam, @NotNull (message = "Fruit kleur mag niet nul zijn") @FormParam ("kleur") String kleur) {Fruit fruit = nieuw Fruit (naam, kleur); SimpleStorageService.storeFruit (fruit); } 

In dit voorbeeld maken we een nieuw Fruit met behulp van twee formulierparameters, naam en kleur. Wij gebruiken de @Niet nul annotatie die al deel uitmaakt van de Bean Validation API.

Dit legt een eenvoudige niet-nulbeperking op aan onze formulierparameters. In het geval dat een van de parameters nul, wordt het bericht dat in de annotatie is gedeclareerd, geretourneerd.

Uiteraard demonstreren we dit met een unit test:

@Test openbare leegte gegevenCreateFruit_whenFormContainsNullParam_thenResponseCodeIsBadRequest () {Form form = new Form (); form.param ("naam", "appel"); form.param ("kleur", null); Antwoordantwoord = target ("fruit / create"). Request (MediaType.APPLICATION_FORM_URLENCODED) .post (Entity.form (formulier)); assertEquals ("Http Response moet 400 zijn", 400, response.getStatus ()); assertThat (response.readEntity (String.class), containsString ("Fruit kleur mag niet null zijn")); } 

In het bovenstaande voorbeeld wij gebruiken de JerseyTest ondersteuningsklasse om onze fruitbron te testen. We sturen een POST-verzoek met een null kleur en controleer of het antwoord het verwachte bericht bevat.

Raadpleeg de documenten voor een lijst met ingebouwde validatiebeperkingen.

4.2. Een aangepaste constraint-annotatie definiëren

Soms moeten we complexere beperkingen opleggen. We kunnen dit doen door onze eigen aangepaste annotatie te definiëren.

Laten we ons, aan de hand van ons eenvoudige Fruit API-voorbeeld, voorstellen dat we moeten valideren dat al het fruit een geldig serienummer heeft:

@PUT @Path ("/ update") @Consumes ("application / x-www-form-urlencoded") public void updateFruit (@SerialNumber @FormParam ("serial") String serial) {// ...} 

In dit voorbeeld is de parameter serieel moet voldoen aan de beperkingen die zijn gedefinieerd door @Serienummer, die we hierna zullen definiëren.

We zullen eerst de annotatie van de beperking definiëren:

@Retention (RetentionPolicy.RUNTIME) @Constraint (validatedBy = {SerialNumber.Validator.class}) openbaar @interface SerialNumber {String message () standaard "Fruit-serienummer is niet geldig"; Klasse [] groepen () standaard {}; Klasse [] payload () standaard {}; } 

Vervolgens definiëren we de validatorklasse Serienummer.Validator:

public class Validator implementeert ConstraintValidator {@Override public void initialize (SerialNumber serial) {} @Override public boolean isValid (String serial, ConstraintValidatorContext constraintValidatorContext) {String serialNumRegex = "^ \ d {3} - \ d {3} - \ \ d {4} $ "; Return Pattern.matches (serialNumRegex, serieel); }} 

Het belangrijkste punt hier is de Validator klasse moet implementeren ConstraintValidator waar T is het type waarde dat we willen valideren, in ons geval a Draad .

Ten slotte implementeren we vervolgens onze aangepaste validatielogica in het is geldig methode.

5. Validatie van middelen

Bovendien stelt de Bean Validation API ons ook in staat om objecten te valideren met behulp van de @Geldig annotatie.

In de volgende sectie zullen we twee verschillende manieren uitleggen om resourceklassen te valideren met behulp van deze annotatie:

  • Vraag eerst bronvalidatie aan
  • Ten tweede: validatie van responsbronnen

Laten we beginnen met het toevoegen van de @Min annotatie bij onze Fruit voorwerp:

@XmlRootElement openbare klasse Fruit {@Min (waarde = 10, bericht = "Vruchtgewicht moet 10 of hoger zijn") privé Geheel getal; // ...} 

5.1. Vraag resource validatie aan

Allereerst zullen we validatie inschakelen met behulp van @Geldig in onze FruitResource klasse:

@POST @Path ("/ create") @Consumes ("application / json") public void createFruit (@Valid Fruit fruit) {SimpleStorageService.storeFruit (fruit); } 

In het bovenstaande voorbeeld als we een vrucht proberen te maken met een gewicht van minder dan 10, krijgen we een validatiefout.

5.2. Validatie van responsbronnen

Evenzo zullen we in het volgende voorbeeld zien hoe we een antwoordbron kunnen valideren:

@GET @Valid @Produces ("application / json") @Path ("/ search / {name}") openbaar Fruit findFruitByName (@PathParam ("naam") String naam) {return SimpleStorageService.findByName (naam); }

Let op, hoe we hetzelfde gebruiken @Geldig annotatie. Maar deze keer gebruiken we het op het niveau van de resourcemethode om er zeker van te zijn dat het antwoord geldig is.

6. Aangepaste handler voor uitzonderingen

In dit laatste deel zullen we kort bekijken hoe u een aangepaste uitzonderingshandler kunt maken. Dit is handig als we een aangepast antwoord willen retourneren als we een bepaalde beperking overtreden.

Laten we beginnen met het definiëren van onze FruitExceptionMapper:

openbare klasse FruitExceptionMapper implementeert ExceptionMapper {@Override public Response toResponse (ConstraintViolationException-uitzondering) {return Response.status (Response.Status.BAD_REQUEST) .entity (preparMessage (uitzondering)) .type ("text / plain") .build (); } private String preparMessage (uitzondering ConstraintViolationException) {StringBuilder message = nieuwe StringBuilder (); voor (ConstraintViolation cv: exception.getConstraintViolations ()) {message.append (cv.getPropertyPath () + "" + cv.getMessage () + "\ n"); } return message.toString (); }}

Allereerst definiëren we een aangepaste provider voor het toewijzen van uitzonderingen. Om dit te doen, implementeren we het ExceptionMapper interface met behulp van een ConstraintViolationException.

Daarom zullen we zien dat wanneer deze uitzondering wordt gegenereerd, de antwoorden methode van onze aangepaste exception-mapper-instantie wordt aangeroepen.

In dit eenvoudige voorbeeld herhalen we ook alle overtredingen en voegen we elke eigenschap en elk bericht toe dat in het antwoord moet worden teruggestuurd.

Om vervolgens onze aangepaste exception-mapper te gebruiken, moeten we onze provider registreren:

@Override beschermde applicatie configure () {ViewApplicationConfig config = nieuwe ViewApplicationConfig (); config.register (FruitExceptionMapper.class); return config; }

Ten slotte voegen we een eindpunt toe om een ​​ongeldig te retourneren Fruit om de exception-handler in actie te laten zien:

@GET @Produces (MediaType.TEXT_HTML) @Path ("/ exception") @Valid openbaar Fruit exception () {Fruit fruit = new Fruit (); fruit.setName ("a"); fruit.setColour ("b"); fruit teruggeven; } 

7. Conclusie

Samenvattend hebben we in deze tutorial de Jersey Bean Validation API-extensie onderzocht.

Ten eerste zijn we begonnen met te introduceren hoe de Bean Validation API in Jersey kan worden gebruikt. We hebben ook gekeken hoe u een voorbeeldwebtoepassing configureert.

Ten slotte hebben we gekeken naar verschillende manieren om validatie uit te voeren met Jersey en hoe we een aangepaste exception handler kunnen schrijven.

Zoals altijd is de volledige broncode van het artikel beschikbaar op GitHub.