java

关注公众号 jb51net

关闭
首页 > 软件编程 > java > Spring Boot 生产级代码模板

Spring Boot后端开发 8 大核心生产级代码模板

作者:漫漫长路

这篇文章主要介绍了SpringBoot后端开发8大核心生产级代码模板,本文结合实例代码给大家介绍的非常详细,需要的朋友可以参考下

1. 全局异常处理 —— 相当于“服务员的统一微笑回复”

// 1. 统一给顾客看的“打包盒”
public record Result<T>(int code, String message, T data) {
    public static <T> Result<T> success(T data) {
        return new Result<>(200, "成功", data);
    }
    public static <T> Result<T> fail(String msg) {
        return new Result<>(500, msg, null);
    }
}
// 2. 兜底的服务员(拦截所有报错)
@RestControllerAdvice
public class GlobalExceptionHandler {
    @ExceptionHandler(Exception.class)
    public Result<Void> handleException(Exception e) {
        // 偷偷把错误记录在后台日志里,但给顾客返回礼貌提示
        return Result.fail("系统出了一点小问题,请稍后重试");
    }
}

2. Redisson 分布式锁 —— 相当于“试衣间锁门”

@Service
@RequiredArgsConstructor
public class SeckillService {
    private final RedissonClient redissonClient;
    public void buyProduct(String productId) {
        RLock lock = redissonClient.getLock("lock:" + productId);
        try {
            // 尝试拿锁:最多等 3 秒,拿到后锁 10 秒
            if (lock.tryLock(3, 10, TimeUnit.SECONDS)) {
                try {
                    // 锁门成功!安心在这里处理买东西的逻辑
                } finally {
                    // 试完了,必须把门锁解开,让给别人
                    if (lock.isHeldByCurrentThread()) {
                        lock.unlock();
                    }
                }
            } else {
                // 等了 3 秒还没门开,直接告诉顾客“没抢到”
            }
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
    }
}

3. MQ 消息手动确认(ACK)—— 相当于“快递签收单”

@Component
public class MQConsumer {
    @RabbitListener(queues = "order.queue", ackMode = "MANUAL")
    public void receiveOrder(String message, Channel channel, @Header(AmqpHeaders.DELIVERY_TAG) long tag) throws IOException {
        try {
            // 1. 拆快递、验货、处理业务
            System.out.println("收到订单消息:" + message);
            // 2. 确认无误,签名签收!(告诉 MQ 可以把这条消息删了)
            channel.basicAck(tag, false);
        } catch (Exception e) {
            // 3. 出错了!拒签,退回给快递公司重新送
            channel.basicNack(tag, false, false);
        }
    }
}

4. 自定义线程池 —— 相当于“招募固定数量的厨师”

@Configuration
public class ThreadPoolConfig {
    @Bean("myThreadPool")
    public ThreadPoolTaskExecutor myThreadPool() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(10);                  // 常驻厨师:10 人
        executor.setMaxPoolSize(20);                   // 忙不过来时最多扩到:20 人
        executor.setQueueCapacity(200);                // 休息区桌子:200 张
        executor.setThreadNamePrefix("my-worker-");   // 给厨师衣服贴工号
        // 人实在装不下了,让来派任务的主线程自己去干
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        executor.initialize();
        return executor;
    }
}

5. Redis + Lua 脚本预扣库存 —— 相当于“黑板刷秒杀法”

@Service
@RequiredArgsConstructor
public class StockService {
    private final StringRedisTemplate redisTemplate;
    // Lua 脚本:在 Redis 内部完成“检查库存 -> 扣减库存”,一体化搞定
    private static final String SCRIPT = 
        "local stock = tonumber(redis.call('get', KEYS[1])); " +
        "if stock and stock > 0 then " +
        "    redis.call('decrby', KEYS[1], 1); " +
        "    return 1; " + // 扣减成功
        "end; " +
        "return 0;"; // 没库存了
    public boolean buy(String stockKey) {
        DefaultRedisScript<Long> redisScript = new DefaultRedisScript<>(SCRIPT, Long.class);
        Long result = redisTemplate.execute(redisScript, Collections.singletonList(stockKey));
        return Long.valueOf(1).equals(result);
    }
}

6. 接口限流 —— 相当于“酒吧门口的保镖”

// 1. 自定义标签:贴在方法上就能限流
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface RateLimit {
    int maxCount() default 10; // 最多进 10 次
    int second() default 60;   // 60 秒内
}
// 2. 门口的保镖(切面)
@Aspect
@Component
@RequiredArgsConstructor
public class RateLimitAspect {
    private final StringRedisTemplate redisTemplate;
    @Around("@annotation(limit)")
    public Object intercept(ProceedingJoinPoint pjp, RateLimit limit) throws Throwable {
        String key = "limit:" + pjp.getSignature().toShortString();
        Long count = redisTemplate.opsForValue().increment(key);
        if (count != null && count == 1) {
            redisTemplate.expire(key, Duration.ofSeconds(limit.second()));
        }
        if (count != null && count > limit.maxCount()) {
            throw new RuntimeException("你刷得太快了,休息一下吧!");
        }
        return pjp.proceed(); // 放行,让他进去
    }
}

7. MyBatis-Plus 分页查询 —— 相当于“看书一页一页翻”

@Service
@RequiredArgsConstructor
public class OrderService {
    private final OrderMapper orderMapper;
    public Page<Order> getOrders(Long userId, int pageNum, int pageSize) {
        // 1. 我要第 pageNum 页,每页 pageSize 条
        Page<Order> page = new Page<>(pageNum, pageSize);
        // 2. 查询条件:查 userId 是这个人的订单,按时间倒序排
        LambdaQueryWrapper<Order> wrapper = new LambdaQueryWrapper<Order>()
                .eq(Order::getUserId, userId)
                .orderByDesc(Order::getCreateTime);
        // 3. 查数据库,只拿这 10 条出来
        return orderMapper.selectPage(page, wrapper);
    }
}

8. RestTemplate 设置超时 —— 相当于“打电话设定最长等待时间”

@Configuration
public class RestConfig {
    @Bean
    public RestTemplate restTemplate(RestTemplateBuilder builder) {
        return builder
                .setConnectTimeout(Duration.ofSeconds(3)) // 等响应建立最多 3 秒
                .setReadTimeout(Duration.ofSeconds(5))    // 等对方传数据最多 5 秒
                .build();
    }
}
// 调用第三方接口
@Service
@RequiredArgsConstructor
public class RemoteCallService {
    private final RestTemplate restTemplate;
    public String callOtherSystem() {
        // 超过时间没反应会直接抛异常挂断,绝对不傻等
        return restTemplate.getForObject("https://api.example.com/data", String.class);
    }
}

还差哪 20% 才能彻底搞定工作与面试?

这 8 个场景帮你封顶了“业务开发”与“高并发”的主干,如果你想做到 100% 稳妥,只需要补齐以下两块:

到此这篇关于Spring Boot后端开发 8 大核心生产级代码模板的文章就介绍到这了,更多相关Spring Boot 生产级代码模板内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文