likes
comments
collection
share

前后端参数传递的各种方式

作者站长头像
站长
· 阅读数 22

本文主要有以下内容

使用postman和axios前端库分别演示后端参数的传递和数据的获取,后端接口主要有以下几种情况:

  • get方法进行参数传递和数据获取,后端没有使用注解
  • get方法进行参数传递和数据获取,后端使用@RequestParam注解
  • post方法进行参数传递,后端没有使用注解
  • post方法进行参数传递,后端使用@RequestParam注解
  • post方法进行参数传递,后端使用@RequestBody注解
  • post方式进行传递时的几种Content-type设置

get方法

get方法进行数据获取,不传递参数

在进行数据获取的时候,后端接口有时候不需要传递参数,此时只需要使用get方法进行数据获取就可以。

话不多说,上菜!后端有一个分页查询用户的接口,后端接口如下:这仨个参数不需要传递

@GetMapping("list_user.do")
public ResponseData<PageData<List<UserVO>>> getUsersByCondition(@RequestParam(defaultValue = "1") Integer currentPage,
                                                                @RequestParam(defaultValue = "10") Integer currentSize,
                                                                @RequestParam(required = false) String username){
    ResponseData<PageData<List<UserVO>>> responseData = new ResponseData<>();
    responseData.setStatus(ResponseConstant.REQUEST_ERROR_CODE);
    responseData.setMsg(ResponseConstant.REQUEST_ERROR);
    Page<UserEntity> userEntities = userService.getUsersWithLikeUsername(currentPage, currentSize, username);
    PageData<List<UserVO>> pageData = new PageData<>();
    if (userEntities.getContent().isEmpty()) {
        return responseData;
    }
    List<UserVO> userVOS = userEntities.getContent().stream().map((userEntity) -> {
        UserVO userVO = new UserVO();
        BeanUtils.copyProperties(userEntity, userVO);
        return userVO;
    }).collect(Collectors.toList());
    pageData.setTotalElements(userEntities.getTotalElements());
    pageData.setCurrentPage(userEntities.getNumber() + 1);
    pageData.setTotalPage( userEntities.getTotalPages()).setCurrentSize(userEntities.getSize()).setData(userVOS);
    responseData.setData(pageData).setStatus(ResponseConstant.REQUEST_OK_CODE).setMsg(ResponseConstant.REQUEST_SUCCESS);
    return responseData;
}

使用postman工具测试效果如下图:证明接口没问题。只需要访问到接口就可以!

前后端参数传递的各种方式

前端搭建的环境是React-18.2 + Antd-5.2.0 + Axios1.3.4;给出请求数据的代码如下

useEffect(()=>{
    axios.get("http://127.0.0.1:8080/user/list_user.do").then((result)=>{
        console.log(result);
    })
},)

请求结果如下图所示:证明这样就可以使用get方法进行数据的获取。比较简单!

前后端参数传递的各种方式

get方法进行参数传递,后端没有使用注解

不需要传递参数的接口毕竟是少数,因此常常看到一些后端接口需要传递一些参数进行数据信息的获取,如传递用户id获取用户的详细信息,传递订单号查看订单的详细信息等情况。以展示用户详细为例说明此种接口该如何请求数据。后端接口如下所示

@GetMapping("detail.do")
public ResponseData<UserVO> getUserDetailById(Long userId){
    log.info("userId = {}",userId);
    ResponseData<UserVO> responseData = new ResponseData<>();
    responseData.setStatus(ResponseConstant.REQUEST_ERROR_CODE)
        .setMsg(ResponseConstant.REQUEST_ERROR);
    Optional<UserVO> detailOpt = userService.getUserDetailByIdWithOpt(userId);
    detailOpt.ifPresent(userVO -> Optional.of(userVO.getId()).ifPresent((uId) -> responseData.setData(userVO)
                                                                        .setStatus(ResponseConstant.REQUEST_OK_CODE)
                                                                        .setMsg(ResponseConstant.REQUEST_SUCCESS)));
    return responseData;
}

