Springboot同时接收前端传来的字符串、对象数组和文件

问题提出

传的数据格式如下:

article = {
    title: '字符串',
    content: '字符串',
    sectionId: 1,
    file: (文件),
    tags: [{tagId: 1, tagName: "qwe"}, {tagId: 2, tagName: "asd"}...]
}

最初, 后端准备直接用一个DTO来接收:

@RequestMapping(value = "/", method = RequestMethod.POST)
    public ResponseEntity<SingleKeyVO> createArticle(ArticleCreateDTO articleDTO)
        

ArticleCreateDTO:

@Data
@NoArgsConstructor
@AllArgsConstructor
public class ArticleCreateDTO implements Serializable {
​
    /**
     * 作者的id
     */
    @JsonProperty("authorId")
    private Integer authorId;
​
    /**
     * Article-文章Id
     */
    @JsonProperty("articleId")
    private String articleId;
​
    /**
     * Article-文章标题
     */
    @JsonProperty("title")
    private String title;
​
    /**
     * Article-文章内容
     */
    @JsonProperty("content")
    private String content;
​
    /**
     * 文章封面图片
     */
    @JsonProperty("file")
    MultipartFile file;
​
    /**
     * 文章分区id
     */
    @JsonProperty("sectionId")
    private Integer sectionId;
​
    /**
     * Tag-文章标签
     */
    @JsonProperty("tags")
    private List<TagIdAndNameVO> tags;

TagIdAndNameVO:

@Data
@NoArgsConstructor
@AllArgsConstructor
public class TagIdAndNameVO implements TagVO, Serializable {
​
    @JsonProperty("tagId")
    private String tagId;
    @JsonProperty("tagName")
    private String tagName;
}

然而SpringMVC并不能解析其中的对象数组(tags),将List<TagIdAndNameVO> 改为 TagIdAndNameVO[] 也无效,所以开始寻求解决方法...

第一个找到的方法时在控制器方法的DTO形参处加@RequestBody注解:

@RequestMapping(value = "/", method = RequestMethod.POST)
    public ResponseEntity<SingleKeyVO> createArticle(@RequestBody ArticleCreateDTO articleDTO)

此时会返回状态码415,原因是前端传来的数据中包含文件。所以将 content-type 改为了 multipart/form-data,但@RequestBody 注解不支持该类型,所以也行不通...

问题解决

后来又看到一位网友说可以先将对象数组转为字符串,后端再通过工具将字符串转为List, 操作如下:

1、前端先将数组转为字符串

let data = new FormData()
data.append("title", topic.title)
data.append("file", topic.file)
data.append("content", topic.content)
data.append("sectionId", topic.sectionId)
// 使用JSON.stringify 方法
data.append("tags", JSON.stringify(topic.tags))
// 注:传给后端的数据包含文件时,需要使用FormData() 否则文件无法传递到后端(前端知识浅薄,不一定对)

2、再修改后端DTO(其他的不变,将tags 改为String 类型即可)

public class ArticleCreateDTO implements Serializable {
​
    /**
     * Tag-文章标签
     */
    @JsonProperty("tags")
    private String tags;
}

3、使用fastjson 将 String 转为List

List<TagIdAndNameVO> tagList = JSON.parseArray(articleCreateDTO.getTags(), TagIdAndNameVO.class);

至此,问题解决,但解决方式仍不够“优雅”,还需要继续学习...


版权声明:本文为l0geek原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。