``` // 模板方法:统一处理发送流程 protected final void executeSend(boolean isAgain, McMsgSendTemplateModel sendTemplate, McTaskMsgContentEntity taskMsgContent, List<McTaskMsgReceiveEntity> receiveListS, UserInfo currentUserInfo) { List<McTaskMsgReceiveEntity> receiveList = JsonUtil.getJsonToList(receiveListS, McTaskMsgReceiveEntity.class); // 1. 参数校验:设计一个通用的校验方法,实现写在基类中;设计一个抽象方法,子类实现具体的校验逻辑,实现个性化校验。 commonPreCheck(taskMsgContent, receiveList); // 公共校验 异常处理 } // 公共校验方法 private List<McTaskMsgReceiveEntity> commonPreCheck(McTaskMsgContentEntity taskMsgContent, List<McTaskMsgReceiveEntity> receiveList) { if (ObjectUtil.isEmpty(taskMsgContent)) { throw new MessageSendException(2, "消息内容为空", null); } Map<Boolean, List<McTaskMsgReceiveEntity>> partitioned = receiveList.stream() .collect(Collectors.partitioningBy(r -> StringUtils.isNotEmpty(r.getReceiveUserId()))); List<McTaskMsgReceiveEntity> thirdNullList = partitioned.get(false); // 原thirdNullList if (CollectionUtil.isNotEmpty(thirdNullList)) { return partitioned.get(true); throw new MessageSendException(2, "无third绑定数据", thirdNullList); } List<McTaskMsgReceiveEntity> thirdNotNullList = partitioned.get(true); // 原thirdNotNullList return receiveList; }```代码片段中有executeSend和commonPreCheck两个函数,现在存在问题,且有一个需求是在commonPreCheck中无论哪种情况都可以在executeSend拿到thirdNotNullList。看怎么优化
时间: 2025-06-26 19:18:57 浏览: 9
<think>嗯,用户给了一个Java代码片段,里面有executeSend和commonPreCheck两个方法。他们提到存在问题,并且需要在commonPreCheck中无论哪种情况,executeSend都能拿到thirdNotNullList。我需要仔细看看代码哪里出问题了。
首先看commonPreCheck方法。这个方法的作用是参数校验。用户传入taskMsgContent和receiveList,然后进行一些检查。问题可能出在异常处理和返回值的逻辑上。
在commonPreCheck中,首先检查taskMsgContent是否为空,如果空就抛异常。没问题。接下来用流处理把receiveList分成两部分:有receiveUserId的和没有的。然后检查thirdNullList是否非空,如果非空,就返回partitioned.get(true),然后抛异常。这里有问题,因为return之后抛异常的代码不会执行,导致无法抛出异常,同时返回了thirdNotNullList,但后面的throw没有被执行,所以这里逻辑有错误。
用户的需求是无论commonPreCheck中哪种情况,executeSend都能拿到thirdNotNullList。但当前代码中,当thirdNullList不为空时,返回了thirdNotNullList,但紧接着抛异常,这会导致异常抛出前返回了列表,但实际执行时return之后的throw不会执行,所以这里存在逻辑错误,同时异常没有被正确抛出,导致后续流程可能继续执行,而thirdNotNullList可能被错误处理。
需要调整commonPreCheck的逻辑,确保在thirdNullList存在时,既抛出异常,又让executeSend能获取到thirdNotNullList。或者,可能需要重新设计返回值,保证即使有异常情况,thirdNotNullList也能被正确传递。
可能的解决方法是:当thirdNullList存在时,将thirdNotNullList作为异常的一部分传递,然后在executeSend中捕获异常并处理。或者,在commonPreCheck中返回thirdNotNullList的同时,将thirdNullList包含在异常信息中,确保调用方可以获取到正确的列表。
另外,注意到commonPreCheck的返回类型是List<McTaskMsgReceiveEntity>,但当前代码在检查到thirdNullList非空时,先return再throw,这是无效的,因为return之后代码不会继续执行。应该先抛出异常,或者在返回之前处理。
可能需要重新构造commonPreCheck方法,使其在遇到thirdNullList非空时,抛出包含thirdNullList的异常,同时仍然返回thirdNotNullList,但这样可能矛盾。或者,在异常中包含必要的参数,让executeSend可以在捕获异常时获取需要的数据。
可能的优化步骤:
1. 修正commonPreCheck中的return和throw顺序,确保抛出异常前不返回,或者调整逻辑。
比如,当thirdNullList非空时,抛出异常,并将thirdNotNullList作为返回值返回。但此时方法已经抛出异常,executeSend无法继续执行。所以可能需要将异常信息和需要的数据一起传递,或者在异常中包含需要的数据,让executeSend在捕获异常时可以获取到thirdNotNullList。
或者,把thirdNotNullList作为异常的一个属性,当抛出异常时,executeSend捕获该异常,并从中获取thirdNotNullList。
或者,调整commonPreCheck的返回值和异常处理方式,例如返回一个包含thirdNotNullList和错误信息的对象,而不是通过异常抛出。但可能不符合现有设计。
另一种思路:commonPreCheck应该总是返回thirdNotNullList,并且在thirdNullList存在时抛出异常,但返回thirdNotNullList。这样,即使抛出异常,方法仍然返回了thirdNotNullList。但Java中,抛出异常会导致方法立即终止,因此返回语句必须位于抛出异常之前,或者需要调整顺序。
比如,修改commonPreCheck中的代码:
当thirdNullList非空时,保存thirdNotNullList到变量,然后抛出异常,同时在异常中包含thirdNotNullList。但这样executeSend在调用commonPreCheck时,如果发生异常,无法继续执行后续代码,除非捕获异常后继续处理。
但用户的需求是无论哪种情况,executeSend都能拿到thirdNotNullList。这可能意味着即使有异常情况,也需要处理thirdNotNullList的数据。例如,当存在thirdNullList时,需要记录错误,但继续处理有效的thirdNotNullList。
但原代码中,当thirdNullList存在时,commonPreCheck返回了thirdNotNullList,然后抛出异常。但此时executeSend中的commonPreCheck调用会得到返回值,但随后异常被抛出,导致后续代码无法执行。这可能需要调整异常处理,或者将错误处理和返回数据分离。
可能正确的做法是,commonPreCheck在发现thirdNullList时,抛出异常,同时将thirdNotNullList作为返回值返回,这样executeSend可以在捕获异常后继续处理thirdNotNullList。但Java中抛出异常会中断执行流程,因此需要将返回值在异常中传递,或者调整逻辑。
可能的解决方案:
1. 在commonPreCheck中,当thirdNullList不为空时,抛出异常,但将thirdNotNullList作为返回值返回。但由于抛出异常后方法退出,因此需要先抛出异常,这样返回值无法被正常接收。这可能不可行。
2. 调整commonPreCheck,使其返回thirdNotNullList,同时在存在thirdNullList时抛出异常,但将thirdNotNullList保存在异常对象中。然后,在executeSend中捕获异常,并从异常中获取thirdNotNullList。这样,无论是否抛出异常,executeSend都能获得thirdNotNullList。
例如,修改commonPreCheck:
抛出异常时,将thirdNotNullList作为异常的一个属性。在executeSend中调用commonPreCheck时,使用try-catch块,捕获异常并从异常中获取thirdNotNullList,然后继续处理。
但原代码中,commonPreCheck是private方法,被executeSend调用,并且executeSend中的逻辑可能在commonPreCheck抛出异常后无法继续执行。这可能需要调整异常处理的结构。
另一种可能性是,commonPreCheck在遇到thirdNullList时,将错误信息记录下来,但依然返回thirdNotNullList,而不是抛出异常。而参数校验的错误可能需要通过其他方式处理。但原代码中commonPreCheck的设计是抛出异常,可能希望终止执行流程。
但用户的需求是无论哪种情况,executeSend都需要拿到thirdNotNullList。可能原代码的问题在于当thirdNullList存在时,commonPreCheck返回了thirdNotNullList,但随后抛出的异常未被正确处理,导致executeSend无法继续执行后续代码,或者thirdNotNullList未被正确处理。
可能正确的优化步骤:
在commonPreCheck中,当存在thirdNullList时,抛出异常,但将thirdNotNullList包含在异常中。然后在executeSend方法中捕获该异常,并从中获取thirdNotNullList,继续处理。
例如:
修改MessageSendException,使其包含thirdNotNullList字段。在抛出异常时,传入thirdNotNullList。然后在executeSend中捕获异常,获取该列表。
调整后的commonPreCheck:
当thirdNullList不为空时,抛出异常,并将thirdNotNullList作为参数传递:
throw new MessageSendException(2, "无third绑定数据", thirdNullList, thirdNotNullList);
然后在executeSend中:
try {
List<McTaskMsgReceiveEntity> thirdNotNullList = commonPreCheck(...);
} catch (MessageSendException e) {
thirdNotNullList = e.getThirdNotNullList();
// 处理异常,同时使用thirdNotNullList继续发送
}
这样,无论是否抛出异常,executeSend都能获取到thirdNotNullList,并处理发送。
但原代码中,commonPreCheck是private方法,返回thirdNotNullList。当抛出异常时,executeSend中的调用将无法获取返回值,因为异常会导致流程中断。所以需要调整commonPreCheck的返回值,或者改变异常处理的方式。
或者,将commonPreCheck改为返回thirdNotNullList,并且在遇到错误时,将错误信息保存,而不是抛出异常。然后在executeSend中进行检查。但可能不符合现有设计。
综上,原代码中的问题在于commonPreCheck在检查到thirdNullList非空时,先返回partitioned.get(true),然后抛出异常,但return之后的throw无法执行。导致此时方法返回了thirdNotNullList,但异常未被抛出,后续代码继续执行,但可能没有正确处理错误。
因此,修正这个问题需要调整顺序,先抛出异常,或者在抛出异常之前处理返回值。但return之后无法执行throw,所以需要交换顺序。
例如,应该先检查thirdNullList是否非空,如果是,则抛出异常,并返回thirdNotNullList。但这在Java中是不可能的,因为抛出异常后方法就退出了,无法返回。因此,正确的做法应该是:
在commonPreCheck中,当存在thirdNullList时,抛出异常,但将thirdNotNullList作为异常的一部分,然后在executeSend中捕获异常,并从中获取thirdNotNullList。
修改后的commonPreCheck:
List<McTaskMsgReceiveEntity> thirdNotNullList = partitioned.get(true);
if (CollectionUtil.isNotEmpty(thirdNullList)) {
throw new MessageSendException(2, "无third绑定数据", thirdNullList, thirdNotNullList);
}
return thirdNotNullList;
这样,当thirdNullList存在时,抛出异常,但异常中携带了thirdNotNullList。然后在executeSend中:
try {
List<McTaskMsgReceiveEntity> thirdNotNullList = commonPreCheck(...);
// 正常流程处理
} catch (MessageSendException e) {
List<McTaskMsgReceiveEntity> thirdNotNullList = e.getThirdNotNullList();
// 处理异常情况,同时使用thirdNotNullList继续执行发送
// 可能需要记录错误或处理thirdNullList的情况
}
这样,无论是否抛出异常,executeSend都可以获取到thirdNotNullList,并根据需要处理。
同时,原代码中的commonPreCheck在抛出异常前返回了thirdNotNullList,但return后的代码不会执行,导致异常未被抛出。所以应该删除return,直接抛出异常,并将thirdNotNullList包含在异常中。
总结优化步骤:
1. 调整commonPreCheck中的逻辑,当thirdNullList非空时,抛出包含thirdNotNullList的异常,而不是返回。
2. 修改MessageSendException,添加字段来保存thirdNotNullList。
3. 在executeSend中调用commonPreCheck时,捕获异常,并从异常中获取thirdNotNullList,继续处理。
因此,代码调整如下:
在commonPreCheck中:
if (CollectionUtil.isNotEmpty(thirdNullList)) {
List<McTaskMsgReceiveEntity> thirdNotNullList = partitioned.get(true);
throw new MessageSendException(2, "无third绑定数据", thirdNullList, thirdNotNullList);
}
然后,在executeSend中:
try {
List<McTaskMsgReceiveEntity> thirdNotNullList = commonPreCheck(...);
// 正常处理
} catch (MessageSendException e) {
List<McTaskMsgReceiveEntity> thirdNotNullList = e.getThirdNotNullList();
List<McTaskMsgReceiveEntity> thirdNullList = e.getThirdNullList();
// 处理异常,记录日志等,然后继续使用thirdNotNullList进行发送
// 例如,发送thirdNotNullList,同时处理thirdNullList的错误情况
}
这样,无论是否出现异常,executeSend都能获得thirdNotNullList,并进行后续处理。
这样修改后,commonPreCheck在遇到thirdNullList时会抛出异常,但异常中携带了有效的thirdNotNullList,executeSend捕获异常后可以继续使用这个列表进行发送,满足用户的需求。
同时,原代码中的错误是在抛出异常前返回,导致throw语句无法执行,修正后应直接抛出异常,并携带必要的数据。</think>针对代码中的问题,分步骤优化如下:
---
### **问题分析**
1. **执行顺序错误**
`commonPreCheck`方法中`return`语句在`throw`之前,导致异常未被抛出(不可达代码)
2. **需求未满足**
当存在无效数据(`thirdNullList`)时,无法在`executeSend`中直接获取有效的`thirdNotNullList`
---
### **优化方案**
#### **步骤 1:重构异常抛出逻辑**
修改`commonPreCheck`,**先抛异常再返回有效数据**,并通过异常对象传递`thirdNotNullList`:
```java
private List<McTaskMsgReceiveEntity> commonPreCheck(...) {
// 基础校验(略)
Map<Boolean, List<McTaskMsgReceiveEntity>> partitioned = receiveList.stream()
.collect(Collectors.partitioningBy(r -> StringUtils.isNotEmpty(r.getReceiveUserId())));
List<McTaskMsgReceiveEntity> thirdNullList = partitioned.get(false);
List<McTaskMsgReceiveEntity> thirdNotNullList = partitioned.get(true);
if (CollectionUtil.isNotEmpty(thirdNullList)) {
// 通过异常传递有效数据
throw new MessageSendException(2, "存在无效接收方", thirdNullList, thirdNotNullList);
}
return thirdNotNullList;
}
```
#### **步骤 2:自定义异常增强**
修改`MessageSendException`,增加字段保存有效数据:
```java
public class MessageSendException extends RuntimeException {
private List<McTaskMsgReceiveEntity> invalidList; // 原thirdNullList
private List<McTaskMsgReceiveEntity> validList; // 原thirdNotNullList
public MessageSendException(int code, String msg,
List<McTaskMsgReceiveEntity> invalidList,
List<McTaskMsgReceiveEntity> validList) {
super(msg);
this.invalidList = invalidList;
this.validList = validList;
}
// Getter方法(略)
}
```
#### **步骤 3:在executeSend中捕获异常并处理**
```java
protected final void executeSend(...) {
try {
List<McTaskMsgReceiveEntity> validReceivers = commonPreCheck(...);
// 正常流程:使用validReceivers继续发送
} catch (MessageSendException e) {
List<McTaskMsgReceiveEntity> validReceivers = e.getValidList(); // 从异常中获取有效数据
List<McTaskMsgReceiveEntity> invalidReceivers = e.getInvalidList();
// 1. 记录无效数据(如日志或告警)
log.warn("无效接收方: {}", invalidReceivers);
// 2. 继续使用validReceivers处理发送(关键需求)
if (CollectionUtil.isNotEmpty(validReceivers)) {
processValidReceivers(validReceivers);
}
}
}
```
---
### **优化效果**
1. **异常处理正确性**
确保异常能被正确抛出,同时避免不可达代码。
2. **需求满足**
无论是否存在无效数据,`executeSend`均能通过正常返回或异常捕获两种方式获取`thirdNotNullList`。
3. **可维护性**
明确分离有效/无效数据处理逻辑,便于后续扩展。
---
### **关键设计思想**
1. **异常传递数据**
通过自定义异常将业务数据(有效/无效列表)与错误信息绑定,实现“异常不阻断关键流程”。
2. **防御式编程**
在`executeSend`中优先保障核心流程(发送有效数据),次要问题(无效数据)通过降级处理(如日志记录)。
阅读全文
相关推荐













