# OpenAPI开发步骤

1 定义访问资源策略枚举类

2 定义访问资源策略接口

3 定义访问资源策略抽象类

4 定义枚举对应枚举策略资源实现类

5 定义资源策略上下文类

6 定义OpenAPI资源类

7 定义访问资源字段校验器

8 定义访问资源幂等校验工具类

9 定义资源rest配置文件

# 1 定义策略枚举类

```

/**
 * 策略键枚举类，用于统一管理策略模式中的 key
 */
public enum StrategyKeyEnum {

    ADD("add", "新增策略"),
    DELETE("delete", "删除策略"),
    UPDATE("update", "更新策略"),
    QUERY("query", "查询策略");

    private final String key;
    private final String desc;

    StrategyKeyEnum(String key, String desc) {
        this.key = key;
        this.desc = desc;
    }

    public String getKey() {
        return key;
    }

    public String getDesc() {
        return desc;
    }

    /**
     * 根据 key 获取对应的枚举值
     *
     * @param key 策略键
     * @return 对应的枚举值，若未找到则返回 null
     */
    public static StrategyKeyEnum getByKey(String key) {
        if (key == null || key.isEmpty()) {
            return null;
        }
        for (StrategyKeyEnum strategyKey : StrategyKeyEnum.values()) {
            if (strategyKey.getKey().equalsIgnoreCase(key)) {
                return strategyKey;
            }
        }
        return null;
    }
}

```



# 2 访问资源策略接口

```

import org.json.JSONString;
/**
 * 访问资源策略接口
 */
public interface IStrategyResources {

    /**
     * 策略执行
     * @param objstr
     * @return
     */
    JSONString execute(JSONString objstr);
}

```

# 3 访问资源策略抽象类

```

import com.alibaba.fastjson.JSONObject;
import nc.bs.framework.common.NCLocator;
import nc.md.persist.framework.IMDPersistenceQueryService;
import nc.md.persist.framework.IMDPersistenceService1;
import nc.vo.pub.IAttributeMeta;
import nc.vo.pub.JavaType;
import nc.vo.pub.lang.UFBoolean;
import nc.vo.pub.lang.UFDate;
import nc.vo.pub.lang.UFDateTime;
import nc.vo.pub.lang.UFDouble;
import nc.vo.pub.lang.UFLiteralDate;
import nc.vo.pub.lang.UFTime;
import nccloud.commons.lang.StringUtils;

import java.math.BigDecimal;

/**
 * 访问资源策略抽象类
 */
public abstract class AbstractStrategyResources {

    //操作服务 => 替换为实际业务的服务接口 =>  replacement => todo...
    private IMDPersistenceService1 service;

    //查询服务=> 替换为实际业务的服务接口 =>  replacement => todo...
    private IMDPersistenceQueryService queryService;

    /**
     * 根据属性获取值
     * 示例获取 IAttributeMeta[]
     * IAttributeMeta[] bodyAttrs = new Kk50shubdzallSlave1VO().getMetaData().getAttributes();
     * @param json
     * @param attribute
     * @return
     */
    public Object getValueByAttr(JSONObject json, IAttributeMeta attribute) {
        Object value = json.get(attribute.getName());

        if (value == null || StringUtils.isEmpty(value.toString())) {
            return null;
        }
        JavaType javaType = attribute.getJavaType();
        switch (javaType) {
            case String:
            case UFStringEnum:
                return value.toString();
            case BigDecimal:
                return new BigDecimal(value.toString());
            case Integer:
            case UFFlag:
                return Integer.valueOf(value.toString());
            case UFDouble:
                return new UFDouble(value.toString());
            case UFBoolean:
                return new UFBoolean(value.toString());
            case UFDate:
                return new UFDate(value.toString());
            case UFDateTime:
                return new UFDateTime(value.toString());
            case UFTime:
                return new UFTime(value.toString());
            case UFLiteralDate:
                return new UFLiteralDate(value.toString());
            default:
                return value;
        }
    }

    /**
     * 替换为实际业务的服务接口
     * replacement => todo...
     * @return
     */
    public IMDPersistenceService1 getService() {
        if (service == null) {
            service = NCLocator.getInstance().lookup(IMDPersistenceService1.class);
        }
        return service;
    }

    /**
     * 替换为实际业务的服务接口
     * replacement => todo...
     * @return
     */
    public IMDPersistenceQueryService getQueryService() {
        if (queryService == null) {
            queryService = NCLocator.getInstance().lookup(IMDPersistenceQueryService.class);
        }
        return queryService;
    }


}

```

