删除不必要的依赖和文件
This commit is contained in:
@@ -127,46 +127,6 @@
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<!-- GIS空间数据处理工具 -->
|
||||
<dependency>
|
||||
<groupId>org.locationtech.jts</groupId>
|
||||
<artifactId>jts-core</artifactId>
|
||||
<version>1.19.0</version>
|
||||
</dependency>
|
||||
|
||||
<!-- PostGIS TypeHandler 支持 -->
|
||||
<dependency>
|
||||
<groupId>org.mybatis</groupId>
|
||||
<artifactId>mybatis-typehandlers-jsr310</artifactId>
|
||||
<version>1.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<!-- PostGIS JTS 支持 -->
|
||||
<dependency>
|
||||
<groupId>net.postgis</groupId>
|
||||
<artifactId>postgis-jdbc</artifactId>
|
||||
<version>2021.1.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.hibernate.orm</groupId>
|
||||
<artifactId>hibernate-spatial</artifactId>
|
||||
<version>6.2.0.Final</version>
|
||||
</dependency>
|
||||
|
||||
<!-- 坐标投影转换 -->
|
||||
<dependency>
|
||||
<groupId>org.locationtech.proj4j</groupId>
|
||||
<artifactId>proj4j</artifactId>
|
||||
<version>1.1.4</version>
|
||||
</dependency>
|
||||
|
||||
<!--常用工具类 -->
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-lang3</artifactId>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
<profiles>
|
||||
|
||||
@@ -1,138 +0,0 @@
|
||||
package com.gis.xian.config.typehandler;
|
||||
|
||||
import net.postgis.jdbc.PGgeometry;
|
||||
import org.apache.ibatis.type.BaseTypeHandler;
|
||||
import org.apache.ibatis.type.JdbcType;
|
||||
import org.apache.ibatis.type.MappedJdbcTypes;
|
||||
import org.apache.ibatis.type.MappedTypes;
|
||||
import org.locationtech.jts.geom.Geometry;
|
||||
import org.locationtech.jts.geom.GeometryFactory;
|
||||
import org.locationtech.jts.geom.PrecisionModel;
|
||||
import org.locationtech.jts.io.WKTReader;
|
||||
import org.locationtech.jts.io.WKTWriter;
|
||||
import org.postgresql.util.PGobject;
|
||||
import java.sql.CallableStatement;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
|
||||
/**
|
||||
* 修复编译报错版:PostgreSQL geometry → JTS Geometry 类型处理器
|
||||
* 解决 JTS Geometry 与 PostGIS Geometry 类的冲突问题
|
||||
*/
|
||||
@MappedTypes(Geometry.class) // 实体类字段类型(JTS 的 Geometry)
|
||||
@MappedJdbcTypes(JdbcType.OTHER) // 数据库 geometry 对应 JDBC 类型 OTHER
|
||||
public class GeometryTypeHandler extends BaseTypeHandler<Geometry> {
|
||||
|
||||
// WKT 解析器(JTS → 数据库,线程安全)
|
||||
private static final WKTReader WKT_READER = new WKTReader();
|
||||
// WKT 生成器(数据库 → JTS,线程安全)
|
||||
private static final WKTWriter WKT_WRITER = new WKTWriter();
|
||||
|
||||
private static final GeometryFactory GEOMETRY_FACTORY = new GeometryFactory(
|
||||
new PrecisionModel(PrecisionModel.FLOATING),
|
||||
4490
|
||||
);
|
||||
|
||||
@Override
|
||||
public void setNonNullParameter(PreparedStatement ps, int i, Geometry parameter, JdbcType jdbcType) throws SQLException {
|
||||
try {
|
||||
// 将 JTS 的 Geometry 转为标准 WKT 字符串
|
||||
String wktText = WKT_WRITER.write(parameter);
|
||||
// 用 WKT 字符串创建 PGgeometry 对象
|
||||
PGgeometry pgGeometry = new PGgeometry(wktText);
|
||||
// 存入 PreparedStatement
|
||||
ps.setObject(i, pgGeometry);
|
||||
} catch (Exception e) {
|
||||
throw new SQLException("将 JTS Geometry 转为 PGgeometry 失败", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Geometry getNullableResult(ResultSet rs, String columnName) throws SQLException {
|
||||
return convertToGeometry(rs.getObject(columnName));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Geometry getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
|
||||
return convertToGeometry(rs.getObject(columnIndex));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Geometry getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
|
||||
return convertToGeometry(cs.getObject(columnIndex));
|
||||
}
|
||||
|
||||
private Geometry convertToGeometry(Object value) {
|
||||
// 处理 null 值
|
||||
if (value == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
String wktText = null;
|
||||
try {
|
||||
// 兼容 PostGIS 的 PGgeometry 格式
|
||||
if (value instanceof PGgeometry) {
|
||||
PGgeometry pgGeometry = (PGgeometry) value;
|
||||
// 转为标准 WKT 文本
|
||||
wktText = pgGeometry.toString();
|
||||
}
|
||||
// 兼容 PostgreSQL 的 PGobject 格式
|
||||
else if (value instanceof PGobject) {
|
||||
PGobject pgObject = (PGobject) value;
|
||||
String pgValue = pgObject.getValue();
|
||||
if (pgValue != null && !pgValue.trim().isEmpty()) {
|
||||
wktText = new PGgeometry(pgValue).toString();
|
||||
}
|
||||
}
|
||||
// 兼容纯 WKT 字符串格式
|
||||
else if (value instanceof String) {
|
||||
wktText = (String) value;
|
||||
}
|
||||
// 未知格式直接返回 null
|
||||
else {
|
||||
return null;
|
||||
}
|
||||
|
||||
// 通用清洗 WKT 字符串
|
||||
String pureWkt = cleanWkt(wktText);
|
||||
if (pureWkt != null && !pureWkt.trim().isEmpty() && !"NULL".equalsIgnoreCase(pureWkt)) {
|
||||
Geometry geometry = WKT_READER.read(pureWkt);
|
||||
// 给几何对象设置 SRID=4490
|
||||
geometry.setSRID(4490);
|
||||
return geometry;
|
||||
}
|
||||
return null;
|
||||
|
||||
} catch (Exception e) {
|
||||
System.err.println("解析 geometry 字段失败,原始 WKT:" + wktText + ",异常:" + e.getMessage());
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 通用版 WKT 清洗方法:支持 Point、LINESTRING 等常见几何类型
|
||||
*/
|
||||
private String cleanWkt(String wkt) {
|
||||
if (wkt == null) {
|
||||
return null;
|
||||
}
|
||||
// 步骤1:去除所有不可见字符(换行、回车、制表符)
|
||||
String cleaned = wkt.replaceAll("[\n\r\t]", "");
|
||||
// 步骤2:去除 SRID 前缀(如 "SRID=4326;")
|
||||
cleaned = cleaned.replaceAll("^SRID=\\d+;", "");
|
||||
// 步骤3:将多个连续空格替换为单个空格(避免坐标间多空格干扰)
|
||||
cleaned = cleaned.replaceAll("\\s+", " ");
|
||||
// 步骤4:去除几何类型与括号间的多余空格(适配 Point、LINESTRING)
|
||||
cleaned = cleaned.replaceAll("(POINT|LINESTRING|POLYGON)\\s*\\(", "$1(");
|
||||
cleaned = cleaned.replaceAll("\\)\\s*$", ")");
|
||||
// 步骤5:去除首尾多余空格
|
||||
cleaned = cleaned.trim();
|
||||
// 步骤6:验证是否为支持的几何类型(可根据需求扩展)
|
||||
if (!cleaned.startsWith("POINT(") && !cleaned.startsWith("LINESTRING(") && !cleaned.startsWith("POLYGON(")) {
|
||||
System.err.println("不支持的几何类型,WKT:" + cleaned);
|
||||
return null;
|
||||
}
|
||||
return cleaned;
|
||||
}
|
||||
}
|
||||
@@ -5,6 +5,7 @@ import com.gis.xian.mapper.*;
|
||||
import com.gis.xian.vo.*;
|
||||
import jakarta.annotation.Resource;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.boot.context.event.ApplicationReadyEvent;
|
||||
import org.springframework.context.event.EventListener;
|
||||
@@ -13,6 +14,7 @@ import org.springframework.scheduling.annotation.Async;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.Executor;
|
||||
|
||||
/**
|
||||
* 初始化数据
|
||||
@@ -57,6 +59,10 @@ public class InitializeData {
|
||||
@Resource
|
||||
RedisTemplate<String, Object> redisTemplate;
|
||||
|
||||
@Resource
|
||||
@Qualifier("xianPool")
|
||||
private Executor xianPoolExecutor;
|
||||
|
||||
@Value("${init.data.base-points.hidden-danger.all}")
|
||||
private String allBasePointsKey;
|
||||
|
||||
@@ -119,7 +125,7 @@ public class InitializeData {
|
||||
)
|
||||
);
|
||||
log.info("加载隐患点信息(总体)并写入redis完成");
|
||||
});
|
||||
}, xianPoolExecutor);
|
||||
|
||||
// 隐患点 - 滑坡
|
||||
CompletableFuture<Void> landslideFuture = CompletableFuture.runAsync(() -> {
|
||||
@@ -129,7 +135,7 @@ public class InitializeData {
|
||||
)
|
||||
);
|
||||
log.info("加载隐患点信息(滑坡)并写入redis完成");
|
||||
});
|
||||
}, xianPoolExecutor);
|
||||
|
||||
// 隐患点 - 崩塌
|
||||
CompletableFuture<Void> collapseFuture = CompletableFuture.runAsync(() -> {
|
||||
@@ -139,7 +145,7 @@ public class InitializeData {
|
||||
)
|
||||
);
|
||||
log.info("加载隐患点信息(崩塌)并写入redis完成");
|
||||
});
|
||||
}, xianPoolExecutor);
|
||||
|
||||
|
||||
// 隐患点 - 泥石流
|
||||
@@ -150,7 +156,7 @@ public class InitializeData {
|
||||
)
|
||||
);
|
||||
log.info("加载隐患点信息(泥石流)并写入redis完成");
|
||||
});
|
||||
}, xianPoolExecutor);
|
||||
|
||||
// 隐患点 - 山洪
|
||||
CompletableFuture<Void> flashFloodFuture = CompletableFuture.runAsync(() -> {
|
||||
@@ -160,7 +166,7 @@ public class InitializeData {
|
||||
)
|
||||
);
|
||||
log.info("加载隐患点信息(山洪)并写入redis完成");
|
||||
});
|
||||
}, xianPoolExecutor);
|
||||
|
||||
// 隐患点 - 内涝
|
||||
CompletableFuture<Void> waterLoggingFuture = CompletableFuture.runAsync(() -> {
|
||||
@@ -170,7 +176,7 @@ public class InitializeData {
|
||||
)
|
||||
);
|
||||
log.info("加载隐患点信息(内涝)并写入redis完成");
|
||||
});
|
||||
}, xianPoolExecutor);
|
||||
|
||||
CompletableFuture<Void> riskFuture = CompletableFuture.runAsync(() -> {
|
||||
redisTemplate.opsForValue().set(riskBasePointsKey, JSON.toJSONString(
|
||||
@@ -179,7 +185,7 @@ public class InitializeData {
|
||||
)
|
||||
);
|
||||
log.info("加载风险点基本信息写入redis完成");
|
||||
});
|
||||
}, xianPoolExecutor);
|
||||
|
||||
CompletableFuture<Void> hospitalsFuture = CompletableFuture.runAsync(() -> {
|
||||
redisTemplate.opsForValue().set(hospitalsBasePointsKey, JSON.toJSONString(
|
||||
@@ -188,7 +194,7 @@ public class InitializeData {
|
||||
)
|
||||
);
|
||||
log.info("加载医院基本信息写入redis完成");
|
||||
});
|
||||
}, xianPoolExecutor);
|
||||
|
||||
CompletableFuture<Void> dangerousSourceFuture = CompletableFuture.runAsync(() -> {
|
||||
redisTemplate.opsForValue().set(dangerousSourceBasePointsKey, JSON.toJSONString(
|
||||
@@ -197,7 +203,7 @@ public class InitializeData {
|
||||
)
|
||||
);
|
||||
log.info("加载危险源基本信息写入redis完成");
|
||||
});
|
||||
}, xianPoolExecutor);
|
||||
|
||||
CompletableFuture<Void> emergencyShelterFuture = CompletableFuture.runAsync(() -> {
|
||||
redisTemplate.opsForValue().set(emergencyShelterBasePointsKey, JSON.toJSONString(
|
||||
@@ -206,7 +212,7 @@ public class InitializeData {
|
||||
)
|
||||
);
|
||||
log.info("加载应急避难所基本信息写入redis完成");
|
||||
});
|
||||
}, xianPoolExecutor);
|
||||
|
||||
CompletableFuture<Void> firefighterFuture = CompletableFuture.runAsync(() -> {
|
||||
redisTemplate.opsForValue().set(firefighterBasePointsKey, JSON.toJSONString(
|
||||
@@ -215,7 +221,7 @@ public class InitializeData {
|
||||
)
|
||||
);
|
||||
log.info("加载消防站基本信息写入redis完成");
|
||||
});
|
||||
}, xianPoolExecutor);
|
||||
|
||||
CompletableFuture<Void> storePointsFuture = CompletableFuture.runAsync(() -> {
|
||||
redisTemplate.opsForValue().set(storePointsBasePointsKey, JSON.toJSONString(
|
||||
@@ -224,7 +230,7 @@ public class InitializeData {
|
||||
)
|
||||
);
|
||||
log.info("加载物资储备点基本信息写入redis完成");
|
||||
});
|
||||
}, xianPoolExecutor);
|
||||
|
||||
CompletableFuture<Void> schoolFuture = CompletableFuture.runAsync(() -> {
|
||||
redisTemplate.opsForValue().set(schoolBasePointsKey, JSON.toJSONString(
|
||||
@@ -233,7 +239,7 @@ public class InitializeData {
|
||||
)
|
||||
);
|
||||
log.info("加载学校基本信息写入redis完成");
|
||||
});
|
||||
}, xianPoolExecutor);
|
||||
|
||||
CompletableFuture<Void> bridgeFuture = CompletableFuture.runAsync(() -> {
|
||||
redisTemplate.opsForValue().set(bridgeBasePointsKey, JSON.toJSONString(
|
||||
@@ -242,7 +248,7 @@ public class InitializeData {
|
||||
)
|
||||
);
|
||||
log.info("加载桥梁基本信息写入redis完成");
|
||||
});
|
||||
}, xianPoolExecutor);
|
||||
|
||||
CompletableFuture<Void> reservoirFuture = CompletableFuture.runAsync(() -> {
|
||||
redisTemplate.opsForValue().set(reservoirBasePointsKey, JSON.toJSONString(
|
||||
@@ -251,7 +257,7 @@ public class InitializeData {
|
||||
)
|
||||
);
|
||||
log.info("加载水库基本信息写入redis完成");
|
||||
});
|
||||
}, xianPoolExecutor);
|
||||
|
||||
CompletableFuture<Void> subwayFuture = CompletableFuture.runAsync(() -> {
|
||||
redisTemplate.opsForValue().set(subwayBasePointsKey, JSON.toJSONString(
|
||||
@@ -260,11 +266,11 @@ public class InitializeData {
|
||||
)
|
||||
);
|
||||
log.info("加载地铁站点基本信息写入redis完成");
|
||||
});
|
||||
}, xianPoolExecutor);
|
||||
|
||||
// 等待所有任务完成
|
||||
CompletableFuture.allOf(
|
||||
allFuture, landslideFuture, debrisFlowFuture,
|
||||
allFuture, landslideFuture, collapseFuture, debrisFlowFuture,
|
||||
flashFloodFuture, waterLoggingFuture,
|
||||
riskFuture, hospitalsFuture,
|
||||
dangerousSourceFuture, emergencyShelterFuture, firefighterFuture, storePointsFuture, schoolFuture,
|
||||
|
||||
@@ -1,682 +0,0 @@
|
||||
package com.gis.xian.utils;
|
||||
|
||||
import org.springframework.util.AntPathMatcher;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* @author zzw
|
||||
* @description: 字符串工具类 (基于RuoYi风格扩展)
|
||||
* @date 2026/5/26 上午9:25
|
||||
*/
|
||||
public class StringUtils extends org.apache.commons.lang3.StringUtils {
|
||||
/** 空字符串 */
|
||||
private static final String NULLSTR = "";
|
||||
|
||||
/** 下划线 */
|
||||
private static final char SEPARATOR = '_';
|
||||
|
||||
/** 星号 */
|
||||
private static final char ASTERISK = '*';
|
||||
|
||||
/**
|
||||
* 获取参数不为空值
|
||||
*
|
||||
* @param value defaultValue 要判断的value
|
||||
* @return value 返回值
|
||||
*/
|
||||
public static <T> T nvl(T value, T defaultValue)
|
||||
{
|
||||
return value != null ? value : defaultValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* * 判断一个Collection是否为空, 包含List,Set,Queue
|
||||
*
|
||||
* @param coll 要判断的Collection
|
||||
* @return true:为空 false:非空
|
||||
*/
|
||||
public static boolean isEmpty(Collection<?> coll)
|
||||
{
|
||||
return isNull(coll) || coll.isEmpty();
|
||||
}
|
||||
|
||||
/**
|
||||
* * 判断一个Collection是否非空,包含List,Set,Queue
|
||||
*
|
||||
* @param coll 要判断的Collection
|
||||
* @return true:非空 false:空
|
||||
*/
|
||||
public static boolean isNotEmpty(Collection<?> coll)
|
||||
{
|
||||
return !isEmpty(coll);
|
||||
}
|
||||
|
||||
/**
|
||||
* * 判断一个对象数组是否为空
|
||||
*
|
||||
* @param objects 要判断的对象数组
|
||||
** @return true:为空 false:非空
|
||||
*/
|
||||
public static boolean isEmpty(Object[] objects)
|
||||
{
|
||||
return isNull(objects) || (objects.length == 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* * 判断一个对象数组是否非空
|
||||
*
|
||||
* @param objects 要判断的对象数组
|
||||
* @return true:非空 false:空
|
||||
*/
|
||||
public static boolean isNotEmpty(Object[] objects)
|
||||
{
|
||||
return !isEmpty(objects);
|
||||
}
|
||||
|
||||
/**
|
||||
* * 判断一个Map是否为空
|
||||
*
|
||||
* @param map 要判断的Map
|
||||
* @return true:为空 false:非空
|
||||
*/
|
||||
public static boolean isEmpty(Map<?, ?> map)
|
||||
{
|
||||
return isNull(map) || map.isEmpty();
|
||||
}
|
||||
|
||||
/**
|
||||
* * 判断一个Map是否为空
|
||||
*
|
||||
* @param map 要判断的Map
|
||||
* @return true:非空 false:空
|
||||
*/
|
||||
public static boolean isNotEmpty(Map<?, ?> map)
|
||||
{
|
||||
return !isEmpty(map);
|
||||
}
|
||||
|
||||
/**
|
||||
* * 判断一个字符串是否为空串
|
||||
*
|
||||
* @param str String
|
||||
* @return true:为空 false:非空
|
||||
*/
|
||||
public static boolean isEmpty(String str)
|
||||
{
|
||||
return isNull(str) || NULLSTR.equals(str.trim());
|
||||
}
|
||||
|
||||
/**
|
||||
* * 判断一个字符串是否为非空串
|
||||
*
|
||||
* @param str String
|
||||
* @return true:非空串 false:空串
|
||||
*/
|
||||
public static boolean isNotEmpty(String str)
|
||||
{
|
||||
return !isEmpty(str);
|
||||
}
|
||||
|
||||
/**
|
||||
* * 判断一个对象是否为空
|
||||
*
|
||||
* @param object Object
|
||||
* @return true:为空 false:非空
|
||||
*/
|
||||
public static boolean isNull(Object object)
|
||||
{
|
||||
return object == null;
|
||||
}
|
||||
|
||||
/**
|
||||
* * 判断一个对象是否非空
|
||||
*
|
||||
* @param object Object
|
||||
* @return true:非空 false:空
|
||||
*/
|
||||
public static boolean isNotNull(Object object)
|
||||
{
|
||||
return !isNull(object);
|
||||
}
|
||||
|
||||
/**
|
||||
* * 判断一个对象是否是数组类型(Java基本型别的数组)
|
||||
*
|
||||
* @param object 对象
|
||||
* @return true:是数组 false:不是数组
|
||||
*/
|
||||
public static boolean isArray(Object object)
|
||||
{
|
||||
return isNotNull(object) && object.getClass().isArray();
|
||||
}
|
||||
|
||||
/**
|
||||
* 去空格
|
||||
*/
|
||||
public static String trim(String str)
|
||||
{
|
||||
return (str == null ? "" : str.trim());
|
||||
}
|
||||
|
||||
/**
|
||||
* 替换指定字符串的指定区间内字符为"*"
|
||||
*
|
||||
* @param str 字符串
|
||||
* @param startInclude 开始位置(包含)
|
||||
* @param endExclude 结束位置(不包含)
|
||||
* @return 替换后的字符串
|
||||
*/
|
||||
public static String hide(CharSequence str, int startInclude, int endExclude)
|
||||
{
|
||||
if (isEmpty(str))
|
||||
{
|
||||
return NULLSTR;
|
||||
}
|
||||
final int strLength = str.length();
|
||||
if (startInclude > strLength)
|
||||
{
|
||||
return NULLSTR;
|
||||
}
|
||||
if (endExclude > strLength)
|
||||
{
|
||||
endExclude = strLength;
|
||||
}
|
||||
if (startInclude > endExclude)
|
||||
{
|
||||
// 如果起始位置大于结束位置,不替换
|
||||
return NULLSTR;
|
||||
}
|
||||
final char[] chars = new char[strLength];
|
||||
for (int i = 0; i < strLength; i++)
|
||||
{
|
||||
if (i >= startInclude && i < endExclude)
|
||||
{
|
||||
chars[i] = ASTERISK;
|
||||
}
|
||||
else
|
||||
{
|
||||
chars[i] = str.charAt(i);
|
||||
}
|
||||
}
|
||||
return new String(chars);
|
||||
}
|
||||
|
||||
/**
|
||||
* 截取字符串
|
||||
*
|
||||
* @param str 字符串
|
||||
* @param start 开始
|
||||
* @return 结果
|
||||
*/
|
||||
public static String substring(final String str, int start)
|
||||
{
|
||||
if (str == null)
|
||||
{
|
||||
return NULLSTR;
|
||||
}
|
||||
|
||||
if (start < 0)
|
||||
{
|
||||
start = str.length() + start;
|
||||
}
|
||||
|
||||
if (start < 0)
|
||||
{
|
||||
start = 0;
|
||||
}
|
||||
if (start > str.length())
|
||||
{
|
||||
return NULLSTR;
|
||||
}
|
||||
|
||||
return str.substring(start);
|
||||
}
|
||||
|
||||
/**
|
||||
* 截取字符串
|
||||
*
|
||||
* @param str 字符串
|
||||
* @param start 开始
|
||||
* @param end 结束
|
||||
* @return 结果
|
||||
*/
|
||||
public static String substring(final String str, int start, int end)
|
||||
{
|
||||
if (str == null)
|
||||
{
|
||||
return NULLSTR;
|
||||
}
|
||||
|
||||
if (end < 0)
|
||||
{
|
||||
end = str.length() + end;
|
||||
}
|
||||
if (start < 0)
|
||||
{
|
||||
start = str.length() + start;
|
||||
}
|
||||
|
||||
if (end > str.length())
|
||||
{
|
||||
end = str.length();
|
||||
}
|
||||
|
||||
if (start > end)
|
||||
{
|
||||
return NULLSTR;
|
||||
}
|
||||
|
||||
if (start < 0)
|
||||
{
|
||||
start = 0;
|
||||
}
|
||||
if (end < 0)
|
||||
{
|
||||
end = 0;
|
||||
}
|
||||
|
||||
return str.substring(start, end);
|
||||
}
|
||||
|
||||
/**
|
||||
* 在字符串中查找第一个出现的 `open` 和最后一个出现的 `close` 之间的子字符串
|
||||
*
|
||||
* @param str 要截取的字符串
|
||||
* @param open 起始字符串
|
||||
* @param close 结束字符串
|
||||
* @return 截取结果
|
||||
*/
|
||||
public static String substringBetweenLast(final String str, final String open, final String close)
|
||||
{
|
||||
if (isEmpty(str) || isEmpty(open) || isEmpty(close))
|
||||
{
|
||||
return NULLSTR;
|
||||
}
|
||||
final int start = str.indexOf(open);
|
||||
if (start != INDEX_NOT_FOUND)
|
||||
{
|
||||
final int end = str.lastIndexOf(close);
|
||||
if (end != INDEX_NOT_FOUND)
|
||||
{
|
||||
return str.substring(start + open.length(), end);
|
||||
}
|
||||
}
|
||||
return NULLSTR;
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断是否为空,并且不是空白字符
|
||||
*
|
||||
* @param str 要判断的value
|
||||
* @return 结果
|
||||
*/
|
||||
public static boolean hasText(String str)
|
||||
{
|
||||
return (str != null && !str.isEmpty() && containsText(str));
|
||||
}
|
||||
|
||||
private static boolean containsText(CharSequence str)
|
||||
{
|
||||
int strLen = str.length();
|
||||
for (int i = 0; i < strLen; i++)
|
||||
{
|
||||
if (!Character.isWhitespace(str.charAt(i)))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 字符串转set
|
||||
*
|
||||
* @param str 字符串
|
||||
* @param sep 分隔符
|
||||
* @return set集合
|
||||
*/
|
||||
public static final Set<String> str2Set(String str, String sep)
|
||||
{
|
||||
return new HashSet<String>(str2List(str, sep, true, false));
|
||||
}
|
||||
|
||||
/**
|
||||
* 字符串转list
|
||||
*
|
||||
* @param str 字符串
|
||||
* @param sep 分隔符
|
||||
* @return list集合
|
||||
*/
|
||||
public static final List<String> str2List(String str, String sep)
|
||||
{
|
||||
return str2List(str, sep, true, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* 字符串转list
|
||||
*
|
||||
* @param str 字符串
|
||||
* @param sep 分隔符
|
||||
* @param filterBlank 过滤纯空白
|
||||
* @param trim 去掉首尾空白
|
||||
* @return list集合
|
||||
*/
|
||||
public static final List<String> str2List(String str, String sep, boolean filterBlank, boolean trim)
|
||||
{
|
||||
List<String> list = new ArrayList<String>();
|
||||
if (StringUtils.isEmpty(str))
|
||||
{
|
||||
return list;
|
||||
}
|
||||
|
||||
// 过滤空白字符串
|
||||
if (filterBlank && StringUtils.isBlank(str))
|
||||
{
|
||||
return list;
|
||||
}
|
||||
String[] split = str.split(sep);
|
||||
for (String string : split)
|
||||
{
|
||||
if (filterBlank && StringUtils.isBlank(string))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (trim)
|
||||
{
|
||||
string = string.trim();
|
||||
}
|
||||
list.add(string);
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断给定的collection列表中是否包含数组array 判断给定的数组array中是否包含给定的元素value
|
||||
*
|
||||
* @param collection 给定的集合
|
||||
* @param array 给定的数组
|
||||
* @return boolean 结果
|
||||
*/
|
||||
public static boolean containsAny(Collection<String> collection, String... array)
|
||||
{
|
||||
if (isEmpty(collection) || isEmpty(array))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (String str : array)
|
||||
{
|
||||
if (collection.contains(str))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 查找指定字符串是否包含指定字符串列表中的任意一个字符串同时串忽略大小写
|
||||
*
|
||||
* @param cs 指定字符串
|
||||
* @param searchCharSequences 需要检查的字符串数组
|
||||
* @return 是否包含任意一个字符串
|
||||
*/
|
||||
public static boolean containsAnyIgnoreCase(CharSequence cs, CharSequence... searchCharSequences)
|
||||
{
|
||||
if (isEmpty(cs) || isEmpty(searchCharSequences))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
for (CharSequence testStr : searchCharSequences)
|
||||
{
|
||||
if (containsIgnoreCase(cs, testStr))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 驼峰转下划线命名
|
||||
*/
|
||||
public static String toUnderScoreCase(String str)
|
||||
{
|
||||
if (str == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
StringBuilder sb = new StringBuilder();
|
||||
// 前置字符是否大写
|
||||
boolean preCharIsUpperCase = true;
|
||||
// 当前字符是否大写
|
||||
boolean curreCharIsUpperCase = true;
|
||||
// 下一字符是否大写
|
||||
boolean nexteCharIsUpperCase = true;
|
||||
for (int i = 0; i < str.length(); i++)
|
||||
{
|
||||
char c = str.charAt(i);
|
||||
if (i > 0)
|
||||
{
|
||||
preCharIsUpperCase = Character.isUpperCase(str.charAt(i - 1));
|
||||
}
|
||||
else
|
||||
{
|
||||
preCharIsUpperCase = false;
|
||||
}
|
||||
|
||||
curreCharIsUpperCase = Character.isUpperCase(c);
|
||||
|
||||
if (i < (str.length() - 1))
|
||||
{
|
||||
nexteCharIsUpperCase = Character.isUpperCase(str.charAt(i + 1));
|
||||
}
|
||||
|
||||
if (preCharIsUpperCase && curreCharIsUpperCase && !nexteCharIsUpperCase)
|
||||
{
|
||||
sb.append(SEPARATOR);
|
||||
}
|
||||
else if ((i != 0 && !preCharIsUpperCase) && curreCharIsUpperCase)
|
||||
{
|
||||
sb.append(SEPARATOR);
|
||||
}
|
||||
sb.append(Character.toLowerCase(c));
|
||||
}
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否包含字符串
|
||||
*
|
||||
* @param str 验证字符串
|
||||
* @param strs 字符串组
|
||||
* @return 包含返回true
|
||||
*/
|
||||
public static boolean inStringIgnoreCase(String str, String... strs)
|
||||
{
|
||||
if (str != null && strs != null)
|
||||
{
|
||||
for (String s : strs)
|
||||
{
|
||||
if (str.equalsIgnoreCase(trim(s)))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 将下划线大写方式命名的字符串转换为驼峰式。如果转换前的下划线大写方式命名的字符串为空,则返回空字符串。 例如:HELLO_WORLD->HelloWorld
|
||||
*
|
||||
* @param name 转换前的下划线大写方式命名的字符串
|
||||
* @return 转换后的驼峰式命名的字符串
|
||||
*/
|
||||
public static String convertToCamelCase(String name)
|
||||
{
|
||||
StringBuilder result = new StringBuilder();
|
||||
// 快速检查
|
||||
if (name == null || name.isEmpty())
|
||||
{
|
||||
// 没必要转换
|
||||
return "";
|
||||
}
|
||||
else if (!name.contains("_"))
|
||||
{
|
||||
// 不含下划线,仅将首字母大写
|
||||
return name.substring(0, 1).toUpperCase() + name.substring(1);
|
||||
}
|
||||
// 用下划线将原始字符串分割
|
||||
String[] camels = name.split("_");
|
||||
for (String camel : camels)
|
||||
{
|
||||
// 跳过原始字符串中开头、结尾的下换线或双重下划线
|
||||
if (camel.isEmpty())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
// 首字母大写
|
||||
result.append(camel.substring(0, 1).toUpperCase());
|
||||
result.append(camel.substring(1).toLowerCase());
|
||||
}
|
||||
return result.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 驼峰式命名法
|
||||
* 例如:user_name->userName
|
||||
*/
|
||||
public static String toCamelCase(String s)
|
||||
{
|
||||
if (s == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
if (s.indexOf(SEPARATOR) == -1)
|
||||
{
|
||||
return s;
|
||||
}
|
||||
s = s.toLowerCase();
|
||||
StringBuilder sb = new StringBuilder(s.length());
|
||||
boolean upperCase = false;
|
||||
for (int i = 0; i < s.length(); i++)
|
||||
{
|
||||
char c = s.charAt(i);
|
||||
|
||||
if (c == SEPARATOR)
|
||||
{
|
||||
upperCase = true;
|
||||
}
|
||||
else if (upperCase)
|
||||
{
|
||||
sb.append(Character.toUpperCase(c));
|
||||
upperCase = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
sb.append(c);
|
||||
}
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 查找指定字符串是否匹配指定字符串列表中的任意一个字符串
|
||||
*
|
||||
* @param str 指定字符串
|
||||
* @param strs 需要检查的字符串数组
|
||||
* @return 是否匹配
|
||||
*/
|
||||
public static boolean matches(String str, List<String> strs)
|
||||
{
|
||||
if (isEmpty(str) || isEmpty(strs))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
for (String pattern : strs)
|
||||
{
|
||||
if (isMatch(pattern, str))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断url是否与规则配置:
|
||||
* ? 表示单个字符;
|
||||
* * 表示一层路径内的任意字符串,不可跨层级;
|
||||
* ** 表示任意层路径;
|
||||
*
|
||||
* @param pattern 匹配规则
|
||||
* @param url 需要匹配的url
|
||||
* @return
|
||||
*/
|
||||
public static boolean isMatch(String pattern, String url)
|
||||
{
|
||||
AntPathMatcher matcher = new AntPathMatcher();
|
||||
return matcher.match(pattern, url);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <T> T cast(Object obj)
|
||||
{
|
||||
return (T) obj;
|
||||
}
|
||||
|
||||
/**
|
||||
* 数字左边补齐0,使之达到指定长度。注意,如果数字转换为字符串后,长度大于size,则只保留 最后size个字符。
|
||||
*
|
||||
* @param num 数字对象
|
||||
* @param size 字符串指定长度
|
||||
* @return 返回数字的字符串格式,该字符串为指定长度。
|
||||
*/
|
||||
public static final String padl(final Number num, final int size)
|
||||
{
|
||||
return padl(num.toString(), size, '0');
|
||||
}
|
||||
|
||||
/**
|
||||
* 字符串左补齐。如果原始字符串s长度大于size,则只保留最后size个字符。
|
||||
*
|
||||
* @param s 原始字符串
|
||||
* @param size 字符串指定长度
|
||||
* @param c 用于补齐的字符
|
||||
* @return 返回指定长度的字符串,由原字符串左补齐或截取得到。
|
||||
*/
|
||||
public static final String padl(final String s, final int size, final char c)
|
||||
{
|
||||
final StringBuilder sb = new StringBuilder(size);
|
||||
if (s != null)
|
||||
{
|
||||
final int len = s.length();
|
||||
if (s.length() <= size)
|
||||
{
|
||||
for (int i = size - len; i > 0; i--)
|
||||
{
|
||||
sb.append(c);
|
||||
}
|
||||
sb.append(s);
|
||||
}
|
||||
else
|
||||
{
|
||||
return s.substring(len - size, len);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = size; i > 0; i--)
|
||||
{
|
||||
sb.append(c);
|
||||
}
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user