java SDK对接金蝶数据包装类(仅查询)

java SDK对接金蝶

SDK下载地址

  1. 如果是Maven管理,可以在pom.xml中加入如下依赖:

    <!--    金蝶云对接    -->
    <dependency>
        <groupId>com.kingdee</groupId>
        <artifactId>k3cloud-webapi</artifactId>
        <version>1.0.0</version>
        <scope>system</scope>
        <!-- jar包存放的位置 -->
        <systemPath>${project.basedir}/lib/k3cloud-webapi-sdk7.9.2.jar</systemPath>
    </dependency>
    
  2. 起步配置有官方教程:查看官方指南

  3. 官网只提供了一些查询数据方法。对于java代码来说写起来很不舒服。下面我做了一些工具类。
    一共设计了10个java文件,下面简单的介绍一下
    (1) AbstractBuilder:抽象构造器,用于构建查询语句的SQL方法定义
    (2) FilterRuleBuilder: 通用的查询条件构造器,继承了AbstractBuilder,可构建常用的查询字段,条件等。使用方式类比mybatis-plus的QueryWrapper
    (3) Builder:针对于实体类的条件构造,继承了AbstractBuilder,修饰了FilterRuleBuilder。功能同上,使用方式类比mybatis-plus的Wrappers。注:如果不设置查询字段则查询类中所有字段
    (4) ConvertType:一个类型转换的枚举类,枚举了需要转换的位置。目的是为了将金蝶中查询字段和实体类的字段之间的_与.符号的转换处理。
    (5) SymbolConvert:符号转换注解,将需要指定特殊转换的字段写入该注解,即可,例:在金蝶中查询字段为A_B.C,java实体类中字段只能为A_B_C,故在该字段上标明@SymbolConvert(ConvertType.Last),表示转换字符只转最后一个。不写注解默认为转换所有符号
    (6) FormId:FormId 注解,看过API的都知道,这是标识查询金蝶的FormId值,不填默认为类名。
    (7) K3Const:K3使用的静态常量
    (8) SFunction:序列化函数式接口
    (9)SFunctionParse:函数式接口解析,很重要,其中解析了@SymbolConvert,解析了表达式
    (10) K3Api:金蝶数据接口工具类,最终使用的是这个查询,该类已注入Spring,可以通过@Autowired自动注入,作用域为一个Session。
    注:FilterRuleBuilder 和 Builder类提供特有的switchAND和switchOR来切换条件判断连接符,默认是and;可通过andLeft 和 orLeft 添加 ’ AND ( ’ 与 ’ OR ( ',通过right添加 ‘)’ 。以上类代码如下:

    3.1 AbstractBuilder抽象类

    
    import java.util.ArrayList;
    import java.util.Date;
    import java.util.List;
    
    /**
     * @Author
     * @Date 2022/5/16 10:03
     * @Description 抽象构造器
     */
    public abstract class AbstractBuilder<T> {
        /**
         * 定义所有的基本类型及包装类型,或者是String
         */
        protected static final List<String> generalType = new ArrayList<String>() {{
            add(Date.class.getName());
            add(Integer.class.getName());
            add(Double.class.getName());
            add(Float.class.getName());
            add(Long.class.getName());
            add(Short.class.getName());
            add(Byte.class.getName());
            add(Boolean.class.getName());
            add(Character.class.getName());
            add(String.class.getName());
            add("int");
            add("double");
            add("float");
            add("long");
            add("short");
            add("byte");
            add("boolean");
            add("char");
        }};
    
        /**
         * 查询参数构造器
         */
    
        protected List<String> fieldKeys = new ArrayList<>();
        /**
         * 过滤条件构造器
         */
        protected StringBuilder filterStrBuilder = new StringBuilder();
        /**
         * 排序规则条件构造器
         */
        protected StringBuilder orderBuilder = new StringBuilder();
        /**
         * 返回总行数
         */
        protected int TopRowCount = 0;
        /**
         * 开始行索引
         */
        protected int StartRow = 0;
        /**
         * 最大行数
         */
        protected int Limit = 0;
    
        protected final String LOGIC_AND = " AND ";
    
        protected final String LOGIC_OR = " OR ";
    
        /**
         * 获取查询字段
         *
         * @return
         */
        public abstract List<String> getFieldKeys();
    
    
        /**
         * 构建查询字段
         *
         * @return
         */
        public abstract String buildFieldKeys();
    
        /**
         * 构造查询条件
         *
         * @return
         */
        public abstract String buildFilter();
    
        /**
         * 构造排序条件
         *
         * @return
         */
        public abstract String buildOrder();
    
        /**
         * 构建总行数
         *
         * @return
         */
        public abstract int buildTopRowCount();
    
        /**
         * 构建起始行数
         *
         * @return
         */
        public abstract int buildStartRow();
    
        /**
         * 构建最大行数
         *
         * @return
         */
        public abstract int buildLimit();
    
    
    }
    

    3.2 FilterRuleBuilder类

    import java.lang.reflect.Field;
    import java.util.Date;
    import java.util.List;
    
    /**
     * @Author
     * @Date 2022/5/12 9:54
     * @Description K3Cloud 查询条件构造
     */
    public class FilterRuleBuilder extends AbstractBuilder {
    
        public FilterRuleBuilder() {
        }
    
    
        /**
         * 逻辑关系,默认and
         */
        protected String logic = LOGIC_AND;
    
        /**
         * 获取查询字段
         *
         * @return
         */
        public List<String> getFieldKeys() {
            return this.fieldKeys;
        }
    
        /**
         * 切换and逻辑
         *
         * @return
         */
        public FilterRuleBuilder switchAND() {
            logic = LOGIC_AND;
            return this;
        }
    
        /**
         * 切换or逻辑
         *
         * @return
         */
        public FilterRuleBuilder switchOR() {
            logic = LOGIC_OR;
            return this;
        }
    
        /**
         * 添加and左括号
         *
         * @return
         */
        public FilterRuleBuilder andLeft() {
            if (filterStrBuilder.length() == 0) {
                filterStrBuilder.append("(");
            } else {
                filterStrBuilder.append(LOGIC_AND + "(");
            }
            return this;
        }
    
        /**
         * 添加or左括号
         *
         * @return
         */
        public FilterRuleBuilder orLeft() {
            if (filterStrBuilder.length() == 0) {
                filterStrBuilder.append("(");
            } else {
                filterStrBuilder.append(LOGIC_OR + "(");
            }
            return this;
        }
    
        /**
         * 添加右括号
         *
         * @return
         */
        public FilterRuleBuilder right() {
            filterStrBuilder.append(")");
            return this;
        }
    
        /**
         * 列表查询字段
         *
         * @param fieldKeys
         * @return
         */
        public FilterRuleBuilder select(List<String> fieldKeys) {
            this.fieldKeys = fieldKeys;
            return this;
        }
    
        /**
         * 查询具体类的所有字段
         *
         * @param cls
         * @return
         */
        public FilterRuleBuilder selectAllFiled(Class cls) {
            Field[] fields = cls.getDeclaredFields();
            for (Field field : fields) {
                String fieldName = SFunctionParse.convertField(cls, field.getName());
                select(fieldName);
            }
            return this;
        }
    
        /**
         * 添加查询字段
         *
         * @param fieldKey
         * @return
         */
        public FilterRuleBuilder select(String fieldKey) {
            fieldKeys.add(fieldKey);
            return this;
        }
    
        /**
         * 添加多个查询字段
         *
         * @param fieldKeys
         * @return
         */
        public FilterRuleBuilder select(String... fieldKeys) {
            for (String fieldKey : fieldKeys) {
                select(fieldKey);
            }
            return this;
        }
    
    
        /**
         * 多字段排序
         *
         * @param fieldNames
         * @return
         */
        public FilterRuleBuilder orderBy(boolean isDesc, String... fieldNames) {
            // 不为空加逻辑关系
            if (orderBuilder.length() != 0) {
                orderBuilder.append(",");
            }
            for (String fieldName : fieldNames) {
                if (isDesc) {
                    orderBuilder.append(String.format("%s DESC,", fieldName));
                } else {
                    orderBuilder.append(String.format("%s ASC,", fieldName));
                }
    
            }
            // 删除最后一个字符
            orderBuilder.deleteCharAt(orderBuilder.length() - 1);
    
            return this;
        }
    
        /**
         * 正序排序
         *
         * @param fieldName
         * @return
         */
        public FilterRuleBuilder orderByAsc(String fieldName) {
            // 不为空加逻辑关系
            if (orderBuilder.length() != 0) {
                orderBuilder.append(",");
            }
            orderBuilder.append(String.format("%s ASC", fieldName));
            return this;
        }
    
        /**
         * 倒序排序
         *
         * @param fieldName
         * @return
         */
        public FilterRuleBuilder orderByDesc(String fieldName) {
            // 不为空加逻辑关系
            if (orderBuilder.length() != 0) {
                orderBuilder.append(",");
            }
            orderBuilder.append(String.format("%s DESC", fieldName));
            return this;
        }
    
        /**
         * 等于构造
         *
         * @param fieldName
         * @param value
         * @return
         */
        public FilterRuleBuilder eq(String fieldName, Object value) {
            // 不为空加逻辑关系,或者前面为左括号不加
            if (filterStrBuilder.length() != 0 && filterStrBuilder.charAt(filterStrBuilder.length() - 1) != '(') {
                filterStrBuilder.append(logic);
            }
            // 字母或数字要加引号
            if (value instanceof String || value instanceof Date) {
                filterStrBuilder.append(String.format("(%s = '%s')", fieldName, value));
            } else {
                filterStrBuilder.append(String.format("(%s = %s)", fieldName, value));
            }
            return this;
        }
    
        /**
         * 不等于构造
         *
         * @param fieldName
         * @param value
         * @return
         */
        public FilterRuleBuilder ne(String fieldName, Object value) {
            // 不为空加逻辑关系,或者前面为左括号不加
            if (filterStrBuilder.length() != 0 && filterStrBuilder.charAt(filterStrBuilder.length() - 1) != '(') {
                filterStrBuilder.append(logic);
            }
            // 字母或数字要加引号
            if (value instanceof String || value instanceof Date) {
                filterStrBuilder.append(String.format("(%s <> '%s')", fieldName, value));
            } else {
                filterStrBuilder.append(String.format("(%s <> %s)", fieldName, value));
            }
            return this;
        }
    
        /**
         * 小于构造
         *
         * @param fieldName
         * @param value
         * @return
         */
        public FilterRuleBuilder lt(String fieldName, Object value) {
            // 不为空加逻辑关系,或者前面为左括号不加
            if (filterStrBuilder.length() != 0 && filterStrBuilder.charAt(filterStrBuilder.length() - 1) != '(') {
                filterStrBuilder.append(logic);
            }
            // 字母或数字要加引号
            if (value instanceof String || value instanceof Date) {
                filterStrBuilder.append(String.format("(%s < '%s')", fieldName, value));
            } else {
                filterStrBuilder.append(String.format("(%s < %s)", fieldName, value));
            }
            return this;
        }
    
        /**
         * 大于构造
         *
         * @param fieldName
         * @param value
         * @return
         */
        public FilterRuleBuilder gt(String fieldName, Object value) {
            // 不为空加逻辑关系,或者前面为左括号不加
            if (filterStrBuilder.length() != 0 && filterStrBuilder.charAt(filterStrBuilder.length() - 1) != '(') {
                filterStrBuilder.append(logic);
            }
            // 字母或数字要加引号
            if (value instanceof String || value instanceof Date) {
                filterStrBuilder.append(String.format("(%s > '%s')", fieldName, value));
            } else {
                filterStrBuilder.append(String.format("(%s > %s)", fieldName, value));
            }
            return this;
        }
    
        /**
         * 小于等于构造
         *
         * @param fieldName
         * @param value
         * @return
         */
        public FilterRuleBuilder le(String fieldName, Object value) {
            // 不为空加逻辑关系,或者前面为左括号不加
            if (filterStrBuilder.length() != 0 && filterStrBuilder.charAt(filterStrBuilder.length() - 1) != '(') {
                filterStrBuilder.append(logic);
            }
            // 字母或数字要加引号
            if (value instanceof String || value instanceof Date) {
                filterStrBuilder.append(String.format("(%s <= '%s')", fieldName, value));
            } else {
                filterStrBuilder.append(String.format("(%s <= %s)", fieldName, value));
            }
            return this;
        }
    
        /**
         * 大于等于构造
         *
         * @param fieldName
         * @param value
         * @return
         */
        public FilterRuleBuilder ge(String fieldName, Object value) {
            // 不为空加逻辑关系,或者前面为左括号不加
            if (filterStrBuilder.length() != 0 && filterStrBuilder.charAt(filterStrBuilder.length() - 1) != '(') {
                filterStrBuilder.append(logic);
            }
            // 字母或数字要加引号
            if (value instanceof String || value instanceof Date) {
                filterStrBuilder.append(String.format("(%s >= '%s')", fieldName, value));
            } else {
                filterStrBuilder.append(String.format("(%s >= %s)", fieldName, value));
            }
            return this;
        }
    
        /**
         * 模糊=构造
         *
         * @param fieldName
         * @param value
         * @return
         */
        public FilterRuleBuilder like(String fieldName, Object value) {
            // 不为空加逻辑关系,或者前面为左括号不加
            if (filterStrBuilder.length() != 0 && filterStrBuilder.charAt(filterStrBuilder.length() - 1) != '(') {
                filterStrBuilder.append(logic);
            }
            // 字母或数字要加引号
            if (value instanceof String || value instanceof Date) {
                filterStrBuilder.append("(" + fieldName + " LIKE '%" + value + "%')");
            }
            return this;
        }
    
        /**
         * 模糊<>构造
         *
         * @param fieldName
         * @param value
         * @return
         */
        public FilterRuleBuilder notLike(String fieldName, Object value) {
            // 不为空加逻辑关系,或者前面为左括号不加
            if (filterStrBuilder.length() != 0 && filterStrBuilder.charAt(filterStrBuilder.length() - 1) != '(') {
                filterStrBuilder.append(logic);
            }
            // 字母或数字要加引号
            if (value instanceof String || value instanceof Date) {
                filterStrBuilder.append("(" + fieldName + " NOT LIKE '%" + value + "%')");
            }
            return this;
        }
    
        /**
         * 模糊Left构造
         *
         * @param fieldName
         * @param value
         * @return
         */
        public FilterRuleBuilder likeLeft(String fieldName, Object value) {
            // 不为空加逻辑关系,或者前面为左括号不加
            if (filterStrBuilder.length() != 0 && filterStrBuilder.charAt(filterStrBuilder.length() - 1) != '(') {
                filterStrBuilder.append(logic);
            }
            // 字母或数字要加引号
            if (value instanceof String || value instanceof Date) {
                filterStrBuilder.append("(" + fieldName + " LIKE '%" + value + "')");
            }
            return this;
        }
    
        /**
         * 模糊Right构造
         *
         * @param fieldName
         * @param value
         * @return
         */
        public FilterRuleBuilder likeRight(String fieldName, Object value) {
            // 不为空加逻辑关系,或者前面为左括号不加
            if (filterStrBuilder.length() != 0 && filterStrBuilder.charAt(filterStrBuilder.length() - 1) != '(') {
                filterStrBuilder.append(logic);
            }
            // 字母或数字要加引号
            if (value instanceof String || value instanceof Date) {
                filterStrBuilder.append("(" + fieldName + " LIKE '" + value + "%')");
            }
            return this;
        }
    
    
        /**
         * between 连接
         *
         * @param fieldName
         * @param startVal
         * @param endVal
         * @return
         */
        public FilterRuleBuilder between(String fieldName, Object startVal, Object endVal) {
            // 不为空加逻辑关系,或者前面为左括号不加
            if (filterStrBuilder.length() != 0 && filterStrBuilder.charAt(filterStrBuilder.length() - 1) != '(') {
                filterStrBuilder.append(logic);
            }
            // 字母或数字要加引号
            if (startVal instanceof String || startVal instanceof Date) {
                filterStrBuilder.append(String.format("(%s BETWEEN '%s'", fieldName, startVal));
            } else {
                filterStrBuilder.append(String.format("(%s BETWEEN %s", fieldName, startVal));
            }
            if (endVal instanceof String || endVal instanceof Date) {
                filterStrBuilder.append(String.format(" AND '%s')", endVal));
            } else {
                filterStrBuilder.append(String.format(" AND '%s')", endVal));
            }
            return this;
        }
    
        /**
         * netBetween 连接
         *
         * @param fieldName
         * @param startVal
         * @param endVal
         * @return
         */
        public FilterRuleBuilder notBetween(String fieldName, Object startVal, Object endVal) {
            // 不为空加逻辑关系,或者前面为左括号不加
            if (filterStrBuilder.length() != 0 && filterStrBuilder.charAt(filterStrBuilder.length() - 1) != '(') {
                filterStrBuilder.append(logic);
            }
            // 字母或数字要加引号
            if (startVal instanceof String || startVal instanceof Date) {
                filterStrBuilder.append(String.format("(%s NOT BETWEEN '%s'", fieldName, startVal));
            } else {
                filterStrBuilder.append(String.format("(%s NOT BETWEEN %s", fieldName, startVal));
            }
            if (endVal instanceof String || endVal instanceof Date) {
                filterStrBuilder.append(String.format(" AND '%s')", endVal));
            } else {
                filterStrBuilder.append(String.format(" AND '%s')", endVal));
            }
            return this;
        }
    
        /**
         * 为空构造
         *
         * @param fieldName
         * @return
         */
        public FilterRuleBuilder isNull(String fieldName) {
            /// 不为空加逻辑关系,或者前面为左括号不加
            if (filterStrBuilder.length() != 0 && filterStrBuilder.charAt(filterStrBuilder.length() - 1) != '(') {
                filterStrBuilder.append(logic);
            }
            filterStrBuilder.append(String.format("(%s IS NULL)", fieldName));
            return this;
        }
    
    
        /**
         * 不为空构造
         *
         * @param fieldName
         * @return
         */
        public FilterRuleBuilder isNotNull(String fieldName) {
            // 不为空加逻辑关系,或者前面为左括号不加
            if (filterStrBuilder.length() != 0 && filterStrBuilder.charAt(filterStrBuilder.length() - 1) != '(') {
                filterStrBuilder.append(logic);
            }
            filterStrBuilder.append(String.format("(%s IS NOT NULL)", fieldName));
            return this;
        }
    
        /**
         * 构建查询字段
         *
         * @return
         */
        public String buildFieldKeys() {
            return String.join(",", fieldKeys);
        }
    
        /**
         * 总行数
         *
         * @param topRowCount
         * @return
         */
        public FilterRuleBuilder topRowCount(int topRowCount) {
            this.TopRowCount = topRowCount;
            return this;
        }
    
        /**
         * 起始行数
         *
         * @param startRow
         * @return
         */
        public FilterRuleBuilder startRow(int startRow) {
            this.StartRow = startRow;
            return this;
        }
    
        /**
         * 最大行数,不可超过2000
         *
         * @param limit
         * @return
         */
        public FilterRuleBuilder limit(int limit) {
            if (limit < 2000) {
                this.Limit = limit;
            } else {
                this.Limit = 2000;
            }
            return this;
        }
    
        /**
         * 构造查询条件
         *
         * @return
         */
        @Override
        public String buildFilter() {
            if (filterStrBuilder.length() != 0) {
                return this.filterStrBuilder.toString();
            } else {
                return "";
            }
        }
    
        /**
         * 构造排序条件
         *
         * @return
         */
        @Override
        public String buildOrder() {
            if (orderBuilder.length() != 0) {
                return this.orderBuilder.toString();
            } else {
                return "";
            }
        }
    
        /**
         * 构建总行数
         *
         * @return
         */
        @Override
        public int buildTopRowCount() {
            return this.TopRowCount;
        }
    
        /**
         * 构建起始行数
         *
         * @return
         */
        @Override
        public int buildStartRow() {
            return this.StartRow;
        }
    
        /**
         * 构建最大行数
         *
         * @return
         */
        @Override
        public int buildLimit() {
            return this.Limit;
        }
    }
    
    

    3.3 Builder类

    import java.lang.reflect.Field;
    import java.lang.reflect.ParameterizedType;
    import java.lang.reflect.Type;
    import java.util.List;
    
    /**
     * @Author
     * @Date 2022/5/14 8:35
     * @Description 针对类的条件构造
     */
    public final class Builder<T> extends AbstractBuilder<T> {
        /**
         * 字段构建器,增强其功能
         */
        private FilterRuleBuilder ruleBuilder;
    
        /**
         * class类
         */
        private Class<T> cls;
    
        public Builder(Class<T> cls) {
            this.cls = cls;
            this.ruleBuilder = new FilterRuleBuilder();
        }
    
        public Class<T> getObjClass() {
            return cls;
        }
    
        /**
         * 静态构造器
         *
         * @param cls
         * @param <T>
         * @return
         */
        public static final <T> Builder<T> builder(Class<T> cls) {
            return new Builder<>(cls);
        }
    
    
        public Builder<T> selectAll() {
            ruleBuilder.selectAllFiled(cls);
            return this;
        }
    
        public <R> Builder<T> select(SFunction<T, R>... fieldNames) {
            ruleBuilder.select(SFunctionParse.resolves(fieldNames));
            return this;
        }
    
        /**
         * 该方法用于查询一个复合类型class,
         * 查询class的包含Object属性或者List属性字段
         *
         * @return
         */
        public Builder<T> selectAllGeneralField() {
            Field[] fields = cls.getDeclaredFields();
            for (Field field : fields) {
                Class<?> fieldType = field.getType();
                // 是否为基本类型或数组
                if (generalType.contains(fieldType.getName()) || fieldType.isArray()) {
                    ruleBuilder.select(SFunctionParse.convertField(cls, field.getName()));
                } else if (fieldType == List.class) {// 列表类型
                    // 获取列表中的泛型
                    Type genericType = field.getGenericType();
                    // 获取类型Class
                    if (genericType instanceof ParameterizedType) {
                        ParameterizedType typeCls = (ParameterizedType) genericType;
                        Class subGenericClass = (Class<?>) typeCls.getActualTypeArguments()[0];
                        Field[] subFields = subGenericClass.getDeclaredFields();
                        for (Field subField : subFields) {
                            ruleBuilder.select(SFunctionParse.convertField(subGenericClass, subField.getName()));
                        }
                    }
                }
            }
            return this;
        }
    
        public <R> Builder<T> orderBy(boolean isDesc, SFunction<T, R>... fieldNames) {
            ruleBuilder.orderBy(isDesc, SFunctionParse.resolves(fieldNames));
            return this;
        }
    
        public <R> Builder<T> orderByAsc(SFunction<T, R> fieldName) {
            ruleBuilder.orderByAsc(SFunctionParse.resolve(fieldName));
            return this;
        }
    
        public <R> Builder<T> orderByDesc(SFunction<T, R> fieldName) {
            ruleBuilder.orderByDesc(SFunctionParse.resolve(fieldName));
            return this;
        }
    
        public <R> Builder<T> eq(SFunction<T, R> fieldName, Object value) {
            ruleBuilder.eq(SFunctionParse.resolve(fieldName), value);
            return this;
        }
    
        public <R> Builder<T> ne(SFunction<T, R> fieldName, Object value) {
            ruleBuilder.ne(SFunctionParse.resolve(fieldName), value);
            return this;
        }
    
        public <R> Builder<T> lt(SFunction<T, R> fieldName, Object value) {
            ruleBuilder.lt(SFunctionParse.resolve(fieldName), value);
            return this;
        }
    
        public <R> Builder<T> gt(SFunction<T, R> fieldName, Object value) {
            ruleBuilder.gt(SFunctionParse.resolve(fieldName), value);
            return this;
        }
    
        public <R> Builder<T> le(SFunction<T, R> fieldName, Object value) {
            ruleBuilder.le(SFunctionParse.resolve(fieldName), value);
            return this;
        }
    
        public <R> Builder<T> ge(SFunction<T, R> fieldName, Object value) {
            ruleBuilder.ge(SFunctionParse.resolve(fieldName), value);
            return this;
        }
    
        public <R> Builder<T> like(SFunction<T, R> fieldName, Object value) {
            ruleBuilder.like(SFunctionParse.resolve(fieldName), value);
            return this;
        }
    
        public <R> Builder<T> notLike(SFunction<T, R> fieldName, Object value) {
            ruleBuilder.notLike(SFunctionParse.resolve(fieldName), value);
            return this;
        }
    
        public <R> Builder<T> likeLeft(SFunction<T, R> fieldName, Object value) {
            ruleBuilder.likeLeft(SFunctionParse.resolve(fieldName), value);
            return this;
        }
    
        public <R> Builder<T> likeRight(SFunction<T, R> fieldName, Object value) {
            ruleBuilder.likeRight(SFunctionParse.resolve(fieldName), value);
            return this;
        }
    
        public <R> Builder<T> between(SFunction<T, R> fieldName, Object startVal, Object endVal) {
            ruleBuilder.between(SFunctionParse.resolve(fieldName), startVal, endVal);
            return this;
        }
    
        public <R> Builder<T> notBetween(SFunction<T, R> fieldName, Object startVal, Object endVal) {
            ruleBuilder.notBetween(SFunctionParse.resolve(fieldName), startVal, endVal);
            return this;
        }
    
        public <R> Builder<T> isNull(SFunction<T, R> fieldName) {
            ruleBuilder.isNull(SFunctionParse.resolve(fieldName));
            return this;
        }
    
        public <R> Builder<T> isNotNull(SFunction<T, R> fieldName) {
            ruleBuilder.isNotNull(SFunctionParse.resolve(fieldName));
            return this;
        }
    
    
        public Builder<T> switchAND() {
            ruleBuilder.switchAND();
            return this;
        }
    
        public Builder<T> switchOR() {
            ruleBuilder.switchOR();
            return this;
        }
    
        /**
         * 添加and左括号
         *
         * @return
         */
        public Builder<T> andLeft() {
            ruleBuilder.andLeft();
            return this;
        }
    
        /**
         * 添加or左括号
         *
         * @return
         */
        public Builder<T> orLeft() {
            ruleBuilder.orLeft();
            return this;
        }
    
        /**
         * 添加右括号
         *
         * @return
         */
        public Builder<T> right() {
            ruleBuilder.right();
            return this;
        }
    
        public Builder<T> topRowCount(int topRowCount) {
            ruleBuilder.topRowCount(topRowCount);
            return this;
        }
    
    
        public Builder<T> startRow(int startRow) {
            ruleBuilder.startRow(startRow);
            return this;
        }
    
        public Builder<T> limit(int limit) {
            ruleBuilder.limit(limit);
            return this;
        }
    
        @Override
        public List<String> getFieldKeys() {
            return ruleBuilder.getFieldKeys();
        }
    
        /**
         * 如果没有设置查询字段,默认查询所有
         * @return
         */
        @Override
        public String buildFieldKeys() {
            if(fieldKeys.size() == 0){
                selectAll();
            }
            return ruleBuilder.buildFieldKeys();
        }
    
        @Override
        public String buildFilter() {
            return ruleBuilder.buildFilter();
        }
    
        @Override
        public String buildOrder() {
            return ruleBuilder.buildOrder();
        }
    
        @Override
        public int buildTopRowCount() {
            return ruleBuilder.buildTopRowCount();
        }
    
        @Override
        public int buildStartRow() {
            return ruleBuilder.buildStartRow();
        }
    
        @Override
        public int buildLimit() {
            return ruleBuilder.buildLimit();
        }
    }
    

    3.4 ConvertType枚举

    /**
     * @Author
     * @Date 2022/5/28 10:15
     * @Description 转换类型 将_转换为.的类型
     */
    public enum ConvertType {
        /**
         * 全部转换
         */
        ALL,
        /**
         * 全部不转换
         */
        NO_ALL,
        /**
         * 转换最后一个
         */
        Last,
    //    ============================以下真实场景没意义====================================
        /**
         * 转换第一个
         */
        FIRST,
    
        /**
         * 不转换第一个
         */
        NO_FIRST,
        /**
         * 不转换最后一个
         */
        NO_LAST,
    }
    

    3.5 SymbolConvert注解

    import java.lang.annotation.ElementType;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    import java.lang.annotation.Target;
    
    /**
     * @Author
     * @Date 2022/5/28 10:09
     * @Description 符号转换值
     */
    @Target(ElementType.FIELD)
    @Retention(RetentionPolicy.RUNTIME)
    public @interface SymbolConvert {
        /**
         * 默认全部转换
         * @return
         */
        ConvertType value() default ConvertType.ALL;
    }
    
    

    3.6 FormId注解

    import java.lang.annotation.ElementType;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    import java.lang.annotation.Target;
    
    /**
     * @Author
     * @Date 2022/5/16 10:32
     * @Description 查询表单Id,如不写,默认为类名
     */
    @Target(ElementType.TYPE)
    @Retention(RetentionPolicy.RUNTIME)
    public @interface FormId {
        String value() default "";
    }
    

    3.7 K3Const常量类

    /**
     * @Author
     * @Date 2022/7/20 9:40
     * @Description K3使用的静态常量
     */
    public final class K3Const {
        public static final String ENABLE = "A";
        public static final String DISABLE = "B";
    }
    

    3.8 SFunction接口

    import java.io.Serializable;
    import java.util.function.Function;
    
    /**
     * @Author
     * @Date 2022/5/14 08:33
     * @Description 序列化函数式接口
     */
    @FunctionalInterface
    public interface SFunction<T, R> extends Function<T, R>, Serializable {
    }
    

    3.9 SFunctionParse类

    import java.lang.invoke.SerializedLambda;
    import java.lang.reflect.Field;
    import java.lang.reflect.Method;
    
    /**
     * @Author
     * @Date 2022/5/16 8:45
     * @Description TODO
     */
    public final class SFunctionParse {
    
        /**
         * java属性转K3查询字段
         * 将属性中的_符号转.
         *
         * @param cls  属性存在的类
         * @param attr
         * @return
         */
        public final static <T> String convertField(Class<T> cls, String attr) {
            try {
                // 没有类,全部转换
                if (cls == null) {
                    return attr.replace("_", ".");
                }
                // 获取字段
                Field field = cls.getDeclaredField(attr);
                // 获取属性的符号转换注解
                SymbolConvert symbolConvert = field.getAnnotation(SymbolConvert.class);
                // 不存在全部转换
                if (symbolConvert == null) {
                    return attr.replace("_", ".");
                }
                ConvertType type = symbolConvert.value();
                String[] strings = attr.split("_");
                StringBuilder builder = new StringBuilder();
                int length = strings.length;
                // 存在判断
                switch (type) {
                    case ALL:
                        // 所有都转
                        return attr.replace("_", ".");
                    case NO_ALL:
                        // 所有都不转
                        return attr;
                    case Last:
                        for (int i = 0; i < length - 1; i++) {
                            builder.append(strings[i]).append("_");
                        }
                        // 最后一个转
                        builder.deleteCharAt(builder.length() - 1).append("." + strings[length - 1]);
                        return builder.toString();
                    case NO_FIRST:
                        // 第一个不转
                        builder.append(strings[0] + "_");
                        // 其余都转
                        for (int i = 1; i < length; i++) {
                            builder.append(strings[i] + ".");
                        }
                        builder.deleteCharAt(builder.length() - 1);
                        return builder.toString();
                    case NO_LAST:
                        // 其余转
                        for (int i = 0; i < length - 1; i++) {
                            builder.append(strings[i] + ".");
                        }
                        // 最后一个不转
                        builder.deleteCharAt(builder.length() - 1).append("_" + strings[length - 1]);
                        return builder.toString();
                    case FIRST:
                        // 第一个转
                        builder.append(strings[0] + ".");
                        // 其余不转
                        for (int i = 1; i < length; i++) {
                            builder.append(strings[i] + "_");
                        }
                        builder.deleteCharAt(builder.length() - 1);
                        return builder.toString();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
            return "";
        }
        
        /**
         * K3查询字段转java属性,字段不能包含. ,必须全转
         * 将属性中的.符号转_
         *
         * @param field
         * @return
         */
        public final static <T> String convertAttr(String field) {
            return field.replace(".", "_");
        }
    
        /**
         * 解析多个表达式
         *
         * @param functions
         * @param convertPoint 是否将字段名中的_转换为点
         * @param <R>
         * @return
         * @throws Exception
         */
        public static final <T, R> String[] resolves(Boolean convertPoint, SFunction<T, R>... functions) {
            String[] fileNames = new String[functions.length];
            String fileName;
            try {
                for (int i = 0; i < functions.length; i++) {
                    SFunction<T, R> function = functions[i];
                    // 直接调用writeReplace
                    Method methods = function.getClass().getDeclaredMethod("writeReplace");
                    methods.setAccessible(true);
                    //反射调用
                    Object sl = methods.invoke(function);
                    SerializedLambda serializedLambda = (SerializedLambda) sl;
                    // 获取类
                    String implClass = serializedLambda.getImplClass();
                    Class<?> aClass = Class.forName(implClass.replace("/", "."));
                    // 获取方法名
                    String methodName = serializedLambda.getImplMethodName();
                    String name = methodName.replace("get", "");
                    // 首字母大写
                    fileName = name.substring(0, 1) + name.substring(1);
                    if (convertPoint) {
                        // 将_替换为.改成查询字段
                        fileName = convertField(aClass, fileName);
                    }
                    fileNames[i] = fileName;
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
            return fileNames;
        }
    
        /**
         * 解析多个表达式, 默认将字段名的_转为.
         *
         * @param functions
         * @param <R>
         * @return
         * @throws Exception
         */
        public static final <T, R> String[] resolves(SFunction<T, R>... functions) {
            return resolves(true, functions);
        }
    
        /**
         * 解析一个表达式
         *
         * @param function
         * @param convertPoint 是否将字段名的下划线转为点
         * @param <R>
         * @return
         * @throws Exception
         */
        public static final <T, R> String resolve(Boolean convertPoint, SFunction<T, R> function) {
            return resolves(convertPoint, function)[0];
        }
    
        /**
         * 解析一个表达式 ,默认将字段名的_转为.
         *
         * @param function
         * @param <R>
         * @return
         * @throws Exception
         */
        public static final <T, R> String resolve(SFunction<T, R> function) {
            return resolve(true, function);
        }
    
    
    }
    

    3.10 K3Api类

    import com.google.gson.internal.LinkedTreeMap;
    import com.kingdee.bos.webapi.entity.QueryParam;
    import com.kingdee.bos.webapi.sdk.K3CloudApi;
    import com.kingdee.bos.webapi.utils.CfgUtil;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.context.annotation.ComponentScan;
    import org.springframework.stereotype.Component;
    import org.springframework.web.context.annotation.SessionScope;
    
    import java.lang.reflect.Field;
    import java.lang.reflect.Method;
    import java.lang.reflect.ParameterizedType;
    import java.lang.reflect.Type;
    import java.text.SimpleDateFormat;
    import java.util.*;
    
    /**
     * @Author 张港
     * @Date 2022/5/11 14:29
     * @Description 金蝶数据接口工具类
     */
    @Component
    @ComponentScan("com.hpmont.scan.util.K3")
    @SessionScope // 防止多用户请求,字段混乱问题
    public class K3Api  {
    
        private final Logger log = LoggerFactory.getLogger(K3Api.class);
        /**
         * K3Cloud对象
         */
        private final K3CloudApi api;
    
        /**
         * 当次查询字段
         */
        private List<String> fieldKeys;
    
        /**
         * SDK方法中获取路径为项目根目录。
         * 反射修改配置文件路径为空,改变配置文件的获取方式为流获取。
         * 改成从项目中jar包读取。隐藏配置文件
         */
        public K3Api() {
            try {
                Class<CfgUtil> cls = CfgUtil.class;
                Method method = cls.getDeclaredMethod("setCfgFilePath", String.class);
                method.setAccessible(true);
                method.invoke(null,"");
            } catch (Exception e) {
                e.printStackTrace();
            }
            api = new K3CloudApi();
        }
    
        /**
         * 解析类上的注解FormId,获取表单Id
         *
         * @param cls
         * @param <T>
         * @return 存在返回FormId,不存在返回空字符
         */
        public <T> String getFormId(Class<T> cls) {
            if(cls == null){
                return "";
            }
            FormId formId = cls.getDeclaredAnnotation(FormId.class);
            if (formId != null) {
                return formId.value();
            } else {
                // 不存在获取类名
                String[] strings = cls.getName().split("\\.");
                return strings[strings.length-1];
            }
        }
    
        /**
         * 获取字段的值
         *
         * @param filedName 字段名称
         * @param obj       对象
         * @return
         */
        private final Object getFieldValue(String filedName, Object obj) {
            try {
                Class<?> objCls = obj.getClass();
                String firstLetter = filedName.substring(0, 1).toUpperCase();
                String getter = "get" + firstLetter + filedName.substring(1);
                Method method = objCls.getMethod(getter, new Class[]{});
                Object value = method.invoke(obj, new Object[]{});
                return value;
            } catch (Exception e) {
                e.printStackTrace();
                return null;
            }
        }
    
        /**
         * 检测查询结果是否异常
         * 错误结果封装格式为: list中包含
         *
         * @param result
         * @return
         */
        public void checkException(List<List<Object>> result) {
            if(result == null){
                throw new CustomException(ErrCode.ERROR_0,"K3连接异常");
            }
            // 返回结果为1条记录,可能为错误信息
            if (result.size() != 1) {
                return;
            }
            List<Object> objList = result.get(0);
            // 每条记录仅一个字段,有可能为错误信息
            if (objList.size() != 1) {
                return;
            }
            Object resultObj = objList.get(0);
            // 错误信息的结果为LinkedTreeMap
            if (!(resultObj instanceof LinkedTreeMap)) {
                return;
            }
            LinkedTreeMap resultMap1 = (LinkedTreeMap) resultObj;
            // 获取一个叫Result的属性
            Object resultObj2 = resultMap1.get("Result");
            if (!(resultObj2 instanceof LinkedTreeMap)) {
                return;
            }
            LinkedTreeMap resultMap2 = (LinkedTreeMap) resultObj2;
            // 获取一个ResponseStatus的属性
            Object respStatusObj = resultMap2.get("ResponseStatus");
            if (!(respStatusObj instanceof LinkedTreeMap)) {
                return;
            }
            /**
             * respStatus为一个响应结果对象
             *  {
             *      ErrorCode: Integer,
             *      IsSuccess: Boolean,
             *      Errors: ArrayList,
             *      SuccessEntitys: ArrayList,
             *      SuccessMessages: ArrayList,
             *      MsgCode: Integer,
             *  }
             */
            LinkedTreeMap respStatus = (LinkedTreeMap) respStatusObj;
            Boolean isSuccess = (Boolean) respStatus.get("IsSuccess");
            // 响应成功
            if (isSuccess) {
                return;
            }
            StringBuffer errorMsg = new StringBuffer("K3友情提示:");
            // 拼接错误消息
            List<LinkedTreeMap> errorList = (List<LinkedTreeMap>) respStatus.get("Errors");
            errorList.forEach(error -> errorMsg.append((String) error.get("Message")).append(";"));
            errorMsg.deleteCharAt(errorMsg.length() - 1);
            // 获取错误码 共有0-13种可能
            Integer msgCode = (Integer) respStatus.get("MsgCode");
            switch (msgCode) {
                case 1:
                 	log.error("上下文丢失:{}",errorMsg.toString());
                case 2:
                    log.error("没有权限:{}",errorMsg.toString());
                case 3:
                    log.error("操作标识为空:{}",errorMsg.toString());
                case 4:
                    log.error("异常:{}",errorMsg.toString());
                case 5:
                    log.error("单据标识为空:{}",errorMsg.toString());
                case 6:
                    log.error("数据库操作失败:{}",errorMsg.toString());
                case 7:
                    log.error("许可错误:{}",errorMsg.toString());
                case 8:
                    log.error("参数错误:{}",errorMsg.toString());
                case 9:
                    log.error("指定字段/值不存在:{}",errorMsg.toString());
                case 10:
                    log.error("未找到对应数据:{}",errorMsg.toString());
                case 11:
                    log.error("验证失败:{}",errorMsg.toString());
                case 12:
                    log.error("不可操作:{}",errorMsg.toString());
                case 13:
                    log.error("网控冲突:{}",errorMsg.toString());
                default:
                    log.error("默认:{}",errorMsg.toString());
            }
        }
    
        /**
         * 设置字段的值
         *
         * @param filedName 字段名称
         * @param value     字段值
         * @param obj       对象
         * @return
         */
        private final void setFieldValue(String filedName, Object value, Object obj) {
            try {
                Class<?> objClass = obj.getClass();
                Field field = objClass.getDeclaredField(filedName);
                String firstLetter = filedName.substring(0, 1).toUpperCase();
                String setter = "set" + firstLetter + filedName.substring(1);
                Method method = objClass.getMethod(setter, field.getType());
                // 日期格式如果值为字符换需要转换
                if (field.getType() == Date.class && !(value instanceof Date)) {
                    // 对标准时间处理
                    String d = value.toString().replace("T", " ").replace("Z", "");
                    SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                    method.invoke(obj, format.parse(d));
                } else {
                    method.invoke(obj, value);
                }
            } catch (Exception e) {
            }
        }
    
        /**
         * 主要用于查询列表中主键对象是否封装
         * 判断列表中是否包含某个子段元素
         *
         * @param list      查询列表
         * @param fieldName 字段名
         * @param value     值
         * @param <T>
         * @return 返回该元素
         */
        private final <T> T containObj(List<T> list, String fieldName, Object value) {
            T t;
            for (T item : list) {
                Object oldValue = getFieldValue(fieldName, item);
                // 字段相同,表示录入同一对象
                if (oldValue != null && oldValue.equals(value)) {
                    t = item;
                    return t;
                }
            }
            return null;
        }
    
        /**
         * 判断类中是否包含某个字段名
         *
         * @param clsMap
         * @param fileName
         * @return 返回包含字段名的类型
         */
        private final String containClass(Map<String, Class> clsMap, String fileName) {
            Set<Map.Entry<String, Class>> entries = clsMap.entrySet();
            Iterator<Map.Entry<String, Class>> iterator = entries.iterator();
            while (iterator.hasNext()) {
                Map.Entry<String, Class> entry = iterator.next();
                Field[] fields = entry.getValue().getDeclaredFields();
                for (Field field : fields) {
                    if (field.getName().equals(fileName)) {
                        return entry.getKey();
                    }
                }
            }
            return null;
        }
    
        /**
         * 查询数据 : 此方法需要在cls上添加注解@FormId
         *
         * @param filter 类条件构建器
         * @param <T>
         * @return List-T
         */
        public <T> List<T> query(Builder<T> filter) throws Exception {
            Class<T> cls = filter.getObjClass();
            String formId = getFormId(cls);
            return query(formId, filter, cls);
        }
    
        /**
         * 查询数据
         *
         * @param formId 查询表单ID
         * @param filter 条件构建器
         * @param cls    查询类
         * @param <T>
         * @return List-T
         */
        public <T> List<T> query(String formId, AbstractBuilder<T> filter, Class<T> cls) throws Exception {
            // 保存当前查询字段
            fieldKeys = filter.getFieldKeys();
            QueryParam queryParam = new QueryParam();
            queryParam.setFormId(formId);
            queryParam.setFieldKeys(filter.buildFieldKeys());
            queryParam.setFilterString(filter.buildFilter());
            queryParam.setOrderString(filter.buildOrder());
            queryParam.setTopRowCount(filter.buildTopRowCount());
            queryParam.setStartRow(filter.buildStartRow());
            queryParam.setLimit(filter.buildLimit());
            // 打印日志
            log.info("请求信息:FormId={};FieldKeys={};FilterString={};OrderString={};StartRow={};Limit={};TopRowCount={}",
                    queryParam.getFormId(), queryParam.getFieldKeys(), queryParam.getFilterString(),
                    queryParam.getOrderString(), queryParam.getStartRow(), queryParam.getLimit(), queryParam.getTopRowCount());
            // 查询结果集
            List<List<Object>> lists = api.executeBillQuery(queryParam.toJson());
            // 查询校验返回结果是否正确
            checkException(lists);
            // 封装结果集
            List<T> resultList = new ArrayList<>();
            lists.forEach(item -> {
                try {
                    T result = cls.newInstance();
                    for (int i = 0; i < fieldKeys.size(); i++) {
                        // 将所有字段中.替换为_
                        String fieldName = SFunctionParse.convertAttr(fieldKeys.get(i));
                        setFieldValue(fieldName, item.get(i), result);
                    }
                    resultList.add(result);
                } catch (InstantiationException e) {
                    e.printStackTrace();
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }
            });
            return resultList;
        }
    
        /**
         * 查询数据
         *
         * @param formId    查询表单ID
         * @param fieldKeys 查询字段
         * @param cls       封装类
         * @param <T>
         * @return List-T
         */
        public <T> List<T> query(String formId, List<String> fieldKeys, Class<T> cls) throws Exception {
            FilterRuleBuilder builder = new FilterRuleBuilder();
            builder.select(fieldKeys);
            return query(formId, builder, cls);
        }
    
        /**
         * 查询数据 : 此方法需要在cls上添加注解@FormId
         *
         * @param fieldKeys 查询字段
         * @param cls       封装类
         * @param <T>
         * @return List-T
         */
        public <T> List<T> query(List<String> fieldKeys, Class<T> cls) throws Exception {
            String formId = getFormId(cls);
            FilterRuleBuilder builder = new FilterRuleBuilder();
            builder.select(fieldKeys);
            return query(formId, builder, cls);
        }
    
        /**
         * 查询数据
         *
         * @param formId 查询表单ID
         * @param filter 条件查询构造器
         * @return List-List<Object>
         */
        public List<List<Object>> query(String formId, AbstractBuilder filter) throws Exception {
    
            fieldKeys = filter.getFieldKeys();
            QueryParam queryParam = new QueryParam();
            queryParam.setFormId(formId).setFieldKeys(filter.buildFieldKeys());
            queryParam.setFilterString(filter.buildFilter());
            queryParam.setOrderString(filter.buildOrder());
            queryParam.setTopRowCount(filter.buildTopRowCount());
            queryParam.setLimit(filter.buildLimit());
            queryParam.setStartRow(filter.buildStartRow());
            // 打印日志
            log.info("请求信息:FormId={};FieldKeys={};FilterString={};OrderString={};StartRow={};Limit={};TopRowCount={}",
                    queryParam.getFormId(), queryParam.getFieldKeys(), queryParam.getFilterString(),
                    queryParam.getOrderString(), queryParam.getStartRow(), queryParam.getLimit(), queryParam.getTopRowCount());
            List<List<Object>> lists = api.executeBillQuery(queryParam.toJson());
            checkException(lists);
            return lists;
        }
    
        /**
         * 查询数据
         *
         * @param formId    查询表单ID
         * @param fieldKeys 查询字段
         * @return List-Object
         */
        public List<List<Object>> query(String formId, List<String> fieldKeys) throws Exception {
            FilterRuleBuilder builder = new FilterRuleBuilder();
            builder.select(fieldKeys);
            return query(formId, builder);
        }
    
        /**
         * 查询一条数据
         *
         * @param formId
         * @param filter 条件构建器
         * @param <T>
         * @return 数据存在一条返回,不存在返回null,多条报错
         */
        public <T> T queryOne(String formId, Builder<T> filter) throws Exception {
            Class<T> cls = filter.getObjClass();
            List<T> query = query(formId, filter, cls);
            int size = query.size();
            if (size == 1) {
                return query.get(0);
            } else if (size == 0) {
                return null;
            } else {
                throw new RuntimeException("查询一条记录,但发现" + query.size() + "条数据");
            }
        }
    
        /**
         * 查询一条数据
         *
         * @param filter
         * @param <T>
         * @return 数据存在一条返回,不存在返回null,多条报错
         */
        public <T> T queryOne(Builder<T> filter) throws Exception {
            // 获取查询类
            Class<T> cls = filter.getObjClass();
            String formId = getFormId(cls);
            return queryOne(formId, filter);
        }
    
        /**
         * 查询一条数据
         *
         * @param formId
         * @param filter
         * @return 数据存在一条返回,不存在返回null,多条报错
         */
        public List<Object> queryOne(String formId, AbstractBuilder filter) throws Exception {
            List<List<Object>> query = query(formId, filter);
            int size = query.size();
            if (size == 1) {
                return query.get(0);
            } else if (size == 0) {
                return null;
            } else {
                throw new RuntimeException("查询一条记录,但发现" + query.size() + "条数据");
            }
        }
    
        /**
         * 统计数量
         * FilterRuleBuilder的查询字段不生效
         *
         * @param formId
         * @return
         */
        public Long count(String formId, AbstractBuilder filter) {
            List<List<Object>> query = null;
            try {
                QueryParam queryParam = new QueryParam();
                queryParam.setFormId(formId);
                queryParam.setFieldKeys("count(1)");
                if (filter != null) {
                    queryParam.setFilterString(filter.buildFilter());
                }
                query = api.executeBillQuery(queryParam.toJson());
            } catch (Exception e) {
                e.printStackTrace();
            }
            return Long.parseLong((String) query.get(0).get(0));
        }
    
        /**
         * 统计数量
         *
         * @param formId
         * @return
         */
        public long count(String formId) {
            return count(formId, null);
        }
    
        /**
         * 结果映射: 除请求参数的属性外,其他字段自动映射
         *
         * @param result     结果集
         * @param cls        映射对象
         * @param fieldId    主键Id
         * @param properties 映射对象中的映射字段,可以是对象或list,不支持数组
         *                   但是list只能有一个,因为映射最小单元是list的单位
         * @param <T>        对象类型
         * @return
         */
        public <T> List<T> resultMap(List result, Class<T> cls, String fieldId, String... properties) {
            List<T> returnResult = new ArrayList<>();
            try {
                // <T> 对象子对象A集合
                Map<String, Class> subObjFields = new HashMap<>();
                // <T> 对象的子列表对象集合
                Map<String, Class> subListFields = new HashMap<>();
                for (String property : properties) {
                    Field field = cls.getDeclaredField(property);
                    if (field.getType() == List.class) {// 列表先获取列表泛型的对象,然后获取对象的字段
                        // 获取列表中的泛型
                        Type genericType = field.getGenericType();
                        // 获取类型Class
                        if (genericType instanceof ParameterizedType) {
                            ParameterizedType typeCls = (ParameterizedType) genericType;
                            Class subGenericClass = (Class<?>) typeCls.getActualTypeArguments()[0];
                            subListFields.put(property, subGenericClass);
                        }
                    } else if (!field.getType().isArray()) {// 对象直接获取对象的字段
                        Class subObjClass = cls.getDeclaredField(property).getType();
                        subObjFields.put(property, subObjClass);
                    }
                }
                int size = result.size();
                // 封装结果
                for (int i = 0; i < size; i++) {
                    Object obj = result.get(i);
                    // obj是一个对象,根据对象封装
                    if (obj instanceof List) {// 列表类型的操作
                        List list = (List) obj;
                        packByList(returnResult, list, cls, fieldId, subObjFields, subListFields);
                    } else {// 对象类型的操作
                        packByObject(returnResult, obj, cls, fieldId, subObjFields, subListFields);
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
            return returnResult;
        }
    
        /**
         * 结果映射: 除请求参数的属性外,其他字段自动映射
         *
         * @param result     结果集
         * @param cls        映射对象
         * @param fieldId    主键Id
         * @param properties 映射对象中的映射字段,可以是对象或list,
         *                   但是list只能有一个,因为映射最小单元是list的单位
         * @param <T>        对象类型
         * @return
         */
        public <T, R> List<T> resultMap(List result, Class<T> cls, SFunction<T, R> fieldId, SFunction<T, R>... properties) {
            return resultMap(result, cls, SFunctionParse.resolve(false, fieldId),
                    SFunctionParse.resolves(false, properties));
        }
    
        /**
         * 包装List结果集,通常指没有第一次包装对象
         *
         * @param returnResult  封装目标结果集
         * @param list          封装源对象
         * @param cls           目标对象
         * @param fieldId       主键字段
         * @param subObjFields  目标对象中的子对象 key: 属性名,value: 对象类
         * @param subListFields 目标对象中的子列表,key: 属性名,value: 子列表中的Class类
         * @param <T>
         * @return
         * @throws IllegalAccessException
         * @throws InstantiationException
         */
        private <T> List<T> packByList(List<T> returnResult, List list, Class<T> cls, String fieldId,
                                       Map<String, Class> subObjFields, Map<String, Class> subListFields) throws IllegalAccessException, InstantiationException {
            // 字段个数
            int size = list.size();
            // 单元素对象
            T t = null;
            Object subObj;
            // 子列表中对象
            Object listObj = null;
            // 子列表
            List<Object> subList;
            for (int j = 0; j < size; j++) {
                // 字段名,将点替换为字段
                String fieldName = SFunctionParse.convertAttr(fieldKeys.get(j));
                // 字段值
                Object value = list.get(j);
                // 主键字段创建新对象
                if (fieldName.equals(fieldId)) {// 主键字段赋值
                    // 获取对象或创建对象
                    t = containObj(returnResult, fieldName, value);
                    // 同时添加到
                    if (t == null) {
                        t = cls.newInstance();
                        setFieldValue(fieldName, value, t);
                        // 创建新的对象并添加到结果集
                        returnResult.add(t);
                    }
                } else {
                    // 判断是否为子对象,返回子对象的属性名
                    String subFieldName = containClass(subObjFields, fieldName);
                    // 获取子对象Class
                    Class subCls = subObjFields.get(subFieldName);
                    // 不为空表示在子对象中
                    if (subFieldName != null) {
                        // 获取当前对象的子对象
                        subObj = getFieldValue(subFieldName, t);
                        // 子对象为空,创建子对象
                        if (subObj == null) {
                            subObj = subCls.newInstance();
                        }
                        // 赋值子对象属性
                        setFieldValue(fieldName, value, subObj);
                        // 赋值对象属性
                        setFieldValue(subFieldName, subObj, t);
                    } else {// 不为子对象判断是否为子
                        // 判断是否为子列表
                        String subListFieldName = containClass(subListFields, fieldName);
    
                        if (subListFieldName == null) {// 为空表示普通属性,自动封装
                            setFieldValue(fieldName, value, t);
                        } else {
                            // 查询对象是否包含子列表,不包含创建,包含赋值
                            subList = (List<Object>) getFieldValue(subListFieldName, t);
                            if (subList == null) {
                                // 并将列表添加在对象中
                                subList = new ArrayList<>();
                                setFieldValue(subListFieldName, subList, t);
                            }
                            // 列表中的子对象是否存在,不存在创建并添加在列表中
                            if (listObj == null) {
                                // 获取子列表中的对象Class
                                Class subListCls = subListFields.get(subListFieldName);
                                listObj = subListCls.newInstance();
                                // 添加到子列表中
                                subList.add(listObj);
                            }
                            // 给列表对象赋值属性
                            setFieldValue(fieldName, value, listObj);
                        }
                    }
                    // 给对象赋值,如果包装对象外也存在该属性,同样进行赋值
                    setFieldValue(fieldName, value, t);
                }
            }
            return returnResult;
        }
    
        /**
         * 根据对象包装结果集
         *
         * @param returnResult  封装目标结果集
         * @param obj           包装源对象
         * @param cls           目标Class
         * @param fieldId       主键Id
         * @param subObjFields  目标对象中的子对象 key: 属性名,value: 对象类
         * @param subListFields 目标对象中的子列表,key: 属性名,value: 子列表中的Class类
         * @param <T>
         * @return
         * @throws IllegalAccessException
         * @throws InstantiationException
         */
        private <T> List<T> packByObject(List<T> returnResult, Object obj, Class<T> cls, String fieldId,
                                         Map<String, Class> subObjFields, Map<String, Class> subListFields)
                throws IllegalAccessException, InstantiationException {
            Field[] resultFields = obj.getClass().getDeclaredFields();
            // 单元素对象
            T t = null;
            Object subObj;
            // 子列表中对象
            Object listObj = null;
            // 子列表
            List<Object> subList;
            for (int j = 0; j < resultFields.length; j++) {
                Field field = resultFields[j];
                // 字段名
                String fieldName = field.getName();
                // 字段值
                Object value = getFieldValue(fieldName, obj);
                // 主键字段创建新对象
                if (fieldName.equals(fieldId)) {// 主键字段赋值
                    // 获取对象或创建对象
                    t = containObj(returnResult, fieldName, value);
                    // 同时添加到
                    if (t == null) {
                        t = cls.newInstance();
                        setFieldValue(fieldName, value, t);
                        // 创建新的对象并添加到结果集
                        returnResult.add(t);
                    }
    
                } else {
                    // 判断是否为子对象,返回子对象的属性名
                    String subFieldName = containClass(subObjFields, fieldName);
                    // 获取子对象Class
                    Class subCls = subObjFields.get(subFieldName);
                    // 不为空表示存在子对象中
                    if (subFieldName != null) {
                        // 获取当前对象的子对象
                        subObj = getFieldValue(subFieldName, t);
                        // 子对象为空,创建子对象
                        if (subObj == null) {
                            subObj = subCls.newInstance();
                        }
                        // 赋值子对象属性
                        setFieldValue(fieldName, value, subObj);
                        // 赋值对象属性
                        setFieldValue(subFieldName, subObj, t);
                    } else {// 不为子对象判断是否为子
                        // 判断是否为子列表
                        String subListFieldName = containClass(subListFields, fieldName);
    
                        if (subListFieldName == null) {// 为空表示普通属性,自动封装
                            setFieldValue(fieldName, value, t);
                        } else {
                            // 查询对象是否包含子列表,不包含创建,包含赋值
                            subList = (List<Object>) getFieldValue(subListFieldName, t);
                            if (subList == null) {
                                // 并将列表添加在对象中
                                subList = new ArrayList<>();
                                setFieldValue(subListFieldName, subList, t);
                            }
                            // 列表中的子对象是否存在,不存在创建并添加在列表中
                            if (listObj == null) {
                                // 获取子列表中的对象Class
                                Class subListCls = subListFields.get(subListFieldName);
                                listObj = subListCls.newInstance();
                                // 添加到子列表中
                                subList.add(listObj);
                            }
                            // 给列表对象赋值属性
                            setFieldValue(fieldName, value, listObj);
                        }
                    }
                    // 给对象赋值,如果包装对象外也存在该属性,同样进行赋值
                    setFieldValue(fieldName, value, t);
                }
            }
            return returnResult;
        }
    
        /**
         * 查询并结果封装,自动识别复合类型封装
         *
         * @param formId
         * @param filter  条件过滤器
         * @param cls     封装类型
         * @param fieldId 主键ID
         * @param <T>
         * @param <R>
         * @return
         */
        public <T, R> List<T> queryAndResultMap(String formId, AbstractBuilder<T> filter,
                                                Class<T> cls, String fieldId) throws Exception {
            // 查询数据列表
            List<List<Object>> result = query(formId, filter);
            // 获取复合类型字段
            Field[] fields = cls.getDeclaredFields();
            List<String> fieldNameList = new ArrayList<>();
            for (Field field : fields) {
                // 判断字段是否为复杂类型,略过数组
                if (!AbstractBuilder.generalType.contains(field.getType().getName())
                        && !field.getType().isArray()) {
                    fieldNameList.add(field.getName());
                }
            }
            return resultMap(result, cls, fieldId, fieldNameList.toArray(new String[]{}));
        }
    
        /**
         * 查询并结果封装,自动识别复合类型封装,此方法需要注解@FormId
         *
         * @param filter  条件过滤器
         * @param fieldId 主键ID
         * @param <T>
         * @param <R>
         * @return
         */
        public <T, R> List<T> queryAndResultMap(Builder<T> filter, SFunction<T, R> fieldId) throws Exception {
            Class<T> cls = filter.getObjClass();
            String formId = getFormId(cls);
            // 查询数据列表
            List<List<Object>> result = query(formId, filter);
            // 获取复合类型字段
            Field[] fields = cls.getDeclaredFields();
            List<String> fieldNameList = new ArrayList<>();
            for (Field field : fields) {
                // 判断字段是否为复杂类型,略过数组
                if (!AbstractBuilder.generalType.contains(field.getType().getName())
                        && !field.getType().isArray()) {
                    fieldNameList.add(field.getName());
                }
            }
            return resultMap(result, cls, SFunctionParse.resolve(fieldId), fieldNameList.toArray(new String[]{}));
        }
    }
    
    
  4. 使用示例: 提示: 实体类字段名最好与查询字段名一致,仅将.替换为_

    @Data
    @NoArgsConstructor
    @AllArgsConstructor
    @FormId("BD_Customer")
    public class Customer {
        private long FCUSTID;
        private String FNumber;
        private String FName;
        private String FShortName;
    
    
        public static void main(String[] args) {
            // 1. 原始方式
            K3CloudApi api = new K3CloudApi();
            List<Customer> datas;
            try {
                QueryParam queryParam = new QueryParam();
                queryParam.setFormId("BD_Customer")
                        .setFieldKeys("fCUSTID,fNumber,fName,fCreateDate")
                        .setFilterString("fCUSTID <= '***'");
                datas = api.executeBillQuery(queryParam, Customer.class);
                datas.forEach(System.out::println);
            } catch (Exception e) {
                e.printStackTrace();
            }
            // 2. 封装 FilterRuleBuilder后
            K3Api k3Api = new K3Api();
            FilterRuleBuilder builder = new FilterRuleBuilder();
            builder.select("fCUSTID", "fNumber", "fName", "fCreateDate")
                    .le("fCUSTID", "***");
            List<Customer> customers = k3Api.query("BD_Customer", builder, Customer.class);
            customers.forEach(System.out::println);
            // 3. 封装 Builder后
            List<Customer> customers1 = k3Api.query(Builder.builder(Customer.class)
                .select(Customer::getFCUSTID, Customer::getFName, Customer::getFCreateDate));
            customers.forEach(System.out::println);
            /**
             * 4. k3Api还封装了queryOne,count方法。
             * 5. query之后,数据可能需要映射,k3Api还封装了resultMap方法。
             *  resultMap的参数如下: 类比mybatis的结果映射
             *      @param result     query的结果集
             *      @param cls        映射对象的类
             *      @param fieldId    对象主键Id
             *      @param properties 需要映射的字段,可以是对象或list,
             *                        但是list只能有一个,因为映射最小单元是list的单位
             * 示例不介绍了。
             */
        }
    }
    
  5. 获取金蝶FomId:可通过administrator账号登录,在web api 测试功能中查看到。

  6. 获取金蝶字段名技巧:金蝶服务器地址可通过浏览器登录,与客户端效果一样,通过浏览器的审查单元格样式,可查看到属性data-field值即为查询字段。如下图所示:
    在这里插入图片描述

  • 3
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 10
    评论
对接金蝶云的JAVA接口可以按照以下流程进行: 1. 获取接口所需数据:根据金蝶云的文档,确定物料接口所需的数据字段。可以将测试数据保存到一个文件中,或者构造对应的JAVA对象。 2. 转换数据格式:将数据转换成JSON格式,以便与金蝶云的接口进行交互。可以使用JAVA中的JSON库,如Jackson或Gson,将数据对象转换为JSON字符串。 3. 发送请求:使用JAVA的HTTP库,如HttpClient或HttpURLConnection,发送HTTP请求到金蝶云的WebAPI接口。在请求中包含转换后的JSON数据。 4. 处理响应:接收金蝶云返回的响应,可以使用JAVA的JSON库将响应数据解析为JAVA对象,或者直接处理JSON字符串。 5. 处理异常:根据金蝶云的接口文档,处理可能出现的异常情况,如网络连接失败、请求超时等。 下面是一个简单的示例代码,演示了JAVA对接金蝶云物料接口的基本流程: ```java import org.apache.http.HttpEntity; import org.apache.http.HttpResponse; import org.apache.http.client.HttpClient; import org.apache.http.client.methods.HttpPost; import org.apache.http.entity.StringEntity; import org.apache.http.impl.client.HttpClientBuilder; import org.apache.http.util.EntityUtils; import java.io.IOException; public class K3CloudAPIExample { public static void main(String[] args) { // 构造请求数据 String jsonData = "{\"materialCode\": \"123\", \"materialName\": \"Test Material\"}"; // 发送请求 HttpClient httpClient = HttpClientBuilder.create().build(); HttpPost request = new HttpPost("https://api.k3cloud.com/materials"); request.addHeader("Content-Type", "application/json"); request.setEntity(new StringEntity(jsonData, "UTF-8")); try { HttpResponse response = httpClient.execute(request); HttpEntity entity = response.getEntity(); String responseJson = EntityUtils.toString(entity, "UTF-8"); // 处理响应数据 System.out.println("Response: " + responseJson); } catch (IOException e) { e.printStackTrace(); } } } ``` 请注意,以上代码为示例,实际使用时需要根据金蝶云的接口文档进行相应的调整和处理。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

£漫步 云端彡

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值