《JAVA八股真解》八、服务框架
#JAVA##JAVA面经##JAVA内推#
1. MyBatis 是什么?有什么优势?
MyBatis 是一个优秀的持久层框架,它支持定制化 SQL、存储过程以及高级映射。
核心特性:
- SQL 映射:将 SQL 语句与 Java 方法绑定,实现灵活的数据库操作。
- 动态 SQL:支持
if、choose、foreach等标签,编写复杂查询。 - 结果映射:通过
resultMap将数据库字段映射到 Java 对象。 - 缓存机制:提供一级缓存(Session)和二级缓存(Mapper),提升查询性能。
优点:
- 轻量级,易于集成。
- SQL 可读性强,便于调试。
- 支持自定义 SQL,灵活性高。
缺点:
- 需要手动编写 SQL,维护成本较高。
- 不适合复杂业务逻辑。
2. MyBatis 的核心组件
MyBatis 主要由以下几部分组成:
- SqlSessionFactoryBuilder:用于创建
SqlSessionFactory。 - SqlSessionFactory:创建
SqlSession的工厂类。 - SqlSession:执行 SQL 操作的核心接口,包含
selectOne()、selectList()、insert()、update()、delete()等方法。 - Executor:执行器,负责 SQL 的执行和结果处理。
- StatementHandler:处理 SQL 语句的生成和执行。
- ParameterHandler:处理参数绑定。
- ResultSetHandler:处理查询结果集。
流程简述:
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader);
SqlSession session = factory.openSession();
try {
User user = session.selectOne("com.example.UserMapper.selectById", 1);
} finally {
session.close();
}
3. ResultType 和 ResultMap 的区别
| 特性 | ResultType | ResultMap |
|---|---|---|
| 用途 | 直接映射简单类型(如 String、Integer)或 POJO 类型 | 处理复杂映射关系,如嵌套对象、关联查询 |
| 配置方式 | 在 <select> 标签中使用 resultType="xxx" |
使用 <resultMap> 定义映射规则 |
| 灵活性 | 简单,适用于一对一映射 | 强大,支持一对多、多对一等复杂关系 |
示例:
<!-- ResultType -->
<select id="selectUser" resultType="com.example.User">
SELECT id, name FROM user WHERE id = #{id}
</select>
<!-- ResultMap -->
<resultMap id="userResultMap" type="com.example.User">
<id property="id" column="id"/>
<result property="name" column="name"/>
<collection property="orders" ofType="com.example.Order">
<id property="id" column="order_id"/>
<result property="amount" column="amount"/>
</collection>
</resultMap>
建议:
- 简单场景使用
resultType。 - 复杂场景使用
resultMap。
4. MyBatis Plus 的常用注解
MyBatis Plus 是 MyBatis 的增强工具,提供了丰富的注解简化开发。
| 注解 | 说明 |
|---|---|
@TableName |
指定实体类对应的数据库表名 |
@TableId |
指定主键字段,支持自增、UUID、雪花算法等 |
@TableField |
指定字段与数据库列的映射关系 |
@Version |
实现乐观锁,自动更新版本号 |
@TableLogic |
实现逻辑删除,标记为“已删除”而非物理删除 |
示例:
@TableName("user")
public class User {
@TableId(value = "id", type = IdType.AUTO)
private Long id;
@TableField("name")
private String name;
@Version
private Integer version;
@TableLogic
private Boolean deleted;
}
5. MyBatisPlus 的常用注解
MyBatis Plus 提供了多种注解,简化 CRUD 操作。
- @TableName:指定表名。
- @TableId:指定主键,支持自增、UUID、雪花算法。
- @TableField:指定字段映射。
- @Version:实现乐观锁。
- @TableLogic:实现逻辑删除。
优势:
- 减少 XML 配置,提高开发效率。
- 支持通用 CRUD 方法,无需手动编写 SQL。
6. Spring Boot 是什么?
Spring Boot 是 Spring 的子项目,旨在简化 Spring 应用的初始搭建和开发过程。
核心特性:
- 自动配置:根据依赖自动配置组件。
- 起步依赖:简化 Maven/Gradle 配置。
- 内嵌服务器:支持 Tomcat、Jetty 等,无需部署 WAR 包。
- Actuator:提供生产级监控和管理功能。
优点:
- 快速启动,减少配置。
- 内置大量常用功能,开箱即用。
7. Spring Boot 的启动方式
Spring Boot 支持多种启动方式:
- IDE 启动:直接运行
main方法。 - Maven/Gradle 命令:
mvn spring-boot:run ./gradlew bootRun - 打包运行:
java -jar myapp.jar
建议:生产环境推荐使用
jar包方式部署。
8. Spring Boot 的常用注解
| 注解 | 说明 |
|---|---|
@SpringBootApplication |
启动类注解,包含 @Configuration、@EnableAutoConfiguration、@ComponentScan |
@RestController |
标记控制器类,返回 JSON 数据 |
@RequestMapping |
映射请求路径 |
@GetMapping |
映射 GET 请求 |
@PostMapping |
映射 POST 请求 |
@RequestBody |
绑定请求体数据 |
@ResponseBody |
返回响应体数据 |
示例:
@RestController
@RequestMapping("/api")
public class UserController {
@GetMapping("/users/{id}")
public User getUser(@PathVariable Long id) {
return userService.findById(id);
}
}
9. Spring Boot 的自动配置原理
Spring Boot 的自动配置基于 @Conditional 注解实现。
- 条件判断:根据类路径、配置文件、Bean 存在与否等条件决定是否启用某个配置。
- 自动配置类:位于
META-INF/spring.factories文件中,定义了所有自动配置类。 - 配置优先级:用户配置 > 自动配置。
示例:
@Configuration
@ConditionalOnClass(DataSource.class)
@EnableConfigurationProperties(DataSourceProperties.class)
public class DataSourceAutoConfiguration {
// ...
}
10. Spring Boot 的核心组件
- Spring Boot Starter:提供一组预定义的依赖组合。
- Spring Boot Autoconfigure:自动配置组件。
- Spring Boot Actuator:监控和管理功能。
- Spring Boot DevTools:开发工具支持热部署。
优势:
- 快速集成第三方库。
- 减少手动配置。
11. Spring Boot 的日志框架
Spring Boot 默认使用 SLF4J + Logback,支持多种日志级别:
TRACEDEBUGINFOWARNERROR
配置方式:
logging:
level:
com.example: DEBUG
file:
name: logs/app.log
12. @Resource 和 @Autowired 的区别
| 特性 | @Resource | @Autowired |
|---|---|---|
| 来源 | JSR-250 规范 | Spring 框架 |
| 默认行为 | 按名称注入 | 按类型注入 |
| 可选性 | 支持 required=false |
支持 required=false |
| 适用范围 | 所有 Java EE 容器 | Spring 容器 |
建议:
- 使用
@Autowired更符合 Spring 习惯。 - 若需按名称注入,使用
@Resource(name="xxx")。
13. Spring MVC 的执行流程
Spring MVC 的请求处理流程如下:
- DispatcherServlet 接收请求。
- HandlerMapping 查找处理器。
- HandlerAdapter 调用处理器。
- ViewResolver 解析视图。
- View 渲染并返回响应。
核心组件:
DispatcherServlet:前端控制器。HandlerMapping:处理器映射。HandlerAdapter:处理器适配器。ViewResolver:视图解析器。
14. Spring MVC 的常用注解
| 注解 | 说明 |
|---|---|
@Controller |
标记控制器类 |
@RestController |
标记 RESTful 控制器 |
@RequestMapping |
映射请求路径 |
@GetMapping |
映射 GET 请求 |
@PostMapping |
映射 POST 请求 |
@RequestParam |
绑定请求参数 |
@RequestBody |
绑定请求体 |
@ResponseBody |
返回响应体 |
示例:
@RestController
@RequestMapping("/api")
public class UserController {
@GetMapping("/users/{id}")
public User getUser(@PathVariable Long id) {
return userService.findById(id);
}
}
15. 如何开启 Spring Boot 的 Web 功能?
在 pom.xml 中引入 spring-boot-starter-web 依赖,即可自动启用 Web 功能。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
自动配置:Spring Boot 会自动配置 DispatcherServlet、HandlerMapping 等组件。
16. Spring Boot 的自动配置原理
Spring Boot 的自动配置基于 @Conditional 注解实现。
- 条件判断:根据类路径、配置文件、Bean 存在与否等条件决定是否启用某个配置。
- 自动配置类:位于
META-INF/spring.factories文件中,定义了所有自动配置类。 - 配置优先级:用户配置 > 自动配置。
示例:
@Configuration
@ConditionalOnClass(DataSource.class)
@EnableConfigurationProperties(DataSourceProperties.class)
public class DataSourceAutoConfiguration {
// ...
}
17. Spring Boot 的启动流程
- 加载配置:加载
application.properties或application.yml。 - 创建上下文:初始化
ApplicationContext。 - 扫描组件:扫描包下的组件。
- 自动配置:根据条件启用自动配置。
- 启动应用:启动内嵌服务器,监听端口。
18. Spring Boot 的常见问题
- 无法启动:检查依赖冲突、配置错误。
- 端口被占用:修改
server.port。 - 日志不输出:检查日志配置。
19. Spring Boot 的核心组件
- Spring Boot Starter:提供一组预定义的依赖组合。
- Spring Boot Autoconfigure:自动配置组件。
- Spring Boot Actuator:监控和管理功能。
- Spring Boot DevTools:开发工具支持热部署。
优势:
- 快速集成第三方库。
- 减少手动配置。
20. Spring Cloud 是什么?
Spring Cloud 是一系列微服务开发工具的集合,提供服务发现、配置管理、负载均衡、熔断器等功能。
核心组件:
- Eureka:服务注册与发现。
- Config:集中化配置管理。
- Feign:声明式 HTTP 客户端。
- Hystrix:熔断器。
- Zuul:API 网关。
- Gateway:新一代 API 网关。
21. Spring Cloud 有哪些组件?
| 组件 | 功能 |
|---|---|
| Eureka | 服务注册与发现 |
| Config | 集中化配置管理 |
| Feign | 声明式 HTTP 客户端 |
| Hystrix | 熔断器 |
| Zuul | API 网关 |
| Gateway | 新一代 API 网关 |
| OpenFeign | 基于 Feign 的增强版 |
22. Eureka 工作原理
Eureka 是 Netflix 开源的服务注册与发现组件,分为两个角色:
- Eureka Server:服务注册中心,维护服务列表。
- Eureka Client:服务提供者或消费者,向 Eureka Server 注册自身信息。
工作流程:
- 服务注册:Client 启动时向 Server 注册。
- 心跳检测:Client 定期发送心跳,Server 判断是否存活。
- 服务发现:Client 从 Server 获取其他服务地址。
- 故障剔除:Server 发现 Client 失效,将其从列表中移除。
23. Nacos 作为注册中心的工作原理
Nacos 是阿里巴巴开源的动态服务发现与配置管理平台,兼具 Eureka 和 Config 的功能。
核心特性:
- 服务注册与发现:支持 DNS 和 RPC 方式。
- 配置管理:支持动态配置推送。
- 健康检查:支持多种探活方式。
优势:
- 功能更强大,支持多协议。
- 适合大规模集群。
24. Nacos 与 Eureka 的区别
| 特性 | Nacos | Eureka |
|---|---|---|
| 一致性模型 | CP(强一致性) | AP(高可用) |
| 配置管理 | 支持 | 不支持 |
| 健康检查 | 支持多种方式 | 支持心跳 |
| 部署复杂度 | 较高 | 较低 |
选择建议:
- 小规模系统:Eureka。
- 大规模系统:Nacos。
25. Feign 工作原理
Feign 是一个声明式的 HTTP 客户端,简化服务调用。
核心流程:
- 定义接口:使用
@FeignClient注解声明远程服务接口。 - 代理生成:Spring Cloud 为接口生成代理对象。
- 请求发送:调用接口方法,自动转换为 HTTP 请求。
- 响应处理:返回结果封装为 Java 对象。
示例:
@FeignClient(name = "user-service")
public interface UserService {
@GetMapping("/users/{id}")
User getUser(@PathVariable Long id);
}
26. Feign 的常用注解
- @FeignClient:声明远程服务接口。
- @RequestMapping:映射请求路径。
- @GetMapping / @PostMapping:映射具体请求方法。
- @RequestParam:绑定请求参数。
- @RequestBody:绑定请求体。
- @ResponseBody:返回响应体。
27. 什么是 Hystrix?
Hystrix 是一个用于实现服务容错和降级的库,在分布式系统中起到保护系统免受服务故障影响的作用。
核心功能:
- 熔断机制:当失败率超过阈值时,快速失败,避免雪崩。
- 降级处理:服务不可用时,返回默认值或缓存数据。
- 隔离机制:限制资源使用,防止连锁反应。
优点:
- 提升系统稳定性。
- 避免服务雪崩。
28. Gateway 网关的特性(作用)
Gateway 是 Spring Cloud 的新一代 API 网关,具备路由、负载均衡、安全认证、限流等功能。
核心特性:
- 路由转发:根据请求路径转发到对应服务。
- 负载均衡:支持多种策略分配流量。
- 安全控制:集成认证与授权机制。
- 限流与熔断:防止系统过载。
- 监控统计:记录请求指标,便于分析。
29. Gateway 的路由断言工厂有哪些?
Spring Cloud Gateway 提供了 11 种基本的路由断言工厂:
| 名称 | 说明 | 示例 |
|---|---|---|
| After | 匹配时间之后的请求 | After=2021-01-20T11:42:47.789-07:00[America/Denver] |
| Before | 匹配时间之前的请求 | Before=2021-04-13T15:14:47.423+00:00[Asia/Shanghai] |
| Between | 匹配时间范围内的请求 | Between=2021-01-20T11:42:47.789-07:00[America/Denver], 2021-01-21T17:42:47.789-07:00[America/Denver] |
| Cookie | 匹配特定 Cookie | Cookie=chocolate, chip |
| Header | 匹配特定 Header | Header=X-Request-Id, Yd |
| Host | 匹配特定 Host | Host="*.somehost.org", anotherhost.org |
| Method | 匹配特定 HTTP 方法 | Method=GET,POST |
| Path | 匹配特定路径 | Path=/red/{segment}, /blue/** |
| Query | 匹配特定查询参数 | Query=name, Jack;age=, Quanyiname |
| RemoteAddr | 匹配特定客户端 IP | RemoteAddr=192.168.1.1/24 |
| Weight | 权重处理 | —— |
30. 事务失效的场景有哪些?
- 非 public 方法上加了事务注解
- 非事务方法调用了事务方法
- 异常被 catch 捕获,没有抛出
- 类上未加 @Service 注解,spring 不会管理组件
- 方法上未加 @Transactional 注解
解决方案:
- 确保事务方法为 public。
- 异常需抛出或重新抛出。
- 使用
@Transactional注解。