几乎所有Java程序员在他的一生中都写过RestController,但是很少有人想知道他是否做得对。 即使您是一位经验丰富的程序员,您也可能会遇到我将要回答的问题。 本文将涵盖诸如1.5和2.0版本的Spring Boot框架以及quarkus(最近出现的Red Hat的Spring Boot竞争对手)的框架。

问题
在Java和Spring Boot 1.5中编程了很长时间。 但是有必要编写一个新项目:
- 我有用于集成1600行的json,某些类具有100个字段
- 我想尝试Kotlin和Quarkus。
- 编写一个rest控制器,该控制器将能够与kotlin数据类一起使用,而无需使用注释并且无需涉及龙目岛魔术。 我希望数据类小
您可能猜到了kotlin数据类是一个不可变的类,或者说是不可变的。 一个类,其构造函数包含所有字段。 我非常相信这样的概念。 创建类后,无法更改;其中没有设置器。 由于无法在世界上更改Docker映像,因此属于控制器的date类是无法更改的。
让我们看一下解决问题的可能方法,更准确地说是在现代项目中如何编写控制器:
标准选项。 在弹簧或弹簧靴1.5上手动
Rest控制器是很久以前出现的,下面的示例是在所有教程中的Java中典型用法的示例。
我们只是创建最简单的控制器
@RestController public class FruitController { @PostMapping("/fruit") public void greeting(@RequestBody Fruit request) { System.out.println(request); } }
并创建一个POJO(普通的旧Java对象)
public class Fruit { public String name; public String description; public Fruit() { } public Fruit(String name, String description) { this.name = name; this.description = description; } }
私有字段和getters / setters或lombok批注可能会有变化,但要点不是。
太好了,我们创建了第一个可工作的rest控制器。 对于90%的情况,工作选项。 你可以留在这里。
问题:
不变的概念被打破了。
有点冗长的数据类。我们可以使一成不变吗?
对这个问题的自然反应是决定删除默认构造函数并阻止编辑类字段。
@Getter public class Fruit { private String name; private String description;
但是现在出现了一个问题,事实证明该库(很可能是杰克逊)无法创建该类。 您很可能会看到类似未
找到默认构造函数的错误
。因此,杰克逊首先
使用不带参数的构造函数创建了该类,然后将其称为getter / setter 。 真是恐怖 毕竟,是否有一个带有所有参数的构造函数? 但是不幸的是,在编译类时,参数看起来像这样。
即 在运行时,java对构造函数中的参数名称一无所知。 编译器会丢失它们。第二个选项是spring或spring boot 1.5 +注释作为救赎
因此,我们意识到我们想要一个不变的类,并且我们知道我们正在使用杰克逊。 然后,厌倦症就来了。
@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; } }
目前,在我们关于sping boot 1.5的项目中,这些注释实际上包含了所有内容。
而且,如果您使用流行的
jsonschema2pojo生成器,它将生成更多注释。 老实说,我不喜欢他们。
尝试在那里复制:
{ "description": "description", "name": "name" }
在输出中,我们得到(您可以斜视和翻阅):
@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; } }
缺点:
注释极大地增加了类。 非常冗长,对于业余爱好者而言。第三选择弹簧或弹簧靴1.5 +龙目岛标志
谢谢
Throwable我会在评论中引用:
“如果您使用Lombok,那么最好的方法是在lombok.config中编写:
lombok.allArgsConstructor.addConstructorProperties = true
这将在构造函数
@java.beans.ConstructorProperties
上生成,Jackson知道如何理解。”
很好的选择。 他一定会让我免于注释的冗长。
缺点:
但是我想不带龙目岛使用Kotlin。
我来不及学习此选项。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; } }
出乎意料的是,Spring Boot 2.0在这种不可变的类中可以安静地工作。 还有他的双胞胎兄弟Kotlin数据班
data class Fruit( val name : String, val description : String)
似乎Java在运行时中不知道构造函数中的参数名称,但是由于某种原因,spring boot2已经知道如何使用数据类。 因此,看看spring-boot-starter-parent,那里已经添加了Kotlin支持。
<plugin> <groupId>org.jetbrains.kotlin</groupId> ... <configuration> <javaParameters>true</javaParameters> </configuration> </plugin> <plugin> <artifactId>maven-compiler-plugin</artifactId> <configuration> <parameters>true</parameters> </configuration> </plugin>
我解密。 为了
使类构造函数中的参数名称在运行时不会丢失,编译器必须传递javac -parameters标志,而spring boot 2.0
会这样做 。
弹簧靴2上的示例项目。
第五个选择。 夸库斯+科特林
Quarkus有
一个休息服务的例子 ,这是我的首选。 即 休息控制器是老式的方法。 但是,如果要与Kotlin一起使用,则必须像Spring Boot 2一样添加标志。
问题描述在
这里 。
在此处为如何向quarkus添加kotlin数据类支持的示例。
结论
您可以使用第一个最简单的选项来创建rest控制器,但我建议您转向不可变的类。 在Kotlin上书写,您将不需要龙目岛。 代码应该越来越容易。 我确信spring的创建者会故意将
javac -parameters添加到编译器选项中,并且这样做不会有任何犯罪。 祝大家在编写完美代码的过程中万事如意。
谢谢大家的关注!