Casi cualquier programador de Java escribió RestController en su vida, pero pocas personas se preguntan si lo hace bien. Incluso si es un programador experimentado, es posible que tenga preguntas que intentaré responder. El artículo cubrirá marcos como las versiones de arranque de primavera 1.5 y 2.0, así como quarkus, el rival recientemente aparecido del arranque de primavera de Red Hat.

El problema
Programado durante mucho tiempo en Java y Spring Boot 1.5. Pero era necesario escribir un nuevo proyecto:
- Tengo json para integrar 1600 líneas, algunas clases tienen 100 campos
- Quería probar Kotlin y Quarkus.
- Escriba un controlador de descanso que pueda trabajar con la clase de datos kotlin sin anotaciones y sin involucrar magia lombok. Quiero que la clase de datos sea pequeña
Probablemente haya adivinado que la clase de datos kotlin es una clase inmutable o inmutable. Una clase cuyo constructor contiene todos los campos. Soy un gran creyente en tal concepto; después de crear una clase, no se puede cambiar; no hay establecedores en ella. Como la imagen de la ventana acoplable no se puede cambiar en el mundo, la clase de fecha que cayó en el controlador es algo que no se puede cambiar.
Veamos las posibles formas de resolver el problema, más precisamente cómo en los proyectos modernos puede escribir un controlador:
La opción estándar. manualmente en la primavera o la bota de primavera 1.5
Los controladores de descanso aparecieron hace mucho tiempo, y el siguiente ejemplo es un ejemplo típico de su uso en Java, que se encuentra en todos los tutoriales.
Simplemente creamos el controlador más simple
@RestController public class FruitController { @PostMapping("/fruit") public void greeting(@RequestBody Fruit request) { System.out.println(request); } }
Y cree un POJO (simple objeto java antiguo)
public class Fruit { public String name; public String description; public Fruit() { } public Fruit(String name, String description) { this.name = name; this.description = description; } }
puede haber variaciones con campos privados y captadores / establecedores o anotaciones de lombok, pero no es el punto.
Genial, creamos el primer controlador de descanso que funciona. Para el 90% de los casos, la opción de trabajo. Puedes quedarte aquí.
Los problemas:
El concepto inmutable está roto.
Una clase de datos un poco detallada.¿Podemos hacer inmutables?
Una reacción natural a este problema será la decisión de eliminar el constructor predeterminado y evitar la edición de los campos de clase.
@Getter public class Fruit { private String name; private String description;
Pero ahora surge un problema, resulta que la biblioteca (probablemente Jackson) no puede crear la clase. Lo más probable es que vea un error como
No se encontró un constructor predeterminado.Entonces, Jackson primero
creó la clase usando el constructor sin parámetros, y luego llamó getter / setter . Que horror Después de todo, ¿hay un constructor con todos los parámetros? Pero desafortunadamente, cuando se compila la clase, los parámetros se ven más o menos así.
Es decir En tiempo de ejecución, Java no sabe nada acerca de los nombres de los parámetros en el constructor. El compilador los pierde.La segunda opción es spring o spring boot 1.5 + anotaciones como salvación
Entonces, nos dimos cuenta de que queremos una clase inmutable, y sabemos que estamos usando Jackson. Entonces la anatomía viene al rescate.
@Getter public class Fruit { private String name; private String description; @JsonCreator public Fruit(@JsonProperty("name") String name, @JsonProperty("description")String description) { this.name = name; this.description = description; } }
Por el momento, en nuestro proyecto sobre sping boot 1.5, estas anotaciones están literalmente llenas de todo.
Y si toma el popular generador
jsonschema2pojo , generará aún más anotaciones. Sinceramente, no me gustan.
Intenta copiar allí:
{ "description": "description", "name": "name" }
En la salida que obtenemos (puede entrecerrar los ojos y pasar):
@JsonInclude(JsonInclude.Include.NON_NULL) @JsonPropertyOrder({ "description", "name" }) public class Example { @JsonProperty("description") private String description; @JsonProperty("name") private String name; @JsonProperty("description") public String getDescription() { return description; } @JsonProperty("description") public void setDescription(String description) { this.description = description; } @JsonProperty("name") public String getName() { return name; } @JsonProperty("name") public void setName(String name) { this.name = name; } }
Contras: las
anotaciones inflan mucho la clase. Muy detallado, para un aficionado.Tercera opción resorte o bota de resorte 1.5 + bandera de lombok
Gracias
Throwable citaré el comentario:
"Si usa Lombok, entonces la mejor manera es escribir en lombok.config:
lombok.allArgsConstructor.addConstructorProperties = true
Esto generará en el constructor
@java.beans.ConstructorProperties
, que Jackson sabe cómo entender ".
Gran opción Seguramente me salvaría de la verbosidad de las anotaciones.
Contras:
Pero quiero usar Kotlin sin lombok.
Aprendí esta opción demasiado tarde.La cuarta versión de Spring boot 2.0
@Getter public class Fruit { private String name; private String description; public Fruit( String name, String description) { this.name = name; this.description = description; } }
Sorprendentemente, Spring Boot 2.0 funciona silenciosamente con una clase tan inmutable. Y también con su hermano gemelo clase de datos Kotlin
data class Fruit( val name : String, val description : String)
Parece que Java en tiempo de ejecución no conoce los nombres de los parámetros en el constructor, pero por alguna razón spring boot2 ya sabe cómo trabajar con la clase de datos. Entonces, mira spring-boot-starter-parent, el soporte de Kotlin se ha agregado allí.
<plugin> <groupId>org.jetbrains.kotlin</groupId> ... <configuration> <javaParameters>true</javaParameters> </configuration> </plugin> <plugin> <artifactId>maven-compiler-plugin</artifactId> <configuration> <parameters>true</parameters> </configuration> </plugin>
Yo descifro. Para
que los nombres de los parámetros en el constructor de la clase no se pierdan durante el tiempo de ejecución, el compilador debe pasar el indicador javac -parameters , y spring boot 2.0 lo hace.
Proyecto de muestra en
el arranque de primavera 2 .
La quinta opción. Quarkus + Kotlin
Quarkus tiene
un ejemplo de un servicio de descanso , un análogo de mi primera opción. Es decir controlador de descanso a la antigua usanza. Sin embargo, si desea usarlo con Kotlin, tendrá que agregar banderas como lo hizo spring boot 2.
Descripción del problema
aquí . Un ejemplo de cómo agregar soporte de clase de datos kotlin a quarkus
aquí .
Conclusiones
Puede usar la primera opción más simple para crear controladores de descanso, pero le recomendaría avanzar hacia clases inmutables. Escribe en Kotlin y no necesitarás lombok. El código debería ser más y más fácil. Estoy seguro de que los creadores de Spring deliberadamente fueron a agregar
parámetros javac a las opciones del compilador y no debería haber ningún delito en esto. Buena suerte a todos en el camino hacia el código perfecto.
¡Gracias a todos por su atención!