# 4 新增策略资源实现类

```

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import nc.vo.pfxx.util.JsonUtils;
import nccloud.api.rest.utils.ResultMessageUtil;
import nccloud.commons.lang.StringUtils;
import nccloud.framework.core.exception.BusinessException;
import org.json.JSONString;

/**
 * openapi 新增策略
 */
public class AddStrategy extends AbstractStrategyResources implements IStrategyResources{

    @Override
    public JSONString execute(JSONString json) {
        //1 参数检验
        if ( json == null || StringUtils.isEmpty(json.toString())){
            return ResultMessageUtil.exceptionToJSON(new NullPointerException("输入参数不能为空！"));
        }

        //2 结构转换
        JSONObject obj = JSON.parseObject(json.toJSONString());

        //3 新增字段校验 =》 创建校验器
        JSONString addValidatorMsg = addValidator(obj);

        //4 幂等校验 根据自己的需求确定幂等字段  replacement =>  todo....
        if (IdempotentCheckUtil.isDuplicateRequest(obj.get("code").toString())) {
            return ResultMessageUtil.exceptionToJSON(new BusinessException("新增校验失败：重复请求，已幂等处理"));
        }
        
        //5 新增数据
        JSONString addResultString = executeAddData(obj);

        //6 数据构建返回
        JSONObject returnJson = new JSONObject();
        if(JsonUtils.isEmpty(addValidatorMsg) && JsonUtils.isEmpty(addResultString)){
            returnJson.put("result", "success");
            returnJson.put("msg", "新增成功");
        }else{
            returnJson.put("addValidatorResult", addValidatorMsg);
            returnJson.put("addResult", addResultString);
            returnJson.put("msg", "新增失败");
        }
        return ResultMessageUtil.toJSON(returnJson);

    }

    /**
     * 执行新增逻辑  replacement =>  todo....
     * @param obj
     * @return
     */
    private JSONString executeAddData(JSONObject obj) {
        //注意构建的vo状态需要为 VOStatus.NEW
        try {
//            JSONObject headJson = (JSONObject) json.get("head");
//            JSONArray bodysJson = json.getJSONArray("bodys");
//            IAttributeMeta[] headAttrs = headVO.getMetaData().getAttributes();
//            for (IAttributeMeta attribute : headAttrs) {
//                Object value = getValueByAttr(headJson, attribute);
//                headVO.setAttributeValue(attribute.getName(), value);
//            }
            //getService() => 抽象类中有 => todo...
        } catch (Exception e) {
            return ResultMessageUtil.exceptionToJSON(e);
        }
        return null;
    }

    /**
     * 新增字段校验  replacement =>  todo....
     * @param json
     */
    private JSONString addValidator(JSONObject json) {
        FieldValidator validator = new FieldValidator();
        validator.addField("字段编码", "字段名称");


        StringBuilder errorMsg = validator.validate(json);
        if (errorMsg.length() > 0) {
            return ResultMessageUtil.exceptionToJSON(new BusinessException("新增校验失败：" + errorMsg.toString()));
        }
        return null;
    }


}

```

# 5 删除策略资源实现类

