JavaWeb开发 —— 请求响应
目录
一、概述
二、请求
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中设置的响应信息来响应数据给浏览器。
请求响应:
- 请求(HttpServletRequest):获取请求数据
- 响应(HttpServletResponse):设置响应数据
- BS架构:Browser / Server,浏览器 / 服务器架构模式。客户端只需要浏览器,应用程序的逻辑和数据都存储在服务端。(维护方便 但 体验一般)
- CS架构:Client / Server,客户端 / 服务器架构模式。(开发、维护麻烦 但 体验不错)
二、请求
1. postman工具
Postman是一款功能强大的网页调试与发送网页HTTP请求的Chrome插件。
作用:常用于进行接口测试
下载:postman下载与安装
2. 简单参数
① 原始方式:在原始的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方式:
- 参数名与形参变量名相同,定义形参即可接收参数。
- 如果方法形参名称与请求参数名称不匹配,可以使用 @RequestParam 完成映射。
//基于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。
3. 实体参数
① 简单实体对象:请求参数名与形参对象属性名相同,定义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";}
4. 数组集合参数
① 数组参数:请求参数名与形参数组名称相同且请求参数为多个,定义数组类型形参即可接收参数。
//数组参数@RequestMapping("/arrayParam")public String arrayParam(String[] hobby){System.out.println(Arrays.toString(hobby));return "OK";}
② 集合参数:请求参数名与形参集合名称相同且请求参数为多个,@RequestParam 绑定参数关系。
//集合参数@RequestMapping("/listParam")public String listParam(@RequestParam List<String> hobby){System.out.println(hobby);return "OK";}
5. 日期参数
日期参数:使用 @DateTimeFormat 注解完成日期参数格式转换
//日期参数@RequestMapping("dataParam")public String dateParam(@DataTimeFormat(Pattern = "yyyy-MM-dd HH:mm;ss")LocalDateTime updateTime){System.out.println(updateTime);return "OK";}
6. JSON参数
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";}
7. 路径参数
路径参数:通过请求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";}
三、响应
1. @ResponseBody
① 类型:方法注解、类注解。
② 位置: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<Address> listAddr(){List<Address> 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格式的数据和数组,每一个接口返回的数据很随意,没有规范而言。但是在实际开发中,我们所涉及的功能接口种类很多,没有统一的规范,前端人员发送请求所访问到我们开发的接口,我们最终返回的数据各式各样,前端人员解析不方便,整个项目不便管理,难以维护。
这里就需要:
2. 统一响应结果
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<Address> 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; //数据 datapublic 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);}@Overridepublic String toString() {return "Result{" +"code=" + code +", msg='" + msg + '\\'' +", data=" + data +'}';}
}
3. 案例
需求:获取员工数据,返回统一响应格式,在页面渲染展示。
- 加载并解析emp.xml文件中的数据,完成数据处理,并在页面展示。
① 操作步骤:
- 在pom.xml文件中引入dom4j的依赖,用于解析XML文件。
- 引入资料中提供的解析XML的工具类XMLParserUtils.对应的实体类Emp. XML文件emp.xml。
- 引入资料中提供的静态页面文件,放在resources 下的static目录下。
- 编写Controller程序,处理请求,响应数据。
- 详细数据见资料分享 。
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<Emp> empList= XmlParserUtils.parse(file, Emp.class);//2.数据进行转换处理 -gender jobempList.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);}
}