在这种情况下,只需要保证前端键值对的key和后端接口形参保持一致(这里为userId),即在url的?之后的字符串为userId=id,只有这种情况下才能正确传递参数。

postman测试:

前后端参数传递的各种方式

如果参数没有保持一致,如使用user/id=userId的形式将会导致后端参数为空,进而可能导致服务异常。

下图为postman接口测试和后端接口异常展示

前后端参数传递的各种方式

Java接口接收到参数为null。

前后端参数传递的各种方式

通过Postman展示了测试结果以及如何正确获取数据之后,接下来就使用axios进行参数的传递和数据的获取

useEffect(()=>{
    axios.get("http://127.0.0.1:8080/user/detail.do",{
        params:{
            userId:2,
        }
    }).then((result)=>{
        console.log(result);
    })
},)

接口返回信息如下图

前后端参数传递的各种方式

get方法进行参数传递,后端使用@RequestParam

修改getUserDetailById的参数列表,使用@RequestParam注解

  public ResponseData<UserVO> getUserDetailById(@RequestParam Long userId){
      // 其余不变
  }

在后端是这种情况的条件下,前端的键值对的key和Java接口的形参userId仍然保持一致,就可以正确传递参数,如上面所示。

当后端接口配置@RequestParam(name= "id")时,此时前端传递的键值对的键要和name的值保持一致才能正确传递的参数,即这里的key为id,postman演示效果如下

public ResponseData<UserVO> getUserDetailById(@RequestParam(name ="id" ) Long userId){
    // 其余不变
}

前后端参数传递的各种方式

post方法

post方法进行参数传递 非 JSON格式

当请求方式为post时,首先要了解Content-type属性的三个取值:

Content-type的三种取值:

  • 'Content-Type: application/json ': 数据以json格式发送到后端
  • 'Content-Type: application/x-www-form-urlencoded':请求体中的数据以普通表单[键值对key=value]的形式发送到后端
  • 'Content-Type: multipart/form-data':以类似这种 boundary=----WebKitFormBoundaryzODWbCB3XjzhvhHL 形式分割参数,既可以传递文件,也可以传递键值对。

后端Post接口形参的几种情况:

  • 没有使用@RequestParam@RequestBody
  • 使用了@RequestParam
  • 使用了@RequestBody

在前两种情形下,和get方式中传递参数的方式是一样的,只不过需要前端需要使用post方法。

login接口予以说明:

@PostMapping("login.do")
public ResponseData<UserVO> login(String username, String password) {
    ResponseData<UserVO> responseData = new ResponseData<>();
    responseData.setStatus(ResponseConstant.REQUEST_ERROR_CODE)
        .setMsg(ResponseConstant.REQUEST_USER_ERROR);
    UserVO user = userService.getUserByUsernameAndPassword(username, password);
    // 根据userId判断是否查询到user
    Optional.ofNullable(user.getId()).ifPresent((userVO) ->{
        responseData.setData(user);
        responseData.setMsg(ResponseConstant.REQUEST_LOGIN_OK)
            .setStatus(ResponseConstant.REQUEST_OK_CODE);
    });
    return responseData;
}

此时前端在传递参数时除了Content-type:application/json外,都可以正常传递参数[需要保持参数名一致]。如果后端配置了@RequestParamname属性,则和name属性的值一样。

前后端参数传递的各种方式

在这种方式下前端可以使用Content-Type: application/x-www-form-urlencoded或者Content-Type: multipart/form-data方式进行参数传递。

使用axios进行传参代码;

useEffect(()=>{
    axios.defaults.headers["Content-Type"] = "application/x-www-form-urlencoded";
    // axios.defaults.headers["Content-Type"] = "multipart/form-data"; // ok
    axios.post("http://127.0.0.1:8080/user/login.do",{
        username:"react911",
        password:'react911'
    }).then((result)=>{
        console.log("loginInfo =",result);
    })
},)

需要说明的是,我们可以不配置Content-type属性进行传递参数,可以使用下列两个JS对象,axios自己会出手!

  • FormData: 对应multipart/form-data
  • URLSearchParams: 对应application/x-www-form-urlencoded

