1. 创建spring boot项目
File => New Module => Spring Boot

勾选web开发相关依赖: Web => Spring Web
2. 开发步骤
在包下新建 XXController
类前加注解 @RestController
方法前加注解 @RequestMapping("")
启动时,运行SpringBootApplication即可
例子:
package com.itheima;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController //标识当前类是一个请求处理类
public class HelloController {
@RequestMapping("/hello") //标识请求路径
public String hello(String name){
System.out.println("HelloController ... hello: " + name);
return "Hello " + name;
}
}为什么一个SpringBootApplication就可以启动web程序?因为我们在创建springboot项目的时候,选择了web开发的起步依赖 spring-boot-starter-web。而spring-boot-starter-web依赖,又依赖了spring-boot-starter-tomcat,由于maven的依赖传递特性,那么在我们创建的springboot项目中也就已经有了tomcat的依赖,这个其实就是springboot中内嵌的tomcat。 而我们运行引导类中的main方法,其实启动的就是springboot中内嵌的Tomcat服务器。 而我们所开发的项目,也会自动的部署在该tomcat服务器中,并占用8080端口号
RestController注解中 包含有ResonseBody,其作用是将 controller 返回值直接作为响应体的数据,
过程是 controller 返回值 -> json -> 响应体
3. bean对象
@Data:生成 Getter、Setter、toString()、equals()和hashCode()方法。@NoArgsConstructor:生成无参构造函数。@AllArgsConstructor:生成全参构造函数。
4. 三层结构
原始版本的代码逻辑:
接受页面请求,先从数据库中读取数据
对读取的数据进行业务逻辑处理
返回处理好的数据

三层结构设计:

职责分离:每一层只负责特定的功能,职责清晰,便于理解和维护
降低耦合性:各层之间通过接口或依赖注入进行交互,降低了代码的耦合性
便于扩展:当需要新增功能时,可以在不影响其他层的情况下进行扩展
便于测试:每一层可以独立测试,便于定位问题和修复 Bug
4.1 controller层(表示层)
Controller 只负责接收请求和返回响应,不涉及具体的业务逻辑或数据操作
接收用户请求:处理 HTTP 请求(如 GET、POST 等)。
调用 Service 层:将用户请求传递给业务逻辑层进行处理。
返回响应:将处理结果封装成 JSON、HTML 或其他格式,返回给客户端。
4.2 Service 层(业务逻辑层)
处理业务逻辑:实现具体的业务规则和流程。
调用 Dao 层:通过 Dao 层访问数据库或其他数据源。
事务管理:确保业务操作的原子性和一致性。
4.3 Dao 层(数据访问层)
与数据库交互:执行数据的增删改查操作。
封装数据访问细节:隐藏数据库的具体实现(如 SQL 语句、ORM 框架等)。
代码书写逻辑
先写dao层的接口,在impl的实现类中实现该接口的方法,返回读取来的原始数据
在service层中写接口,在impl的实现类中,new一个dao层的对象来调用方法获取原始数据,然后对原始数据进行业务处理,返回处理好的数据
在controller层中,new一个service层的对象来调用方法获取处理好的数据,直接返回给前端
5. 分层解耦
先前代码的缺点: controller层中有 new service层对象的代码,service层有new dao层对象的代码,这样导致三层之间具有耦合性
控制反转: Inversion Of Control,简称IOC。对象的创建控制权由程序自身转移到外部(容器),这种思想称为控制反转。
对象的创建权由程序员主动创建转移到容器(由容器创建、管理对象)。这个容器称为:IOC容器或Spring容器。
依赖注入: Dependency Injection,简称DI。容器为应用程序提供运行时,所依赖的资源,称之为依赖注入。
程序运行时需要某个资源,此时容器就为其提供这个资源。
例:EmpController程序运行时需要EmpService对象,Spring容器就为其提供并注入EmpService对象。
bean对象:IOC容器中创建、管理的对象,称之为:bean对象。
解决方法:将Dao、service层的实现类,交给IOC容器管理(在实现类前加@Component);
为controller、service注入所依赖的对象(在声明变量前加 @Autowired)
5.1 IOC
规范注解:controller层前加 @RestController
service层实现类前加 @Service
dao层实现类前加 @Repository
修改在IOC容器中bean对象的名字:例如@Service("userService")
以上注解要生效,必须由 @ComponentScan 组件来扫描。
application启动类中的 @SpringBootApplication就包含了 @ComponentScan 组件,它会扫描文件所在包及其子包下的所有注解
5.2 DI
1). 属性注入
@RestController
public class UserController {
//方式一: 属性注入
@Autowired
private UserService userService;
}优点:代码简洁、方便快速开发。
缺点:隐藏了类之间的依赖关系、可能会破坏类的封装性。
2). 构造函数注入
@RestController
public class UserController {
//方式二: 构造器注入
private final UserService userService;
@Autowired //如果当前类中只存在一个构造函数, @Autowired可以省略
public UserController(UserService userService) {
this.userService = userService;
}
} 优点:能清晰地看到类的依赖关系、提高了代码的安全性。
缺点:代码繁琐、如果构造参数过多,可能会导致构造函数臃肿。
注意:如果只有一个构造函数,@Autowired注解可以省略。(通常来说,也只有一个构造函数)
3). setter注入
/**
* 用户信息Controller
*/
@RestController
public class UserController {
//方式三: setter注入
private UserService userService;
@Autowired
public void setUserService(UserService userService) {
this.userService = userService;
}
} 优点:保持了类的封装性,依赖关系更清晰。
缺点:需要额外编写setter方法,增加了代码量。
推荐 第一种 和 第二种 方式
存在多个相同类型的bean对象,会报错
解决方案:
方案一:使用@Primary注解
当存在多个相同类型的Bean注入时,加上@Primary注解,来确定优先注入的bean。
@Primary
@Service
public class UserServiceImpl implements UserService {
}方案二:使用@Qualifier注解
指定当前要注入的bean对象。 在@Qualifier的value属性中,指定注入的bean的名称。 @Qualifier注解不能单独使用,必须配合@Autowired使用。
@RestController
public class UserController {
@Qualifier("userServiceImpl")
@Autowired
private UserService userService;方案三:使用@Resource注解
是按照bean的名称进行注入。通过name属性指定要注入的bean的名称。
@RestController
public class UserController {
@Resource(name = "userServiceImpl")
private UserService userService;面试题:@Autowird 与 @Resource的区别
@Autowired 是spring框架提供的注解,而@Resource是JDK提供的注解
@Autowired 默认是按照类型注入,而@Resource是按照名称注入

参与讨论
(Participate in the discussion)
参与讨论