Pengesahan Kekacang di Jersey

1. Gambaran keseluruhan

Dalam tutorial ini, kita akan melihat Bean Validation menggunakan Jersey framework sumber terbuka.

Seperti yang telah kita lihat dalam artikel sebelumnya, Jersey adalah kerangka sumber terbuka untuk mengembangkan RESTful Web Services. Kami boleh mendapatkan lebih banyak maklumat mengenai Jersey dalam pengenalan kami mengenai cara membuat API dengan Jersey dan Spring.

2. Pengesahan Kacang di Jersey

Pengesahan adalah proses mengesahkan bahawa beberapa data mematuhi satu atau lebih kekangan yang telah ditentukan . Sudah tentu, ini adalah kes penggunaan yang sangat biasa di kebanyakan aplikasi.

Rangka kerja Java Bean Validation (JSR-380) telah menjadi standard de-facto untuk mengendalikan operasi seperti ini di Java. Untuk mengupas asas-asas Pengesahan Kacang Java, sila rujuk tutorial kami sebelumnya.

Jersey mengandungi modul lanjutan untuk menyokong Bean Validation . Untuk menggunakan kemampuan ini dalam aplikasi kita, pertama kita perlu mengkonfigurasinya. Di bahagian seterusnya, kita akan melihat cara mengkonfigurasi aplikasi kita.

3. Persediaan Aplikasi

Sekarang, mari kita bina contoh API Buah sederhana dari artikel Jersey MVC Support yang sangat baik.

3.1. Ketergantungan Maven

Pertama sekali, mari tambah pergantungan Bean Validation ke pom.xml kami :

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

Kita boleh mendapatkan versi terbaru dari Maven Central.

3.2. Mengkonfigurasi Pelayan

Di Jersey, kami biasanya mendaftarkan ciri peluasan yang ingin kami gunakan di kelas konfigurasi sumber tersuai kami.

Walau bagaimanapun, untuk pelanjutan pengesahan kacang, tidak perlu melakukan pendaftaran ini. Nasib baik, ini adalah salah satu daripada beberapa sambungan yang dibuat oleh kerangka Jersey secara automatik.

Akhirnya, untuk menghantar kesalahan pengesahan kepada pelanggan, kami akan menambahkan harta pelayan ke konfigurasi sumber tersuai kami :

public ViewApplicationConfig() { packages("com.baeldung.jersey.server"); property(ServerProperties.BV_SEND_ERROR_IN_RESPONSE, true); } 

4. Mengesahkan Kaedah Sumber JAX-RS

Di bahagian ini, kami akan menerangkan dua cara yang berbeza untuk mengesahkan parameter input menggunakan anotasi kekangan:

  • Menggunakan kekangan API Pengesahan Bean terbina dalam
  • Membuat kekangan dan pengesahan tersuai

4.1. Menggunakan Anotasi Kekangan Buatan Dalam

Mari mulakan dengan melihat anotasi kekangan terbina dalam:

@POST @Path("/create") @Consumes(MediaType.APPLICATION_FORM_URLENCODED) public void createFruit( @NotNull(message = "Fruit name must not be null") @FormParam("name") String name, @NotNull(message = "Fruit colour must not be null") @FormParam("colour") String colour) { Fruit fruit = new Fruit(name, colour); SimpleStorageService.storeFruit(fruit); } 

Dalam contoh ini, kami membuat Buah baru menggunakan dua parameter bentuk, nama dan warna . Kami menggunakan anotasi @NotNull yang sudah menjadi sebahagian daripada Bean Validation API.

Ini mengenakan kekangan sederhana dan tidak kosong pada parameter borang kami. Sekiranya salah satu parameter nol , mesej yang dinyatakan dalam anotasi akan dikembalikan .

Secara semula jadi, kami akan menunjukkan ini dengan ujian unit:

@Test public void givenCreateFruit_whenFormContainsNullParam_thenResponseCodeIsBadRequest() { Form form = new Form(); form.param("name", "apple"); form.param("colour", null); Response response = target("fruit/create").request(MediaType.APPLICATION_FORM_URLENCODED) .post(Entity.form(form)); assertEquals("Http Response should be 400 ", 400, response.getStatus()); assertThat(response.readEntity(String.class), containsString("Fruit colour must not be null")); } 

Dalam contoh di atas, kami menggunakan kelas sokongan JerseyTest untuk menguji sumber buah kami . Kami menghantar permintaan POST dengan warna nol dan memastikan bahawa respons mengandungi mesej yang diharapkan.

Untuk senarai kekangan pengesahan terbina dalam, lihat dokumennya.