前端代码如下:

// const formData = new FormData();
const formData = new URLSearchParams();
formData.append("username","xiputerst");
formData.append("password","xipu123")
​
useEffect(()=>{
    // axios.defaults.headers["Content-Type"] = "application/x-www-form-urlencoded";
    // axios.defaults.headers["Content-Type"] = "multipart/form-data"; // ok
    axios.post("http://127.0.0.1:8080/user/login.do",formData).then((result)=>{
        console.log("loginInfo =",result);
    })
},)

Content-type:application/x-www-form-urlencoded方式的请求如下所示

前后端参数传递的各种方式

前后端参数传递的各种方式

Content-type:mutipart/form-data的参数传递方式

前后端参数传递的各种方式

JSON方式传递数据

有些时候,后端接口使用@RequestBody注解一个实体类时,就需要参数以json方式传递。

@PostMapping("add_user.do")
public ResponseData<UserVO> createNewUser(@RequestBody UserDTO newUser){
​
    log.info("newUser = {}",newUser);
    ResponseData<UserVO> responseData = new ResponseData<>();
    responseData.setStatus(ResponseConstant.REQUEST_ERROR_CODE)
        .setMsg(ResponseConstant.REQUEST_ERROR);
​
    UserVO newUserVO = userService.createNewUserEntity(newUser);
    Optional<Long> optionalLong = Optional.ofNullable(newUserVO.getId());
    optionalLong.ifPresent((id) ->{
        responseData.setStatus(ResponseConstant.REQUEST_OK_CODE)
            .setMsg(ResponseConstant.REQUEST_SUCCESS)
            .setData(newUserVO);
    });
​
    return responseData;
}

如果此时还以mutipart/form-data的方式传递参数,则会出错。

前后端参数传递的各种方式

正确的参数传递方式:

前后端参数传递的各种方式

使用axios进行参数传递

注意:axios在默认的情况下post使用的就是json格式,在不指定content-type的情况下,具体参见这里。JS代码如下

const newUser ={
    "username":'axios-post-jsonData',
    "password":"password-axios",
    "nickName":"axios是一个基于Promise封装的库",
    "phoneNumber":"1112223344"
}
​
axios.post("http://127.0.0.1:8080/user/add_user.do",newUser).then((result)=>{
    console.log("newUser =",result);
})

在这里也可以看到Content-type:'application/json;

前后端参数传递的各种方式

总结

基于上面所描述的那样,虽然分了很多种情况去讨论这个问题,但实际上就只需要注意一下post方式传参

post方式

  • 后端使用RequestBody注解了参数,则以json的方式传递
  • 其他情况不管使没使用@RequestParam只需要保证传递的key和形参或者@RequestParam的name属性的值保持一致就可以。至于Content-type属性是什么,并不重要,只有在传递文件的时候才强制为mutipart/form-data.

get方式

  • 参数一致即可,没有Content-type关系

你以为这就结束了?

不知道是否考虑过这么一种搭配方式,get方式传递json数据?你可能没见过,但是他确实存在,

@GetMapping("test.do")
public ResponseData<UserVO> testGetJson(@RequestBody UserEntity user){
    log.info("user = {}",user);
    ResponseData<UserVO> responseData = new ResponseData<>();
    UserVO userVO = new UserVO();
    BeanUtils.copyProperties(user,userVO);
    responseData.setData(userVO).setStatus(ResponseConstant.REQUEST_OK_CODE).setMsg(ResponseConstant.REQUEST_SUCCESS);
    return responseData;
}

postman接口测试

前后端参数传递的各种方式

发现没有!!!get方式传递json数据是可以的!但是为什么工作中没人这么用?以及为什么没有展示axios的代码去演示这个,

前者的答案就参考这里吧,至于后者吧,好像前面的参考连接也给答案了,但!!最重要的是axios不支持get传递json数据。

人家postman测试得好好的,为什么要使用axios?axios是什么东西,axios他没这个能力,你知道吧!手动狗头.jpg

一定是有什么特别的缘分,才让我们在这里相遇。祝君好运!

参考资料: