后端期望的格式(LostItemController.java
):
@RequestPart LostItemRequestDTO request
接收 JSON 对象(自动反序列化)@RequestPart MultipartFile image
接收 文件Content-Type: multipart/form-data
前端实际发送的格式:
request
字段(formData.append('request', JSON.stringify(requestData))
)request
字段中的 JSON 字符串,导致 415 错误前端不需要手动 JSON.stringify
,直接让 FormData
按字段拆分
async submitForm() {
const formData = new FormData();
// 直接添加字段(不要包裹成 JSON 字符串)
formData.append('category', this.formData.category);
formData.append('description', this.formData.description);
formData.append('lostLocation', this.formData.lostLocation);
formData.append('lostTime', new Date(this.formData.lostTime).toISOString());
// 添加图片
if (this.formData.image) {
formData.append('image', this.formData.image);
}
try {
const response = await fetch('/api/lost', {
method: 'POST',
body: formData, // 不要手动设置 Content-Type!
});
// 处理响应...
} catch (error) {
alert('提交失败: ' + error.message);
}
}
如果必须保持前端发送 request
字段,后端需调整:
@PostMapping(value = "/lost", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
public Result add(
@RequestPart String request, // 改为接收字符串
@RequestPart(required = false) MultipartFile image
) {
// 手动解析 JSON
LostItemRequestDTO requestData = new ObjectMapper().readValue(request, LostItemRequestDTO.class);
// 后续逻辑...
}
LostItemRequestDTO
对象,具体错误为:Cannot construct instance of `com.text.pojo.LostItemRequestDTO`
(no Creators, like default constructor, exist)
image
)后端问题:
LostItemRequestDTO
类缺少 默认构造函数 或 Jackson 反序列化所需的注解。LostItemRequestDTO
对象。前端问题:
FormData
,但后端期望的是 multipart/form-data
中的 JSON 对象(@RequestPart LostItemRequestDTO request
)解决办法:
在 LostItemRequestDTO
中添加 无参构造函数 和 Setter 方法
package com.text.pojo;
public class LostItemRequestDTO {
private String category;
private String description;
private String lostLocation;
private String lostTime;
// 1. 必须添加无参构造函数
public LostItemRequestDTO() {}
// 2. 必须提供所有字段的 getter/setter
public String getCategory() { return category; }
public void setCategory(String category) { this.category = category; }
// 其他字段的 getter/setter...
}
如果无法修改 DTO,可以手动解析 JSON:
@PostMapping(value = "/lost", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
public Result add(
@RequestPart String request, // 改为接收字符串
@RequestPart(required = false) MultipartFile image
) {
// 手动解析 JSON
ObjectMapper objectMapper = new ObjectMapper();
LostItemRequestDTO requestData = objectMapper.readValue(request, LostItemRequestDTO.class);
// 后续逻辑...
}
如果后端坚持用 @RequestPart LostItemRequestDTO request
,前端需要 按字段拆分 FormData(不推荐,但可行):
const formData = new FormData();
formData.append('category', this.formData.category);
formData.append('description', this.formData.description);
formData.append('lostLocation', this.formData.lostLocation);
formData.append('lostTime', this.formData.lostTime);
formData.append('image', this.formData.image);
LocalDateTime
反序列化失败:
lostTime
是字符串(如 "2025-06-05T20:06:13"
),但后端无法自动将其转换为 LocalDateTime
。LocalDateTime
配置自定义反序列化器。DTO 构造函数冲突:
package com.text.pojo;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
import java.time.LocalDateTime;
public class LostItemRequestDTO {
private String category;
private String description;
private String lostLocation;
@JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss") // 指定日期格式
@JsonDeserialize(using = LocalDateTimeDeserializer.class) // 使用反序列化器
private LocalDateTime lostTime;
// 只保留无参构造函数
public LostItemRequestDTO() {}
// 移除全参构造函数(避免干扰 Jackson)
// getters/setters...
}
确保前端发送的时间字符串格式与 @JsonFormat
一致:
// 前端代码(格式化时间)
const requestData = {
category: this.formData.category,
description: this.formData.description,
lostLocation: this.formData.lostLocation,
lostTime: new Date(this.formData.lostTime).toISOString().slice(0, 19) // 格式:YYYY-MM-DDTHH:mm:ss
};
formData.append('request', JSON.stringify(requestData));
jackson 的默认行为:
@JsonProperty
标注参数您的实际错误:
LocalDateTime
字段没有配置反序列化规则(主因)