You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Boot REST请求含邮件、短信双操作时应如何做异常处理

解决方案

一、先修复现有Service的逻辑错误

你当前Service代码存在严重逻辑问题:无论邮件是否发送成功,最终都会执行smsService.sendSMS(act, "Email Success"),如果邮件发送失败,会连续发送「邮件失败」「邮件成功」两条错误短信,完全不符合业务预期。

二、具体改造步骤

1. 定义业务结果DTO

用来封装邮件、短信的发送状态,方便传递给客户端

// 先定义状态枚举,也可以直接用布尔值简化
public enum SendStatus {
    SUCCESS, FAILED
}

@Data
public class AlertSendResult {
    private SendStatus emailStatus;
    private String emailErrorMsg;
    private SendStatus smsStatus;
    private String smsErrorMsg;
}

2. 重构Service层逻辑

调整发送流程,捕获每个环节的异常,记录状态,不再向上抛无意义的通用异常

@Override
public AlertSendResult createAlert(Action act) {
    AlertSendResult result = new AlertSendResult();
    // 处理邮件发送逻辑
    try {
        emailService.sendEmail(act);
        result.setEmailStatus(SendStatus.SUCCESS);
        // 邮件发送成功,发送对应通知短信
        try {
            smsService.sendSMS(act, "Email Success");
            result.setSmsStatus(SendStatus.SUCCESS);
        } catch (Exception smsEx) {
            log.error("Send success notice sms failed", smsEx);
            result.setSmsStatus(SendStatus.FAILED);
            result.setSmsErrorMsg(smsEx.getMessage());
        }
    } catch (Exception emailEx) {
        log.error("Send email failed", emailEx);
        result.setEmailStatus(SendStatus.FAILED);
        result.setEmailErrorMsg(emailEx.getMessage());
        // 邮件发送失败,发送对应通知短信
        try {
            smsService.sendSMS(act, "Email Failed");
            result.setSmsStatus(SendStatus.SUCCESS);
        } catch (Exception smsEx) {
            log.error("Send fail notice sms failed", smsEx);
            result.setSmsStatus(SendStatus.FAILED);
            result.setSmsErrorMsg(smsEx.getMessage());
        }
    }
    return result;
}

3. 改造Controller层返回结果

把Service返回的详细状态直接返回给客户端,客户端可以通过返回体的字段明确判断每个环节的执行结果

@Override
public ResponseEntity<AlertSendResult> sendAction(Action act) {        
    try {
        AlertSendResult result = actionService.createAlert(act);
        // 可根据业务需求调整HTTP状态码,比如只要不是系统级异常都返回200,业务状态从返回体读取
        return new ResponseEntity<>(result, HttpStatus.OK);
    }catch (Exception e) {
        log.error("Exception occured while generating alerts. " , e);
        AlertSendResult errorResult = new AlertSendResult();
        errorResult.setEmailStatus(SendStatus.FAILED);
        errorResult.setSmsStatus(SendStatus.FAILED);
        errorResult.setEmailErrorMsg("System internal error");
        errorResult.setSmsErrorMsg("System internal error");
        return new ResponseEntity<>(errorResult, HttpStatus.INTERNAL_SERVER_ERROR);            
    }
}

三、可选优化点

  • 发送邮件、短信属于IO密集型操作,可以放到异步线程池执行,避免阻塞接口响应,异步场景下需单独处理结果记录逻辑
  • 可以把每一次的发送结果持久化到数据库,方便后续对账、故障排查
  • 针对发送失败的场景,可以增加有限次数的重试机制,避免临时网络波动导致的发送失败

内容的提问来源于stack exchange,提问作者Thinker

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.30 04:27:01