大家好,我是渣哥,是一个每天都在攒钱植发的程序猿。
前两天有小伙伴在问我:
渣哥,我后端Controller写的好好的,前端去访问的时候为啥总是404呢?
还有小伙伴问我:
渣哥,我把数据从前端发送到后端,但是为什么后端接到的参数却是null?
别急,那今天渣哥就来跟大家聊聊关于前后端传参的那些事,如果你也有这方面的疑问,就请跟着渣哥一起了解一下吧!
注:阅读本篇文章你需要至少有一定前端基础,需要至少了解SpringMVC。
Get
先聊聊Get的传参问题吧,这个相对简单很多,我们知道浏览器的默认请求方式就是Get。当我们在浏览器里输入:
http://localhost:8080/login?username=zhage&password=1234
点击回车之后,浏览器就会去访问一个地址为:localhost:8080/login
的服务,并且携带上两个参数,分别是 username=zhage
和password=1234
那我们来创建这样一个接口服务:
@Controller
public class TestController {
@GetMapping("login")
public void login(String username, String password) {
System.out.println(username);
System.out.println(password);
}
}
咱们来运行一下程序,并在第一个输出这里打个断点。
再回到浏览器,访问刚刚的Url,来看看发生了什么。
果然,咱们成功的把参数给接到了。能接到的原因是什么呢?不知道。
那接下来咱们做个实验:
把访问的url改成:
http://localhost:8080/login?username=zhage&p=1234
咱们再试一次。
欸,这个时候就发现问题了,username
这个参数,因为传参和接参对于参数名称都是一致的,所以接到了,但是另一个参数,传参的时候是p
,接参的时候是password
,所以就没有接到。
所以我们就可以得出结论,使用Get请求传输基本参数的时候,需要保持传参和接参时的参数名一致,后端才可以接收的到,否则接收不到。
Post
聊完了Get接参之后,再聊聊Post请求接参,Post请求的话,会稍微复杂一些,因为我们知道Post请求的参数是不能直接写在Url里的,其实也简单,只要写一个Ajax就可以了。
$.post("http://localhost:8080/login", { username: "zhage", password: "1234" } );
我们再去后端看看,是不是已经接到了?
看了上面的例子,相信你也明白了,基础数据类型的传参,无论是Get请求还是Post请求,只需要参数名一致即可。那么问题来了,如果参数名不一致怎么办呢?
简单接参:@RequestParam
现在有这么一个情况,前端给我传的参数是name='xxx'&pwd='yyy'
,这样我要怎么接参呢?
只需要在参数前加一个@RequestParam
注解并指名需要把名为name
的参数,赋值给第一个参数,把名为pwd
的参数,赋值给第二个参数就可以了,当然如果参数名称一致的话,括号内的部分就可以省略了。
@Controller
public class TestController {
@GetMapping("login")
public void login(@requestParam("name") String username, @requestParam("pwd")String password)
{
System.out.println(username);
System.out.println(password);
}
}
并且当你为参数加上了@RequestParam
之后,就是表名该参数是必须有的,前端访问你的这个接口,是必须要传给你这个参数的,不然的话就访问不到,就会报404啦。当然这个是否必须是可以设置的,如果想知道怎么设置可以自己去查一查,不难。
上面的传参方式,听起来是不是非常简单,但是,如果只有一个两个三个参数,还好说,要是五六个,七八个、甚至十来个参数,这样写不累死掉,所以当参数数量变多时,有没有更简单一些的方法呢?当然有!
以对象形式接参
把接收到的参数,封装成一个对象的属性,只要属性名相同与传来的数据的Key同名即可
比如现在有个User类:
public class User {
String username;
String password;
//get/set/构造函数等等的我就省略了哈。。。
}
然后现在一个接口需要接的几个参数都是这个对象的属性,那么就可以这么写:
@GetMapping("login")
public void login3(User user) {
System.out.println(user.getUsername());
System.out.println(user.getPassword());
}
List集合接参:@RequestBoby
上面我们学会了当遇到多个参数的时候,把参数封装成一个对象来接收,那如果涉及到一个场景,我们需要前端需要传多个对象到后端的话,怎么办呢?答案是通过List集合来接收,集合接收的话,会稍微麻烦一些,我们一起来看看前后端分别怎么写吧!
前端:
var users = [
{username: 'zhage', password: '1234'},
{username: 'lisi', password: '1234'}
];
$.ajax({
method: 'post',
url: 'testList',
contentType: "application/json",
data: JSON.stringify(users),
});
首先,我们在发送请求的时候,添加了一个ContentType
的参数,指定了发送到后台的参数类型为application/json
,告诉后台,前端传给你的数据,是以JSON字符串的形式发送的。第二点改变的是,我们使用了JSON.stringify
这个函数,把我们的数组对象转成了JSON字符串。
后端:
@PostMapping("login")
public void login(@RequestBody List<User> users) {
System.out.println(users);
}
后端这边我们用到了一个注解:@RequestBoby
,我们都知道Post请求的数据是在请求体里的,简单理解这个注解的功能就是从请求体里把这个数据取出来,然后作为这个方法的参数,以达到前后端数据传递的目的。
@PathVariable
在前后端分离开发的过程中,我们后端的接口规范大部分情况下都是遵守REST风格的,我们知道对于采用了REST风格的API来说,每个资源都有一个唯一的URL,如:
http://localhost:8080/xxx/users //所有用户
http://localhost:8080/xxx/user/1 //用户ID为1的用户
然后针对不同的行为,如增删改查,使用对应的请求方式去访问资源的Url;
比如我想查询id为1的用户的所有信息,那我应该用Get
请求去访问http://localhost:8080/xxx/user/1
;
这样就会存在一种情况,url里就会有参数,但是这种参数,跟之前的username=zhage
还不太一样,那这种参数我们后端怎么去接收呢?
看好了哈,我们这么写:
@GetMapping("/user/{id}")
public void selectUser(@PathVariable Integer id){
//调用service层查询并输出
}
看,后端这里我们又用到了一个@PathVariable
的注解,简单理解这个注解的作用,就是把路径中的占位参数取出,放到方法的入参里。即可达到从前端接参的效果。
咱们今天讲了项目中前后端传参的最常用的几种方式,相信你看了这篇文章之后,应该对前后端之间的传参有更深层的了解了吧,前后端交互是项目中最常见的场景,以后在实际项目中遇到了可千万不能掉链子呀!
加油!我是渣哥,我们下期再见!