feat: (REQ-3540) 加上wps自定义异常

This commit is contained in:
xudawei 2025-03-21 18:09:05 +08:00
parent 25208f0410
commit d5307ea09b
9 changed files with 203 additions and 21 deletions

View File

@ -0,0 +1,34 @@
package cn.axzo.nanopart.doc.api.enums;
import cn.axzo.framework.domain.web.code.IRespCode;
import lombok.AllArgsConstructor;
import lombok.Getter;
/**
* @author xudawei@axzo.cn
* @date 2025/03/21
* @description wps错误码枚举
*/
@Getter
@AllArgsConstructor
public enum WpsErrorCodeEnum implements IRespCode {
TOKEN_INVALID("40002", "用户凭证即x-weboffice-token头, 无效"),
NO_PERMISSION("40003", "用户操作权限不足"),
FILE_NOT_EXIST("40004", "文档不存在"),
REQUEST_PARAMETER_ERROR("40005", "请求参数错误"),
STORAGE_SPACE_IS_FULL("40006", "存储空间已满"),
CUSTOM_ERROR("40007", "自定义错误,可以用来返回自定义错误信息"),
FILE_NAME_CONFLICT("40008", "文档名称冲突,例如重命名文档时"),
FILE_VERSION_NOT_EXIST("40009", "文档版本不存在"),
USER_NOT_EXIST("40010", "用户不存在"),
UPLOAD_ERROR("41001", "文件未正确上传"),
SYSTEM_ERROR("50001", "系统错误导致的请求不能正常响应"),
;
private String code;
private String message;
}

View File

@ -0,0 +1,36 @@
package cn.axzo.nanopart.doc.api.util;
/**
* @author xudawei@axzo.cn
* @date 2025/3/21
* @description 静态类
*/
public class Constants {
/**
* WPS-上传地址的content-type
*/
public static final String WPS_UPLOAD_ADDRESS_CONTENT_TYPE = "Content-Type";
/**
* WPS-上传地址的form-data
*/
public static final String WPS_UPLOAD_ADDRESS_FORM_DATA = "multipart/form-data";
/**
* WPS-上传地址的Host
*/
public static final String WPS_UPLOAD_ADDRESS_HOST = "Host";
/**
* WPS-上传地址的PUT
*/
public static final String WPS_UPLOAD_ADDRESS_PUT = "PUT";
/**
* WPS-准备上传摘要算法-sha1
*/
public static final String WPS_UPLOAD_PREPARE_SHA1 = "sha1";
}

View File

@ -1,6 +1,8 @@
package cn.axzo.nanopart.doc.integration;
import cn.axzo.nanopart.doc.api.enums.WpsErrorCodeEnum;
import cn.axzo.nanopart.doc.wps.support.WpsException;
import cn.axzo.oss.http.api.ServerFileServiceApi;
import cn.axzo.oss.http.model.ApiSignUrlDownloadRequest;
import cn.axzo.oss.http.model.ApiSignUrlDownloadResponse;
@ -42,7 +44,7 @@ public class DocOssGateway {
}
catch (Exception e) {
log.warn("DocOssGateway-signUrlFetchDownload exception", e);
throw e;
throw new WpsException(WpsErrorCodeEnum.UPLOAD_ERROR);
}
}
@ -75,7 +77,7 @@ public class DocOssGateway {
return response.getData();
} catch (Exception e) {
log.warn("DocOssGateway-signUrlFetchUpload exception", e);
throw e;
throw new WpsException(WpsErrorCodeEnum.UPLOAD_ERROR);
}
}

View File

@ -0,0 +1,37 @@
package cn.axzo.nanopart.doc.wps.support;
import cn.axzo.framework.domain.web.code.IRespCode;
import org.apache.commons.lang3.StringUtils;
/**
* @author xudawei@axzo.cn
* @date 2025/3/21
* @description TODO
*/
public class WpsAssertUtil {
public static void notNull(Object object, IRespCode code) {
if (object == null) {
fail(code);
}
}
public static void notEmpty(String object, IRespCode code) {
if (StringUtils.isEmpty(object)) {
fail(code);
}
}
public static void isFalse(boolean condition, IRespCode code) {
if (condition) {
fail(code);
}
}
public static void fail(IRespCode code) {
throw new WpsException(Integer.parseInt(code.getCode()), code.getMessage());
}
}

View File

@ -0,0 +1,28 @@
package cn.axzo.nanopart.doc.wps.support;
import cn.axzo.framework.domain.web.code.IRespCode;
import lombok.Data;
/**
* @author xudawei@axzo.cn
* @date 2025/3/21
* @description Wps异常
*/
@Data
public class WpsException extends RuntimeException {
private Integer errorCode;
private String errorMessage;
public WpsException(Integer code, String msg) {
super(msg);
this.errorCode = code;
this.errorMessage = msg;
}
public WpsException(IRespCode code) {
super(code.getMessage());
this.errorCode = Integer.parseInt(code.getCode());
this.errorMessage = code.getMessage();
}
}

View File

