Java Records (JEP359) 作为 Spring 控制器请求和响应 DTOs

huangapple go评论109阅读模式
英文:

Java Records (JEP359) as Spring Controller Request and Response DTOs

问题

我只是在这些新的Java Records上进行实验,我想知道是否可以将它们用作Spring Boot应用程序中请求/响应类型的DTOs。

因此,我只是修改了一些代码(将带有大量样板getter/setter的类改成了records),编译并启动了我的应用程序。尝试了一些REST端点,但我得到的只是一个异常,告诉我:

找不到类x.y.CreateNewShopListeCommand$Item的序列化程序,也没有发现任何属性来创建BeanSerializer(要避免异常,请禁用SerializationFeature.FAIL_ON_EMPTY_BEANS)

好吧,records不会创建带有'get'前缀的getter方法。现在我想知道:是否可以将records用作Spring Boot控制器的请求/响应类型?

编辑:示例应用程序(https://github.com/kaipaysen/playground-jdk14-records-as-dto)

// HelloController.java
@RestController
@RequestMapping("/hello")
public class HelloController {
    
    public record HelloRequest(
        @JsonProperty("name") String name
    ) {}

    public record HelloResponse(
        @JsonProperty("message") String message
    ) {}

    @RequestMapping(method = RequestMethod.POST)
    public HelloResponse hello(@RequestBody @Valid HelloRequest query) {
        return new HelloResponse("Hello " + query.name());
    }
    
}

调用curl -X POST -H "Content-Type: application/json" -d '{"name":"Max"}' http://localhost:8080/hello 返回 {"message":"Hello null"}。调试hello方法揭示出请求未被正确反序列化。对此有什么想法吗?

编辑#2:
刚刚在FasterXML存储库中找到了这个问题Support for JDK 14 record types #2709。他们正在为jackson 2.12版解决这个问题。

英文:

I'm just experimenting with these new Java Records and I'm wondering if I could use them as DTOs for my request / response types in a spring boot application.

Therefore I just modified some code (class with a lot of boilerplate getter/setter to records), compiled and started my application. Trying some rest endpoints and all I got was an exception telling me:

No serializer found for class x.y.CreateNewShopListeCommand$Item and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS

Well, ok, records do not create 'get'prefixed getter methods. Now I wonder: is it possible to use records as request / response types for spring boot controller?

EDIT: Sample Application (https://github.com/kaipaysen/playground-jdk14-records-as-dto)

// HelloController.java
@RestController
@RequestMapping("/hello")
public class HelloController {
    
    public record HelloRequest(
        @JsonProperty("name") String name
    ) {}

    public record HelloResponse(
        @JsonProperty("message") String message
    ) {}

    @RequestMapping(method = RequestMethod.POST)
    public HelloResponse hello(@RequestBody @Valid HelloRequest query) {
        return new HelloResponse("Hello " + query.name());
    }
    
}

Calling curl -X POST -H "Content-Type: application/json" -d '{"name":"Max"}' http://localhost:8080/hello returns {"message":"Hello null"}. Debugging hello reveals that the Request is not properly deserialized. Any ideas on that spot?

EDIT#2:
Just found this issue Support for JDK 14 record types #2709 in the FasterXML repo. They are working on it for jackson 2.12.

答案1

得分: 1

你需要将这个类级别的注解添加到你的记录中。

@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY)

在 jackson 版本 1.12 中,它应该在没有注解的情况下可用。

我认为这是 Jackson 的一个 bug,你需要为你的记录添加第二个字段,因为它对只有一个字段的记录不起作用。

英文:

You need to add this class level annotation to yours records.

@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY)

In the jackson version 1.12 it should be available without annotation.

I think this's a bug in Jackson, You need to add a second field to your record because it doesn't work for the record which has only one field.

huangapple
  • 本文由 发表于 2020年9月3日 03:14:25
  • 转载请务必保留本文链接:https://go.coder-hub.com/63712187.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定