Postman表单提交及Java后端入参定义

Postman表单提交及Java后端入参定义

一、问题描述

        起因是当时我做项目的需求,既要上传音频文件,又有json字符串等普通数据。所以选用表单提交,但是方法的入参使用@RequestParam注解表单后,Postman测试接口死活不进方法。我也看到很多网友是这样注解表单的,都没有我这种情况。我就很困惑,但是放到param就不会报错,以下是我写的测试方法:

在Params传参正常

在Body传参就报错了

二、@RequestParam与@RequestPart的区别

1.@RequestParam注解

        ‌@RequestParam注解可以用于处理表单数据‌。但是表单类型为application/x-www-form-urlencoded,而且这个类型不能传输文件数据。@RequestParam注解通常用于处理HTTP请求中的参数,包括GET请求的查询参数和POST请求的表单参数。它可以从请求的查询字符串或表单数据中提取参数值,并将其绑定到控制器方法的参数上‌。

使用场景

  1. GET请求‌:在GET请求中,@RequestParam常用于处理URL中的查询参数。例如,一个URL可能是这样的:http://localhost:8080/users?name=John&age=30。在这个例子中,nameage就是通过@RequestParam注解获取的参数‌。
  2. POST请求‌:在POST请求中,@RequestParam也可以用于处理application/x-www-form-urlencoded类型的数据。这意味着在POST请求的Body部分,数据需要以键值对的形式提交,例如:name=John&age=30。这种情况下,@RequestParam同样可以用于提取这些参数‌。

配置参数

@RequestParam注解有几个配置参数:

  • required‌:表示参数是否必须。默认为true,即参数必须存在。可以设置为false,表示参数可以不存在,此时如果参数不存在,方法的参数将为null而不是抛出异常‌。
  • defaultValue‌:可以为参数设置一个默认值,当请求中没有该参数时,将使用这个默认值‌。
  • value‌或‌name‌:指定请求中的参数名‌。

示例代码

下面是一个使用@RequestParam注解处理GET请求的示例:

@GetMapping("/users")
public String getUsers(@RequestParam(value = "name", required = false) String name,
                        @RequestParam(value = "age", defaultValue = "20") int age) {
    return "Name: " + name + ", Age: " + age;
}

2.@RequestPart注解

RequestPart注解Spring框架中的作用是处理multipart/form-data类型的请求,特别是用于文件上传和复杂的表单提交‌。它用于从multipart/form-data请求中提取某一部分的数据,并将其绑定到控制器方法的参数上‌。

使用场景

  1. 文件上传‌:当需要上传文件时,可以使用RequestPart注解将上传的文件绑定到MultipartFile类型的参数上。MultipartFile是Spring提供的一个接口,用于表示上传的文件‌。
  2. 复杂表单提交‌:当表单中包含多个部分,如文件和其他表单字段时,可以使用RequestPart注解分别提取这些部分的数据‌。

配置参数

@RequestPart注解有几个配置参数:

  • name/value‌:指定multipart/form-data请求中的部分名称。这个名称应该与前端发送请求时指定的部分名称相匹配。
  • required‌:指定该部分是否是必需的。默认为true,表示该部分是必需的。如果设置为false,则表示该部分是可选的,如果请求中未包含该部分,则不会抛出异常‌。

示例代码

以下是一个使用RequestPart注解处理文件上传和复杂表单提交的示例代码:

import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestPart;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

@RestController
public class FileUploadController {
    @PostMapping("/upload")
    public String handleFileUpload(
        @RequestPart("file") MultipartFile file) {
        // 处理文件上传逻辑
        return "文件上传成功";
    }
}

三、问题原因

        原因是我使用@RequestParam注解的时候,我的表单类型是multipart/form-data,最最重要的是我的是响应式代码,不支持@RequestParam来注解我表单数据。

四、解决办法

1.有文件和参数

方法一:看效果