```

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import nc.vo.pfxx.util.JsonUtils;
import nccloud.api.rest.utils.ResultMessageUtil;
import nccloud.commons.lang.StringUtils;
import nccloud.framework.core.exception.BusinessException;
import org.json.JSONString;

/**
 * openapi 删除策略
 */
public class DeleteStrategy extends AbstractStrategyResources implements IStrategyResources{

    @Override
    public JSONString execute(JSONString json) {
        //1 参数检验
        if ( json == null || StringUtils.isEmpty(json.toString())){
            return ResultMessageUtil.exceptionToJSON(new NullPointerException("输入参数不能为空！"));
        }
        //2 结构转换
        JSONObject obj = JSON.parseObject(json.toJSONString());

        //3 新增字段校验 =》 创建校验器
        JSONString deleteValidatorMsg = deleteValidator(obj);

        //4 幂等校验 根据自己的需求确定幂等字段 replacement =>  todo....
        if (IdempotentCheckUtil.isDuplicateRequest(obj.get("code").toString())) {
            return ResultMessageUtil.exceptionToJSON(new BusinessException("删除校验失败：重复请求，已幂等处理"));
        }

        //5 删除数据 =》 示例
        JSONString deleteResultString = executeDeleteData(obj);

        //6 数据构建返回
        JSONObject returnJson = new JSONObject();
        if(JsonUtils.isEmpty(deleteValidatorMsg) && JsonUtils.isEmpty(deleteResultString)){
            returnJson.put("result", "success");
            returnJson.put("msg", "删除成功");
        }else{
            returnJson.put("deleteValidatorResult", deleteValidatorMsg);
            returnJson.put("deleteResult", deleteResultString);
            returnJson.put("msg", "删除失败");
        }
        return ResultMessageUtil.toJSON(returnJson);

    }

    /**
     *  replacement =>  todo....
     * @param obj
     * @return
     */
    private JSONString executeDeleteData(JSONObject obj) {

        try {
            //getService()  => 抽象类中有 => todo...
        } catch (Exception e) {
            return ResultMessageUtil.exceptionToJSON(e);
        }
        return null;
    }

    /**
     *  replacement =>  todo....
     * @param json
     * @return
     */
    private JSONString deleteValidator(JSONObject json) {
        FieldValidator validator = new FieldValidator();
        validator.addField("字段编码", "字段名称");

        StringBuilder errorMsg = validator.validate(json);
        if (errorMsg.length() > 0) {
            return ResultMessageUtil.exceptionToJSON(new BusinessException("删除校验失败：" + errorMsg.toString()));
        }
        return null;
    }

}

```

# 6 查询策略资源实现类

```

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import nc.vo.pfxx.util.JsonUtils;
import nccloud.api.rest.utils.ResultMessageUtil;
import nccloud.commons.lang.StringUtils;
import nccloud.framework.core.exception.BusinessException;
import org.json.JSONString;

/**
 * openapi 查询策略
 */
public class QueryStrategy extends AbstractStrategyResources implements IStrategyResources{

    @Override
    public JSONString execute(JSONString json) {
        //1 参数检验
        if ( json == null || StringUtils.isEmpty(json.toString())){
            return ResultMessageUtil.exceptionToJSON(new NullPointerException("输入参数不能为空！"));
        }
        //2 结构转换
        JSONObject obj = JSON.parseObject(json.toJSONString());

        //3 查询字段校验 =》 创建校验器
        JSONString queryValidatorMsg = queryValidator(obj);

        //4 查询数据
        JSONString queryResultString = executeQueryData(obj);

        // 数据构建返回
        JSONObject returnJson = new JSONObject();
        if(JsonUtils.isEmpty(queryValidatorMsg) && JsonUtils.isEmpty(queryResultString)){
            returnJson.put("result", "success");
            returnJson.put("msg", "查询成功");
        }else{
            returnJson.put("queryValidatorResult", queryValidatorMsg);
            returnJson.put("queryResult", queryResultString);
            returnJson.put("msg", "查询失败");
        }
        return ResultMessageUtil.toJSON(returnJson);
    }

    /**
     * 执行查询逻辑
     * @param obj
     * @return
     */
    private JSONString executeQueryData(JSONObject obj) {
        //注意构建的vo状态需要为 VOStatus.NEW
        try {
            //getQueryService() => 抽象类中有 => todo...
        } catch (Exception e) {
            return ResultMessageUtil.exceptionToJSON(e);
        }
        return null;
    }

    /**
     * 查询校验
     * replacement =>  todo....
     * @param json
     */
    private JSONString queryValidator(JSONObject json) {
        FieldValidator validator = new FieldValidator();
        validator.addField("字段编码", "字段名称");

        StringBuilder errorMsg = validator.validate(json);
        if (errorMsg.length() > 0) {
            return ResultMessageUtil.exceptionToJSON(new BusinessException("查询校验失败：" + errorMsg.toString()));
        }
        return null;
    }

}


```

# 7 更新策略资源实现类

