From 6bd0b2f0e073cfc665d66b7d0d40bfa0cb112a7f Mon Sep 17 00:00:00 2001 From: weike001 Date: Thu, 20 Feb 2025 15:01:49 +0800 Subject: [PATCH] =?UTF-8?q?feat(mybatis):=20=E6=B7=BB=E5=8A=A0=E9=80=9A?= =?UTF-8?q?=E7=94=A8=E6=9F=A5=E8=AF=A2=E5=92=8C=E5=88=86=E9=A1=B5=E5=8A=9F?= =?UTF-8?q?=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 新增 AutoQueryUtil 工具类,实现自动查询功能 - 添加 BaseEntity基类,包含通用的创建和更新字段 - 修改 DefaultDBFieldHandler,支持 BaseEntity 的字段填充 - 新增 PageQuery 类,用于构建分页查询对象 - 添加 TableDataInfo 类,用于封装分页查询结果 - 在 ServletUtils 中增加 getHeader 方法,用于获取请求头信息 --- .../common/util/servlet/ServletUtils.java | 25 +++ .../mybatis/core/dataobject/BaseEntity.java | 71 ++++++++ .../core/handler/DefaultDBFieldHandler.java | 43 ++++- .../mybatis/core/page/PageQuery.java | 141 +++++++++++++++ .../mybatis/core/page/TableDataInfo.java | 70 ++++++++ .../mybatis/core/util/AutoQueryUtil.java | 166 ++++++++++++++++++ .../src/main/resources/application.yaml | 2 +- 7 files changed, 511 insertions(+), 7 deletions(-) create mode 100644 yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/dataobject/BaseEntity.java create mode 100644 yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/page/PageQuery.java create mode 100644 yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/page/TableDataInfo.java create mode 100644 yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/util/AutoQueryUtil.java diff --git a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/servlet/ServletUtils.java b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/servlet/ServletUtils.java index 8edbb50..7777415 100644 --- a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/servlet/ServletUtils.java +++ b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/servlet/ServletUtils.java @@ -4,6 +4,7 @@ import cn.hutool.core.io.IoUtil; import cn.hutool.core.util.StrUtil; import cn.hutool.extra.servlet.ServletUtil; import cn.iocoder.yudao.framework.common.util.json.JsonUtils; +import org.apache.commons.lang3.StringUtils; import org.springframework.http.MediaType; import org.springframework.web.context.request.RequestAttributes; import org.springframework.web.context.request.RequestContextHolder; @@ -13,6 +14,8 @@ import javax.servlet.ServletRequest; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; +import java.io.UnsupportedEncodingException; +import java.net.URLDecoder; import java.net.URLEncoder; import java.util.Map; @@ -59,6 +62,28 @@ public class ServletUtils { return ua != null ? ua : ""; } + public static String getHeader(HttpServletRequest request, String name){ + String value = request.getHeader(name); + if (StringUtils.isEmpty(value)) { + return StringUtils.EMPTY; + } + return urlDecode(value); + } + + /** + * 内容解码 + * + * @param str 内容 + * @return 解码后的内容 + */ + public static String urlDecode(String str) { + try { + return URLDecoder.decode(str,"UTF-8"); + } catch (UnsupportedEncodingException e) { + throw new RuntimeException(e); + } + } + /** * 获得请求 * diff --git a/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/dataobject/BaseEntity.java b/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/dataobject/BaseEntity.java new file mode 100644 index 0000000..22778ad --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/dataobject/BaseEntity.java @@ -0,0 +1,71 @@ +package cn.iocoder.yudao.framework.mybatis.core.dataobject; + +import com.baomidou.mybatisplus.annotation.FieldFill; +import com.baomidou.mybatisplus.annotation.TableField; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonInclude; +import lombok.Data; +import java.io.Serializable; +import java.time.LocalDateTime; +import java.util.Date; +import java.util.HashMap; +import java.util.Map; + +/** + * Entity基类 + * + * @author Lion Li + */ +@Data +public class BaseEntity implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 搜索值 + */ + @JsonIgnore + @TableField(exist = false) + private String searchValue; + +// /** +// * 创建部门 +// */ +// @TableField(fill = FieldFill.INSERT) +// private Long deptId; + + /** + * 创建者 + */ + @TableField(fill = FieldFill.INSERT) + private Long createBy; + + /** + * 创建时间 + */ + @TableField(fill = FieldFill.INSERT) + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss") + private LocalDateTime createTime; + + /** + * 更新者 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private Long updateBy; + + /** + * 更新时间 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss") + private LocalDateTime updateTime; + + /** + * 请求参数 + */ + @JsonInclude(JsonInclude.Include.NON_EMPTY) + @TableField(exist = false) + private Map params = new HashMap<>(); + +} diff --git a/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/handler/DefaultDBFieldHandler.java b/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/handler/DefaultDBFieldHandler.java index 94dada1..42e6b6b 100644 --- a/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/handler/DefaultDBFieldHandler.java +++ b/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/handler/DefaultDBFieldHandler.java @@ -1,6 +1,7 @@ package cn.iocoder.yudao.framework.mybatis.core.handler; import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseEntity; import cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils; import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler; import org.apache.ibatis.reflection.MetaObject; @@ -41,6 +42,28 @@ public class DefaultDBFieldHandler implements MetaObjectHandler { if (Objects.nonNull(userId) && Objects.isNull(baseDO.getUpdater())) { baseDO.setUpdater(userId.toString()); } + }else if (Objects.nonNull(metaObject) && metaObject.getOriginalObject() instanceof BaseEntity) { + BaseEntity baseEntity = (BaseEntity) metaObject.getOriginalObject(); + + LocalDateTime current = LocalDateTime.now(); + // 创建时间为空,则以当前时间为插入时间 + if (Objects.isNull(baseEntity.getCreateTime())) { + baseEntity.setCreateTime(current); + } + // 更新时间为空,则以当前时间为更新时间 + if (Objects.isNull(baseEntity.getUpdateTime())) { + baseEntity.setUpdateTime(current); + } + + Long userId = WebFrameworkUtils.getLoginUserId(); + // 当前登录用户不为空,创建人为空,则当前登录用户为创建人 + if (Objects.nonNull(userId) && Objects.isNull(baseEntity.getCreateBy())) { + baseEntity.setCreateBy(userId); + } + // 当前登录用户不为空,更新人为空,则当前登录用户为更新人 + if (Objects.nonNull(userId) && Objects.isNull(baseEntity.getUpdateBy())) { + baseEntity.setUpdateBy(userId); + } } } @@ -51,12 +74,20 @@ public class DefaultDBFieldHandler implements MetaObjectHandler { if (Objects.isNull(modifyTime)) { setFieldValByName("updateTime", LocalDateTime.now(), metaObject); } - - // 当前登录用户不为空,更新人为空,则当前登录用户为更新人 - Object modifier = getFieldValByName("updater", metaObject); - Long userId = WebFrameworkUtils.getLoginUserId(); - if (Objects.nonNull(userId) && Objects.isNull(modifier)) { - setFieldValByName("updater", userId.toString(), metaObject); + if (Objects.nonNull(metaObject) && metaObject.getOriginalObject() instanceof BaseDO) { + // 当前登录用户不为空,更新人为空,则当前登录用户为更新人 + Object modifier = getFieldValByName("updater", metaObject); + Long userId = WebFrameworkUtils.getLoginUserId(); + if (Objects.nonNull(userId) && Objects.isNull(modifier)) { + setFieldValByName("updater", userId.toString(), metaObject); + } + }else if (Objects.nonNull(metaObject) && metaObject.getOriginalObject() instanceof BaseEntity) { + // 当前登录用户不为空,更新人为空,则当前登录用户为更新人 + Object modifier = getFieldValByName("updateBy", metaObject); + Long userId = WebFrameworkUtils.getLoginUserId(); + if (Objects.nonNull(userId) && Objects.isNull(modifier)) { + setFieldValByName("updateBy", userId, metaObject); + } } } } diff --git a/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/page/PageQuery.java b/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/page/PageQuery.java new file mode 100644 index 0000000..f390939 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/page/PageQuery.java @@ -0,0 +1,141 @@ +package cn.iocoder.yudao.framework.mybatis.core.page; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.ObjectUtil; +import cn.hutool.core.util.StrUtil; +import cn.iocoder.yudao.framework.common.exception.ServiceException; +import com.baomidou.mybatisplus.core.metadata.OrderItem; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import lombok.Data; +import org.apache.commons.lang3.StringUtils; +import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; + +/** + * 分页查询实体类 + * + * @author Lion Li + */ +@Data +public class PageQuery implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 分页大小 + */ + private Integer pageSize; + + /** + * 当前页数 + */ + private Integer pageNum; + + /** + * 排序列 + */ + private String orderByColumn; + + /** + * 排序的方向desc或者asc + */ + private String isAsc; + + /** + * 当前记录起始索引 默认值 + */ + public static final int DEFAULT_PAGE_NUM = 1; + + /** + * 每页显示记录数 默认值 默认查全部 + */ + public static final int DEFAULT_PAGE_SIZE = Integer.MAX_VALUE; + + /** + * 仅支持字母、数字、下划线、空格、逗号、小数点(支持多个字段排序) + */ + public static final String SQL_PATTERN = "[a-zA-Z0-9_\\ \\,\\.]+"; + + public static final String SEPARATOR = ","; + + /** + * 构建分页对象 + */ + public Page build() { + Integer pageNum = ObjectUtil.defaultIfNull(getPageNum(), DEFAULT_PAGE_NUM); + Integer pageSize = ObjectUtil.defaultIfNull(getPageSize(), DEFAULT_PAGE_SIZE); + if (pageNum <= 0) { + pageNum = DEFAULT_PAGE_NUM; + } + Page page = new Page<>(pageNum, pageSize); + List orderItems = buildOrderItem(); + if (CollUtil.isNotEmpty(orderItems)) { + page.addOrder(orderItems); + } + return page; + } + + /** + * 构建排序 + * + * 支持的用法如下: + * {isAsc:"asc",orderByColumn:"id"} order by id asc + * {isAsc:"asc",orderByColumn:"id,createTime"} order by id asc,create_time asc + * {isAsc:"desc",orderByColumn:"id,createTime"} order by id desc,create_time desc + * {isAsc:"asc,desc",orderByColumn:"id,createTime"} order by id asc,create_time desc + */ + private List buildOrderItem() { + if (StringUtils.isBlank(orderByColumn) || StringUtils.isBlank(isAsc)) { + return null; + } + String orderBy = escapeOrderBySql(orderByColumn); + orderBy = StrUtil.toUnderlineCase(orderBy); + + // 兼容前端排序类型 + isAsc = StringUtils.replaceEach(isAsc, new String[]{"ascending", "descending"}, new String[]{"asc", "desc"}); + + String[] orderByArr = orderBy.split(SEPARATOR); + String[] isAscArr = isAsc.split(SEPARATOR); + if (isAscArr.length != 1 && isAscArr.length != orderByArr.length) { + throw new ServiceException(500,"排序参数有误"); + } + + List list = new ArrayList<>(); + // 每个字段各自排序 + for (int i = 0; i < orderByArr.length; i++) { + String orderByStr = orderByArr[i]; + String isAscStr = isAscArr.length == 1 ? isAscArr[0] : isAscArr[i]; + if ("asc".equals(isAscStr)) { + list.add(OrderItem.asc(orderByStr)); + } else if ("desc".equals(isAscStr)) { + list.add(OrderItem.desc(orderByStr)); + } else { + throw new ServiceException(500,"排序参数有误"); + } + } + return list; + } + + public Integer getFirstNum() { + return (pageNum - 1) * pageSize; + } + + /** + * 检查字符,防止注入绕过 + */ + public static String escapeOrderBySql(String value) { + if (StringUtils.isNotEmpty(value) && !isValidOrderBySql(value)) { + throw new IllegalArgumentException("参数不符合规范,不能进行查询"); + } + return value; + } + + /** + * 验证 order by 语法是否符合规范 + */ + public static boolean isValidOrderBySql(String value) { + return value.matches(SQL_PATTERN); + } + +} diff --git a/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/page/TableDataInfo.java b/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/page/TableDataInfo.java new file mode 100644 index 0000000..5796654 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/page/TableDataInfo.java @@ -0,0 +1,70 @@ +package cn.iocoder.yudao.framework.mybatis.core.page; + +import com.baomidou.mybatisplus.core.metadata.IPage; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serializable; +import java.util.List; + +/** + * 表格分页数据对象 + * + * @author Lion Li + */ +@Data +@NoArgsConstructor +public class TableDataInfo implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 总记录数 + */ + private long total; + + /** + * 列表数据 + */ + private List list; + + /** + * 分页 + * + * @param list 列表数据 + * @param total 总记录数 + */ + public TableDataInfo(List list, long total) { + this.list = list; + this.total = total; + } + + /** + * 根据分页对象构建表格分页数据对象 + */ + public static TableDataInfo build(IPage page) { + TableDataInfo rspData = new TableDataInfo<>(); + rspData.setList(page.getRecords()); + rspData.setTotal(page.getTotal()); + return rspData; + } + + /** + * 根据数据列表构建表格分页数据对象 + */ + public static TableDataInfo build(List list) { + TableDataInfo rspData = new TableDataInfo<>(); + rspData.setList(list); + rspData.setTotal(list.size()); + return rspData; + } + + /** + * 构建表格分页数据对象 + */ + public static TableDataInfo build() { + TableDataInfo rspData = new TableDataInfo<>(); + return rspData; + } + +} diff --git a/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/util/AutoQueryUtil.java b/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/util/AutoQueryUtil.java new file mode 100644 index 0000000..3580290 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/util/AutoQueryUtil.java @@ -0,0 +1,166 @@ +package cn.iocoder.yudao.framework.mybatis.core.util; + +import cn.hutool.core.util.StrUtil; +import cn.iocoder.yudao.framework.common.exception.ServiceException; +import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import org.apache.commons.lang3.StringUtils; +import org.apache.commons.lang3.reflect.MethodUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.servlet.http.HttpServletRequest; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.time.*; +import java.util.Arrays; +import java.util.Date; +import java.util.HashMap; +import java.util.Map; + +public class AutoQueryUtil { + + private static final Logger log = LoggerFactory.getLogger(AutoQueryUtil.class); + + /** + * 根据实体类的属性值是否为空自动创建LambdaQueryWrapper。 + * + * @param entity 实体对象 + * @param 实体类型 + * @return LambdaQueryWrapper + */ + public static QueryWrapper autoQuery(T entity) { + QueryWrapper queryWrapper = new QueryWrapper<>(); + if (entity == null) { + return queryWrapper; + } + + Class clazz = entity.getClass(); + // 遍历当前类和所有父类的字段 + while (clazz != null) { + Map getterMethods = new HashMap<>(); + for (Field field : clazz.getDeclaredFields()) { + field.setAccessible(true); + String fieldName = field.getName(); + Class finalClazz = clazz; + Method getterMethod = getterMethods.computeIfAbsent( + "get" + capitalize(fieldName), + k -> { + try { + return MethodUtils.getAccessibleMethod(finalClazz, k, (Class[]) null); + } catch (Exception e) { + log.error("No such getter method: {}", k, e); + return null; + } + } + ); + + if (getterMethod != null) { + try { + Object value = getterMethod.invoke(entity); + if (value != null && !"".equals(value)) { + handleFieldValue(queryWrapper, field, value); + } + } catch (Exception e) { + log.error("Error invoking getter method: {}", getterMethod.getName(), e); + } + } + } + // 获取父类,继续遍历父类的字段 + clazz = clazz.getSuperclass(); + } + + return queryWrapper; + } + + public static String getTenantId(){ + HttpServletRequest request = ServletUtils.getRequest(); + if (null != request) { + // 获取request的header中的x-tenant-id + String tenantId = ServletUtils.getHeader(request, "x-tenant-id"); + if (StringUtils.isNotBlank(tenantId)) { + return tenantId; + } + } + return null; + } + + private static void handleFieldValue(QueryWrapper queryWrapper, Field field, Object value) { + String fieldName = field.getName(); + + if (String.class.isAssignableFrom(field.getType())) { + queryWrapper.like(StrUtil.toUnderlineCase(fieldName), value); + } else if (Integer.class.isAssignableFrom(field.getType()) || + Long.class.isAssignableFrom(field.getType()) || + Double.class.isAssignableFrom(field.getType()) || + Float.class.isAssignableFrom(field.getType()) || + Boolean.class.isAssignableFrom(field.getType()) || + Short.class.isAssignableFrom(field.getType()) || + Byte.class.isAssignableFrom(field.getType()) || + Character.class.isAssignableFrom(field.getType()) || + Date.class.isAssignableFrom(field.getType()) || + LocalDateTime.class.isAssignableFrom(field.getType()) || + LocalDate.class.isAssignableFrom(field.getType()) || + LocalTime.class.isAssignableFrom(field.getType()) || + ZonedDateTime.class.isAssignableFrom(field.getType()) || + Instant.class.isAssignableFrom(field.getType())) { + queryWrapper.eq(StrUtil.toUnderlineCase(fieldName), String.valueOf(value)); + } else { + // 如果是其他类型,可以添加更多条件,或者忽略 + log.warn("Unsupported field type: {}", field.getType().getName()); + } + } + + /** + * 获取 pageReqVO 中所有 LocalDate[]、LocalDateTime[] 和 Date[] 类型字段的名称 + */ + public static String[] getDateRangeFieldNames(Object pageReqVO) { + return Arrays.stream(pageReqVO.getClass().getDeclaredFields()) + .filter(field -> field.getType().equals(LocalDate[].class) + || field.getType().equals(LocalDateTime[].class) + || field.getType().equals(Date[].class)) + .map(Field::getName) + .toArray(String[]::new); + } + + /** + * 动态处理 pageReqVO 中所有 LocalDate[]、LocalDateTime[] 和 Date[] 类型字段,设置时间段查询条件 + */ + public static void handleDateRangeFields(Object pageReqVO, QueryWrapper queryWrapper) { + for (Field field : pageReqVO.getClass().getDeclaredFields()) { + field.setAccessible(true); + try { + Object fieldValue = field.get(pageReqVO); + if (fieldValue == null) { + continue; // 跳过值为 null 的字段 + } + + if (field.getType().equals(LocalDate[].class)) { + LocalDate[] dateRange = (LocalDate[]) fieldValue; + if (dateRange.length == 2) { + String columnName = StrUtil.toUnderlineCase(field.getName()); // 字段名转换为数据库列名 + queryWrapper.between(columnName, dateRange[0], dateRange[1]); + } + } else if (field.getType().equals(LocalDateTime[].class)) { + LocalDateTime[] dateTimeRange = (LocalDateTime[]) fieldValue; + if (dateTimeRange.length == 2) { + String columnName = StrUtil.toUnderlineCase(field.getName()); // 字段名转换为数据库列名 + queryWrapper.between(columnName, dateTimeRange[0], dateTimeRange[1]); + } + } else if (field.getType().equals(Date[].class)) { + Date[] range = (Date[]) fieldValue; + if (range.length == 2) { + String columnName = StrUtil.toUnderlineCase(field.getName()); // 字段名转换为数据库列名 + queryWrapper.between(columnName, range[0], range[1]); + } + } + } catch (IllegalAccessException e) { + throw new ServiceException(500,"Failed to access field " + field.getName() + ": " + e.getMessage()); + } + } + } + + private static String capitalize(String str) { + return str.substring(0, 1).toUpperCase() + str.substring(1); + } +} diff --git a/yudao-module-system/yudao-module-system-biz/src/main/resources/application.yaml b/yudao-module-system/yudao-module-system-biz/src/main/resources/application.yaml index 45470da..2f9df22 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/resources/application.yaml +++ b/yudao-module-system/yudao-module-system-biz/src/main/resources/application.yaml @@ -163,7 +163,7 @@ yudao: description: 提供管理员管理的所有功能 version: ${yudao.info.version} tenant: # 多租户相关配置项 - enable: true + enable: false ignore-urls: - /admin-api/system/tenant/get-id-by-name # 基于名字获取租户,不许带租户编号 - /admin-api/system/tenant/get-by-website # 基于域名获取租户,不许带租户编号