Java微服务与中间件技术 总结

从基础到实战,涵盖MyBatis-Plus、Spring Cloud Gateway、Lucene、Elasticsearch、Redis、Quartz等核心技术

目录

  1. MyBatis-Plus核心使用
  2. Spring事务管理
  3. Maven多模块与依赖管理
  4. Spring Cloud Gateway网关详解
  5. Lucene全文检索原理
  6. Elasticsearch分布式搜索引擎
  7. Redis与限流
  8. Quartz任务调度
  9. 分布式共识算法
  10. 日常开发实用技巧

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)-> 倒排索引

分析器处理流程:

  1. Tokenizer(分词):将文本切分成最小单位
  2. TokenFilter(词项过滤器链):小写转换、停用词过滤、同义词扩展、词干提取
  3. 输出词项(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将共识问题拆分为三个子问题:

  1. 领导者选举(Leader Election)
  2. 日志复制(Log Replication)
  3. 安全性(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微服务架构的技术栈基础。

掌握这些技术的核心原理和最佳实践,是构建高可用、高性能分布式系统的基础。

本文档基于真实项目实践整理,持续更新中。