```

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import nc.vo.pfxx.util.JsonUtils;
import nccloud.api.rest.utils.ResultMessageUtil;
import nccloud.commons.lang.StringUtils;
import nccloud.framework.core.exception.BusinessException;
import org.json.JSONString;

/**
 * openapi 更新策略
 */
public class UpdateStrategy extends AbstractStrategyResources implements IStrategyResources{

    @Override
    public JSONString execute(JSONString json) {
        //1 参数检验
        if ( json == null || StringUtils.isEmpty(json.toString())){
            return ResultMessageUtil.exceptionToJSON(new NullPointerException("输入参数不能为空！"));
        }
        //2 结构转换
        JSONObject obj = JSON.parseObject(json.toJSONString());

        //3 更新字段校验 =》 创建校验器
        JSONString updateValidatorMsg = updateValidator(obj);

        //4 幂等校验   replacement =>  todo....
        if (IdempotentCheckUtil.isDuplicateRequest(obj.get("code").toString())) {
            return ResultMessageUtil.exceptionToJSON(new BusinessException("更新校验失败：重复请求，已幂等处理"));
        }

        //5 更新数据
        JSONString updateResultMsg = executeUpdateData(obj);

        //6 数据构建返回
        JSONObject returnJson = new JSONObject();
        if(JsonUtils.isEmpty(updateValidatorMsg) && JsonUtils.isEmpty(updateResultMsg)){
            returnJson.put("result", "success");
            returnJson.put("msg", "更新成功");
        }else{
            returnJson.put("updateValidatorResult", updateValidatorMsg);
            returnJson.put("updateResult", updateResultMsg);
            returnJson.put("msg", "更新失败");
        }
        return ResultMessageUtil.toJSON(returnJson);
    }

    /**
     * 更新数据
     * replacement =>  todo....
     * @param json
     */
    private JSONString executeUpdateData(JSONObject json) {
        //注意构建的vo状态需要为 VOStatus.UPDATED
        try {
//            JSONObject headJson = (JSONObject) json.get("head");
//            JSONArray bodysJson = json.getJSONArray("bodys");
//            IAttributeMeta[] headAttrs = headVO.getMetaData().getAttributes();
//            for (IAttributeMeta attribute : headAttrs) {
//                Object value = getValueByAttr(headJson, attribute);
//                headVO.setAttributeValue(attribute.getName(), value);
//            }
            //getService() =>  抽象类中有 => todo...
        } catch (Exception e) {
            return ResultMessageUtil.exceptionToJSON(e);
        }
        return null;
    }

    /**
     * 更新校验
     * replacement =>  todo....
     * @param json
     */
    private JSONString updateValidator(JSONObject json) {
        FieldValidator validator = new FieldValidator();
        validator.addField("字段编码", "字段名称");

        StringBuilder errorMsg = validator.validate(json);
        if (errorMsg.length() > 0) {
            return ResultMessageUtil.exceptionToJSON(new BusinessException("更新校验失败：" + errorMsg.toString()));
        }
        return null;
    }

}

```

# 8 资源策略上下文类

```

import java.util.HashMap;
import java.util.Map;
import nccloud.api.rest.utils.ResultMessageUtil;
import org.json.JSONString;

/**
 * 资源策略上下文
 */
public class StrategyContext {

    private Map<String, IStrategyResources> strategies = new HashMap<>();

    public StrategyContext() {
        strategies.put("add", new AddStrategy());
        strategies.put("delete", new DeleteStrategy());
        strategies.put("update", new UpdateStrategy());
        strategies.put("query", new QueryStrategy());
    }

    public JSONString executeStrategy(String methodName, JSONString obj)  {
        if (methodName == null || methodName.length() == 0) {
            return ResultMessageUtil.exceptionToJSON(new NullPointerException("执行策略的操作类型不能为空！"));
        }
        for (Map.Entry<String, IStrategyResources> entry : strategies.entrySet()) {
            if (methodName.indexOf(entry.getKey()) >= 0) {
                return entry.getValue().execute(obj);
            }
        }
        return ResultMessageUtil.exceptionToJSON(new UnsupportedOperationException("不支持的操作类型：" + methodName));
    }

}

```

# 9 OpenAPI资源类

```

package nccloud.api.resources;

import nccloud.ws.rest.resource.AbstractNCCRestResource;
import org.json.JSONString;
import javax.ws.rs.Consumes;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;

/**
 * OpenAPI资源类
 */
@Path("模块编码/组件编码+manage/实体编码")
public class DemoManageResources extends AbstractNCCRestResource {

    private final static StrategyContext context = new StrategyContext();

    private final static String modulecode = "模块编码";

    @Override
    public String getModule() {
        return modulecode;
    }

    @POST
    @Path("/add+实体编码")
    @Consumes({ "application/json" })
    @Produces({ "application/json" })
    public JSONString add(JSONString json) {
        return context.executeStrategy(StrategyKeyEnum.ADD.getKey(), json);
    }

    @POST
    @Path("/query+实体编码")
    @Consumes({ "application/json" })
    @Produces({ "application/json" })
    public JSONString query(JSONString json) {
        return context.executeStrategy(StrategyKeyEnum.QUERY.getKey(), json);
    }


    @POST
    @Path("/delete+实体编码")
    @Consumes({ "application/json" })
    @Produces({ "application/json" })
    public JSONString delete(JSONString json) {
        return context.executeStrategy(StrategyKeyEnum.DELETE.getKey(), json);
    }


    @POST
    @Path("/update+实体编码")
    @Consumes({ "application/json" })
    @Produces({ "application/json" })
    public JSONString update(JSONString json) {
        return context.executeStrategy(StrategyKeyEnum.UPDATE.getKey(), json);
    }

}

```

