Bootstrap

请求响应(学习笔记)

请求响应


请求响应

  • 请求(HttpServeltRequest):获取请求数据
  • 响应(HttpServletResponse): 设置响应数据
  • BS架构:Browser/Server 浏览器/服务器 架构模式,客户端只需要浏览器,应用程序的逻辑和数据都存储在服务端。(维护方便,体验一般)
  • CS架构:Client/Server 客户端/服务端架构模式。(开发、维护麻烦,体验不错)

请求

Postman

当前最主流的开发模式:前后端分离开发。

由于前后端分离,后端开发没有前端页面,浏览器发送的请求都是get请求

Postman是一款功能强大的网页调试与发送网页HTTP请求的Chrome插件

作用:常用于进行接口测试。

简单参数

  • 原始方式

    在原始的web程序中,获取请求参数,需要通过HttpServletRequest对象手动获取

package com.itheima;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.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";
    }
}


//使用postman发送Get请求
//http://localhost:8080/simpleParam?name=Tom&age=10
//ok
  • SpringBoot方式

    简单参数:参数名与形参变量名相同,定义形参即可接收参数

    //SpringBoot方式
    @RequestMapping("simpleParam")
    public String simpleParam(String name,Integer age) {
        System.out.println(name+":"+age);
        return"OK";
    }

​ 简单参数:如果方法形参名称与请求参数名称不匹配,可以使用@RequestParam完成映射

    @RequestMapping("/simpleParam")
    public String simpleParam(@RequestParam(name ="name")String username,Integer age) {
        System.out.println(username+":"+age);
        return "OK";
    }

//使用postname发送GET请求
//http://localhost:8080/simpleParam?name=ZAY&age=3
//

@RequestParm 中的required默认属性为true,代表该请求参数必须传递,如果不传递将报错。如果该参数是可选的,可以将required属性设置为false

实体参数

当参数需要传输过多,使用简单参数就会变得繁琐,可以将所有的参数封装到一个实体类之中

  • 简单实体对象:请求参数名与形参对象属性名相同,定义POJO接收即可
    @RequestMapping("/simplePojo")
    public String simplePojo(User user) {
        System.out.println(user);
        return "OK";
    }

public class User{
    private String name;
    private Integer age;
    
    public User(String name,Integer age){
        this.name = name;
        this.age = age;
    }
    public User(){
        
    }
    
    public String getName(){
        return this.name;
    }
    public void setName(String name){
        this.name = name;
    }
    
    public Integer getAge(){
        return age;
    }
    
    public void setAge(Integer age){
        this.age = age;
    }
}
  • 复杂实体对象:请求参数名与形参对象属性名相同,按照对象层次结构关系即可接收嵌套POJO属性参数
public class Address {
    private String province;
    private String city;

    public String getProvince() {
        return province;
    }

    public void setProvince(String province) {
        this.province = province;
    }

    public String getCity() {
        return city;
    }

    public void setCity(String city) {
        this.city = city;
    }

    @Override
    public String toString() {
        return "Address{" +
                "province='" + province + '\'' +
                ", city='" + city + '\'' +
                '}';
    }
}


public class User {
    private String name;
    private Integer age;
    private Address address;
    public User(String name, Integer age) {
        this.name = name;
        this.age = age;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public Integer getAge() {
        return age;
    }
    public void setAge(Integer age) {
        this.age = age;
    }

    public User() {

    }

    public Address getAddress() {
        return address;
    }

    public void setAddress(Address address) {
        this.address = address;
    }

    @Override
    public String toString() {
        return "User{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", address=" + address +
                '}';
    }
}

@RequestMapping("/complexPojo")
public String complexPojo(User user){
    Systm.out.println(user);
    return "OK";
}


//使用Postman发送GET请求
//http://localhost:8080/complexPojo?name=ZAY&age=10&address.province=北京&address.city=上海
//console返回OK

数组集合参数

数组参数

数组参数:请求参数名与形参组名称相同且请求参数为多个,定义数组类型形参即可接收参数

@RequestMapping("/arrayParam")
public String arrayParam(String []hobby){
    System.out.println(Arrays,toString(hobby));
    return "OK";
}

//使用Postman发送GET请求
//http://localhost:8080/arrayParam?hobby=game&hobby=java&hobby=sing

//[game, java, sing]
集合参数

集合参数:请求参数名与形参集合名称相同且请求参数为多个,通过@RequestParam绑定参数关系

    @RequestMapping("/listParam")
    public String listParam(@RequestParam List<String> hobby) {
        System.out.println(hobby);
        return "OK";
    }

//使用Postman发送GET请求
//http://localhost:8080/listParam?hobby=game&hobby=java&hobby=sing

//[game, java, sing]

日期参数

日期参数:使用@DateTimeFormat注解完成日期参数格式转换

    //日期时间参数
    @RequestMapping("/dateParam")
    public String dateParam(@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") LocalDateTime updateTime){
        System.out.println(updateTime);
        return "OK";
    }
//使用Postman发送GET请求
//http://localhost:8080/dateParam?updateTime=2022-12-12 10:00:05

//2022-12-12T10:00:05

JSON参数

Json参数:JSON数据键名与形参对象属性名相同,定义POJO类型形参即可接收参数,需要使用**@RequestBody**表示

    @RequestMapping("/jsonParam")
    public String jsonParam(@RequestBody User user) {
        System.out.println(user);
        return "OK";
    }
//使用Postman发送POST请求
//http://localhost:8080/jsonParam

{
    "name":"ZAY",
    "age":18,
    "address":{
        "province":"安徽",
        "city":"合肥"
    }
}

//User{name='ZAY', age=18, address=Address{province='安徽', city='合肥'}}

路径参数

路径参数:通过请求URL直接传递参数,使用{…}来表示该路径参数,需要使用**@PathVariable**获取路径参数

    //路径参数

    @RequestMapping("/path/{id}")
    public String path(@PathVariable Integer id) {
        System.out.println(id);
        return "OK";
    }

//使用Postman发送GET请求
//http://localhost:8080/path/10086
//10086
@RequestMapping("/path/{id}/{name}")
public String path(@PathVariable Integer id, @PathVariable String name) {
    System.out.println(id +":"+name);
    return "OK";
}

//使用Postman发送请求
//http://localhost:8080/path/1/ITCAST
//1:ITCAST

响应

响应数据

@ResponseBody

  • 类型:方法注解、注解类
  • 位置:Controller方法上/类上
  • 作用:将方法返回值直接响应,如果返回值类型是 实体对象/集合,将会转换为JSON格式响应
  • 说明:@RestController = @Controller + @ResponseBody
统一响应结果
public class Result{
    //响应码 1,成功  / 0,失败
    private Integer code;
    //提示信息
    private String msg;
    //返回数据
    private Object data;
}
{
    "code":"1",
    "msg":"操作成功",
    "data":...
}
    
    

统一响应结果

package com.itheima.pojo;

/**
 * 统一响应结果封装类
 */
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 +
                '}';
    }
}

分层解耦

三层架构

三层架构: Controller(接收请求、响应数据)、Service(逻辑处理)、Dao(数据访问)

  • controller:控制层,接收前端发送的请求,对请求进行处理,并响应数据。
  • service:业务逻辑层,处理具体的业务逻辑
  • dao:数据访问层(Data Access Object)(持久层),负责数据访问操作,包括数据的增删改查
