目录
一、概述
二、请求
1. postman工具
2. 简单参数
3. 实体参数
4. 数组集合参数
5. 日期参数
6. JSON参数
7. 路径参数
三、响应
1. @ResponseBody
2. 统一响应结果
3. 案例
通过之前对 JavaWeb开发 —— Web入门 的学习,我们开发了一个很简单的入门程序。
我们运行启动类运行启动内嵌的Tomcat Web服务器之后,就可以打开浏览器,然后在浏览器地址栏通过访问路径访问到我们部署在Tomcat中的应用程序。Controller接收到请求之后并处理,处理完毕之后再给浏览器响应对应的结果。
客户端浏览器与服务器进行数据传输的时候,是基于HTTP协议。HTTP协议就规定了浏览器与服务器进行数据传输的规则。而我们之前编写的Controller 仅仅是一个简单的Java类,并没有实现任何的接口,也没用继承任何的类,那么这个程序不能被Tomcat识别不能够直接运行。
Tomcat虽然不识别我们编写的Controller程序,但是其识别JavaEE规范中的Servlet,因为Tomcat我们也称为Servlet容器。而我们基于SpringBoot开发的Web入门程序当中,SpringBoot底层给我们提供了一个非常核心的Servlet程序 —— DispatcherServlet,其就实现了Servlet规范当中的Servlet接口。
有了DispatcherServlet之后,前端浏览器发送的请求都会先经过DispatcherServlet,并将请求传给后面各个Controller程序,由Controller程序再对请求进行处理,处理完毕后再由Controller程序返回给DispatcherServlet,再响应给浏览器数据。因此我们也称DispatcherServlet为前端控制器。
① 那么我们如何从DispatcherServlet 中获取请求的数据呢?
前端浏览器发送请求会携带HTTP的请求数据,而Web服务器就负责对这些请求数据进行解析,所以Tomcat就会接收到这些请求数据,并对请求数据进行解析,并且将解析后的所有信息最终封装到一个对象当中 —— HttpServletRequest(请求对象),接下来应用程序就可以从HttpServletRequest对象当中获取请求数据,然后再对数据进行处理,处理完毕之后Tomcat服务器就会根据HTTP协议响应数据格式给浏览器响应数据。
② Tomcat如何知道给浏览器响应什么数据呢?
在Servlet程序当中,我们可以借助另外一个对象来设置响应数据 —— HttpServletResponse(响应对象),通过这个对象就可以设置我们想要的数据,然后Tomcat根据我们在 HttpServletResponse中设置的响应信息来响应数据给浏览器。
请求响应:
Postman是一款功能强大的网页调试与发送网页HTTP请求的Chrome插件。
作用:常用于进行接口测试
① 原始方式:在原始的web程序中,获取请求参数,需要通过HttpServletRequest对象手动获取。
//测试请求参数接收
@RestController
public class RequestController {
//原始方式
@RequestMapping("/simpleParam")
public String simpleParam(HttpServletRequest request){
//获取请求参数
String name = request.getParameter("name");
String ageStr = request.getParameter("age");
int age = Integer.parseInt(ageStr);
System.out.println(name+" : "+age);
return "OK";
}
}
② SpringBoot方式:
//基于SpringBoot方式
@RequestMapping("/simpleParam")
public String simpleParam(String name,Integer age){
System.out.println(name+" : "+age);
return "OK";
}
@RequestMapping("/simpleParam")
public String simpleParam(@RequestParam(name = "name")String username,Integer age){
System.out.println(username+" : "+age);
return "OK";
}
注意事项:@RequestParam 中的required属性默认为true,代表该请求参数必须传递,如果不传递将报错。如果该参数是可选的,可以将required属性设置为false。
① 简单实体对象:请求参数名与形参对象属性名相同,定义POJO接收即可。
public class User {
private String name;
private Integer age;
}
//简单实体参数
@RequestMapping("/simplePojo")
public String simplePojo(User user){
System.out.println(user);
return "OK";
}
② 复杂实体对象:请求参数名与形参对象属性名相同,按照对象层次结构关系即可接收嵌套POJO属性参数。
public class User {
private String name;
private Integer age;
private Address address;
}
public class Address{
private String province;
private String city;
}
//复杂实体参数
@RequestMapping("/simplePojo")
public String simplePojo(User user){
System.out.println(user);
return "OK";
}
① 数组参数:请求参数名与形参数组名称相同且请求参数为多个,定义数组类型形参即可接收参数。
//数组参数
@RequestMapping("/arrayParam")
public String arrayParam(String[] hobby){
System.out.println(Arrays.toString(hobby));
return "OK";
}
② 集合参数:请求参数名与形参集合名称相同且请求参数为多个,@RequestParam 绑定参数关系。
//集合参数
@RequestMapping("/listParam")
public String listParam(@RequestParam List hobby){
System.out.println(hobby);
return "OK";
}
日期参数:使用 @DateTimeFormat 注解完成日期参数格式转换
//日期参数
@RequestMapping("dataParam")
public String dateParam(@DataTimeFormat(Pattern = "yyyy-MM-dd HH:mm;ss")LocalDateTime updateTime){
System.out.println(updateTime);
return "OK";
}
JSON参数:JSON数据键名与形参对象属性名相同,定义POJO类型形参即可接收参数,需要使用 @RequestBody 标识。
public class User {
private String name;
private Integer age;
private Address address;
}
public class Address{
private String province;
private String city;
}
//JSON参数
@RequestMapping("/jsonParam")
public String jsonParam(@RequestBody User user){
System.out.println(user);
return "OK";
}
路径参数:通过请求URL直接传递参数,使用 {..} 来标识该路径参数,需要使用 @PathVariable 获取路径参数。
① 单个路径:
//路径参数
//单个路径
//路径{id}动态
@RequestMapping("/path/{id}")
public String pathParam(@PathVariable Integer id){
System.out.println(id);
return "OK";
}
② 多个路径:
//路径参数
//多个路径
@RequestMapping("/path/{id}/{name}")
public String pathParam2(@PathVariable Integer id,@PathVariable String name){
System.out.println(id);
System.out.println(name);
return "OK";
}
① 类型:方法注解、类注解。
② 位置:Controller方法上 / 类上。
③ 作用:将方法返回值直接响应,如果返回值类型是 实体对象 / 集合,将会转换为JSON格式响应。
④ 说明:@RestController = @Controller + @ResponseBody ;
@RestController
public class ResponseController {
@RequestMapping("/hello")
public String hello(){
System.out.println("Hello World");
return "Hello World";
}
@RequestMapping("/getAddr")
public Address getAddr(){
Address addr = new Address();
addr.setProvince("北京");
addr.setCity("北京");
return addr;
}
@RequestMapping("listAddr")
public List listAddr(){
List list = new ArrayList<>();
Address addr1 = new Address();
addr1.setProvince("北京");
addr1.setCity("北京");
Address addr2 = new Address();
addr2.setProvince("山东");
addr2.setCity("青岛");
list.add(addr1);
list.add(addr2);
return list;
}
}
每一个方法其实都是一个功能接口,而之前我们学习的项目开发中的开发文档就是用来描述功能接口的请求路径、请求参数、响应数据各是什么。
在上面的代码经过@ResponseBody处理返回给前端数据分别为字符串、JSON格式的数据和数组,每一个接口返回的数据很随意,没有规范而言。但是在实际开发中,我们所涉及的功能接口种类很多,没有统一的规范,前端人员发送请求所访问到我们开发的接口,我们最终返回的数据各式各样,前端人员解析不方便,整个项目不便管理,难以维护。
这里就需要:
public class Result {
//响应码,1代表成功; 0代表失败
private Integer code;
//提示信息
private String msg;
//返回的数据
private Object data;
}
更改上述代码格式:
@RestController
public class ResponseController {
@RequestMapping("/hello")
public Result hello(){
System.out.println("Hello World");
//return new Result(1,"success","Hello World");
return Result.success("Hello World");
}
@RequestMapping("/getAddr")
public Result getAddr(){
Address addr = new Address();
addr.setProvince("北京");
addr.setCity("北京");
return Result.success(addr);
}
@RequestMapping("listAddr")
public Result listAddr(){
List list = new ArrayList<>();
Address addr1 = new Address();
addr1.setProvince("北京");
addr1.setCity("北京");
Address addr2 = new Address();
addr2.setProvince("山东");
addr2.setCity("青岛");
list.add(addr1);
list.add(addr2);
return Result.success(list);
}
}
//统一响应结果封装类
public class Result {
private Integer code; // 1 成功 0 失败
private String msg; //提示信息
private Object data; //数据 data
public Result(){}
public Result(Integer code,String msg,Object data){
this.code = code;
this.msg = msg;
this.data = data;
}
public Integer getCode() {
return code;
}
public void setCode(Integer code) {
this.code = code;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
public Object getData() {
return data;
}
public void setData(Object data) {
this.data = data;
}
public static Result success(Object data){
return new Result(1,"success",data);
}
public static Result success(){
return new Result(1,"success",null);
}
public static Result error(String msg){
return new Result(0,msg,null);
}
@Override
public String toString() {
return "Result{" +
"code=" + code +
", msg='" + msg + '\'' +
", data=" + data +
'}';
}
}
需求:获取员工数据,返回统一响应格式,在页面渲染展示。
① 操作步骤:
Springboot项目的静态资源(html,css,js等前端资源)默认存放目录为:classpath:/static 、 classpath:/public、classpath:/resources。
② 代码实现:
//EmpController
@RestController
public class EmpController {
@RequestMapping("/listEmp")
public Result list(){
//1.加载并解析emp.xml
//String file = "F:\\idea\\idea_workplace\\springboot-web-req-resp\\src\\main\\resources\emp.xml";
//动态获取
String file = this.getClass().getClassLoader().getResource("emp.xml").getFile();
System.out.println(file);
List empList= XmlParserUtils.parse(file, Emp.class);
//2.数据进行转换处理 -gender job
empList.stream().forEach(emp ->{
String gender = emp.getGender();
if("1".equals(gender)){
emp.setGender("男");
}else if ("2".equals(gender)){
emp.setGender("女");
}
String job = emp.getJob();
if("1".equals(job)){
emp.setJob("讲师");
}else if ("2".equals(job)){
emp.setJob("班主任");
}else if ("3".equals(job)){
emp.setJob("就业指导");
}
});
//3.响应数据
return Result.success(empList);
}
}