# Java核心编程与设计模式实战指南
> 🎯 从基础到进阶:网络编程 + Stream流 + AOP + 注解 + 设计模式
> 涵盖:企业级实战场景、代码示例、最佳实践
---
## 📚 目录
1. [网络编程实战](#一网络编程实战)
2. [Stream流式编程](#二stream流式编程)
3. [AOP切面编程](#三aop切面编程)
4. [Spring Boot常用注解](#四spring-boot常用注解)
5. [自定义注解实战](#五自定义注解实战)
6. [设计模式在项目中的应用](#六设计模式在项目中的应用)
7. [其他重要知识点](#七其他重要知识点)
---
# 一、网络编程实战
## 1.1 BIO vs NIO vs AIO
| 模型 | 说明 | 适用场景 | 代表框架 |
|------|------|---------|---------|
| **BIO** | 同步阻塞,一个连接一个线程 | 连接数少 | 传统Socket |
| **NIO** | 同步非阻塞,多路复用 | 高并发、长连接 | Netty |
| **AIO** | 异步非阻塞 | Linux下性能不如NIO | - |
## 1.2 HTTP客户端实战
**场景:调用第三方API(支付、短信、物流)**
### 方式1:RestTemplate(Spring传统方式)
```java
@Configuration
public class RestTemplateConfig {
@Bean
public RestTemplate restTemplate() {
SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory();
factory.setConnectTimeout(5000); // 连接超时5秒
factory.setReadTimeout(10000); // 读超时10秒
RestTemplate restTemplate = new RestTemplate(factory);
// 添加拦截器(统一处理)
restTemplate.setInterceptors(Collections.singletonList(
new ClientHttpRequestInterceptor() {
@Override
public ClientHttpResponse intercept(HttpRequest request,
byte[] body,
ClientHttpRequestExecution execution) throws IOException {
// 打印请求日志
log.info("Request: {} {}", request.getMethod(), request.getURI());
// 统一添加Header
request.getHeaders().add("User-Agent", "MyApp/1.0");
long start = System.currentTimeMillis();
ClientHttpResponse response = execution.execute(request, body);
long cost = System.currentTimeMillis() - start;
log.info("Response: status={}, cost={}ms", response.getStatusCode(), cost);
return response;
}
}
));
return restTemplate;
}
}
/**
* 调用第三方支付接口
*/
@Service
@Slf4j
public class PaymentHttpClient {
@Autowired
private RestTemplate restTemplate;
/**
* GET请求
*/
public String queryOrder(String orderNo) {
String url = "https://api.payment.com/order/{orderNo}";
try {
ResponseEntity<String> response = restTemplate.getForEntity(
url,
String.class,
orderNo
);
if (response.getStatusCode() == HttpStatus.OK) {
return response.getBody();
}
log.error("查询订单失败: status={}", response.getStatusCode());
return null;
} catch (RestClientException e) {
log.error("调用支付接口异常", e);
throw new BusinessException("查询订单失败");
}
}
/**
* POST请求(JSON)
*/
public PaymentResponse createPayment(PaymentRequest request) {
String url = "https://api.payment.com/pay";
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
headers.set("Authorization", "Bearer " + getToken());
HttpEntity<PaymentRequest> entity = new HttpEntity<>(request, headers);
try {
ResponseEntity<PaymentResponse> response = restTemplate.postForEntity(
url,
entity,
PaymentResponse.class
);
return response.getBody();
} catch (HttpClientErrorException e) {
// 4xx错误
log.error("客户端错误: status={}, body={}",
e.getStatusCode(), e.getResponseBodyAsString());
throw new BusinessException("支付请求参数错误");
} catch (HttpServerErrorException e) {
// 5xx错误
log.error("服务端错误: status={}", e.getStatusCode());
throw new BusinessException("支付服务异常");
}
}
}
```
### 方式2:OkHttp(推荐)
```java
@Configuration
public class OkHttpConfig {
@Bean
public OkHttpClient okHttpClient() {
return new OkHttpClient.Builder()
.connectTimeout(5, TimeUnit.SECONDS)
.readTimeout(10, TimeUnit.SECONDS)
.writeTimeout(10, TimeUnit.SECONDS)
// 连接池
.connectionPool(new ConnectionPool(10, 5, TimeUnit.MINUTES))
// 重试
.retryOnConnectionFailure(true)
// 拦截器
.addInterceptor(new LoggingInterceptor())
.build();
}
}
/**
* OkHttp调用示例
*/
@Service
@Slf4j
public class OkHttpService {
@Autowired
private OkHttpClient okHttpClient;
@Autowired
private ObjectMapper objectMapper;
/**
* GET请求
*/
public String get(String url) throws IOException {
Request request = new Request.Builder()
.url(url)
.get()
.build();
try (Response response = okHttpClient.newCall(request).execute()) {
if (!response.isSuccessful()) {
throw new IOException("请求失败: " + response);
}
return response.body().string();
}
}
/**
* POST JSON
*/
public <T> T postJson(String url, Object requestBody, Class<T> responseType) throws IOException {
String json = objectMapper.writeValueAsString(requestBody);
RequestBody body = RequestBody.create(
json,
MediaType.get("application/json; charset=utf-8")
);
Request request = new Request.Builder()
.url(url)
.post(body)
.build();
try (Response response = okHttpClient.newCall(request).execute()) {
if (!response.isSuccessful()) {
throw new IOException("请求失败: " + response);
}
String responseBody = response.body().string();
return objectMapper.readValue(responseBody, responseType);
}
}
}
```
### 方式3:WebClient(Spring WebFlux,异步)
```java
@Configuration
public class WebClientConfig {
@Bean
public WebClient webClient() {
return WebClient.builder()
.baseUrl("https://api.payment.com")
.defaultHeader("User-Agent", "MyApp/1.0")
.filter(ExchangeFilterFunction.ofRequestProcessor(
request -> {
log.info("Request: {} {}", request.method(), request.url());
return Mono.just(request);
}
))
.build();
}
}
/**
* WebClient异步调用
*/
@Service
public class WebClientService {
@Autowired
private WebClient webClient;
/**
* 异步GET
*/
public Mono<String> getAsync(String uri) {
return webClient.get()
.uri(uri)
.retrieve()
.bodyToMono(String.class);
}
/**
* 异步POST
*/
public Mono<PaymentResponse> postAsync(PaymentRequest request) {
return webClient.post()
.uri("/pay")
.contentType(MediaType.APPLICATION_JSON)
.bodyValue(request)
.retrieve()
.bodyToMono(PaymentResponse.class);
}
/**
* 批量并发请求
*/
public Flux<Order> batchQuery(List<String> orderNos) {
return Flux.fromIterable(orderNos)
.flatMap(orderNo ->
webClient.get()
.uri("/order/{orderNo}", orderNo)
.retrieve()
.bodyToMono(Order.class)
)
.onErrorContinue((error, orderNo) -> {
log.error("查询订单失败: orderNo={}", orderNo, error);
});
}
}
```
## 1.3 WebSocket实战
**场景:实时推送(订单状态、消息通知)**
```java
/**
* WebSocket配置
*/
@Configuration
@EnableWebSocket
public class WebSocketConfig implements WebSocketConfigurer {
@Autowired
private OrderWebSocketHandler orderHandler;
@Override
public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
registry.addHandler(orderHandler, "/ws/order")
.setAllowedOrigins("*"); // 生产环境要配置具体域名
}
}
/**
* WebSocket处理器
*/
@Component
@Slf4j
public class OrderWebSocketHandler extends TextWebSocketHandler {
// 存储连接(用户ID -> WebSocket会话)
private static final ConcurrentHashMap<Long, WebSocketSession> SESSIONS = new ConcurrentHashMap<>();
@Override
public void afterConnectionEstablished(WebSocketSession session) throws Exception {
// 从URL获取用户ID
Long userId = getUserId(session);
SESSIONS.put(userId, session);
log.info("WebSocket连接建立: userId={}", userId);
}
@Override
protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
log.info("收到消息: {}", message.getPayload());
// 回复消息
session.sendMessage(new TextMessage("收到: " + message.getPayload()));
}
@Override
public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
Long userId = getUserId(session);
SESSIONS.remove(userId);
log.info("WebSocket连接关闭: userId={}", userId);
}
/**
* 推送订单状态给指定用户
*/
public void pushOrderStatus(Long userId, OrderStatusDTO status) {
WebSocketSession session = SESSIONS.get(userId);
if (session != null && session.isOpen()) {
try {
String json = new ObjectMapper().writeValueAsString(status);
session.sendMessage(new TextMessage(json));
} catch (Exception e) {
log.error("推送消息失败", e);
}
}
}
/**
* 广播消息给所有在线用户
*/
public void broadcast(String message) {
SESSIONS.values().forEach(session -> {
if (session.isOpen()) {
try {
session.sendMessage(new TextMessage(message));
} catch (Exception e) {
log.error("广播消息失败", e);
}
}
});
}
private Long getUserId(WebSocketSession session) {
// 从URL或Header中获取用户ID
return 1L; // 示例
}
}
```
---
# 二、Stream流式编程
## 2.1 基础操作
```java
@Service
public class StreamBasicService {
/**
* 场景1:过滤 + 映射 + 收集
*
* 需求:查询所有已支付订单的订单号列表
*/
public List<String> getOrderNos(List<Order> orders) {
return orders.stream()
.filter(order -> order.getStatus() == 1) // 过滤已支付
.map(Order::getOrderNo) // 提取订单号
.collect(Collectors.toList()); // 收集为List
}
/**
* 场景2:去重
*
* 需求:获取所有订单中的唯一用户ID
*/
public Set<Long> getUniqueUserIds(List<Order> orders) {
return orders.stream()
.map(Order::getUserId)
.collect(Collectors.toSet()); // 自动去重
}
/**
* 场景3:排序
*
* 需求:按金额降序排列订单
*/
public List<Order> sortByAmount(List<Order> orders) {
return orders.stream()
.sorted(Comparator.comparing(Order::getTotalAmount).reversed())
.collect(Collectors.toList());
}
/**
* 场景4:分页
*
* 需求:获取前10条订单
*/
public List<Order> getTop10(List<Order> orders) {
return orders.stream()
.limit(10)
.collect(Collectors.toList());
}
}
```
## 2.2 高级操作
```java
@Service
public class StreamAdvancedService {
/**
* 场景1:分组
*
* 需求:按状态分组订单
* 结果:Map<Integer, List<Order>>
*/
public Map<Integer, List<Order>> groupByStatus(List<Order> orders) {
return orders.stream()
.collect(Collectors.groupingBy(Order::getStatus));
}
/**
* 场景2:分组统计
*
* 需求:统计每个用户的订单总金额
* 结果:Map<Long, BigDecimal>
*/
public Map<Long, BigDecimal> sumAmountByUser(List<Order> orders) {
return orders.stream()
.collect(Collectors.groupingBy(
Order::getUserId,
Collectors.reducing(
BigDecimal.ZERO,
Order::getTotalAmount,
BigDecimal::add
)
));
}
/**
* 场景3:分组计数
*
* 需求:统计每个状态的订单数量
* 结果:Map<Integer, Long>
*/
public Map<Integer, Long> countByStatus(List<Order> orders) {
return orders.stream()
.collect(Collectors.groupingBy(
Order::getStatus,
Collectors.counting()
));
}
/**
* 场景4:分区(二分类)
*
* 需求:将订单分为大额订单和普通订单
* 结果:Map<Boolean, List<Order>>
*/
public Map<Boolean, List<Order>> partitionByAmount(List<Order> orders) {
return orders.stream()
.collect(Collectors.partitioningBy(
order -> order.getTotalAmount().compareTo(new BigDecimal("1000")) > 0
));
}
/**
* 场景5:拼接字符串
*
* 需求:将所有订单号用逗号拼接
* 结果:"O001,O002,O003"
*/
public String joinOrderNos(List<Order> orders) {
return orders.stream()
.map(Order::getOrderNo)
.collect(Collectors.joining(","));
}
/**
* 场景6:flatMap(扁平化)
*
* 需求:获取所有订单的所有商品ID
*/
public List<Long> getAllProductIds(List<Order> orders) {
return orders.stream()
.flatMap(order -> order.getItems().stream()) // 扁平化
.map(OrderItem::getProductId)
.distinct()
.collect(Collectors.toList());
}
/**
* 场景7:多条件过滤
*
* 需求:查询已支付且金额>1000的订单
*/
public List<Order> complexFilter(List<Order> orders) {
return orders.stream()
.filter(order -> order.getStatus() == 1)
.filter(order -> order.getTotalAmount().compareTo(new BigDecimal("1000")) > 0)
.collect(Collectors.toList());
}
/**
* 场景8:peek(调试)
*
* 需求:在处理过程中打印日志
*/
public List<String> processWithLog(List<Order> orders) {
return orders.stream()
.filter(order -> order.getStatus() == 1)
.peek(order -> log.info("处理订单: {}", order.getOrderNo()))
.map(Order::getOrderNo)
.peek(orderNo -> log.info("订单号: {}", orderNo))
.collect(Collectors.toList());
}
}
```
## 2.3 实战案例:订单统计报表
```java
@Service
public class OrderStatisticsService {
/**
* 复杂统计报表
*
* 需求:
* 1. 按日期分组
* 2. 统计每天的订单数、总金额、平均金额
*/
public List<OrderStatisticsVO> dailyStatistics(List<Order> orders) {
Map<LocalDate, List<Order>> dateMap = orders.stream()
.collect(Collectors.groupingBy(
order -> order.getCreateTime().toLocalDate()
));
return dateMap.entrySet().stream()
.map(entry -> {
LocalDate date = entry.getKey();
List<Order> dayOrders = entry.getValue();
OrderStatisticsVO vo = new OrderStatisticsVO();
vo.setDate(date);
vo.setOrderCount(dayOrders.size());
// 总金额
BigDecimal totalAmount = dayOrders.stream()
.map(Order::getTotalAmount)
.reduce(BigDecimal.ZERO, BigDecimal::add);
vo.setTotalAmount(totalAmount);
// 平均金额
BigDecimal avgAmount = totalAmount.divide(
new BigDecimal(dayOrders.size()),
2,
RoundingMode.HALF_UP
);
vo.setAvgAmount(avgAmount);
return vo;
})
.sorted(Comparator.comparing(OrderStatisticsVO::getDate))
.collect(Collectors.toList());
}
/**
* 找出Top N用户
*/
public List<UserOrderStatVO> topUsers(List<Order> orders, int topN) {
return orders.stream()
.collect(Collectors.groupingBy(
Order::getUserId,
Collectors.collectingAndThen(
Collectors.toList(),
orderList -> {
UserOrderStatVO vo = new UserOrderStatVO();
vo.setUserId(orderList.get(0).getUserId());
vo.setOrderCount(orderList.size());
vo.setTotalAmount(
orderList.stream()
.map(Order::getTotalAmount)
.reduce(BigDecimal.ZERO, BigDecimal::add)
);
return vo;
}
)
))
.values().stream()
.sorted(Comparator.comparing(UserOrderStatVO::getTotalAmount).reversed())
.limit(topN)
.collect(Collectors.toList());
}
}
```
---
# 三、AOP切面编程
## 3.1 AOP核心概念
```
切面(Aspect):横切关注点的模块化
连接点(JoinPoint):程序执行的某个点(方法调用)
切入点(Pointcut):匹配连接点的表达式
通知(Advice):切面在特定连接点执行的动作
- Before:方法前
- After:方法后
- AfterReturning:方法返回后
- AfterThrowing:方法抛异常后
- Around:方法前后
```
## 3.2 切入点表达式
```java
// 1. 匹配指定包下所有类的所有方法
@Pointcut("execution(* cn.ufood.fny.mall.service.*.*(..))")
// 2. 匹配指定类的所有方法
@Pointcut("execution(* cn.ufood.fny.mall.service.OrderService.*(..))")
// 3. 匹配指定方法
@Pointcut("execution(* cn.ufood.fny.mall.service.OrderService.createOrder(..))")
// 4. 匹配带有指定注解的方法
@Pointcut("@annotation(cn.ufood.fny.mall.annotation.Log)")
// 5. 匹配指定包及子包
@Pointcut("execution(* cn.ufood.fny.mall.service..*.*(..))")
// 6. 组合表达式
@Pointcut("execution(* cn.ufood.fny.mall.service..*.*(..)) && @annotation(log)")
```
## 3.3 实战场景1:操作日志记录
```java
/**
* 操作日志注解
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface OperationLog {
/**
* 操作模块
*/
String module() default "";
/**
* 操作类型
*/
OperationType type() default OperationType.OTHER;
/**
* 操作描述(支持SpEL表达式)
*/
String description() default "";
}
/**
* 操作日志切面
*/
@Aspect
@Component
@Slf4j
public class OperationLogAspect {
@Autowired
private OperationLogService operationLogService;
@Pointcut("@annotation(cn.ufood.fny.mall.annotation.OperationLog)")
public void logPointcut() {}
@Around("logPointcut() && @annotation(operationLog)")
public Object around(ProceedingJoinPoint joinPoint, OperationLog operationLog) throws Throwable {
long startTime = System.currentTimeMillis();
// 构建日志对象
OperationLogEntity logEntity = new OperationLogEntity();
logEntity.setModule(operationLog.module());
logEntity.setType(operationLog.type());
logEntity.setDescription(parseDescription(operationLog.description(), joinPoint));
// 获取请求信息
HttpServletRequest request = getRequest();
if (request != null) {
logEntity.setRequestUrl(request.getRequestURI());
logEntity.setRequestMethod(request.getMethod());
logEntity.setIp(getIpAddress(request));
}
// 获取方法信息
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
logEntity.setMethod(signature.getDeclaringTypeName() + "." + signature.getName());
logEntity.setParams(JSON.toJSONString(joinPoint.getArgs()));
// 获取用户信息
Long userId = UserContext.getCurrentUserId();
logEntity.setUserId(userId);
Object result = null;
try {
// 执行方法
result = joinPoint.proceed();
logEntity.setStatus(1); // 成功
logEntity.setResult(JSON.toJSONString(result));
} catch (Throwable e) {
logEntity.setStatus(0); // 失败
logEntity.setErrorMsg(e.getMessage());
throw e;
} finally {
long costTime = System.currentTimeMillis() - startTime;
logEntity.setCostTime(costTime);
logEntity.setCreateTime(new Date());
// 异步保存日志
operationLogService.saveAsync(logEntity);
}
return result;
}
/**
* 解析描述(支持SpEL表达式)
*
* 例如:@OperationLog(description = "创建订单,订单号:#{#orderNo}")
*/
private String parseDescription(String description, ProceedingJoinPoint joinPoint) {
if (!description.contains("#{")) {
return description;
}
// 使用SpEL解析
ExpressionParser parser = new SpelExpressionParser();
EvaluationContext context = new StandardEvaluationContext();
// 获取方法参数
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
String[] paramNames = signature.getParameterNames();
Object[] args = joinPoint.getArgs();
for (int i = 0; i < paramNames.length; i++) {
context.setVariable(paramNames[i], args[i]);
}
return parser.parseExpression(description, new TemplateParserContext()).getValue(context, String.class);
}
}
// 使用示例
@Service
public class OrderService {
@OperationLog(
module = "订单管理",
type = OperationType.INSERT,
description = "创建订单,订单号:#{#order.orderNo}"
)
public void createOrder(Order order) {
// 业务逻辑
}
@OperationLog(
module = "订单管理",
type = OperationType.UPDATE,
description = "取消订单,订单号:#{#orderNo}"
)
public void cancelOrder(String orderNo) {
// 业务逻辑
}
}
```
## 3.4 实战场景2:防重复提交
```java
/**
* 防重复提交注解
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface PreventDuplicateSubmit {
/**
* 锁定时间(秒)
*/
int lockTime() default 3;
/**
* 提示信息
*/
String message() default "请勿重复提交";
}
/**
* 防重复提交切面
*/
@Aspect
@Component
@Slf4j
public class PreventDuplicateSubmitAspect {
@Autowired
private RedisTemplate<String, String> redisTemplate;
@Around("@annotation(preventDuplicateSubmit)")
public Object around(ProceedingJoinPoint joinPoint, PreventDuplicateSubmit preventDuplicateSubmit) throws Throwable {
// 生成唯一key:用户ID + 方法签名
Long userId = UserContext.getCurrentUserId();
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
String methodName = signature.getDeclaringTypeName() + "." + signature.getName();
String key = "duplicate:submit:" + userId + ":" + methodName;
// 尝试获取锁
Boolean success = redisTemplate.opsForValue().setIfAbsent(
key,
"1",
preventDuplicateSubmit.lockTime(),
TimeUnit.SECONDS
);
if (Boolean.FALSE.equals(success)) {
log.warn("重复提交: userId={}, method={}", userId, methodName);
throw new BusinessException(preventDuplicateSubmit.message());
}
try {
return joinPoint.proceed();
} finally {
// 方法执行完成,删除锁(可选)
// redisTemplate.delete(key);
}
}
}
// 使用示例
@PostMapping("/order")
@PreventDuplicateSubmit(lockTime = 5, message = "订单提交中,请勿重复提交")
public Result createOrder(@RequestBody OrderCreateRequest request) {
orderService.createOrder(request);
return Result.success();
}
```
## 3.5 实战场景3:性能监控
```java
/**
* 性能监控切面
*/
@Aspect
@Component
@Slf4j
public class PerformanceMonitorAspect {
/**
* 监控Service层所有方法
*/
@Around("execution(* cn.ufood.fny.mall.service..*.*(..))")
public Object monitor(ProceedingJoinPoint joinPoint) throws Throwable {
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
String methodName = signature.getDeclaringTypeName() + "." + signature.getName();
long startTime = System.currentTimeMillis();
Object result = null;
try {
result = joinPoint.proceed();
return result;
} finally {
long costTime = System.currentTimeMillis() - startTime;
// 超过1秒打印警告
if (costTime > 1000) {
log.warn("慢方法: method={}, costTime={}ms", methodName, costTime);
} else {
log.debug("方法耗时: method={}, costTime={}ms", methodName, costTime);
}
// 上报到监控系统(Prometheus、Skywalking等)
reportMetrics(methodName, costTime);
}
}
}
```
---
# 四、Spring Boot常用注解
## 4.1 核心注解
```java
/**
* 1. @SpringBootApplication
*
* 组合注解,包含:
* - @SpringBootConfiguration:表明这是一个配置类
* - @EnableAutoConfiguration:启用自动配置
* - @ComponentScan:组件扫描
*/
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
/**
* 2. @Configuration + @Bean
*
* 配置类,替代XML配置
*/
@Configuration
public class AppConfig {
@Bean
public RestTemplate restTemplate() {
return new RestTemplate();
}
@Bean
@ConditionalOnMissingBean // 只有不存在时才创建
public RedisTemplate<String, Object> redisTemplate() {
// ...
}
}
/**
* 3. @Component、@Service、@Repository、@Controller
*
* 组件注解,交给Spring管理
*/
@Service // 业务层
public class OrderService {}
@Repository // 数据访问层
public class OrderMapper {}
@Controller // 控制层
public class OrderController {}
@Component // 通用组件
public class MessageSender {}
/**
* 4. @Autowired、@Resource、@Inject
*
* 依赖注入
*/
@Service
public class OrderService {
// 推荐:构造器注入
private final OrderMapper orderMapper;
@Autowired
public OrderService(OrderMapper orderMapper) {
this.orderMapper = orderMapper;
}
// 或者:字段注入(简单但不推荐)
@Autowired
private UserService userService;
// 或者:@Resource(按名称注入)
@Resource(name = "orderMapper")
private OrderMapper mapper;
}
/**
* 5. @Value、@ConfigurationProperties
*
* 读取配置
*/
@Component
public class AppProperties {
// 单个属性
@Value("${app.name}")
private String appName;
// 默认值
@Value("${app.version:1.0}")
private String appVersion;
// SpEL表达式
@Value("#{systemProperties['user.name']}")
private String userName;
}
@Component
@ConfigurationProperties(prefix = "app")
@Data
public class AppConfig {
private String name;
private String version;
private Map<String, String> properties;
}
/**
* 6. @Conditional系列
*
* 条件注解
*/
@Configuration
public class ConditionalConfig {
@Bean
@ConditionalOnProperty(name = "feature.enabled", havingValue = "true")
public FeatureService featureService() {
return new FeatureService();
}
@Bean
@ConditionalOnClass(name = "com.mysql.cj.jdbc.Driver")
public DataSource mysqlDataSource() {
// ...
}
@Bean
@ConditionalOnMissingBean
public CacheManager cacheManager() {
// ...
}
}
```
## 4.2 Web注解
```java
@RestController // @Controller + @ResponseBody
@RequestMapping("/api/order")
public class OrderController {
/**
* GET请求
*/
@GetMapping("/{id}")
public Result<Order> getOrder(@PathVariable Long id) {
return Result.success(orderService.getById(id));
}
/**
* POST请求
*/
@PostMapping
public Result createOrder(@RequestBody @Valid OrderCreateRequest request) {
orderService.createOrder(request);
return Result.success();
}
/**
* PUT请求
*/
@PutMapping("/{id}")
public Result updateOrder(
@PathVariable Long id,
@RequestBody OrderUpdateRequest request
) {
orderService.updateOrder(id, request);
return Result.success();
}
/**
* DELETE请求
*/
@DeleteMapping("/{id}")
public Result deleteOrder(@PathVariable Long id) {
orderService.deleteOrder(id);
return Result.success();
}
/**
* 多个参数
*/
@GetMapping("/list")
public Result<Page<Order>> listOrders(
@RequestParam(required = false) Integer status,
@RequestParam(defaultValue = "1") Integer pageNum,
@RequestParam(defaultValue = "10") Integer pageSize
) {
Page<Order> page = orderService.listOrders(status, pageNum, pageSize);
return Result.success(page);
}
/**
* 获取Header
*/
@GetMapping("/info")
public Result getInfo(@RequestHeader("User-Agent") String userAgent) {
return Result.success(userAgent);
}
}
```
## 4.3 数据校验注解
```java
@Data
public class OrderCreateRequest {
@NotNull(message = "用户ID不能为空")
private Long userId;
@NotBlank(message = "收货地址不能为空")
@Length(max = 200, message = "地址长度不能超过200")
private String address;
@NotBlank(message = "手机号不能为空")
@Pattern(regexp = "^1[3-9]\\d{9}$", message = "手机号格式不正确")
private String phone;
@NotEmpty(message = "商品列表不能为空")
@Size(min = 1, max = 20, message = "商品数量必须在1-20之间")
private List<OrderItemRequest> items;
@DecimalMin(value = "0.01", message = "金额必须大于0")
@DecimalMax(value = "999999.99", message = "金额不能超过999999.99")
private BigDecimal totalAmount;
@Email(message = "邮箱格式不正确")
private String email;
@Past(message = "日期必须是过去的时间")
private Date birthday;
}
// 使用
@PostMapping
public Result createOrder(@RequestBody @Valid OrderCreateRequest request) {
// 如果校验失败,会自动抛出MethodArgumentNotValidException
orderService.createOrder(request);
return Result.success();
}
```
---
# 五、自定义注解实战
## 5.1 实战场景1:接口限流
```java
/**
* 限流注解
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface RateLimit {
/**
* 限流key(支持SpEL)
*/
String key() default "";
/**
* 时间窗口(秒)
*/
int time() default 60;
/**
* 最大请求数
*/
int count() default 100;
/**
* 限流类型
*/
LimitType limitType() default LimitType.DEFAULT;
}
public enum LimitType {
DEFAULT, // 默认策略(全局)
IP, // 按IP限流
USER // 按用户限流
}
/**
* 限流切面
*/
@Aspect
@Component
@Slf4j
public class RateLimitAspect {
@Autowired
private RedisTemplate<String, String> redisTemplate;
@Around("@annotation(rateLimit)")
public Object around(ProceedingJoinPoint joinPoint, RateLimit rateLimit) throws Throwable {
String key = generateKey(joinPoint, rateLimit);
// Lua脚本实现限流(原子性)
String luaScript =
"local key = KEYS[1] " +
"local count = tonumber(ARGV[1]) " +
"local time = tonumber(ARGV[2]) " +
"local current = redis.call('get', key) " +
"if current and tonumber(current) >= count then " +
" return 0 " +
"end " +
"current = redis.call('incr', key) " +
"if tonumber(current) == 1 then " +
" redis.call('expire', key, time) " +
"end " +
"return 1";
RedisScript<Long> script = RedisScript.of(luaScript, Long.class);
Long result = redisTemplate.execute(
script,
Collections.singletonList(key),
String.valueOf(rateLimit.count()),
String.valueOf(rateLimit.time())
);
if (result == 0) {
log.warn("触发限流: key={}", key);
throw new BusinessException("访问过于频繁,请稍后再试");
}
return joinPoint.proceed();
}
private String generateKey(ProceedingJoinPoint joinPoint, RateLimit rateLimit) {
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
String methodName = signature.getDeclaringTypeName() + "." + signature.getName();
StringBuilder keyBuilder = new StringBuilder("rate_limit:");
switch (rateLimit.limitType()) {
case IP:
String ip = getIpAddress();
keyBuilder.append("ip:").append(ip).append(":");
break;
case USER:
Long userId = UserContext.getCurrentUserId();
keyBuilder.append("user:").append(userId).append(":");
break;
default:
break;
}
keyBuilder.append(methodName);
if (StrUtil.isNotBlank(rateLimit.key())) {
keyBuilder.append(":").append(rateLimit.key());
}
return keyBuilder.toString();
}
}
// 使用示例
@RestController
public class OrderController {
// 全局限流:每分钟最多100次
@RateLimit(time = 60, count = 100)
@GetMapping("/list")
public Result list() {
return Result.success();
}
// 按IP限流:每10秒最多5次
@RateLimit(time = 10, count = 5, limitType = LimitType.IP)
@PostMapping("/submit")
public Result submit() {
return Result.success();
}
// 按用户限流:每天最多创建10个订单
@RateLimit(time = 86400, count = 10, limitType = LimitType.USER)
@PostMapping("/order")
public Result createOrder() {
return Result.success();
}
}
```
## 5.2 实战场景2:数据权限控制
```java
/**
* 数据权限注解
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface DataPermission {
/**
* 权限类型
*/
PermissionType type() default PermissionType.SELF;
/**
* 部门字段名
*/
String deptColumn() default "dept_id";
/**
* 用户字段名
*/
String userColumn() default "user_id";
}
public enum PermissionType {
ALL, // 查看所有
DEPT, // 查看本部门
DEPT_SUB, // 查看本部门及子部门
SELF // 只看自己
}
/**
* 数据权限切面(通过修改SQL实现)
*/
@Aspect
@Component
public class DataPermissionAspect {
@Around("@annotation(dataPermission)")
public Object around(ProceedingJoinPoint joinPoint, DataPermission dataPermission) throws Throwable {
// 获取当前用户信息
SysUser currentUser = UserContext.getCurrentUser();
// 管理员不限制
if (currentUser.isAdmin()) {
return joinPoint.proceed();
}
// 设置数据权限上下文
DataPermissionContext context = new DataPermissionContext();
context.setType(dataPermission.type());
context.setUserId(currentUser.getId());
context.setDeptId(currentUser.getDeptId());
context.setDeptColumn(dataPermission.deptColumn());
context.setUserColumn(dataPermission.userColumn());
DataPermissionHolder.set(context);
try {
return joinPoint.proceed();
} finally {
DataPermissionHolder.clear();
}
}
}
/**
* MyBatis拦截器(拦截SQL并添加条件)
*/
@Intercepts({
@Signature(type = StatementHandler.class, method = "prepare", args = {Connection.class, Integer.class})
})
public class DataPermissionInterceptor implements Interceptor {
@Override
public Object intercept(Invocation invocation) throws Throwable {
StatementHandler statementHandler = (StatementHandler) invocation.getTarget();
BoundSql boundSql = statementHandler.getBoundSql();
String sql = boundSql.getSql();
// 获取数据权限上下文
DataPermissionContext context = DataPermissionHolder.get();
if (context == null) {
return invocation.proceed();
}
// 修改SQL
String newSql = appendDataPermissionSql(sql, context);
// 通过反射设置新SQL
Field field = boundSql.getClass().getDeclaredField("sql");
field.setAccessible(true);
field.set(boundSql, newSql);
return invocation.proceed();
}
private String appendDataPermissionSql(String sql, DataPermissionContext context) {
StringBuilder condition = new StringBuilder(" AND (");
switch (context.getType()) {
case SELF:
condition.append(context.getUserColumn())
.append(" = ")
.append(context.getUserId());
break;
case DEPT:
condition.append(context.getDeptColumn())
.append(" = ")
.append(context.getDeptId());
break;
case DEPT_SUB:
// 查询部门及子部门ID
List<Long> deptIds = getDeptAndSubIds(context.getDeptId());
condition.append(context.getDeptColumn())
.append(" IN (")
.append(StringUtils.join(deptIds, ","))
.append(")");
break;
}
condition.append(")");
// 在WHERE后面添加条件
return sql.replaceFirst("(?i)WHERE", "WHERE" + condition.toString());
}
}
// 使用示例
@Service
public class OrderService {
// 只能查看自己的订单
@DataPermission(type = PermissionType.SELF, userColumn = "user_id")
public List<Order> getMyOrders() {
return orderMapper.selectList(null);
// 自动添加条件:WHERE user_id = 当前用户ID
}
// 部门经理可以查看本部门所有订单
@DataPermission(type = PermissionType.DEPT, deptColumn = "dept_id")
public List<Order> getDeptOrders() {
return orderMapper.selectList(null);
// 自动添加条件:WHERE dept_id = 当前部门ID
}
}
```
---
# 六、设计模式在项目中的应用
## 6.1 策略模式(支付方式)
**场景:支持多种支付方式(微信、支付宝、银行卡)**
```java
/**
* 支付策略接口
*/
public interface PayStrategy {
/**
* 支付方式类型
*/
String getType();
/**
* 创建支付订单
*/
PayResult pay(PayRequest request);
/**
* 查询支付结果
*/
PayResult query(String orderNo);
}
/**
* 微信支付策略
*/
@Service
public class WxPayStrategy implements PayStrategy {
@Override
public String getType() {
return "WECHAT";
}
@Override
public PayResult pay(PayRequest request) {
// 调用微信支付API
return new PayResult();
}
@Override
public PayResult query(String orderNo) {
// 查询微信支付结果
return new PayResult();
}
}
/**
* 支付宝支付策略
*/
@Service
public class AliPayStrategy implements PayStrategy {
@Override
public String getType() {
return "ALIPAY";
}
@Override
public PayResult pay(PayRequest request) {
// 调用支付宝API
return new PayResult();
}
@Override
public PayResult query(String orderNo) {
// 查询支付宝支付结果
return new PayResult();
}
}
/**
* 策略工厂
*/
@Component
public class PayStrategyFactory {
private final Map<String, PayStrategy> strategyMap;
@Autowired
public PayStrategyFactory(List<PayStrategy> strategies) {
// Spring自动注入所有PayStrategy实现类
this.strategyMap = strategies.stream()
.collect(Collectors.toMap(
PayStrategy::getType,
strategy -> strategy
));
}
public PayStrategy getStrategy(String type) {
PayStrategy strategy = strategyMap.get(type);
if (strategy == null) {
throw new BusinessException("不支持的支付方式: " + type);
}
return strategy;
}
}
/**
* 支付服务(使用策略)
*/
@Service
public class PaymentService {
@Autowired
private PayStrategyFactory payStrategyFactory;
public PayResult pay(PayRequest request) {
// 根据支付方式获取对应策略
PayStrategy strategy = payStrategyFactory.getStrategy(request.getPayType());
// 执行支付
return strategy.pay(request);
}
}
```
## 6.2 模板方法模式(订单流程)
**场景:不同类型订单创建流程类似,但部分步骤不同**
```java
/**
* 订单创建模板
*/
@Slf4j
public abstract class AbstractOrderCreateTemplate {
/**
* 创建订单(模板方法)
*/
public final OrderResult createOrder(OrderRequest request) {
// 1. 参数校验
validateParams(request);
// 2. 检查库存
checkStock(request);
// 3. 计算价格(不同订单类型计算方式不同)
BigDecimal totalAmount = calculatePrice(request);
// 4. 创建订单
Order order = buildOrder(request, totalAmount);
orderMapper.insert(order);
// 5. 扣减库存
deductStock(request);
// 6. 业务特殊处理(钩子方法,子类可选实现)
afterOrderCreated(order);
// 7. 发送MQ
sendOrderMessage(order);
log.info("订单创建成功: orderNo={}", order.getOrderNo());
return OrderResult.success(order);
}
/**
* 参数校验(通用)
*/
private void validateParams(OrderRequest request) {
if (request.getUserId() == null) {
throw new BusinessException("用户ID不能为空");
}
if (CollectionUtils.isEmpty(request.getItems())) {
throw new BusinessException("商品列表不能为空");
}
}
/**
* 检查库存(通用)
*/
private void checkStock(OrderRequest request) {
for (OrderItemRequest item : request.getItems()) {
Integer stock = stockService.getStock(item.getProductId());
if (stock < item.getQuantity()) {
throw new BusinessException("商品库存不足");
}
}
}
/**
* 计算价格(抽象方法,子类必须实现)
*/
protected abstract BigDecimal calculatePrice(OrderRequest request);
/**
* 扣减库存(通用)
*/
private void deductStock(OrderRequest request) {
for (OrderItemRequest item : request.getItems()) {
stockService.deduct(item.getProductId(), item.getQuantity());
}
}
/**
* 订单创建后处理(钩子方法,子类可选实现)
*/
protected void afterOrderCreated(Order order) {
// 默认空实现
}
/**
* 发送MQ(通用)
*/
private void sendOrderMessage(Order order) {
mqProducer.send("order-created", order);
}
private Order buildOrder(OrderRequest request, BigDecimal totalAmount) {
Order order = new Order();
order.setOrderNo(generateOrderNo());
order.setUserId(request.getUserId());
order.setTotalAmount(totalAmount);
order.setStatus(0);
order.setCreateTime(new Date());
return order;
}
}
/**
* 普通订单(原价)
*/
@Service("normalOrderCreate")
public class NormalOrderCreateTemplate extends AbstractOrderCreateTemplate {
@Override
protected BigDecimal calculatePrice(OrderRequest request) {
return request.getItems().stream()
.map(item -> {
Product product = productService.getById(item.getProductId());
return product.getPrice().multiply(new BigDecimal(item.getQuantity()));
})
.reduce(BigDecimal.ZERO, BigDecimal::add);
}
}
/**
* 秒杀订单(秒杀价)
*/
@Service("seckillOrderCreate")
public class SeckillOrderCreateTemplate extends AbstractOrderCreateTemplate {
@Override
protected BigDecimal calculatePrice(OrderRequest request) {
// 使用秒杀价
return request.getItems().stream()
.map(item -> {
SeckillProduct seckill = seckillService.getById(item.getProductId());
return seckill.getSeckillPrice().multiply(new BigDecimal(item.getQuantity()));
})
.reduce(BigDecimal.ZERO, BigDecimal::add);
}
@Override
protected void afterOrderCreated(Order order) {
// 秒杀订单需要记录秒杀信息
SeckillRecord record = new SeckillRecord();
record.setOrderId(order.getId());
record.setUserId(order.getUserId());
record.setCreateTime(new Date());
seckillRecordMapper.insert(record);
}
}
/**
* 拼团订单
*/
@Service("groupOrderCreate")
public class GroupOrderCreateTemplate extends AbstractOrderCreateTemplate {
@Override
protected BigDecimal calculatePrice(OrderRequest request) {
// 使用拼团价
return request.getItems().stream()
.map(item -> {
GroupProduct group = groupService.getById(item.getProductId());
return group.getGroupPrice().multiply(new BigDecimal(item.getQuantity()));
})
.reduce(BigDecimal.ZERO, BigDecimal::add);
}
@Override
protected void afterOrderCreated(Order order) {
// 拼团订单需要加入拼团
groupService.joinGroup(order.getUserId(), order.getId());
}
}
/**
* 订单服务(使用模板)
*/
@Service
public class OrderService {
@Autowired
private ApplicationContext applicationContext;
public OrderResult createOrder(OrderRequest request) {
// 根据订单类型获取对应模板
String beanName = request.getOrderType() + "OrderCreate";
AbstractOrderCreateTemplate template = applicationContext.getBean(beanName, AbstractOrderCreateTemplate.class);
return template.createOrder(request);
}
}
```
## 6.3 责任链模式(订单校验)
**场景:订单创建前需要多个校验步骤**
```java
/**
* 校验处理器接口
*/
public interface OrderValidateHandler {
/**
* 处理校验
*/
void handle(OrderRequest request);
/**
* 设置下一个处理器
*/
void setNext(OrderValidateHandler next);
}
/**
* 抽象处理器
*/
public abstract class AbstractOrderValidateHandler implements OrderValidateHandler {
protected OrderValidateHandler next;
@Override
public void setNext(OrderValidateHandler next) {
this.next = next;
}
@Override
public void handle(OrderRequest request) {
// 当前处理器处理
doHandle(request);
// 传递给下一个处理器
if (next != null) {
next.handle(request);
}
}
/**
* 具体处理逻辑(子类实现)
*/
protected abstract void doHandle(OrderRequest request);
}
/**
* 1. 用户状态校验
*/
@Component
@Order(1)
public class UserStatusValidateHandler extends AbstractOrderValidateHandler {
@Autowired
private UserService userService;
@Override
protected void doHandle(OrderRequest request) {
SysUser user = userService.getById(request.getUserId());
if (user == null) {
throw new BusinessException("用户不存在");
}
if (user.getStatus() != 1) {
throw new BusinessException("用户状态异常");
}
}
}
/**
* 2. 商品状态校验
*/
@Component
@Order(2)
public class ProductStatusValidateHandler extends AbstractOrderValidateHandler {
@Autowired
private ProductService productService;
@Override
protected void doHandle(OrderRequest request) {
for (OrderItemRequest item : request.getItems()) {
Product product = productService.getById(item.getProductId());
if (product == null) {
throw new BusinessException("商品不存在");
}
if (product.getStatus() != 1) {
throw new BusinessException("商品已下架");
}
}
}
}
/**
* 3. 库存校验
*/
@Component
@Order(3)
public class StockValidateHandler extends AbstractOrderValidateHandler {
@Autowired
private StockService stockService;
@Override
protected void doHandle(OrderRequest request) {
for (OrderItemRequest item : request.getItems()) {
Integer stock = stockService.getStock(item.getProductId());
if (stock < item.getQuantity()) {
throw new BusinessException("商品库存不足");
}
}
}
}
/**
* 4. 限购校验
*/
@Component
@Order(4)
public class LimitBuyValidateHandler extends AbstractOrderValidateHandler {
@Autowired
private OrderMapper orderMapper;
@Override
protected void doHandle(OrderRequest request) {
// 查询用户今日购买次数
int count = orderMapper.selectCount(
Wrappers.<Order>lambdaQuery()
.eq(Order::getUserId, request.getUserId())
.ge(Order::getCreateTime, DateUtil.beginOfDay(new Date()))
);
if (count >= 5) {
throw new BusinessException("今日购买次数已达上限");
}
}
}
/**
* 责任链工厂
*/
@Component
public class OrderValidateChainFactory {
private final OrderValidateHandler chain;
@Autowired
public OrderValidateChainFactory(List<AbstractOrderValidateHandler> handlers) {
// 按@Order排序
handlers.sort(Comparator.comparingInt(h ->
h.getClass().getAnnotation(Order.class).value()
));
// 构建责任链
for (int i = 0; i < handlers.size() - 1; i++) {
handlers.get(i).setNext(handlers.get(i + 1));
}
this.chain = handlers.get(0);
}
public OrderValidateHandler getChain() {
return chain;
}
}
/**
* 订单服务(使用责任链)
*/
@Service
public class OrderService {
@Autowired
private OrderValidateChainFactory chainFactory;
public void createOrder(OrderRequest request) {
// 执行责任链校验
chainFactory.getChain().handle(request);
// 校验通过,创建订单
// ...
}
}
```
## 6.4 观察者模式(订单事件)
**场景:订单创建后,需要通知多个模块(库存、积分、优惠券等)**
```java
/**
* 订单事件
*/
@Data
public class OrderCreatedEvent {
private Long orderId;
private Long userId;
private BigDecimal amount;
private Date createTime;
}
/**
* 发布事件
*/
@Service
public class OrderService {
@Autowired
private ApplicationEventPublisher eventPublisher;
public void createOrder(OrderRequest request) {
// 创建订单
Order order = new Order();
order.setOrderNo(generateOrderNo());
order.setUserId(request.getUserId());
order.setTotalAmount(request.getTotalAmount());
orderMapper.insert(order);
// 发布订单创建事件
OrderCreatedEvent event = new OrderCreatedEvent();
event.setOrderId(order.getId());
event.setUserId(order.getUserId());
event.setAmount(order.getTotalAmount());
event.setCreateTime(order.getCreateTime());
eventPublisher.publishEvent(event);
}
}
/**
* 监听器1:扣减库存
*/
@Component
@Slf4j
public class StockEventListener {
@Autowired
private StockService stockService;
@EventListener
@Async // 异步处理
public void onOrderCreated(OrderCreatedEvent event) {
log.info("监听到订单创建事件,开始扣减库存: orderId={}", event.getOrderId());
stockService.deductByOrderId(event.getOrderId());
}
}
/**
* 监听器2:增加积分
*/
@Component
@Slf4j
public class PointsEventListener {
@Autowired
private PointsService pointsService;
@EventListener
@Async
public void onOrderCreated(OrderCreatedEvent event) {
log.info("监听到订单创建事件,开始增加积分: userId={}", event.getUserId());
// 消费100元增加1积分
int points = event.getAmount().divide(new BigDecimal("100"), 0, RoundingMode.DOWN).intValue();
pointsService.add(event.getUserId(), points, "订单消费赠送");
}
}
/**
* 监听器3:发送通知
*/
@Component
@Slf4j
public class NotificationEventListener {
@Autowired
private NotificationService notificationService;
@EventListener
@Async
public void onOrderCreated(OrderCreatedEvent event) {
log.info("监听到订单创建事件,开始发送通知: userId={}", event.getUserId());
notificationService.sendOrderNotification(event.getUserId(), event.getOrderId());
}
}
```
## 6.5 工厂模式(导出服务)
**场景:支持多种格式导出(Excel、PDF、CSV)**
```java
/**
* 导出服务接口
*/
public interface ExportService {
/**
* 导出类型
*/
String getType();
/**
* 导出数据
*/
byte[] export(List<?> data);
}
/**
* Excel导出
*/
@Service
public class ExcelExportService implements ExportService {
@Override
public String getType() {
return "EXCEL";
}
@Override
public byte[] export(List<?> data) {
// 使用EasyExcel导出
ByteArrayOutputStream out = new ByteArrayOutputStream();
EasyExcel.write(out).sheet("数据").doWrite(data);
return out.toByteArray();
}
}
/**
* PDF导出
*/
@Service
public class PdfExportService implements ExportService {
@Override
public String getType() {
return "PDF";
}
@Override
public byte[] export(List<?> data) {
// 使用iText导出PDF
// ...
return new byte[0];
}
}
/**
* 导出工厂
*/
@Component
public class ExportServiceFactory {
private final Map<String, ExportService> serviceMap;
@Autowired
public ExportServiceFactory(List<ExportService> services) {
this.serviceMap = services.stream()
.collect(Collectors.toMap(
ExportService::getType,
service -> service
));
}
public ExportService getService(String type) {
ExportService service = serviceMap.get(type);
if (service == null) {
throw new BusinessException("不支持的导出类型: " + type);
}
return service;
}
}
/**
* 使用
*/
@RestController
public class ExportController {
@Autowired
private ExportServiceFactory exportFactory;
@GetMapping("/export")
public void export(@RequestParam String type, HttpServletResponse response) throws IOException {
// 查询数据
List<Order> orders = orderService.list();
// 获取导出服务
ExportService exportService = exportFactory.getService(type);
// 导出
byte[] data = exportService.export(orders);
// 返回文件
response.setContentType("application/octet-stream");
response.setHeader("Content-Disposition", "attachment; filename=orders." + type.toLowerCase());
response.getOutputStream().write(data);
}
}
```
---
# 七、其他重要知识点
## 7.1 异步编程(CompletableFuture)
```java
@Service
@Slf4j
public class AsyncService {
@Autowired
private OrderService orderService;
@Autowired
private ProductService productService;
@Autowired
private UserService userService;
/**
* 场景:订单详情页需要查询多个接口
*
* 串行:500ms + 300ms + 200ms = 1000ms
* 并行:max(500ms, 300ms, 200ms) = 500ms
*/
public OrderDetailVO getOrderDetail(Long orderId) {
CompletableFuture<Order> orderFuture = CompletableFuture.supplyAsync(() -> {
// 查询订单(500ms)
return orderService.getById(orderId);
});
CompletableFuture<Product> productFuture = CompletableFuture.supplyAsync(() -> {
// 查询商品(300ms)
return productService.getById(1L);
});
CompletableFuture<User> userFuture = CompletableFuture.supplyAsync(() -> {
// 查询用户(200ms)
return userService.getById(1L);
});
// 等待所有任务完成
CompletableFuture.allOf(orderFuture, productFuture, userFuture).join();
// 组装结果
OrderDetailVO vo = new OrderDetailVO();
vo.setOrder(orderFuture.join());
vo.setProduct(productFuture.join());
vo.setUser(userFuture.join());
return vo;
}
/**
* 场景:级联查询
*
* 先查订单 → 再查订单明细 → 再查商品详情
*/
public OrderDetailVO getOrderDetailCascade(Long orderId) {
return CompletableFuture.supplyAsync(() -> {
// 1. 查订单
return orderService.getById(orderId);
})
.thenApply(order -> {
// 2. 查订单明细
List<OrderItem> items = orderItemService.listByOrderId(order.getId());
return Pair.of(order, items);
})
.thenApply(pair -> {
// 3. 查商品详情
List<Long> productIds = pair.getRight().stream()
.map(OrderItem::getProductId)
.collect(Collectors.toList());
List<Product> products = productService.listByIds(productIds);
// 组装结果
OrderDetailVO vo = new OrderDetailVO();
vo.setOrder(pair.getLeft());
vo.setItems(pair.getRight());
vo.setProducts(products);
return vo;
})
.exceptionally(ex -> {
log.error("查询订单详情失败", ex);
return null;
})
.join();
}
}
```
## 7.2 线程池配置
```java
@Configuration
@EnableAsync
public class ThreadPoolConfig {
/**
* 核心线程池
*/
@Bean("taskExecutor")
public ThreadPoolTaskExecutor taskExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
// 核心线程数(CPU密集型:CPU核数,IO密集型:CPU核数*2)
executor.setCorePoolSize(8);
// 最大线程数
executor.setMaxPoolSize(16);
// 队列容量
executor.setQueueCapacity(100);
// 线程空闲时间(秒)
executor.setKeepAliveSeconds(60);
// 线程名前缀
executor.setThreadNamePrefix("task-");
// 拒绝策略(队列满时)
// CallerRunsPolicy:调用者线程执行
// AbortPolicy:抛异常(默认)
// DiscardPolicy:丢弃
// DiscardOldestPolicy:丢弃最旧的任务
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
// 等待任务完成后关闭
executor.setWaitForTasksToCompleteOnShutdown(true);
executor.setAwaitTerminationSeconds(60);
executor.initialize();
return executor;
}
/**
* 异步方法异常处理
*/
@Bean
public AsyncUncaughtExceptionHandler asyncUncaughtExceptionHandler() {
return (ex, method, params) -> {
log.error("异步方法执行异常: method={}, params={}",
method.getName(), Arrays.toString(params), ex);
};
}
}
/**
* 使用
*/
@Service
public class AsyncTaskService {
@Async("taskExecutor")
public void asyncTask() {
log.info("异步任务执行,线程: {}", Thread.currentThread().getName());
// 业务逻辑
}
@Async("taskExecutor")
public CompletableFuture<String> asyncTaskWithResult() {
// 带返回值的异步任务
String result = "处理结果";
return CompletableFuture.completedFuture(result);
}
}
```
## 7.3 缓存注解
```java
@Configuration
@EnableCaching
public class CacheConfig {
@Bean
public CacheManager cacheManager(RedisConnectionFactory factory) {
RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()
.entryTtl(Duration.ofMinutes(10)) // 默认过期时间10分钟
.serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer()))
.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new GenericJackson2JsonRedisSerializer()))
.disableCachingNullValues(); // 不缓存null值
return RedisCacheManager.builder(factory)
.cacheDefaults(config)
.build();
}
}
@Service
public class ProductService {
/**
* @Cacheable:先查缓存,没有再执行方法,并缓存结果
*/
@Cacheable(value = "product", key = "#id")
public Product getById(Long id) {
log.info("查询数据库: id={}", id);
return productMapper.selectById(id);
}
/**
* @CachePut:执行方法,并更新缓存
*/
@CachePut(value = "product", key = "#product.id")
public Product update(Product product) {
productMapper.updateById(product);
return product;
}
/**
* @CacheEvict:删除缓存
*/
@CacheEvict(value = "product", key = "#id")
public void deleteById(Long id) {
productMapper.deleteById(id);
}
/**
* 删除所有缓存
*/
@CacheEvict(value = "product", allEntries = true)
public void deleteAll() {
// ...
}
/**
* 条件缓存:只缓存价格>100的商品
*/
@Cacheable(value = "product", key = "#id", condition = "#result != null && #result.price > 100")
public Product getExpensiveProduct(Long id) {
return productMapper.selectById(id);
}
}
```
## 7.4 重试机制
```java
@Configuration
@EnableRetry
public class RetryConfig {}
@Service
public class PaymentService {
/**
* @Retryable:自动重试
*
* value:哪些异常需要重试
* maxAttempts:最大重试次数
* backoff:重试间隔策略
*/
@Retryable(
value = {RemoteServiceException.class},
maxAttempts = 3,
backoff = @Backoff(delay = 1000, multiplier = 2) // 1秒、2秒、4秒
)
public PayResult pay(PayRequest request) {
log.info("调用支付接口");
// 调用第三方支付
PayResult result = remotePayService.pay(request);
if (!result.isSuccess()) {
throw new RemoteServiceException("支付失败");
}
return result;
}
/**
* @Recover:重试失败后的兜底方法
*/
@Recover
public PayResult recover(RemoteServiceException e, PayRequest request) {
log.error("支付重试失败,执行兜底逻辑", e);
// 兜底逻辑:记录失败订单,人工处理
saveFailedOrder(request);
return PayResult.fail("支付服务暂时不可用,请稍后重试");
}
}
```
---
## 📝 面试速记卡
```
【网络编程】
RestTemplate | OkHttp | WebClient(异步)
WebSocket实时推送
【Stream流】
filter → map → collect
groupingBy → 分组统计
flatMap → 扁平化
【AOP】
@Around:操作日志、性能监控、防重复提交
切入点:execution | @annotation
【注解】
核心:@SpringBootApplication | @Configuration | @Bean
Web:@RestController | @RequestMapping | @Valid
注入:@Autowired | @Value | @ConfigurationProperties
条件:@ConditionalOnProperty | @ConditionalOnClass
【自定义注解】
@Target | @Retention | @Documented
配合AOP实现:限流、日志、权限
【设计模式】
策略模式:支付方式(微信/支付宝)
模板方法:订单流程(普通/秒杀/拼团)
责任链:订单校验(用户/商品/库存/限购)
观察者:订单事件(库存/积分/通知)
工厂模式:导出服务(Excel/PDF/CSV)
【其他】
CompletableFuture:异步编程
线程池:@Async + ThreadPoolTaskExecutor
缓存:@Cacheable | @CachePut | @CacheEvict
重试:@Retryable + @Recover
```
---
## 🎯 后端技术清单(补充)
除了已经写过的,这些也很重要:
### 已完成 ✅
1. ✅ Spring核心(IOC、AOP、事务)
2. ✅ MyBatis-Plus高阶
3. ✅ Redis(缓存、分布式锁)
4. ✅ MySQL(索引、事务、优化)
5. ✅ 运维DevOps(Linux、Docker、K8s、Nginx)
6. ✅ 流程引擎Flowable
7. ✅ 分库分表、信创改造
8. ✅ 网络编程、Stream、AOP、注解、设计模式
### 建议补充(可选)
9. **消息队列**:RabbitMQ/Kafka(发送、消费、死信队列、延迟消息)
10. **分布式**:Nacos(配置中心、服务注册)、Seata(分布式事务)
11. **搜索引擎**:Elasticsearch(全文检索、聚合分析)
12. **定时任务**:XXL-Job(分片、失败重试、监控)
13. **安全认证**:Shiro/Spring Security + JWT
14. **API网关**:Gateway(路由、限流、熔断)
15. **链路追踪**:Skywalking(性能监控、调用链路)
---
**文档版本**:v1.0
**创建时间**:2026-01-19
**适用场景**:Java核心编程与设计模式面试