You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring WebFlux中使用Lombok时POJO无法序列化问题排查

问题描述

我开发了一个用于学习WebClient用法的简单响应式Web应用,仅包含一个PostController,它将请求委托给外部API,获取响应后序列化再返回给客户端。但运行时出现序列化失败的错误。

错误信息

Caused by: com.fasterxml.jackson.databind.exc.InvalidDefinitionException: No serializer found for class com.example.spring_webclient_lombok_demo.entity.Post and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS)

代码示例

PostController.java

import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.reactive.function.client.WebClient;
import com.example.spring_webclient_lombok_demo.entity.Post;
import reactor.core.publisher.Mono;

@RestController
@RequestMapping("/posts")
public class PostController {
    
    @Autowired
    private WebClient webClient;

    @GetMapping("")
    public Mono<List<Post>> getPosts() {
        return webClient.get()
                .uri("/posts")
                .retrieve()
                .bodyToFlux(Post.class)
                .collectList();
    }
    
    @GetMapping("{postId}")
    public Mono<Post> getPostById(@PathVariable int postId) {
        return webClient.get()
                .uri("/posts/{id}", postId)
                .retrieve()
                .bodyToMono(Post.class);
    }
}

Post.java

import java.util.Objects;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@AllArgsConstructor
public class Post {
    private int userId;
    private int id;
    private String title;
    private String body;
    
    // 注释掉的显式构造、getter/setter等方法...
}

SpringWebclientLombokDemoApplication.java

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.web.reactive.function.client.WebClient;

@SpringBootApplication
public class SpringWebclientLombokDemoApplication {
    public static void main(String[] args) {
        SpringApplication.run(SpringWebclientLombokDemoApplication.class, args);
    }
    
    @Bean
    public WebClient getWebClient() {
        return WebClient.builder()
                .baseUrl("https://jsonplaceholder.typicode.com")
                .build();
    }
}

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>3.4.3</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.example</groupId>
    <artifactId>spring-webclient-lombok-demo</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>war</packaging>
    <name>spring-webclient-lombok-demo</name>
    <description>Demo spring project for practicing Webclient and Lombok</description>
    <properties>
        <java.version>17</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-validation</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-webflux</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>io.projectreactor</groupId>
            <artifactId>reactor-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <annotationProcessorPaths>
                        <path>
                            <groupId>org.projectlombok</groupId>
                            <artifactId>lombok</artifactId>
                        </path>
                    </annotationProcessorPaths>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <excludes>
                        <exclude>
                            <groupId>org.projectlombok</groupId>
                            <artifactId>lombok</artifactId>
                        </exclude>
                    </excludes>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>
原因分析
  1. 缺少无参构造函数:Jackson反序列化Java对象时,默认需要类提供无参构造函数。你在Post类上添加了@AllArgsConstructor,这会让Lombok只生成全参构造,而不会自动生成无参构造;虽然@Data注解包含getter、setter等,但不会在存在显式构造(包括Lombok生成的全参构造)的情况下生成无参构造,导致Jackson无法实例化Post类,进而认为该类没有可序列化的属性。
  2. IDE注解处理器未启用:如果IDE没有启用Lombok插件或者注解处理功能,编译时Lombok不会生成对应的getter、setter和构造函数,运行时自然会出现序列化失败。
解决方案
  1. 补充无参构造注解:在Post类上添加@NoArgsConstructor,和@Data、@AllArgsConstructor配合使用,确保Lombok生成无参构造:
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Post {
    private int userId;
    private int id;
    private String title;
    private String body;
}
  1. 检查IDE配置:
    • 确保IDE安装了Lombok插件(比如IDEA的Lombok插件)。
    • 开启注解处理功能:IDEA中进入Settings -> Build, Execution, Deployment -> Compiler -> Annotation Processors,勾选Enable annotation processing。
  2. 验证编译结果:执行mvn clean compile,然后查看target/classes下的Post.class文件,反编译确认是否生成了无参构造、getter和setter方法。

内容的提问来源于stack exchange,提问作者Shri

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.13 20:05:05