Spring Boot REST API 不支持的媒体类型

Posted

技术标签:

【中文标题】Spring Boot REST API 不支持的媒体类型【英文标题】:Spring Boot REST API unsupported media type 【发布时间】:2021-12-21 17:49:52 【问题描述】:

我有两个 API:s ,端口 8080 上的 CarRental-API 和端口 8081 上的 CarRental-CRUD。

CarRental-CRUD 使用 JpaRepository 访问 h2 内存数据库。

我想使用 CarRental-API 通过 webclient 向 CarRental-CRUD 发出请求。

在 CarRental-CRUD 中,我可以使用此服务发出发布请求并将汽车添加到数据库:

public String addCar(Car car) 
    
    carRepository.save(car);
    
    return loggerService.writeLoggerMsg("CREATED CAR AND ADDED TO DB");

然后在控制器中:

@RestController
@RequestMapping("/crud/v1")
public class AdminCarController 

    @Autowired
    private AdminCarService adminCarService;
    
    @PostMapping(path = "/addcar",  consumes = "application/json")
    public String addCar(@RequestBody Car car) 
        return adminCarService.addCar(car);
    

我尝试在 CarRental-API 中使用 webclient 发布请求:

@Service
public class AdminCarService 

    @Autowired 
    LoggerService loggerService;
    
    @Autowired
    private WebClient.Builder webClientBuilder;

    public String  addCar(Car car) 

            webClientBuilder
                    .build()
                    .post()
                    .uri("localhost:8081/crud/v1/addcar")
                    .retrieve()
                    .bodyToFlux(Car.class);

        return loggerService.writeLoggerMsg("ADDED CAR TO DB");
        

但是,使用 carRental-API 时,当我尝试发布请求时,邮递员会收到此错误:

 "status": 500,
"error": "Internal Server Error",
"trace": "org.springframework.web.reactive.function.client.WebClientResponseException: 200 OK from POST localhost:8081/crud/v1/addcar; nested exception is org.springframework.web.reactive.function.UnsupportedMediaTypeException: Content type 'text/plain;charset=UTF-8' not supported for bodyType=com.backend.carrentalapi.entity.Car\n\tat 

这是汽车实体:

@Getter
@Setter
@RequiredArgsConstructor
@NoArgsConstructor
@Entity
@Table(name = "TBL_CAR")
public class Car 

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private long carId;

    @Column(name = "NAME")
    private String carName;

    @Column(name = "MODEL")
    private String carModel;

    @Column(name = "DAILY_PRICE")
    private double dailyPrice;



我似乎无法在代码中找到生成文本/纯文本的位置。我在邮递员中确定我正在发布一个原始 JSON 正文请求,并且标题显示内容类型:application/json。

【问题讨论】:

【参考方案1】:

在您的 WebClient 中,您没有添加请求正文,而是期望从您正在调用的 API 返回一个 Car(并且此 API 返回一个简单的 String)。以下应该可以工作。

@Service
public class AdminCarService 

    @Autowired 
    LoggerService loggerService;
    
    @Autowired
    private WebClient.Builder webClientBuilder;

    public String  addCar(Car car) 

            webClientBuilder
                    .build()
                    .post()
                    .uri("localhost:8081/crud/v1/addcar")
                    .body(BodyInserters.fromValue(car))
                    .retrieve()
                    .toBodilessEntity();

        return loggerService.writeLoggerMsg("ADDED CAR TO DB");
        

使用.toBodilessEntity(),因为您实际上并没有对响应做任何事情。

【讨论】:

谢谢,post 请求现在可以工作了,但是当我添加一辆新车时,数据库似乎没有得到值。这和回复有关系吗? 不,与响应无关。你的CarRental-CRUD 服务也是基于 Spring WebFlux 的吗? 不是,是基于JpaRepository接口的 您是否确认调用已使用断点或其他方式到达CarRental-CRUDController? 是的,但是您的应用程序不是 100% 响应式的,因为此时您正在阻塞线程。在完全反应式应用程序中应不惜一切代价避免使用.block(),您应该处理MonoFlux 数据类型。而不是.block() 尝试.subscribe()

以上是关于Spring Boot REST API 不支持的媒体类型的主要内容,如果未能解决你的问题,请参考以下文章

Spring boot:REST API 行为不一致后版本升级

在 Spring Boot 中使用 FeignClient 进行同步 Rest API 调用

Spring Boot 和 Rest 服务(不支持 405 方法)

使用Swagger生成Spring Boot REST客户端(支持Feign)(待实践)

NGINX 反向代理背后的 Spring Boot API REST

解决了! - Spring boot:获取 415 不支持的媒体类型