//controller层
@RestController
public class EmpController{
    private EmpService empService = new EmpServiceA();
    @RequestMapping("/listEmp")
    public Result list(){
        //调用service 获取数据
        List<Emp> empList = empService.listEmp();
        //组装数据并返回
        return Result.success(empList);
    }
}
//dao层
public class EmpDaoA implements EmpDao{
    public List<Emp>listEmp(){
        //加载emp.xml 解析emp.xml中的数据
        String file = this.getClass().getClassLoader().getResource("emp.xml").getFile();
        List<Emp> empList = XmlParesrUtiles.parse(file,Emp.class);
        return empList;
    }
}
//service层
public class EmpServiceA implements EmpService{
    private EmpDao empDao = new EmpDaoA();
    pulic List<Emp> listEmp(){
        //调用dao层 获取数据
        List<Emp> empList = empDao.listEmp();
        
        //对员工信息中的gender job字段进行处理
        empList.stream().forEach(emp ->{
            if('1'.equals(gender)){
                emp.setGender('男')}else if("2".equlas(gender)){
                emp.setGender('女');
            }
        });
        
        return empList;
    }
}

分层解耦

  • 内聚:软件中各个模块内部的功能联系
  • 耦合:衡量软件中各个层/模块之间的依赖、关联的成都
  • 软件设计原则:高内聚、低耦合

控制反转:Inversion Of Control 简称IOC。对象的串讲控制权由程序自身转移到外部(容器),这种思想称为控制反转

依赖注入:Dependency Injection 简称DI。容器为应用程序提供运行时,所依赖的资源,称之为依赖注入。

Bean对象:IOC容器中创建、管理的对象,称之为bean

IOC & DI 入门

  • Service层 及 Dao层的实现类,交给IOC容器管理
@Component
public class EmpDaoA implements EmpDao{
    public List<Emp> listEmp(){
        //从文件中查询数据
        String file = this.getClass().getClassLoader().getResource("emp.xml").getFile();
        List<Emp> empList = XmpParserUtils.parse(file,Emp.class);
        return empList;
    }
}
@Component
public class EmpServiceA implements EmpService{
    private EmpDao empDao;
    public List<Emp>listEmp(){
        //调用dao层 查询数据
        List<Emp> empList = empDao.listEmp();
    }
}
  • 为Controller及Service注入运行时,依赖的对象
@RestController
public class EmpController{
    @Autowired
    private EmpService empService;
    
    @RequestMapping("/listEmp")
    public Result listEmp() throws Exception{
        List<Emp> empList = empService.listEmp();
        return Resultsuccess(empList);
    }
}
@Component
public class EmpServiceA implements EmpService{
    @Autowired
    private EmpDao empDao;
    public List<Emp> listEmp(){
        //调用dao层 查询数据
        List<Emp>empList = empDao.listEmp();
    }
}
  • 运行测试
@Component 	//将当前类交给IOC容器管理,称为IOC容器中的bean(对象)
@Autowired	//运行时,IOC容器会提供该类型的bean对象,并赋值给该变量-依赖注入

IOC详解

Bean的声明:

要把某个对象交给IOC容器管理,需要在对应的类上加上如下注解之一

注解说明位置
@Component声明bean的基础注解不属于以下三类,用此注解
@Controller@Component的衍生注解标注在控制器类上
@Service@Component的衍生注解标注在业务类上
@Repository@Component的衍生注解标注在数据访问类上

注意事项

  • 声明bean的时候,可以通过value属性指定bean的名字,如果没有指定,默认为雷鸣的首字母小写
  • 使用以上四个注解都可以声明bean,但是在springboot集成web开发中,声明控制器bean只能用@Controller

Bean组件扫描

  • 前面声明bean的四大注解,想要生效,还需要被组件扫描注解@ComponentScan扫描
  • @ComponentScan注解虽然没有显式配置,但是时间上已经包含在了启动类声明注解@SpringBootApplication中,默认扫描的范围是启动类所在包及其子包

DI详解

Bean注入

  • @Autowired注解默认是按照类型进行,如果存在多个相同类型的bean,会报错
  • 通过以下几种方案解决:
    • @Primary
    • @Qualifiler
    • @Resource
;