从基础到实战,涵盖MyBatis-Plus、Spring Cloud Gateway、Lucene、Elasticsearch、Redis、Quartz等核心技术
目录
- MyBatis-Plus核心使用
- Spring事务管理
- Maven多模块与依赖管理
- Spring Cloud Gateway网关详解
- Lucene全文检索原理
- Elasticsearch分布式搜索引擎
- Redis与限流
- Quartz任务调度
- 分布式共识算法
- 日常开发实用技巧
1. MyBatis-Plus核心使用
1.1 ServiceImpl与IService原理
MyBatis-Plus提供了三层架构设计,让开发变得极其高效:
- IService接口:业务接口层,定义规范
- ServiceImpl实现类:业务实现层,实现通用CRUD
- BaseMapper接口:数据访问层,执行SQL
泛型参数详解
java
public class ServiceImpl<M extends BaseMapper<T>, T> implements IService<T>
| 泛型 | 含义 | 示例 |
|---|---|---|
| M extends BaseMapper | 具体的Mapper类型 | UserMapper |
| T | 实体类类型 | User |
实际使用示例
java
// 1. 实体类
@Data
@TableName("user")
public class User {
@TableId(type = IdType.AUTO)
private Long id;
private String name;
private Integer age;
}
// 2. Mapper接口
@Mapper
public interface UserMapper extends BaseMapper<User> {
@Select("SELECT * FROM user WHERE age > #{age}")
List<User> selectByAge(@Param("age") Integer age);
}
// 3. Service接口
public interface UserService extends IService<User> {
User findByName(String name);
}
// 4. Service实现
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
@Override
public User findByName(String name) {
return this.lambdaQuery()
.eq(User::getName, name)
.one();
}
}
1.2 LambdaQueryWrapper对比QueryWrapper
| 特性 | QueryWrapper | LambdaQueryWrapper |
|---|---|---|
| 字段引用方式 | 字符串(如"name") | Lambda方法引用(如User::getName) |
| 编译期检查 | 不检查,运行时才报错 | 编译期检查,IDE提示 |
| 代码重构 | 字段改名需手动修改 | IDE自动同步 |
| 多表联查 | 支持 | 不支持 |
推荐使用LambdaQueryWrapper
java
// 使用QueryWrapper - 字段名用字符串,容易写错
QueryWrapper<User> qw = new QueryWrapper<>();
qw.eq("name", "张三");
// 使用LambdaQueryWrapper - 类型安全,推荐
LambdaQueryWrapper<User> lqw = new LambdaQueryWrapper<>();
lqw.eq(User::getName, "张三")
.like(User::getAge, 18)
.orderByDesc(User::getCreateTime);
1.3 条件构建器的使用场景
Wrapper条件构建器推荐在Service层使用:
java
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
// 推荐:Service层构建Wrapper,封装查询逻辑
public List<User> findUsersByCondition(String name, Integer minAge) {
LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
wrapper.like(StringUtils.hasText(name), User::getName, name)
.ge(minAge != null, User::getAge, minAge);
return this.list(wrapper);
}
}
1.4 分页插件配置
java
@Configuration
public class MybatisPlusConfig {
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
// 添加分页插件
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
// 可添加其他插件:乐观锁、防全表更新等
return interceptor;
}
}
2. Spring事务管理
2.1 TransactionAspectSupport手动回滚
在Transactional方法中,如果吞掉了异常,需要手动标记回滚:
java
@Service
public class OrderService {
@Transactional
public void createOrder() {
try {
orderDao.insert(order);
inventoryDao.deduct(stock);
} catch (Exception e) {
// 记录日志
// 手动标记事务为回滚
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
}
}
}
2.2 TransactionTemplate编程式事务
对于复杂的事务逻辑,使用TransactionTemplate更灵活:
java
@Service
public class UserService {
@Autowired
private TransactionTemplate transactionTemplate;
public User updateUser(Long userId, String newName) {
return transactionTemplate.execute(new TransactionCallback<User>() {
@Override
public User doInTransaction(TransactionStatus status) {
User user = userDao.findById(userId);
user.setName(newName);
userDao.update(user);
return user;
}
});
}
}
对比总结
| 特性 | Transactional | TransactionAspectSupport | TransactionTemplate |
|---|---|---|---|
| 本质 | 声明式事务 | 声明式事务的辅助工具 | 编程式事务 |
| 控制粒度 | 方法级别 | 方法内部代码块 | 方法内部代码块 |
| 代码侵入 | 低 | 低 | 较高 |
| 适用场景 | 绝大多数场景 | 局部精细化控制 | 复杂事务逻辑 |
3. Maven多模块与依赖管理
3.1 dependencies对比dependencyManagement
| 标签 | 作用 | 子模块是否继承 |
|---|---|---|
| dependencies | 实际引入Jar包 | 强制继承 |
| dependencyManagement | 仅声明版本,不引入Jar包 | 不继承,需显式声明 |
3.2 父工程配置示例
xml
<!-- 父工程 pom.xml -->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.1.6</version>
</parent>
<properties>
<java.version>17</java.version>
<spring-cloud.version>2022.0.3</spring-cloud.version>
<mybatis.version>3.0.3</mybatis.version>
</properties>
<!-- 直接引入 - 子模块自动继承 -->
<dependencies>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
<!-- 版本管理 - 子模块需显式声明 -->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>${mybatis.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
3.3 子模块引用
xml
<!-- 子模块无需写版本号,从父工程继承 -->
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
</dependency>
</dependencies>
3.4 Maven私服配置
settings.xml配置
xml
<settings>
<!-- 镜像:拦截所有请求到私服 -->
<mirrors>
<mirror>
<id>my-nexus</id>
<mirrorOf>*</mirrorOf>
<url>http://nexus-server:8081/repository/maven-public/</url>
</mirror>
</mirrors>
<!-- 认证:用于上传构件 -->
<servers>
<server>
<id>my-nexus</id>
<username>admin</username>
<password>your-password</password>
</server>
</servers>
</settings>
项目pom.xml配置发布地址
xml
<distributionManagement>
<repository>
<id>my-nexus</id>
<url>http://nexus-server:8081/repository/maven-releases/</url>
</repository>
<snapshotRepository>
<id>my-nexus</id>
<url>http://nexus-server:8081/repository/maven-snapshots/</url>
</snapshotRepository>
</distributionManagement>
4. Spring Cloud Gateway网关详解
4.1 核心路由配置
yaml
server:
port: 10030
spring:
application:
name: gateway
cloud:
nacos:
discovery:
server-addr: 110.41.51.65:10020
gateway:
routes:
- id: product-service
uri: lb://product-service
predicates:
- Path=/product/**
filters:
- AddRequestParameter=userName, bite
- StripPrefix=1
4.2 时间断言(After/Before/Between)
yaml
predicates:
- Path=/product/**
- After=2025-01-01T00:00:00+08:00[Asia/Shanghai]
时间格式说明:
- After:在指定时间之后生效
- Before:在指定时间之前生效
- Between:在指定时间范围内生效
4.3 限流过滤器(RequestRateLimiter)
yaml
filters:
- name: RequestRateLimiter
args:
redis-rate-limiter.replenishRate: 10
redis-rate-limiter.burstCapacity: 20
redis-rate-limiter.requestedTokens: 1
key-resolver: "#{@userKeyResolver}"
自定义KeyResolver
java
@Component
public class UserKeyResolver implements KeyResolver {
@Override
public Mono<String> resolve(ServerWebExchange exchange) {
String userId = exchange.getRequest().getHeaders().getFirst("user-id");
if (userId == null) {
userId = exchange.getRequest().getRemoteAddress()
.getAddress().getHostAddress();
}
return Mono.just(userId);
}
}
4.4 重试过滤器(Retry)
yaml
filters:
- name: Retry
args:
retries: 3
statuses: BAD_REQUEST
methods: GET,POST
series: SERVER_ERROR
backoff:
firstBackoff: 50ms
maxBackoff: 500ms
factor: 2
4.5 自定义GatewayFilter
java
@Component
public class CustomLogGatewayFilterFactory
extends AbstractGatewayFilterFactory<CustomLogGatewayFilterFactory.Config> {
@Override
public GatewayFilter apply(Config config) {
return (exchange, chain) -> {
// 前置处理
long startTime = System.currentTimeMillis();
String path = exchange.getRequest().getPath().value();
log.info("请求开始: {}", path);
return chain.filter(exchange).then(
Mono.fromRunnable(() -> {
// 后置处理
long elapsed = System.currentTimeMillis() - startTime;
log.info("请求完成: {}, 耗时: {}ms", path, elapsed);
})
);
};
}
@Data
public static class Config {
private String logLevel = "INFO";
private boolean enableTrace = false;
}
}
4.6 Actuator监控配置
properties
# 开启Gateway指标
spring.cloud.gateway.metrics.enabled=true
# Actuator端点配置
management.endpoints.web.exposure.include=health,info,metrics,gateway
management.endpoint.health.show-details=always
management.endpoint.shutdown.enabled=false
# 自定义端点路径
management.endpoints.web.base-path=/management
4.7 配置文件格式转换
YAML转Properties规则:缩进层级变为点分隔符
yaml
# YAML格式
spring:
cloud:
gateway:
routes:
- id: product-service
uri: lb://product-service
properties
# Properties格式
spring.cloud.gateway.routes[0].id=product-service
spring.cloud.gateway.routes[0].uri=lb://product-service
5. Lucene全文检索原理
5.1 核心概念:倒排索引
Lucene的核心是倒排索引(Inverted Index):
| 正排索引 | 倒排索引 |
|---|---|
| 文档1 -> 内容A | 关键词X -> 文档1, 文档3 |
| 文档2 -> 内容B | 关键词Y -> 文档2, 文档4 |
| 文档3 -> 内容A | 关键词Z -> 文档1, 文档2, 文档5 |
5.2 索引建立流程
原始文档 -> 分析器(Analyzer)-> 倒排索引
分析器处理流程:
- Tokenizer(分词):将文本切分成最小单位
- TokenFilter(词项过滤器链):小写转换、停用词过滤、同义词扩展、词干提取
- 输出词项(Term)
5.3 搜索流程示例
java
// 1. 打开索引库
Directory directory = FSDirectory.open(Paths.get("D:\\lucene"));
IndexReader indexReader = DirectoryReader.open(directory);
IndexSearcher indexSearcher = new IndexSearcher(indexReader);
// 2. 创建查询解析器
QueryParser parser = new QueryParser("content", new SmartChineseAnalyzer());
Query query = parser.parse("浓眉");
// 3. 执行搜索
TopDocs docs = indexSearcher.search(query, 10);
System.out.println("总条数: " + docs.totalHits);
// 4. 处理结果
for (ScoreDoc scoreDoc : docs.scoreDocs) {
Document doc = indexReader.document(scoreDoc.doc);
System.out.println("标题: " + doc.get("title"));
System.out.println("得分: " + scoreDoc.score);
}
5.4 分析器规则
原始文本: "浓眉大眼的詹姆斯今天得了30分"
分词器处理: "浓眉", "大眼", "詹姆斯", "今天", "得了", "30", "分"
过滤处理: 停用词("的", "了")被移除
最终词项: "浓眉", "大眼", "詹姆斯", "今天", "30", "分"
重要规则:索引时的分析器和搜索时的分析器必须一致
5.5 BM25评分算法
Lucene默认使用BM25算法计算相关性得分:
Score = IDF * (TF * (k1 + 1)) / (TF + k1 * (1 - b + b * (fieldLen / avgFieldLen)))
| 因素 | 说明 | 影响 |
|---|---|---|
| TF(词频) | 搜索词在文档中出现的次数 | 越多得分越高 |
| IDF(逆文档频率) | 搜索词在所有文档中的稀有程度 | 越稀有得分越高 |
| 字段长度 | 当前字段的长度 | 越短得分越高 |
5.6 Lucene对比Elasticsearch
| 特性 | Lucene | Elasticsearch |
|---|---|---|
| 本质 | Java库(Library) | 分布式搜索引擎(Server) |
| 使用方式 | 编写Java代码 | RESTful API |
| 分布式 | 需自己实现 | 原生支持 |
| 适用场景 | 嵌入式搜索 | 海量数据搜索、日志分析 |
6. Elasticsearch分布式搜索引擎
6.1 核心概念类比
| Elasticsearch | 关系数据库 (MySQL) |
|---|---|
| 索引 (Index) | 数据库 (Database) |
| 映射 (Mapping) | 表结构 (Schema) |
| 文档 (Document) | 行 (Row) |
| 字段 (Field) | 列 (Column) |
6.2 字段类型
json
{
"mappings": {
"properties": {
"name": { "type": "text" },
"status": { "type": "keyword" },
"age": { "type": "integer" },
"price": { "type": "float" },
"createTime": { "type": "date" },
"address": { "type": "object" },
"tags": { "type": "keyword" }
}
}
}
6.3 Java客户端使用
java
// 1. 创建客户端
RestClient restClient = RestClient.builder(
new HttpHost("localhost", 9200, "http")).build();
ElasticsearchTransport transport = new RestClientTransport(
restClient, new JacksonJsonpMapper());
ElasticsearchClient client = new ElasticsearchClient(transport);
// 2. 索引文档
Product product = new Product("1", "华为Mate 70", 7999.00);
client.index(i -> i
.index("products")
.id(product.getId())
.document(product)
);
// 3. 搜索文档
var response = client.search(s -> s
.index("products")
.query(q -> q
.match(t -> t
.field("name")
.query("华为")
)
),
Product.class
);
6.4 Spring Data Elasticsearch
java
@Document(indexName = "products")
public class Product {
@Id
private String id;
private String name;
private double price;
}
public interface ProductRepository extends ElasticsearchRepository<Product, String> {
List<Product> findByNameContaining(String keyword);
}
7. Redis与限流
7.1 配置
properties
# Redis连接配置
spring.data.redis.host=localhost
spring.data.redis.port=6379
spring.data.redis.database=0
spring.data.redis.password=
# Jedis连接池
spring.redis.jedis.pool.max-active=8
spring.redis.jedis.pool.max-idle=8
spring.redis.jedis.pool.min-idle=0
spring.redis.jedis.pool.max-wait=-1
7.2 令牌桶限流原理
| 参数 | 说明 |
|---|---|
| replenishRate | 每秒生成的令牌数(稳定速率) |
| burstCapacity | 令牌桶容量(最大突发请求数) |
| requestedTokens | 每个请求消耗的令牌数 |
限流效果示例:replenishRate=10,burstCapacity=20,requestedTokens=1
- 瞬间可处理20个请求(桶内令牌)
- 长期稳定在10个/秒
8. Quartz任务调度
8.1 三大核心组件
| 组件 | 作用 | 类比 |
|---|---|---|
| Job & JobDetail | 定义任务逻辑(做什么) | 工作内容 |
| Trigger | 定义执行时间(何时做) | 闹钟 |
| Scheduler | 调度器(总调度室) | 总指挥 |
8.2 使用示例
java
// 1. 定义任务
public class MyJob implements Job {
@Override
public void execute(JobExecutionContext context) {
System.out.println("执行任务: " + new Date());
}
}
// 2. 创建JobDetail
JobDetail job = JobBuilder.newJob(MyJob.class)
.withIdentity("job1", "group1")
.build();
// 3. 创建Trigger(每2秒执行一次)
Trigger trigger = TriggerBuilder.newTrigger()
.withIdentity("trigger1", "group1")
.withSchedule(CronScheduleBuilder.cronSchedule("0/2 * * * * ?"))
.build();
// 4. 注册到Scheduler
Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
scheduler.scheduleJob(job, trigger);
scheduler.start();
8.3 Quartz对比Spring Task对比分布式调度
| 特性 | Quartz | Spring Scheduled | XXL-JOB / Elastic-Job |
|---|---|---|---|
| 集群支持 | 支持 | 不支持 | 支持 |
| 任务持久化 | 支持 | 不支持 | 支持 |
| 可视化UI | 不支持 | 不支持 | 支持 |
| 任务分片 | 不支持 | 不支持 | 支持 |
| 适用场景 | 企业级应用 | 简单定时任务 | 大型分布式系统 |
9. 分布式共识算法
9.1 Raft算法
Raft将共识问题拆分为三个子问题:
- 领导者选举(Leader Election)
- 日志复制(Log Replication)
- 安全性(Safety)
三种节点角色
| 角色 | 职责 |
|---|---|
| Leader(领导者) | 处理客户端请求,同步日志到Followers |
| Follower(跟随者) | 被动接收Leader的日志复制和心跳 |
| Candidate(候选者) | 选举期间的角色,向其他节点拉票 |
选举规则
- 获得超过半数节点投票的Candidate成为Leader
- 每个节点每个任期(Term)只能投一票
- 选举超时时间随机(避免选票分裂)
9.2 Redis与Raft的关系
| 特性 | Redis Cluster | RedisRaft(模块) |
|---|---|---|
| 核心算法 | Gossip协议 + 自研故障转移 | Raft共识算法 |
| 目标 | 高可用 + 高性能 + 水平扩展 | 强一致性 + 数据安全 |
| 一致性模型 | 最终一致性 | 强一致性 |
| 适用场景 | 缓存、高吞吐场景 | 配置管理、分布式锁 |
10. 日常开发实用技巧
10.1 try-with-resources资源管理
java
// try-with-resources(简洁安全)
try (BufferedReader reader = new BufferedReader(new FileReader("test.txt"))) {
String line = reader.readLine();
System.out.println(line);
} catch (IOException e) {
e.printStackTrace();
}
// 资源自动关闭,无需finally
10.2 ObjectMapper JSON处理
java
ObjectMapper mapper = new ObjectMapper();
// 对象转JSON
User user = new User(1L, "张三", 25);
String json = mapper.writeValueAsString(user);
// JSON转对象
User user2 = mapper.readValue(json, User.class);
// JSON数组转List
List<User> users = mapper.readValue(jsonArray,
new TypeReference<List<User>>() {});
// 常用注解
@JsonProperty("user_name") // 指定JSON字段名
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") // 日期格式
@JsonIgnore // 忽略字段
@JsonIgnoreProperties(ignoreUnknown = true) // 忽略未知字段
10.3 PathVariable对比RequestParam
java
// PathVariable:从URL路径取
// URL: /users/123
@GetMapping("/users/{id}")
public User getUser(@PathVariable Long id) { ... }
// RequestParam:从查询字符串取
// URL: /users?page=1&size=10
@GetMapping("/users")
public List<User> getUsers(@RequestParam int page,
@RequestParam int size) { ... }
10.4 SuppressWarnings使用
java
// 消除未检查类型转换警告
@SuppressWarnings("unchecked")
public List<String> convertToList(Object obj) {
return (List<String>) obj;
}
// 常用参数
// "unchecked" - 未检查的类型转换
// "unused" - 未使用的变量/方法
// "deprecation" - 使用过时方法
// "rawtypes" - 未指定泛型
// "serial" - 缺少serialVersionUID
10.5 GPG签名
GPG是OpenPGP标准的开源实现,用于数字签名和数据加密:
bash
# 生成密钥对
gpg --full-generate-key
# 导出公钥
gpg --export --armor YOUR_KEY_ID > public-key.asc
# 签名文件
gpg --sign --armor document.txt
# 验证签名
gpg --verify document.txt.asc document.txt
应用场景:
- 向Maven中央仓库发布制品
- Git提交签名(显示Verified标识)
- 验证下载软件的真伪
10.6 SSL证书
SSL证书 = 数字身份证 + 加密钥匙
| 证书类型 | 验证级别 | 适用场景 |
|---|---|---|
| DV(域名验证型) | 验证域名所有权 | 个人博客 |
| OV(组织验证型) | 验证域名 + 组织信息 | 企业官网 |
| EV(扩展验证型) | 最严格验证 | 银行、金融机构 |
HTTPS中的S是Secure(安全),而SSL证书是实现安全的手段。
总结
本文涵盖了从MyBatis-Plus的ORM框架使用,到Spring Cloud Gateway的网关配置,再到Lucene/Elasticsearch的全文检索原理,以及Redis限流、Quartz调度、分布式共识算法等核心技术。这些技术共同构成了现代Java微服务架构的技术栈基础。
掌握这些技术的核心原理和最佳实践,是构建高可用、高性能分布式系统的基础。
本文档基于真实项目实践整理,持续更新中。