Commit 991beeb7 by 周田

feat: TDengine 工具类

parent b083d2ec
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Palette2">
<group name="Swing">
<item class="com.intellij.uiDesigner.HSpacer" tooltip-text="Horizontal Spacer" icon="/com/intellij/uiDesigner/icons/hspacer.svg" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="1" hsize-policy="6" anchor="0" fill="1" />
</item>
<item class="com.intellij.uiDesigner.VSpacer" tooltip-text="Vertical Spacer" icon="/com/intellij/uiDesigner/icons/vspacer.svg" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="1" anchor="0" fill="2" />
</item>
<item class="javax.swing.JPanel" icon="/com/intellij/uiDesigner/icons/panel.svg" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3" />
</item>
<item class="javax.swing.JScrollPane" icon="/com/intellij/uiDesigner/icons/scrollPane.svg" removable="false" auto-create-binding="false" can-attach-label="true">
<default-constraints vsize-policy="7" hsize-policy="7" anchor="0" fill="3" />
</item>
<item class="javax.swing.JButton" icon="/com/intellij/uiDesigner/icons/button.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="3" anchor="0" fill="1" />
<initial-values>
<property name="text" value="Button" />
</initial-values>
</item>
<item class="javax.swing.JRadioButton" icon="/com/intellij/uiDesigner/icons/radioButton.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" />
<initial-values>
<property name="text" value="RadioButton" />
</initial-values>
</item>
<item class="javax.swing.JCheckBox" icon="/com/intellij/uiDesigner/icons/checkBox.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" />
<initial-values>
<property name="text" value="CheckBox" />
</initial-values>
</item>
<item class="javax.swing.JLabel" icon="/com/intellij/uiDesigner/icons/label.svg" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="0" anchor="8" fill="0" />
<initial-values>
<property name="text" value="Label" />
</initial-values>
</item>
<item class="javax.swing.JTextField" icon="/com/intellij/uiDesigner/icons/textField.svg" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
<preferred-size width="150" height="-1" />
</default-constraints>
</item>
<item class="javax.swing.JPasswordField" icon="/com/intellij/uiDesigner/icons/passwordField.svg" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
<preferred-size width="150" height="-1" />
</default-constraints>
</item>
<item class="javax.swing.JFormattedTextField" icon="/com/intellij/uiDesigner/icons/formattedTextField.svg" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
<preferred-size width="150" height="-1" />
</default-constraints>
</item>
<item class="javax.swing.JTextArea" icon="/com/intellij/uiDesigner/icons/textArea.svg" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JTextPane" icon="/com/intellij/uiDesigner/icons/textPane.svg" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JEditorPane" icon="/com/intellij/uiDesigner/icons/editorPane.svg" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JComboBox" icon="/com/intellij/uiDesigner/icons/comboBox.svg" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="2" anchor="8" fill="1" />
</item>
<item class="javax.swing.JTable" icon="/com/intellij/uiDesigner/icons/table.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JList" icon="/com/intellij/uiDesigner/icons/list.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="2" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JTree" icon="/com/intellij/uiDesigner/icons/tree.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JTabbedPane" icon="/com/intellij/uiDesigner/icons/tabbedPane.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3">
<preferred-size width="200" height="200" />
</default-constraints>
</item>
<item class="javax.swing.JSplitPane" icon="/com/intellij/uiDesigner/icons/splitPane.svg" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3">
<preferred-size width="200" height="200" />
</default-constraints>
</item>
<item class="javax.swing.JSpinner" icon="/com/intellij/uiDesigner/icons/spinner.svg" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" />
</item>
<item class="javax.swing.JSlider" icon="/com/intellij/uiDesigner/icons/slider.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" />
</item>
<item class="javax.swing.JSeparator" icon="/com/intellij/uiDesigner/icons/separator.svg" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3" />
</item>
<item class="javax.swing.JProgressBar" icon="/com/intellij/uiDesigner/icons/progressbar.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1" />
</item>
<item class="javax.swing.JToolBar" icon="/com/intellij/uiDesigner/icons/toolbar.svg" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1">
<preferred-size width="-1" height="20" />
</default-constraints>
</item>
<item class="javax.swing.JToolBar$Separator" icon="/com/intellij/uiDesigner/icons/toolbarSeparator.svg" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="0" anchor="0" fill="1" />
</item>
<item class="javax.swing.JScrollBar" icon="/com/intellij/uiDesigner/icons/scrollbar.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="0" anchor="0" fill="2" />
</item>
</group>
</component>
</project>
\ No newline at end of file
...@@ -3,27 +3,67 @@ package org.linkor; ...@@ -3,27 +3,67 @@ package org.linkor;
import java.sql.Connection; import java.sql.Connection;
import java.sql.DriverManager; import java.sql.DriverManager;
import java.sql.SQLException; import java.sql.SQLException;
import java.util.Properties; import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
import java.util.*;
import com.taosdata.jdbc.TSDBDriver; import com.taosdata.jdbc.TSDBDriver;
import org.linkor.entities.Modbus;
import org.linkor.utils.TDengineUtil;
public class Main { public class Main {
public static void main(String[] args) throws SQLException { public static void main(String[] args) throws SQLException, ClassNotFoundException, IllegalAccessException, InstantiationException {
// 使用 RESTful API 连接 // 使用 RESTful API 连接
// String jdbcUrl = "jdbc:TAOS-RS://192.168.0.176:6030?user=root&password=taosdata"; // String jdbcUrl = "jdbc:TAOS-RS://192.168.0.176:6030?user=root&password=taosdata";
// Connection conn = DriverManager.getConnection(jdbcUrl); // Connection conn = DriverManager.getConnection(jdbcUrl);
// System.out.println("Connected"); // System.out.println("Connected");
// conn.close(); // conn.close();
String jdbcUrl = "jdbc:TAOS://192.168.0.176:6030?user=root&password=taosdata"; // String jdbcUrl = "jdbc:TAOS://192.168.0.176:6030?user=root&password=taosdata";
Properties connProps = new Properties(); // Properties connProps = new Properties();
connProps.setProperty(TSDBDriver.PROPERTY_KEY_CHARSET, "UTF-8"); // connProps.setProperty(TSDBDriver.PROPERTY_KEY_CHARSET, "UTF-8");
connProps.setProperty(TSDBDriver.PROPERTY_KEY_LOCALE, "en_US.UTF-8"); // connProps.setProperty(TSDBDriver.PROPERTY_KEY_LOCALE, "en_US.UTF-8");
connProps.setProperty(TSDBDriver.PROPERTY_KEY_TIME_ZONE, "UTC-8"); // connProps.setProperty(TSDBDriver.PROPERTY_KEY_TIME_ZONE, "UTC-8");
Connection conn = DriverManager.getConnection(jdbcUrl, connProps); // Connection conn = DriverManager.getConnection(jdbcUrl, connProps);
System.out.println("Connected"); // System.out.println("Connected");
conn.close(); // conn.close();
// System.out.println(System.currentTimeMillis());
//
// String datePattern = "yyyy-MM-dd HH:mm:ss.SSS";
// DateTimeFormatter formatter = DateTimeFormatter.ofPattern(datePattern);
//
// System.out.println("===============");
// String time = new SimpleDateFormat(datePattern).format(System.currentTimeMillis());
// long epochMilli = LocalDateTime.parse(time, formatter).toInstant(ZoneOffset.of("+8")).toEpochMilli();
// System.out.println(epochMilli);
TDengineUtil util = new TDengineUtil("jdbc:TAOS://192.168.0.176:6030/power","root","taosdata",true);
// util.insert("t", new HashMap<>(Map.of(
// "ss", "123"
// )));
util.insert(
"s",
new HashMap<>(Map.of(
"ts", new Date(),
"st", true,
"temperature", 1,
"press", 2
))
);
List<Modbus> list = util.getList("select * from power.s;", Modbus.class);
list.forEach(e -> System.out.println(e.toString()));
// System.out.println("===============");
// Modbus m = util.getOne("select * from power.s;", Modbus.class);
// System.out.println(m.toString());
} }
} }
\ No newline at end of file
package org.linkor.entities;
import java.util.Date;
/**
* modbus 数据类
*/
public class Modbus {
Date time;
boolean st;
int temperature;
int press;
public Modbus() {
}
public Modbus(Date time, boolean st, int temperature, int press) {
this.time = time;
this.st = st;
this.temperature = temperature;
this.press = press;
}
public Date getTime() {
return time;
}
public void setTime(Date time) {
this.time = time;
}
public boolean isSt() {
return st;
}
public void setSt(boolean st) {
this.st = st;
}
public int getTemperature() {
return temperature;
}
public void setTemperature(int temperature) {
this.temperature = temperature;
}
public int getPress() {
return press;
}
public void setPress(int press) {
this.press = press;
}
@Override
public String toString() {
return "Modbus{" +
"time=" + time +
", st=" + st +
", temperature=" + temperature +
", press=" + press +
'}';
}
}
package org.linkor.utils;
/**
* TDengine 工具类
*/
import com.taosdata.jdbc.TSDBDriver;
import java.lang.reflect.Method;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class TDengineUtil
{
private Connection connection;
//是否启用驼峰转下划线规则获得数据库字段名
private boolean databaseColumnHumpToLine;
/**
* @param url url 例如 : "jdbc:TAOS://127.0.0.1:6020/netuo_iot"
* @param username 例如: "root"
* @param password 例如: "taosdata"
* @param databaseColumnHumpToLine 是否需要数据库列名下划线转驼峰
*/
public TDengineUtil(String url, String username, String password, boolean databaseColumnHumpToLine) throws ClassNotFoundException, SQLException
{
Class.forName("com.taosdata.jdbc.TSDBDriver");
String jdbcUrl = url;
Properties connProps = new Properties();
connProps.setProperty(TSDBDriver.PROPERTY_KEY_USER, username);
connProps.setProperty(TSDBDriver.PROPERTY_KEY_PASSWORD, password);
connProps.setProperty(TSDBDriver.PROPERTY_KEY_CHARSET, "UTF-8");
connProps.setProperty(TSDBDriver.PROPERTY_KEY_LOCALE, "en_US.UTF-8");
connProps.setProperty(TSDBDriver.PROPERTY_KEY_TIME_ZONE, "UTC-8");
this.connection = DriverManager.getConnection(jdbcUrl, connProps);
this.databaseColumnHumpToLine = databaseColumnHumpToLine;
}
/**
* @param connection
* @param databaseColumnHumpToLine
*/
public TDengineUtil(Connection connection, boolean databaseColumnHumpToLine)
{
this.connection = connection;
this.databaseColumnHumpToLine = databaseColumnHumpToLine;
}
/**
* 执行sql(无论是否返回结果),将结果注入到指定的类型实例中,且返回
* 当查询到的数据大于一个时,取第一个
* <p>
* 对象遵从以下说明<br/>
* 1.对象字段为String类型,数据库类型(通过jdbc读取到的)无论什么类型,都将调用Object.toString方法注入值<br/>
* 2.对象字段为数据库类型(通过jdbc读取到的)一致的情况下,将会直接注入<br/>
* 3.对象字段与数据库类型(通过jdbc读取到的)不一致的情况下,将尝试使用{@link Class#cast(Object)}方法转型,失败此值会是类型默认值(故实体推荐使用封装类型)<br/>
* 4.对象字段为{@link Date}时,数据库类型为Date才可以注入,如果为long(例如TDengine)将会被当作毫秒的时间戳注入<br/>
*
* @param sql 要执行的sql
* @param clazz 要注入的实体类型
* @param <T> 要注入的实体类型
* @return
* @throws IllegalAccessException
* @throws InstantiationException
* @throws SQLException
*/
public <T> T getOne(String sql, Class<T> clazz) throws IllegalAccessException, InstantiationException, SQLException
{
Method[] setterMethods = getSetterMethods(clazz);
ResultSet resultSet = connection.createStatement().executeQuery(sql);
//只有一个结果直接下一个就行
resultSet.next();
return resultSetToObject(resultSet, setterMethods, clazz);
}
/**
* 执行sql(无论是否返回结果),将结果注入到指定的类型实例中,且返回
* 当查询到的结果没有时,返回一个大小为0的list;
* <p>
* 对象遵从以下说明<br/>
* 1.对象字段为String类型,数据库类型(通过jdbc读取到的)无论什么类型,都将调用Object.toString方法注入值<br/>
* 2.对象字段为数据库类型(通过jdbc读取到的)一致的情况下,将会直接注入<br/>
* 3.对象字段与数据库类型(通过jdbc读取到的)不一致的情况下,将尝试使用{@link Class#cast(Object)}方法转型,失败此值会是类型默认值(故实体推荐使用封装类型)<br/>
* 4.对象字段为{@link Date}时,数据库类型为Date才可以注入,如果为long(例如TDengine)将会被当作毫秒的时间戳注入<br/>
*
* @param sql 要执行的sql
* @param clazz 要注入的实体类型
* @param <T> 要注入的实体类型
* @return
* @throws IllegalAccessException
* @throws InstantiationException
* @throws SQLException
*/
public <T> List<T> getList(String sql, Class<T> clazz) throws IllegalAccessException, InstantiationException, SQLException
{
List<T> list = new ArrayList<>();
Method[] setterMethods = getSetterMethods(clazz);
ResultSet resultSet = connection.createStatement().executeQuery(sql);
while (resultSet.next())
{
list.add(resultSetToObject(resultSet, setterMethods, clazz));
}
return list;
}
/**
* 插入对象到指定的表里面
*
* @param tableName
* @param o
* @return
* @throws SQLException
*/
@SuppressWarnings("all")
public boolean insert(String tableName, Map<String, Object> map) throws SQLException
{
String sql = createInsertSql(tableName, map);
return connection.createStatement().execute(sql);
}
public boolean insertWithStable(String tableName, String sTableName, Map<String, Object> map, String... tags) throws SQLException
{
String sql = createInsertStableSql(tableName,sTableName, map,tags);
return connection.createStatement().execute(sql);
}
/**
* 生成插入Stable的sql语句
*
* @param tableName
* @param map
* @return
*/
public static String createInsertStableSql(String tableName, String sTbaleName, Map<String, Object> map, String... tags)
{
StringBuilder builder = new StringBuilder();
builder.append("INSERT INTO ").append(tableName);
builder.append(stableToSQL(sTbaleName, tags));
builder.append(mapToSQL(map));
return builder.toString();
}
private static String stableToSQL(String sTableName, String... tags)
{
StringBuilder builder = new StringBuilder();
builder.append(" using ").append(sTableName).append(" TAGS ( ");
for (String tag : tags)
{
builder.append("'").append(tag).append("',");
}
builder.deleteCharAt(builder.length() - 1).append(" ) ");
return builder.toString();
}
/**
* 生成插入sql语句
*
* @param tableName
* @param map
* @return
*/
public static String createInsertSql(String tableName, Map<String, Object> map)
{
StringBuilder builder = new StringBuilder();
builder.append("INSERT INTO ").append(tableName);
builder.append(mapToSQL(map));
return builder.toString();
}
public static String mapToSQL(Map<String, Object> map)
{
StringBuilder builder = new StringBuilder();
Set<Map.Entry<String, Object>> set = map.entrySet();
StringBuilder keys = new StringBuilder(" ");
StringBuilder value = new StringBuilder(" ");
for (Map.Entry<String, Object> entry : set)
{
keys.append(humpToLine(entry.getKey())).append(",");
try
{
if (entry.getValue().getClass().equals(Date.class))
{
Date d = (Date) entry.getValue();
value.append(d.getTime()).append(",");
}
else
{
value.append("'").append(entry.getValue()).append("'").append(",");
}
}
catch (Exception ignored)
{
}
}
keys.deleteCharAt(keys.length() - 1);
value.deleteCharAt(value.length() - 1);
builder.append(" (").append(keys).append(") VALUES( ").append(value).append(")");
return builder.toString();
}
/**
* 将resultSet注入到指定的类型实例中,且返回
* 对象遵从以下说明<br/>
* 1.对象字段为String类型,数据库类型(通过jdbc读取到的)无论什么类型,都将调用Object.toString方法注入值<br/>
* 2.对象字段为数据库类型(通过jdbc读取到的)一致的情况下,将会直接注入<br/>
* 3.对象字段与数据库类型(通过jdbc读取到的)不一致的情况下,将尝试使用{@link Class#cast(Object)}方法转型,失败此值会是类型默认值(故实体推荐使用封装类型)<br/>
* 4.对象字段为{@link Date}时,数据库类型为Date才可以注入,如果为long(例如TDengine)将会被当作毫秒的时间戳注入<br/>
* <p>
* 注意,此方法只会注入一个结果,不会循环{@link ResultSet#next()}方法,请从外部调用。<br/>
* 传入setterMethods的目的是为了方便外部循环使用此方法,这样方法内部不会重复调用,提高效率<br/>
*
* @param resultSet 查询结果,一定要是{@link ResultSet#next()}操作过的,不然没有数据
* @param setterMethods clazz对应的所有setter方法,可以使用{@link this#getSetterMethods(Class)}获取
* @param clazz 注入对象类型
* @param <T> 注入对象类型
* @return
* @throws IllegalAccessException
* @throws InstantiationException
*/
public <T> T resultSetToObject(ResultSet resultSet, Method[] setterMethods, Class<T> clazz) throws IllegalAccessException, InstantiationException
{
T result;
try
{
result = clazz.newInstance();
}
catch (InstantiationException e)
{
System.out.println("请检查类" + clazz.getCanonicalName() + "是否有无参构造方法");
throw e;
}
for (Method method : setterMethods)
{
try
{
String fieldName = getFieldNameBySetter(method);
//因为标准的setter方法只会有一个参数,所以取一个就行了
Class getParamClass = method.getParameterTypes()[0];
//获得查询的结果
Object resultObject;
//是否启用驼峰转下划线规则获得数据库字段名
if (databaseColumnHumpToLine)
{
resultObject = resultSet.getObject(humpToLine(fieldName));
}
else
{
resultObject = resultSet.getObject(fieldName);
}
//如果实体类的类型是String类型,那么无论x数据库类型是什么,都调用其toString方法获取值
if (getParamClass.equals(String.class))
{
method.invoke(result, resultObject.toString());
}
else if (getParamClass.equals(Date.class) && resultObject.getClass().equals(Long.class))
{
method.invoke(result, new Date((Long) resultObject));
}
else
{
try
{
method.invoke(result, resultObject);
}
catch (IllegalArgumentException e)
{
//对象字段与数据库类型(通过jdbc读取到的)不一致的情况下,将尝试强制转型
method.invoke(result, getParamClass.cast(resultObject));
}
}
}
catch (Exception ignored)
{
//所有的转型都失败了,则使用默认值
}
}
return result;
}
/**
* 通过setter method,获取到其对应的属性名
*
* @param method
* @return
*/
public static String getFieldNameBySetter(Method method)
{
return toLowerCaseFirstOne(method.getName().substring(3));
}
/**
* 获取指定类型方法的所有的setter方法
* 方法属性名为key,对应的方法为value
*
* @param clazz
* @return
*/
public static Map<String, Method> getSetterMethodsMap(Class clazz)
{
Method[] methods = clazz.getMethods();
Map<String, Method> setterMethods = new HashMap<>(methods.length / 2);
for (Method m : methods)
{
if (m.getName().startsWith("set"))
{
setterMethods.put(toLowerCaseFirstOne(m.getName().substring(3)), m);
}
}
return setterMethods;
}
/**
* 获取指定类型方法的所有的setter方法
*
* @param clazz
* @return
*/
public static Method[] getSetterMethods(Class clazz)
{
Method[] methods = clazz.getMethods();
Method[] setterMethods = new Method[methods.length / 2];
int i = 0;
for (Method m : methods)
{
if (m.getName().startsWith("set"))
{
setterMethods[i] = m;
i++;
}
}
return setterMethods;
}
/**
* 首字母转小写
*/
public static String toLowerCaseFirstOne(String s)
{
if (Character.isLowerCase(s.charAt(0)))
{
return s;
}
else
{
return Character.toLowerCase(s.charAt(0)) + s.substring(1);
}
}
/**
* 首字母转大写
*/
public static String toUpperCaseFirstOne(String s)
{
if (Character.isUpperCase(s.charAt(0)))
{
return s;
}
else
{
return Character.toUpperCase(s.charAt(0)) + s.substring(1);
}
}
private static Pattern linePattern = Pattern.compile("_(\\w)");
/**
* 下划线转驼峰
*/
public static String lineToHump(String str)
{
str = str.toLowerCase();
Matcher matcher = linePattern.matcher(str);
StringBuffer sb = new StringBuffer();
while (matcher.find())
{
matcher.appendReplacement(sb, matcher.group(1).toUpperCase());
}
matcher.appendTail(sb);
return sb.toString();
}
private static Pattern humpPattern = Pattern.compile("[A-Z]");
/**
* 驼峰转下划线,效率比上面高
*/
public static String humpToLine(String str)
{
Matcher matcher = humpPattern.matcher(str);
StringBuffer sb = new StringBuffer();
while (matcher.find())
{
matcher.appendReplacement(sb, "_" + matcher.group(0).toLowerCase());
}
matcher.appendTail(sb);
return sb.toString();
}
}
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment