前几天遇到个这么个问题,其他系统调用我们的接口,我们的接口将文件上传到s3之后,再将文件路径写入到数据库,这样下次有客户需要下载的时候,就直接去数据库查到文件路径再进行下载就行了。但是正式环境却出现了文件上传到s3成功,路径也写入到数据库中,但是下载下来的文件却打不开的问题。
以下是代码,我已经进行了简化
@Service
@Log4j2
public class ServiceImpl implements Service {
@Autowired(required = false)
private S3Tool s3Tool;
@Override
public Result updatePDF(Command command) {
Result result;
List<String> errorData = new ArrayList<>();
try {
//文件上传S3
PDF uploadPdf = uploadByS3(command);
if (uploadPdf != null){
List<String> packageList = command.getList();
for (String packageNumber : packageList) {
// 此处进行业务操作
}
}
}catch(Exception e){
log.error("上传失败{}",e)
}
public void uploadByS3(Command command){
try{
s3Tool.upload(command.getFile,command.getFileName)
}catch(Exception e){
log.error("上传异常{}",e)
}
}
}
而S3Tool这个工具类的upload方法是这样的
@Slf4j
@Component
public class S3Tool{
public void upload(File file,String name){
try{
S3.putObject(new PutObjectRequest(name, file))
}catch(AmazonServiceException e){
log.error("上传文件报错{}", e);
}
}
}
咋一看代码是一点问题都么有,那只能从日志下手了,于是只好苦逼的去翻了当天的日志,最终看到了报错原因
com.amazonaws.services.s3.model.AmazonS3Exception: ReplicaSetMonitor for set shard1 is removed (Service: Amazon S3; Status Code: 599; Error Code: ErrorOccurred)
看到这里,我想各位彦祖就已经发现了问题所在,是的,这就是关于Exception处理的失误。
1.在调用S3Tool.upload的时候就已经抛出异常,但是upload中的代码已经处理了,并没有就行上抛。
2.S3Tool.upload上传失败,但是uploadByS3这个方法没能捕获到Exception进行处理,仍然正常执行了
3.所以updatePDF调用完uploadByS3后,虽然文件上传S3失败,但是仍然将文件的路径写入到了数据库中,才会导致本次的缺陷。
其实观察下来,这段代码也不复杂,但是已经使用了3次try,catch,但是唯一生效的却是在upload方法中,其他的基本等于没用!
而AmazonS3Exception,是继承的RuntimeException,也是Unchecked Exceptions,其实也不需要在upload显式地进行处理。
项目是接手的,代码不是我们写的,但是缺陷却要算在我们头上!!!
总结,本次的缺陷就是代码处理Exception不规范导致的:
1.Exception的捕获和处理应该是在高层处理,不应该是在执行方法的时候
2.try,catch时应该注意是否能捕获到Exception,捕获不到,try,catch等于没写!
最后祝大家都能接受个好项目!!!