# 10 访问资源字段校验器

```

import java.util.HashMap;
import java.util.Map;
import com.alibaba.fastjson.JSONObject;
import nccloud.commons.lang.StringUtils;
import java.util.Map.Entry;
import java.util.Set;

/**
 * 访问资源字段校验器
 */
public class FieldValidator {

    // 存储字段名和中文名的映射
    private Map<String, String> fieldMap = new HashMap<>();

    // 动态添加字段
    public void addField(String fieldName, String fieldLabel) {
        fieldMap.put(fieldName, fieldLabel);
    }

    // 移除字段
    public void removeField(String fieldName) {
        fieldMap.remove(fieldName);
    }

    // 清空字段
    public void clearFields() {
        fieldMap.clear();
    }

    // 执行校验
    public StringBuilder validate(JSONObject jsonObject) {
        StringBuilder errorBuilder = new StringBuilder();

        Set<Entry<String, String>> entrySet = fieldMap.entrySet();
        for (Entry<String, String> entry : entrySet) {
            String fieldName = entry.getKey();
            String fieldLabel = entry.getValue();

            Object value = jsonObject.get(fieldName);
            if (value == null || StringUtils.isEmpty(value.toString())) {
                errorBuilder.append(fieldLabel).append("不能为空;");
            }
        }

        return errorBuilder;
    }

}

```

# 11 访问资源幂等校验工具类

```

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

/**
 * 访问资源幂等校验工具类
 */
public class IdempotentCheckUtil {

    // 存储请求标识和时间戳
    private static final Map<String, Long> REQUEST_CACHE = new ConcurrentHashMap<>();

    // 默认缓存过期时间（毫秒）：5分钟
    private static final long EXPIRE_TIME = 5 * 60 * 1000;

    // 定时清理过期请求标识的线程池
    private static final ScheduledExecutorService CLEANER = Executors.newSingleThreadScheduledExecutor();

    static {
        // 每隔1分钟清理一次过期数据
        CLEANER.scheduleAtFixedRate(IdempotentCheckUtil::cleanExpiredRequests, 1, 1, TimeUnit.MINUTES);
    }

    /**
     * 校验是否重复请求
     *
     * @param requestId 请求唯一标识（如 UUID、token、业务唯一键）
     * @return true 表示重复请求，false 表示首次请求
     */
    public static boolean isDuplicateRequest(String requestId) {
        if (requestId == null || requestId.isEmpty()) {
            return false;
        }

        long currentTime = System.currentTimeMillis();

        // 如果已存在且未过期，说明是重复请求
        if (REQUEST_CACHE.containsKey(requestId)) {
            return true;
        }

        // 否则记录请求标识
        REQUEST_CACHE.put(requestId, currentTime);
        return false;
    }

    /**
     * 清理过期的请求标识
     */
    private static void cleanExpiredRequests() {
        long currentTime = System.currentTimeMillis();
        REQUEST_CACHE.forEach((key, value) -> {
            if (currentTime - value > EXPIRE_TIME) {
                REQUEST_CACHE.remove(key);
            }
        });
    }

    /**
     * 手动移除某个请求标识（可选）
     *
     * @param requestId 请求标识
     */
    public static void removeRequestId(String requestId) {
        if (requestId != null && !requestId.isEmpty()) {
            REQUEST_CACHE.remove(requestId);
        }
    }
}
```

# 12 资源rest配置文件

```
说明：这个给用户创建文件时以upm文件进行创建 比如 => XXX.upm    

<?xml version="1.0" encoding='gb2312'?>
<module>
	<rest>
		<resource classname="DemoManageResources全路径"  exinfo=""/>
	</rest>
</module>
```

