本文是对黑马程序员的java web部分课程的一个总结,课程视频链接如下:
黑马程序员2023新版JavaWeb开发教程,实现javaweb企业开发全流程
SpringBootWeb开发涉及到很多注解,有时候很难记忆,本文主要通过理清思路的过程来对这些注解进行记忆,同时是对课程的部分总结。
0 先写总结
注解 | 说明 |
---|---|
@RestController | 表明这是一个请求处理类 |
@PathVariable | 获取路径参数 |
@RequestBody | 将JSON数据映射到形参的实体类对象中(JSON中的key和实体类中的属性名保持一致) |
@RequestParam(defaultValue=“默认值”) | 设置请求参数默认值 |
@DateTimeFormat(pattern = “yyyy-MM-dd”) | 指定前端传递过来的时间的格式 |
@RequestMapping | 表明用来处理哪个请求路径 |
@GetMapping | RequestMapping的衍生注解,直接指明是get请求 |
控制反转:@Component | 声明bean的基础注解,不属于以下三类时,用此注解 |
控制反转:@Controller | @Component的衍生注解,标注在控制器类上 |
控制反转: @Service | @Component的衍生注解 标注在业务类上 |
控制反转:@Repository | @Component的衍生注解 标注在数据访问类上(由于与mybatis整合,用的少) |
依赖注入:@Autowired | 默认是按照类型进行自动装配的(去IOC容器中找某个类型的对象,然后完成注入操作) |
依赖注入:@Primary | 当存在多个相同类型的Bean注入时,加上@Primary注解,来确定默认的实现 |
依赖注入:@Qualifier | 指定当前要注入的bean对象。 在@Qualifier的value属性中,指定注入的bean的名称。 @Qualifier注解不能单独使用,必须配合@Autowired使用 |
依赖注入:@Resource | 是按照bean的名称进行注入。通过name属性指定要注入的bean的名称 |
@Slf4j | 会自动生成Logger对象,对象名是log |
@Value,具体用法为: @Value(“${配置文件中的key}”) | 获取配置文件中的数据,通常用于外部配置的属性注入,只能一个一个的进行外部属性的注入 |
@ConfigurationProperties`注解,并通过perfect属性来指定配置参数项的前缀 | 可以批量的将外部的属性配置注入到bean对象的属性中 |
1. SpringBoot Web的Hello world
首先,web开发就是浏览器向服务器发送请求,然后服务器对请求进行响应的过程。
任何编程的学习都要从最简单的hello world开始,SpringBoot Web的Hello world程序构建过程如下:
- 第1步:创建SpringBoot工程项目 -
- 第2步:定义HelloController类,添加方法hello,并添加注解
- 第3步:测试运行
如果是用maven进行开发,那么工程的结构如下:
可以看到这是maven工程构架,在所创建的pakage下有主函数和请求处理类。请求处理类的代码如下:
package com.itheima.controller;
import org.springframework.web.bind.annotation.*;
@RestController
public class HelloController {
@RequestMapping("/hello")
public String hello(){
System.out.println("Hello World ~");
return "Hello World ~";
}
}
请求处理类就是接收到请求后做的处理,然后将结果返回给浏览器。这里有两个问题:
1)如何表明这是一个请求处理类
2)请求路径有很多,一个请求路径对应一个处理。如何确定是对哪个请求路径做的处理
这就是上面两个注解的作用:
注解@RestController表明这是一个请求处理类
注解 @RequestMapping表明用来处理哪个请求路径
2.分层解耦
上面的Helloworld程序结构比较简单,我们看到从接收请求到返回响应,这个过程中的处理都是在请求处理类中进行的,比如讲义中的案例:
如果业务逻辑再稍微复杂一点,会看到Controller方法的代码量就很大了。
- 当我们要修改操作数据部分的代码,需要改动Controller
- 当我们要完善逻辑处理部分的代码,需要改动Controller
- 当我们需要修改数据响应的代码,还是需要改动Controller
这样会造成整个工程代码的复用性比较差,而且代码难以维护。 如何解决这个问题呢?其实在现在的开发中,有非常成熟的解决思路,那就是分层开发。
其实我们上述案例的处理逻辑呢,从组成上看可以分为三个部分:
- 数据访问:负责业务数据的维护操作,包括增、删、改、查等操作。
- 逻辑处理:负责业务逻辑处理的代码。
- 请求处理、响应数据:负责,接收页面的请求,给页面响应数据。
按照上述的三个组成部分,在我们项目开发中呢,可以将代码分为三层:
- Controller:控制层。接收前端发送的请求,对请求进行处理,并响应数据。
- Service:业务逻辑层。处理具体的业务逻辑。
- Dao:数据访问层(Data Access Object),也称为持久层。负责数据访问操作,包括数据的增、删、改、查。
基于三层架构的程序执行流程:
- 前端发起的请求,由Controller层接收(Controller响应数据给前端)
- Controller层调用Service层来进行逻辑处理(Service层处理完后,把处理结果返回给Controller层)
- Serivce层调用Dao层(逻辑处理过程中需要用到的一些数据要从Dao层获取)
- Dao层操作文件中的数据(Dao拿到的数据会返回给Service层)
如果按照上面的思想改造之前的代码如下:
首先代码结构上,把三个层分开,然后每个层代码如下:
虽然这样代码之间分层了,但是依然存在一定的耦合。
3 控制反转和依赖注入
所以问题是如何解耦。就是控制反转和依赖注入(IOC & DI)
3.1 控制反转
关于控制反转的注解
3.2 依赖注入
依赖注入,是指IOC容器要为应用程序去提供运行时所依赖的资源,而资源指的就是对象。
在入门程序案例中,我们使用了@Autowired这个注解,完成了依赖注入的操作,而这个Autowired翻译过来叫:自动装配。
@Autowired注解,默认是按照类型进行自动装配的(去IOC容器中找某个类型的对象,然后完成注入操作)
那如果在IOC容器中,存在多个相同类型的bean对象,程序会报错。如何解决上述问题呢?Spring提供了以下几种解决方案:
-
@Primary:使用@Primary注解:当存在多个相同类型的Bean注入时,加上@Primary注解,来确定默认的实现
-
@Qualifier:使用@Qualifier注解:指定当前要注入的bean对象。 在@Qualifier的value属性中,指定注入的bean的名称。 @Qualifier注解不能单独使用,必须配合@Autowired使用
-
@Resource:使用@Resource注解:是按照bean的名称进行注入。通过name属性指定要注入的bean的名称。