@PostMapping("/upload")
    public Mono<String> handleFileUpload(ServerWebExchange exchange) {
        // 获取 multipart 数据
        return exchange.getMultipartData()
                .flatMap(multipartData -> {
                    // 获取文件数据
                    FilePart filePart = (FilePart) multipartData.getFirst("file");
                    if (filePart == null) {
                        return Mono.error(new ResponseStatusException(HttpStatus.BAD_REQUEST, "File is required"));
                    }

                    // 获取字符串数据(例如:username, description)
                    // 获取文本字段并读取其值
                    String username = extractFormFieldValue(multipartData, "username");
                    String description = extractFormFieldValue(multipartData, "description");
                    // 你可以在这里处理文件和其他表单字段
                    // 例如:保存文件,或者将数据保存到数据库

                    System.out.println("-----------------------------------------------------------Username: " + username);
                    System.out.println("------------------------------------------------------------Description: " + description);

                    // 处理文件数据(比如保存到磁盘)
                    return filePart.transferTo(new java.io.File("D:/" + filePart.filename()))
                            .then(Mono.just("File uploaded su***essfully"));
                });
    }
    private String extractFormFieldValue(MultiValueMap<String, Part> multipartData, String fieldName) {
        Part part = multipartData.getFirst(fieldName);
        if (part instanceof FormFieldPart) {
            FormFieldPart formFieldPart = (FormFieldPart) part;
            return formFieldPart.value();
        }
        return null;
    }

方法二:使用@RequestPart注解

    2.如果只接收单个文件上传, 可以用 Mono<FilePart> 。

            在 Java 中,使用 Mono<FilePart> 可以通过 Spring WebFlux 来处理单个文件的上传。Mono 是 Reactor 库中的一个类,表示一个异步的、单值的操作,而 FilePart 是一个接口,用于表示上传的文件部分。

            步骤一:首先,确保你的项目中已经引入了 spring-boot-starter-webflux 和相关的依赖。

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-webflux</artifactId>
    </dependency>
    

            步骤二:创建一个简单的控制器,用于接收文件上传。

    import org.springframework.core.io.FileSystemResource;
    import org.springframework.http.ResponseEntity;
    import org.springframework.web.bind.annotation.*;
    import org.springframework.web.multipart.MultipartFile;
    import reactor.core.publisher.Mono;
    import org.springframework.web.server.ServerWebExchange;
    
    import java.io.File;
    import java.io.IOException;
    
    @RestController
    @RequestMapping("/upload")
    public class FileUploadController {
    
        @PostMapping
        public Mono<ResponseEntity<String>> handleFileUpload(@RequestPart("file") Mono<FilePart> filePartMono) {
            return filePartMono.flatMap(filePart -> {
                // 保存文件到指定位置
                String filePath = "path/to/your/file/directory/" + filePart.filename();
                try {
                    // 将文件保存到磁盘
                    File file = new File(filePath);
                    filePart.transferTo(file).subscribe(); // 异步保存文件
    
                    // 返回成功响应
                    return Mono.just(ResponseEntity.ok("File uploaded su***essfully to " + filePath));
                } catch (IOException e) {
                    // 处理异常
                    return Mono.just(ResponseEntity.status(500).body("Failed to upload file: " + e.getMessage()));
                }
            });
        }
    }
    

    3.使用 ServerRequest 作为参数。通过 formData 接收。 

    Spring WebFlux 示例:

    import org.springframework.web.bind.annotation.*;
    import org.springframework.web.server.ServerRequest;
    import org.springframework.http.MediaType;
    import reactor.core.publisher.Mono;
    
    @RestController
    @RequestMapping("/example")
    public class ExampleController {
    
        // 通过 ServerRequest 获取表单数据
        @PostMapping("/submit")
        public Mono<String> handleFormData(ServerRequest request) {
            return request.formData()
                .flatMap(formData -> {
                    // 获取表单字段
                    String name = formData.getFirst("name");  // 获取 'name' 字段
                    String email = formData.getFirst("email");  // 获取 'email' 字段
                    return Mono.just("Received name: " + name + " and email: " + email);
                });
        }
    }
    

    解释:

    1. ServerRequest 是一个Spring WebFlux类,它代表了传入的HTTP请求。

    2. formData() 方法用于从请求中提取表单数据,它返回一个 Mono<FormData> 对象。

    3. formData.getFirst("fieldName") 用于获取特定表单字段的第一个值。

    什么问题都可以评论区留言,看见都会回复的

    如果你觉得本篇文章对你有所帮助的,把“文章有帮助的”打在评论区

    多多支持吧!!!

    点赞加藏评论,是对小编莫大的肯定。抱拳了!

    转载请说明出处内容投诉
    CSS教程网 » Postman表单提交及Java后端入参定义

    发表评论

    欢迎 访客 发表评论

    一个令你着迷的主题!

    查看演示 官网购买