SpringMvc获取请求参数
1,概述
我们使用SpringMvc的控制器的时候,接受参数其实就是我们做业务开发的第一步。本节课开始,V哥就会细细的给大家讲SpringMvc接受参数。就是我们使用HttpServletReqeust本来也是可以接收参数的,但是SpringMvc为我们提供了更好的,更方便的接收参数的方式。
2,通过参数名完全匹配的方式获取请求参数
就是说,我们定义Controller对应的方法的时候,我们写入对应的方法参数,参数的名字和请求中参数的名字完全匹配。这个时候,SpringMvc会自动的把请求的参数的值赋值到方法参数上。
@Controller
@RequestMapping("/param")
public class ParamController {
@GetMapping("/name-equals")
public ModelAndView nameEqueals(String name, Integer age) {
System.out.println("name=" + name + ", age=" + age);
ModelAndView modelAndView = new ModelAndView();
modelAndView.setViewName("sayhello");
return modelAndView;
}
}
3,指定请求参数名获取请求参数
有的时候我们用户提交上来的参数性可能我们定义的Controller的方法的方法参数的名字不匹配,这个时候怎么办?我们只需要增加@RequestParam注解就行了。
@GetMapping("/name-not-equals")
public ModelAndView nameNotEqueals(@RequestParam("n") String name, @RequestParam("a") Integer age) {
System.out.println("name=" + name + ", age=" + age);
ModelAndView modelAndView = new ModelAndView();
modelAndView.setViewName("sayhello");
return modelAndView;
}
4,GET请求和POST请求获取参数方式一样
意思就是我们通过GET请求或者POST请求,我们获取参数的方式都是一样的。我们直接用Postman演示一下就行。
5,自定义对象接受参数
上线我们是通过定义方法参数的名字和请求参数的名字一模一样,或者加上@RequestParam注解的方式来接受客户端提交上来的参数。但是有时候有一个很大的问题。就说如果提交上来的参数非常多怎么办?比如我们要添加用户,我们需要添加用户名,密码,昵称,年龄,性别,籍贯…等等一共假如说有20个参数,这个时候,你直接在方法上写20哥方法参数是不是非常的麻烦啊?还有,我们学习编码规范的时候,我们都知道,一个方法的参数的数量不能太多,一般情况下,参数的个数不能超过7个。这个时候,我们可以自定义一个封装对象来接受参数。
1,定义自定义对象:
package com.vgxit.learn.springmvc.quickstart.ro;
import lombok.Data;
@Data
public class UserAddRO {
private String username;
private String nickname;
private Integer age;
}
2,编写接受参数的方法:
@PostMapping("/add-user")
public ModelAndView addUser(UserAddRO userAddRO) {
System.out.println(userAddRO);
ModelAndView modelAndView = new ModelAndView();
modelAndView.setViewName("sayhello");
return modelAndView;
}
6,使用URL来传递参数
这个往往在基于RestFul风格的Api系统中非常常见,比如我们要获取一个用户的数据,可能对外提供的Api接口的地址如下:“GET http://www.vgxit.com/api/v1/user/1”,其实在这个URL中的1表示请求上来的一个参数,这个1代表的就是用户的id。那如果遇到这种情况,我们怎么样来做呢?
@GetMapping("/get-user/{id}")
public ModelAndView getUser(@PathVariable("id") int id) {
System.out.println("id=" + id);
ModelAndView modelAndView = new ModelAndView();
modelAndView.setViewName("sayhello");
return modelAndView;
}
7,Rest接口,返回json数据
就是我们使用Rest接口的时候,一般我们是在前后端分离的项目中使用,这个时候,我们返回的数据通常就是Json格式的,而我们上面的方式,只是简单的通过ModelAndView来指定了一个视图层页面。这个显然是不满足需求的。那么如果我们要使用Json格式返回数据,怎么办?
1,首先,我们要引入一个包,一个jackson-databind包:
<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.12.4</version>
</dependency>
2,定义Rest接口的Controller:
@GetMapping("/get-user/{id}")
public ModelAndView getUser(@PathVariable("id") int id) {
User user = User.builder()
.id(id)
.username("liyitong")
.nickname("李一桐")
.age(30)
.build();
ModelAndView modelAndView = new ModelAndView();
//设置返回的视图为Json格式,MappingJackson2JsonView就是Jackson给我们提供的返回json格式数据的视图
modelAndView.setView(new MappingJackson2JsonView());
//再把我们要返回的数据设置到这个modelAndView中
modelAndView.addObject(user);
return modelAndView;
}
8,Rest接口返回Json简写方式
但是我们上面写的通过modelAndView的方式来返回Json是比较麻烦的,那么SpringMvc为我们提供了一个简单的方式来返回Json数据:
@GetMapping("/get-json-user/{id}")
//@ResponseBody表示我们返回的数据格式是对应的Java对象的Json
public @ResponseBody User getJsonUser(@PathVariable("id") int id) {
User user = User.builder()
.id(id)
.username("liyitong")
.nickname("李一桐")
.age(30)
.build();
return user;
}
9,整个项目全Rest接口,Json返回方式
就是我们现阶段的开发中,基本上都是前后端分离的项目,比如前端可能就是用Vue或者React来通过Ajax来访问后端接口的。相当于,我们后端程序员,不用再来些页面了,我们后端的代码中,没有Html、Css、Js都没有。我们提供的全是接口。这个时候,我们所有的接口全部都是返回Json数据。按照上面的方式,每个接口我们都需要加上@ResponseBody注解,真的是非常的麻烦。这个时候,我们只需要通过另外一个注解来修饰COntroller就行了。
package com.vgxit.learn.springmvc.quickstart;
import com.vgxit.learn.springmvc.quickstart.po.User;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.ArrayList;
import java.util.List;
@RestController
@RequestMapping("/user")
public class UserController {
@GetMapping("/get-user/{id}")
public User getUser(@PathVariable("id") int id) {
User user = User.builder()
.id(id)
.username("liyitong")
.nickname("李一桐")
.age(30)
.build();
return user;
}
@GetMapping("/all")
public List<User> all() {
List<User> users = new ArrayList<User>();
for (int i = 0; i < 10; i++) {
User user = User.builder()
.id(i + 1)
.username("username" + i)
.nickname("nickname" + i)
.age(20 + i)
.build();
users.add(user);
}
return users;
}
}
10,使用json的方式来传递参数
在Rest接口的开发中,前端给我们Post,PUT提交参数的时候,往往是直接用Json格式来提交的。
对应的Controller代码如下:
@PostMapping("/add")
//@RequestBody的意思,就是表示我们的UserAddRO中的数据由客户端提交上来的Json数据填充
public String add(@RequestBody UserAddRO userAddRO) {
System.out.println(userAddRO);
return "ok";
}
对应的Jsp页面我们用Json来实现提交:
<%--
Created by IntelliJ IDEA.
User: Administrator
Date: 2021/8/14
Time: 18:18
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
<script type="text/javascript" src="https://vgxitdata-1256295173.cos.ap-chengdu.myqcloud.com/jquery-files/jquery-1.12.4.min.js"></script>
<script type="text/javascript">
function addUser() {
var postData = {
"username":"liyitong",
"nickname":"桐桐",
"age":30
};
$.post({
url:"http://localhost/01quickstart/user/add",
"contentType":"application/json",
data: JSON.stringify(postData),
success: function (res) {
alert(res);
}
})
}
</script>
</head>
<body>
<button onclick="addUser();">点击提交</button>
</body>
</html>
11,json方式接受列表数据
有些同学可能会问V哥,如果我们一次性添加多个用户,怎么办?一次性添加多个用户,无非就是一次性上传一个Json的数组上来,而我们Java的Controller用一个List来接收,是不是就好了?
@PostMapping("/batch-add")
public String batchAdd(@RequestBody List<UserAddRO> userAddROS) {
System.out.println(userAddROS);
return "ok";
}
12,转换器
之前,我们定义参数的时候,我们都是用的String,Int,就是我们使用的是基本数据类型+String来接受参数的。但是如果我们接收的参数不是基本数据类型和String的时候怎么办。比如我们接受的数据类型是Date类型。
@GetMapping("/test-date")
public String testDate(Date date) {
System.out.println(date);
return "ok";
}
以上代码,程序直接报错了,因为我们传上来的date是一个String类型的数据。如果我们要转化成Date类型的数据,那么我们要使用SimpleDateFormat来转换,而现在,我们的SpringMvc根本就不知道你用的是什么格式来转化,所以直接就报错。
那么我们要解决上线的问题,我们需要编写一个转换器,这个转换器就是我们写了一段代码,这段代码告诉我们如何把String转化为Date。然后我们把这个转换器提供了SpringMvc就可以了。
1,首先要编写一个转换器,这个转换器必须实现一个接口Converter:
package com.vgxit.learn.springmvc.quickstart.converter;
import org.springframework.core.convert.converter.Converter;
import org.springframework.util.ObjectUtils;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class VgeStringToDateConverter implements Converter<String, Date> {
//这个方法就是具体的吧String转换成Date的方法
public Date convert(String s) {
if (ObjectUtils.isEmpty(s)) {
throw new NullPointerException("要转换的日期不能为空");
}
DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
try {
Date date = dateFormat.parse(s);
return date;
} catch (ParseException e) {
throw new RuntimeException(e);
}
}
}
2,配置转换器工厂:
<!--配置一个转换器工厂-->
<bean id="converterService" class="org.springframework.context.support.ConversionServiceFactoryBean">
<!--注入一个新的类型的转换器-->
<property name="converters">
<set>
<bean class="com.vgxit.learn.springmvc.quickstart.converter.VgeStringToDateConverter"/>
</set>
</property>
</bean>
<!--通过conversion-service="converterService"引用配置器工厂-->
<mvc:annotation-driven conversion-service="converterService"/>
转换器,不光是可以转换Date类型,其他类型依然是可以转换的。比如我们自定义的类型也是可以转换的:
@GetMapping("/test-user")
public String testUser(UserAddRO userAddRO) {
System.out.println(userAddRO);
return "ok";
}
package com.vgxit.learn.springmvc.quickstart.converter;
import com.vgxit.learn.springmvc.quickstart.ro.UserAddRO;
import org.springframework.core.convert.converter.Converter;
public class VgeStringToUserAddRoConverter implements Converter<String, UserAddRO> {
public UserAddRO convert(String s) {
String[] split = s.split(":");
UserAddRO userAddRO = new UserAddRO();
userAddRO.setUsername(split[0]);
userAddRO.setNickname(split[1]);
userAddRO.setAge(Integer.parseInt(split[2]));
return userAddRO;
}
}
就是,我们如果是Json格式提交的时候,那么是什么情况。就是我们干掉了我们配置的转换器工厂之后,我们用Json格式提交参数,数据转换是没有问题的,比如我们把UserAddRO里面的age改成Date类型的birthday,也是转换没问题的。这个是应为我们做Json转换的时候,用的Jackson包给我们提供的工具,MappingJackson2HttpMessageConverter,这个工具他在转换的时候,就已经定义好了一些日期转换的格式,所以,我们不需要再自定义转换器的。
package com.vgxit.learn.springmvc.quickstart.ro;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import java.util.Date;
@Data
public class UserAddRO {
private String username;
private String nickname;
@JsonFormat(timezone = "GMT+8", pattern = "yyyy年MM月dd号")//指定日期格式
private Date birthday;
}