SpringbootWeb请求和响应 - 三重解耦(IOC和DI)
1 请求
1.1 作用
请求前端发送过来的数据
1.2 简单参数
常用于前端发送过来的数据量比较小的时候
ps: 接收数据建议使用包装类,否则输入null会报空指针异常
简单参数:参数名与形参变量名相同,定义形参即可接收参数。
// Responsebody + Controller
@RestController
public class mainController{
}
@RequestMapping("/simpleParam")
public String method(String name, Integer age) {
System.out.println(name + "," + age);
return "OK";
}
简单参数:如果方法形参名称与请求参数名称不匹配,可以使用 @RequestParam 完成映射。
//@RequestParam -绑定参数关系
@RequestMapping("/simpleParam")
public String method(@RequestParam (name = "name") String username, Integer age) {
System.out.println(username + "," + age);
return "OK";
}
1.3 实体参数
常用于前端发送过来的数据比较多的时候
简单实体对象:请求参数名与形参对象属性名相同,定义POJO接收即可, 类放置于pojo文件夹中, 类成员变量的名字一定要和请求的参数名字一样
@RequestMapping("/simplePojo")
public String simplePojo(User user) {
System.out.println(user);
return "ok";
}
复杂实体对象:请求参数名与形参对象属性名相同,按照对象层次结构关系即可接收嵌套POJO属性参数。 如果返回的对象有包括xxx.yyy则一定为对象表达
@RequestMapping("/complexPojo")
public String complexPojoMtd(Student student, Address address) {
System.out.println(student);
return "OK";
}
1.4 数组集合参数
常用于多选框的时候,使用数组或者集合。【前端发送过来的多个键名字是一样的时候】
数组参数:请求参数名与形参数组名称相同且请求参数为多个,定义数组类型形参即可接收参数
@RequestMapping("/arrayParam")
public String arrayParamMtd(@RequestParam(name = "hobby") String[] arr) {
System.out.println(Arrays.toString(arr));
return "OK";
}
集合参数:请求参数名与形参集合名称相同且请求参数为多个,@RequestParam 绑定参数关系
@RequestMapping("/listParam")
public String listParamMtd(@RequestParam(name = "hobby") List<String> hobby) {
System.out.println(hobby);
return "OK";
}
1.5 日期参数
日期参数:需要使用@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") 指定时间的格式
// 日期+时间
@RequestMapping("/dateParam")
public String dateParamMtd(@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") @RequestParam(name = "updateTime") LocalDateTime ldt){
System.out.println(ldt);
return "OK";
}
//仅日期
@RequestMapping("/dateParam")
public String dateParamMtd(@DateTimeFormat(pattern = "yyyy-MM-dd") @RequestParam(name = "updateTime") LocalDate ldt) {
System.out.println(ldt);
return "OK";
}
1.6 Json参数
JSON参数:JSON数据键名与形参对象属性名相同,定义POJO类型形参即可接收参数,需要使用 @RequestBody 标识, 注意此时的JSON对象位于body中
@RequestMapping("jsonParam")
public String getjson(@RequestBody User user){
System.out.println(user);
return "OK";
}
1.7 路径参数
路径参数:通过请求URL直接传递参数,使用{…}来标识该路径参数,需要使用 @PathVariable 获取路径参数, 注意定义的变量名要和路径中变量名一致
//单层路径
@RequestMapping("/path/{id}")
public String getIdOnce(@PathVariable String id) {
System.out.println(id);
return "OK";
}
//多层路径
@RequestMapping("/path/{id1}/{id2}")
public String getIdTwice(@PathVariable String id1, @PathVariable String id2) {
System.out.println(id1 + " == > " + id2);
return "OK";
}
2 响应
2.1 作用
把后端的数据响应给前端
2.2 @ResponseBody注解
ResponseBody注解可以添加在Controller方法上或者类上, 当添加在类上时, 将自动 给类下的方法附加注解, 从而将方法返回值直接响应,如果返回值类型是 实体对象/集合 ,将会转换为JSON格式响应.
@RestController = @Controller + @ResponseBody ;
2.3 响应的格式
一般为了代码格式统一, 应响应一个Result类, 包括有code(0,1代表状态), msg(String 代表响应信息), data(代表响应数据)
代码实现:
//Result类
public class Result {
// 响应的状态码 0 / 1
private Integer code;
// 响应给前端的信息
private String msg;
// 响应数据
private Object data;
//以下省略JavaBean
public static Result failure(String msg, Object data) {
return new Result(0, msg, data);
}
public static Result uccess(String msg, Object data) {
return new Result(1, msg, data);
}
@RestController
public class responseController {
@RequestMapping("/login")
public Result loginMtd(@RequestParam(name = "name") String username, @RequestParam(name = "password") String password) {
if ("admin".equals(username) && "admin".equals(password)) {
return Result.ok("登陆成功");
} else {
return Result.failure("失败");
}
}
}
3 分层解耦
3.1 三层架构
/\ Controller:控制层,接收前端发送的请求,对请求进行处理,并响应数据。 /\ Service:业务逻辑层,处理具体的业务逻辑。 /\ DAO:数据访问层(Data Access Object)(持久层),负责数据访问操作,包括数据的增、删、改、查。
3.2 分层解耦
3.2.1 为什么要分层解耦
/\ 内聚:软件中各个功能模块内部的功能联系。
/\ 耦合:衡量软件中各个层/模块之间的依赖、关联的程度。
==> 软件设计原则:高内聚低耦合
==> 1) 一个类只实现一个功能, 不要new别的对象, 把这个权力交给Spring容器 (IOC))
==> 2) 把容器里的对象给接口去使用 (DI)
3.3 分层解耦的实现方法 - 三层架构
开发顺序: 1) 构建架构
2) controller -> service -> dao
3.3.1 controller
接收请求,响应数据
Controller访问service, 获取处理完的数据
// 接收请求, 响应数据
@RestController
public class EmployeeControllerIocDi {
@Autowired
private EmpServiceImp empService;// = new EmpServiceImp();
@RequestMapping("/listEmp")
public Result listEmployee() {
List list = empService.listEmployee();
return new Result(1, "Success!", list);
}
}
3.3.2 service
指处理业务. 面向接口编程的实现方法 (所以均用多态创建对象), 访问dao, 获取数据, 并对数据进行分析和处理
//接口
public interface EmpService {
public List listEmployee();
}
//service实现类
@Component
public class EmpServiceImp implements EmpService {
@Autowired
private EmpDao empDao; //= new EmpDaoImp();
@Override
public List listEmployee() {
List<Emp> list = empDao.listEmployee();
for (Emp emp : list) {
if ("1".equals(emp.getGender())) {
emp.setGender("男");
} else {
emp.setGender("女");
}
if ("1".equals(emp.getJob())) {
emp.setJob("总经理");
} else if ("2".equals(emp.getJob())) {
emp.setJob("部门主管");
} else {
emp.setJob("组长");
}
}
return list;
}
}
3.3.3 dao
面向接口编程的具体实现方法, 访问数据【包含数据的增删改查】
public interface EmpDao {
public List listEmployee();
}
// 数据访问
@Component
public class EmpDaoImp implements EmpDao {
@Override
public List listEmployee() {
//引入了一个jar包, 通过dom4j读取文档
List list = XmlParserUtils.parse("D:\\code\\Web\\src\\main\\resources\\emp.xml", Emp.class);
return list;
}
}
3.3.4 上述代码利用了以下三种思维
/\ 控制反转: Inversion Of Control,简称IOC。对象的创建控制权由程序自身转移到外部(容器),或把对象的创建权力交给Spring容器, 这种思想称为控制反转。 /\ 依赖注入: Dependency Injection,简称DI。容器为应用程序提供运行时,所依赖的资源,或把容器的对象注入到接口中, 称之为依赖注入。 /\ Bean对象:IOC容器中创建、管理的对象,称之为bean。
3.2.4 IoC
控制反转(Inversion of Control,简称IoC)指把某个对象交给IOC容器管理,将对象的创建、配置、依赖关系的管理等责任从应用程序代码中分离出来,转交给容器来完成的一种机制, 用于实现代码的松耦合和高内聚。需要在对应的类上加上如下注解之一
| 注解 | 说明 | 位置 |
|---|---|---|
| @Component | 声明bean的基础注解 | 不属于以下三类时,用此注解 |
| @Controller | @Component的衍生注解 | 标注在控制器类上 |
| @Service | @Component的衍生注解 | 标注在业务类上 |
| @Repository | @Component的衍生注解 | 标注在数据访问类上(由于与mybatis整合,用的少) |
3.2.5 DI
依赖注入(Dependency Injection,DI)指 IoC 容器通过自动或手动注入对象的方式,解决对象之间的依赖关系。它会自动将依赖的对象注入到目标对象中,使得目标对象可以直接使用这些依赖对象。
-
@Autowired用于自动装配Bean,通过根据类型匹配进行依赖注入。
-
@Component是通用的Spring组件注解,被标记的类会被自动注册为Bean。
-
@Service是用于标识服务层组件的特殊@Component注解。
-
@Repository是用于标识数据访问层组件的特殊@Component注解。
总的来说, IoC(Inversion of Control,控制反转)容器用于管理和组织应用程序中的对象(或称为 Bean)。它负责创建和管理这些对象的生命周期,并处理它们之间的依赖关系 (这时需要通过DI注入依赖)。
IoC 容器的主要作用是实现对象的控制权反转,即将对象的创建和依赖关系的管理交给容器来完成,而不是由应用程序代码显式地创建和管理对象。这样可以降低对象之间的耦合度,提高代码的可维护性和扩展性。
3.2.7 Bean重复的解决办法
如果同类型的bean存在多个: @Primary @Autowired + @Qualifier("bean的名称") @Resource(name="bean的名称")
添加bean名称从一定程度上增大了耦合
4 前后端分工
4.1 前端
1) 发送请求
2) 获取服务器返回的数据, 并做处理
4.2 后端
1) 接收请求
2) 从文件/数据库中先获取数据
3) 再对数据进行处理
4) 再把处理完的数据响应给前端