@ -0,0 +1,34 @@
package cn.axzo.nanopart.doc.wps.support;
import cn.axzo.nanopart.doc.api.enums.WpsErrorCodeEnum;
import cn.axzo.nanopart.doc.dao.IndexNodeDao;
import cn.axzo.nanopart.doc.entity.IndexNode;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
/**
* @author xudawei@axzo.cn
* @date 2025/3/21
* @description wps支持
*/
@Slf4j
@Component
@RequiredArgsConstructor
public class WpsSupport {
private final IndexNodeDao indexNodeDao;
public IndexNode findAndCheckByCode(String docCode) {
IndexNode node = indexNodeDao.findOrNull(docCode);
WpsAssertUtil.notNull(node, WpsErrorCodeEnum.FILE_NOT_EXIST);
return node;
}
public IndexNode findAndCheckForUpdateByCode(String docCode) {
IndexNode node = indexNodeDao.findForUpdateOrNull(docCode);
WpsAssertUtil.notNull(node, WpsErrorCodeEnum.FILE_NOT_EXIST);
return node;
}
}

View File

@ -2,6 +2,7 @@ package cn.axzo.nanopart.doc.wps.wpsbase;
import cn.axzo.basics.common.util.AssertUtil;
import cn.axzo.basics.profiles.dto.basic.PersonProfileDto;
import cn.axzo.nanopart.doc.api.enums.WpsErrorCodeEnum;
import cn.axzo.nanopart.doc.api.wps.request.WpsPermissionRequest;
import cn.axzo.nanopart.doc.api.wps.request.WpsRenameRequest;
import cn.axzo.nanopart.doc.api.wps.request.WpsUsersRequest;
@ -15,6 +16,8 @@ import cn.axzo.nanopart.doc.dao.IndexNodeDao;
import cn.axzo.nanopart.doc.entity.IndexNode;
import cn.axzo.nanopart.doc.integration.DocOssGateway;
import cn.axzo.nanopart.doc.integration.DocUserProfileGateway;
import cn.axzo.nanopart.doc.wps.support.WpsAssertUtil;
import cn.axzo.nanopart.doc.wps.support.WpsSupport;
import cn.axzo.oss.http.model.ApiSignUrlDownloadRequest;
import cn.axzo.oss.http.model.ApiSignUrlDownloadResponse;
import cn.axzo.oss.http.model.file.UpdateFileInfoRequest;
@ -43,13 +46,14 @@ public class WpsBaseManager {
private final DocUserProfileGateway docUserProfileGateway;
private final DocPermissionProps docPermissionProps;
private final WpsSupport wpsSupport;
/**
* 获取文件基础信息
* @param docCode 文件编码
*/
public WpsFetchFileResponse fetchFileBase(String docCode) {
IndexNode node = indexNodeDao.findOrNull(docCode);
IndexNode node = wpsSupport.findAndCheckByCode(docCode);
return WpsFetchFileResponse.builder()
.docCode(docCode)
.name(node.getFullFileName())
@ -67,7 +71,7 @@ public class WpsBaseManager {
* @param docCode 文件编码
*/
public WpsFetchDownloadResponse fetchDownload(String docCode) {
IndexNode node = indexNodeDao.findOrNull(docCode);
IndexNode node = wpsSupport.findAndCheckByCode(docCode);
return WpsFetchDownloadResponse.builder()
.url(this.downloadUrl(node.getAttributes().getFileAttributes().getOssFileKey()))
.digest("")
@ -85,8 +89,11 @@ public class WpsBaseManager {
}
ApiSignUrlDownloadRequest request = new ApiSignUrlDownloadRequest();
request.setFileKeys(Lists.newArrayList(fileKey));
List<ApiSignUrlDownloadResponse> apiSignUrlDownloadResponses = docOssGateway.signUrlFetchDownload(request);
return apiSignUrlDownloadResponses.get(0).getSignUrl();
List<ApiSignUrlDownloadResponse> responseList = docOssGateway.signUrlFetchDownload(request);
WpsAssertUtil.isFalse(CollectionUtil.isEmpty(responseList) || StringUtils.isBlank(responseList.get(0).getSignUrl()), WpsErrorCodeEnum.UPLOAD_ERROR);
return responseList.get(0).getSignUrl();
}
/**
@ -113,14 +120,11 @@ public class WpsBaseManager {
* 用户信息
*/
public WpsUsersResponse users(WpsUsersRequest request) {
AssertUtil.isFalse(Objects.isNull(request) || CollectionUtil.isEmpty(request.getPersonIds()), "入参错误");
WpsAssertUtil.isFalse(Objects.isNull(request) || CollectionUtil.isEmpty(request.getPersonIds()), WpsErrorCodeEnum.REQUEST_PARAMETER_ERROR);
//查询人员档案
List<PersonProfileDto> personProfiles = this.docUserProfileGateway.personProfileByPersonIds(request.getPersonIds().stream().map(Long::parseLong).collect(Collectors.toList()));
WpsAssertUtil.isFalse(CollectionUtil.isEmpty(personProfiles), WpsErrorCodeEnum.USER_NOT_EXIST);
if (CollectionUtil.isEmpty(personProfiles)) {
return WpsUsersResponse.builder().build();
}
return WpsUsersResponse.builder()
.users(personProfiles.stream()
.map(item -> WpsUsersResponse.WpsUser.builder()
@ -135,7 +139,7 @@ public class WpsBaseManager {
*/
public WpsRenameResponse rename(WpsRenameRequest request) {
AssertUtil.isFalse(Objects.isNull(request) || StringUtils.isEmpty(request.getDocCode()) || StringUtils.isEmpty(request.getName()), "参数错误");
IndexNode node = indexNodeDao.findOrNull(request.getDocCode());
IndexNode node = wpsSupport.findAndCheckByCode(request.getDocCode());
if (Objects.isNull(node)
|| Objects.isNull(node.getAttributes())
|| Objects.isNull(node.getAttributes().getFileAttributes())

View File

@ -5,6 +5,8 @@ import java.util.Map;
import java.util.Objects;
import cn.axzo.nanopart.doc.api.domain.FileAttributes;
import cn.axzo.nanopart.doc.api.util.Constants;
import cn.axzo.nanopart.doc.wps.support.WpsSupport;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.stereotype.Component;
@ -48,6 +50,7 @@ public class WpsEditManager {
private final DocOssGateway docOssGateway;
private final FileBroadcaster fileBroadcaster;
private final DocProps docProps;
private final WpsSupport wpsSupport;
/**
* 文档编辑
@ -56,7 +59,7 @@ public class WpsEditManager {
*
*/
public WpsEditUploadPrepareResponse uploadPrepare(WpsEditUploadPrepareRequest request) {
return WpsEditUploadPrepareResponse.builder().digestTypes(new String[]{"sha1"}).build();
return WpsEditUploadPrepareResponse.builder().digestTypes(new String[]{Constants.WPS_UPLOAD_PREPARE_SHA1}).build();
}
/**
@ -66,7 +69,7 @@ public class WpsEditManager {
* 此外回调中也会带上本次保存的一些额外信息如文档大小手动/自动保存等
*/
public WpsEditUploadAddressResponse uploadAddress(WpsEditUploadAddressRequest request) {
IndexNode node = indexNodeDao.findOrNull(request.getDocCode());
IndexNode node = wpsSupport.findAndCheckByCode(request.getDocCode());
String fileKey = StringUtils.EMPTY;
if (Objects.nonNull(node)
@ -83,11 +86,9 @@ public class WpsEditManager {
.fileKey(fileKey)
.build());
return WpsEditUploadAddressResponse.builder()
.url(response.getSignUrl())
.method("PUT") //上传文档的 HTTP Method(WPS)暂只支持 PUT文件实体将在 Body 传递
.method(Constants.WPS_UPLOAD_ADDRESS_PUT) //上传文档的 HTTP Method(WPS)暂只支持 PUT文件实体将在 Body 传递
.headers(this.buildUploadAddressHost(response))//构建请求上传地址的header信息
.params(null)
.sendBackParams(null)
@ -99,8 +100,8 @@ public class WpsEditManager {
*/
private Map<String, String> buildUploadAddressHost(ApiSignUrlUploadResponse response) {
Map<String, String> header = new HashMap<>();
header.put("Content-Type", "multipart/form-data");
header.put("Host", response.getHost());
header.put(Constants.WPS_UPLOAD_ADDRESS_CONTENT_TYPE, Constants.WPS_UPLOAD_ADDRESS_FORM_DATA);
header.put(Constants.WPS_UPLOAD_ADDRESS_HOST, response.getHost());
return header;
}
@ -113,7 +114,7 @@ public class WpsEditManager {
public WpsEditUploadCompleteResponse uploadComplete(WpsEditUploadCompleteRequest request) {
log.info("wpsEditManager-uploadComplete-params,request:{}", request);
//加锁
IndexNode node = indexNodeDao.getForUpdateOrThrow(request.getDocCode());
IndexNode node = wpsSupport.findAndCheckForUpdateByCode(request.getDocCode());
//当上传完成后更新文件基础信息
this.updateIndexNodeWhenUploadComplete(node, request);

View File

@ -1,6 +1,7 @@
package cn.axzo.nanopart.config.exception;
import cn.axzo.framework.domain.web.result.ApiResult;
import cn.axzo.nanopart.doc.wps.support.WpsException;
import cn.axzo.pokonyan.exception.BusinessException;
import cn.axzo.workflow.common.exception.WorkflowEngineException;
import lombok.extern.slf4j.Slf4j;
@ -71,5 +72,10 @@ public class ExceptionAdviceHandler {
log.warn("业务异常", e);
return ApiResult.err(e.getMessage());
}
@ExceptionHandler(WpsException.class)
public ApiResult<Void> wpsExceptionHandler(WpsException e) {
log.warn("wps业务异常", e);
return ApiResult.err(e.getErrorCode(), e.getErrorMessage());
}
}