4.2. Menentukan Anotasi Kekangan Khusus

Kadang kala kita perlu mengenakan kekangan yang lebih kompleks. Kita boleh melakukan ini dengan menentukan anotasi tersuai kita sendiri.

Dengan menggunakan contoh Fruit API kami yang sederhana, bayangkan kita perlu mengesahkan bahawa semua buah mempunyai nombor siri yang sah:

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

Dalam contoh ini, siri parameter mesti memenuhi batasan yang ditentukan oleh @SerialNumber , yang akan kami tetapkan seterusnya.

Kami akan terlebih dahulu menentukan anotasi kekangan:

@Retention(RetentionPolicy.RUNTIME) @Constraint(validatedBy = { SerialNumber.Validator.class }) public @interface SerialNumber { String message() default "Fruit serial number is not valid"; Class[] groups() default {}; Class[] payload() default {}; } 

Seterusnya, kami akan menentukan kelas validator SerialNumber.Validator :

public class Validator implements 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, serial); } } 

Perkara utama di sini ialah Validator kelas mesti melaksanakan ConstraintValidator mana T adalah jenis nilai kita mahu validate, dalam kes kami String .

Akhirnya, kami kemudian menerapkan logik pengesahan tersuai kami dalam kaedah isValid .

5. Pengesahan Sumber

Selanjutnya, Bean Validation API juga membolehkan kami mengesahkan objek menggunakan anotasi @Valid .

Di bahagian seterusnya, kami akan menerangkan dua cara berbeza untuk mengesahkan kelas sumber menggunakan anotasi ini:

  • Pertama, Minta pengesahan sumber
  • Kedua, pengesahan sumber Respons

Mari mulakan dengan menambahkan anotasi @Min ke objek Buah kami :

@XmlRootElement public class Fruit { @Min(value = 10, message = "Fruit weight must be 10 or greater") private Integer weight; //... } 

5.1. Minta Pengesahan Sumber

Pertama sekali, kami akan mengaktifkan pengesahan menggunakan @Valid di kelas FruitResource kami :

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

Dalam contoh di atas, jika kita berusaha membuat buah dengan berat kurang dari 10 kita akan mendapat kesalahan pengesahan.

5.2. Pengesahan Sumber Respons

Begitu juga, dalam contoh seterusnya, kita akan melihat cara mengesahkan sumber respons:

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

Perhatikan, bagaimana kami menggunakan anotasi @Valid yang sama Tetapi kali ini kami menggunakannya pada tahap kaedah sumber untuk memastikan responsnya sah.

6. Pengendali Pengecualian Tersuai

Pada bahagian terakhir ini, kami akan melihat secara ringkas cara membuat pengendali pengecualian tersuai. Ini berguna apabila kita ingin mengembalikan respons tersuai jika kita melanggar batasan tertentu.

Let's begin by defining our FruitExceptionMapper:

public class FruitExceptionMapper implements ExceptionMapper { @Override public Response toResponse(ConstraintViolationException exception) { return Response.status(Response.Status.BAD_REQUEST) .entity(prepareMessage(exception)) .type("text/plain") .build(); } private String prepareMessage(ConstraintViolationException exception) { StringBuilder message = new StringBuilder(); for (ConstraintViolation cv : exception.getConstraintViolations()) { message.append(cv.getPropertyPath() + " " + cv.getMessage() + "\n"); } return message.toString(); } }

First of all, we define a custom exception mapping provider. In order to do this, we implement the ExceptionMapper interface using a ConstraintViolationException.

Hence, we'll see that when this exception is thrown the toResponse method of our custom exception mapper instance will be invoked .

Also, in this simple example, we iterate through all the violations and append each property and message to be sent back in the response.

Next, in order to use our custom exception mapper we need to register our provider:

@Override protected Application configure() { ViewApplicationConfig config = new ViewApplicationConfig(); config.register(FruitExceptionMapper.class); return config; }

Finally, we add an endpoint to return an invalid Fruit to show the exception handler in action:

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

7. Conclusion

Sebagai kesimpulan, dalam tutorial ini, kami telah meneroka pelanjutan Jersey Bean Validation API.

Pertama, kami memulakan dengan memperkenalkan bagaimana Bean Validation API dapat digunakan di Jersey. Kami juga melihat bagaimana mengkonfigurasi aplikasi web contoh.

Akhirnya, kami melihat beberapa cara untuk membuat pengesahan dengan Jersey dan cara menulis pengendali pengecualian tersuai.

Seperti biasa, kod sumber penuh artikel terdapat di GitHub.