Looly 5 years ago
parent
commit
be65a142b4

+ 2 - 0
CHANGELOG.md

@@ -14,9 +14,11 @@
 * 【extra  】     SpringUtil增加getActiveProfiles、getBeansOfType、getBeanNamesForType方法(issue#I1FXF3@Gitee)
 * 【bloomFilter】 避免布隆过滤器数字溢出(pr#119@Gitee)
 * 【core   】     增加IoUtil.writeObj(issue#I1FZIE)
+* 【core   】     增加FastStringWriter
 
 ### Bug修复
 * 【core   】     修复URLBuilder中请求参数有`&`导致的问题(issue#850@Github)
+* 【db     】     修复SqlBuilder中orderBy无效问题(issue#856@Github)
 
 -------------------------------------------------------------------------------------------------------------
 

+ 91 - 0
hutool-core/src/main/java/cn/hutool/core/io/FastStringWriter.java

@@ -0,0 +1,91 @@
+package cn.hutool.core.io;
+
+import cn.hutool.core.text.StrBuilder;
+
+import java.io.Writer;
+
+/**
+ * 借助{@link StrBuilder} 提供快读的字符串写出,相比jdk的StringWriter非线程安全,速度更快。
+ *
+ * @author looly
+ * @since 5.3.3
+ */
+public final class FastStringWriter extends Writer {
+
+	private final StrBuilder builder;
+
+	/**
+	 * 构造
+	 */
+	public FastStringWriter() {
+		this(StrBuilder.DEFAULT_CAPACITY);
+	}
+
+	/**
+	 * 构造
+	 *
+	 * @param initialSize 初始容量
+	 */
+	public FastStringWriter(int initialSize) {
+		super();
+		if (initialSize < 0) {
+			initialSize = StrBuilder.DEFAULT_CAPACITY;
+		}
+		this.builder = new StrBuilder(initialSize);
+	}
+
+
+	@Override
+	public void write(final int c) {
+		this.builder.append((char) c);
+	}
+
+
+	@Override
+	public void write(final String str) {
+		this.builder.append(str);
+	}
+
+
+	@Override
+	public void write(final String str, final int off, final int len) {
+		this.builder.append(str, off, off + len);
+	}
+
+
+	@Override
+	public void write(final char[] cbuf) {
+		this.builder.append(cbuf, 0, cbuf.length);
+	}
+
+
+	@Override
+	public void write(final char[] cbuf, final int off, final int len) {
+		if ((off < 0) || (off > cbuf.length) || (len < 0) ||
+				((off + len) > cbuf.length) || ((off + len) < 0)) {
+			throw new IndexOutOfBoundsException();
+		} else if (len == 0) {
+			return;
+		}
+		this.builder.append(cbuf, off, len);
+	}
+
+
+	@Override
+	public void flush() {
+		// Nothing to be flushed
+	}
+
+
+	@Override
+	public void close() {
+		// Nothing to be closed
+	}
+
+
+	@Override
+	public String toString() {
+		return this.builder.toString();
+	}
+
+}

+ 1 - 1
hutool-core/src/main/java/cn/hutool/core/io/FileUtil.java

@@ -3578,6 +3578,6 @@ public class FileUtil {
 	 * @param charset 编码
 	 */
 	public static void tail(File file, Charset charset) {
-		FileUtil.tail(file, charset, Tailer.CONSOLE_HANDLER);
+		tail(file, charset, Tailer.CONSOLE_HANDLER);
 	}
 }

+ 1 - 1
hutool-core/src/main/java/cn/hutool/core/io/checksum/CRC16.java

@@ -66,7 +66,7 @@ public class CRC16 implements Checksum, Serializable {
 	@Override
 	public void update(byte[] b, int off, int len) {
 		for (int i = off; i < off + len; i++)
-			update((int) b[i]);
+			update(b[i]);
 	}
 
 	@Override

+ 3 - 9
hutool-core/src/main/java/cn/hutool/core/io/resource/BytesResource.java

@@ -1,5 +1,8 @@
 package cn.hutool.core.io.resource;
 
+import cn.hutool.core.io.IORuntimeException;
+import cn.hutool.core.util.StrUtil;
+
 import java.io.BufferedReader;
 import java.io.ByteArrayInputStream;
 import java.io.InputStream;
@@ -8,10 +11,6 @@ import java.io.StringReader;
 import java.net.URL;
 import java.nio.charset.Charset;
 
-import cn.hutool.core.io.IORuntimeException;
-import cn.hutool.core.util.CharsetUtil;
-import cn.hutool.core.util.StrUtil;
-
 /**
  * 基于byte[]的资源获取器<br>
  * 注意:此对象中getUrl方法始终返回null
@@ -71,11 +70,6 @@ public class BytesResource implements Resource, Serializable {
 	}
 
 	@Override
-	public String readUtf8Str() throws IORuntimeException {
-		return readStr(CharsetUtil.CHARSET_UTF_8);
-	}
-
-	@Override
 	public byte[] readBytes() throws IORuntimeException {
 		return this.bytes;
 	}

+ 0 - 6
hutool-core/src/main/java/cn/hutool/core/io/resource/InputStreamResource.java

@@ -2,7 +2,6 @@ package cn.hutool.core.io.resource;
 
 import cn.hutool.core.io.IORuntimeException;
 import cn.hutool.core.io.IoUtil;
-import cn.hutool.core.util.CharsetUtil;
 
 import java.io.BufferedReader;
 import java.io.InputStream;
@@ -75,11 +74,6 @@ public class InputStreamResource implements Resource, Serializable {
 	}
 
 	@Override
-	public String readUtf8Str() throws IORuntimeException {
-		return readStr(CharsetUtil.CHARSET_UTF_8);
-	}
-
-	@Override
 	public byte[] readBytes() throws IORuntimeException {
 		InputStream in = null;
 		try {

+ 2 - 2
hutool-core/src/main/java/cn/hutool/core/io/resource/MultiResource.java

@@ -94,7 +94,7 @@ public class MultiResource implements Resource, Iterable<Resource>, Iterator<Res
 	}
 
 	@Override
-	public Resource next() {
+	public synchronized Resource next() {
 		if (cursor >= resources.size()) {
 			throw new ConcurrentModificationException();
 		}
@@ -110,7 +110,7 @@ public class MultiResource implements Resource, Iterable<Resource>, Iterator<Res
 	/**
 	 * 重置游标
 	 */
-	public void reset() {
+	public synchronized void reset() {
 		this.cursor = 0;
 	}
 	

+ 6 - 3
hutool-core/src/main/java/cn/hutool/core/io/resource/Resource.java

@@ -1,13 +1,14 @@
 package cn.hutool.core.io.resource;
 
+import cn.hutool.core.io.IORuntimeException;
+import cn.hutool.core.util.CharsetUtil;
+
 import java.io.BufferedReader;
 import java.io.IOException;
 import java.io.InputStream;
 import java.net.URL;
 import java.nio.charset.Charset;
 
-import cn.hutool.core.io.IORuntimeException;
-
 /**
  * 资源接口定义<br>
  * 资源可以是文件、URL、ClassPath中的文件亦或者jar包中的文件
@@ -60,7 +61,9 @@ public interface Resource {
 	 * @return 读取资源内容
 	 * @throws IORuntimeException 包装IOException
 	 */
-	String readUtf8Str() throws IORuntimeException;
+	default String readUtf8Str() throws IORuntimeException{
+		return readStr(CharsetUtil.CHARSET_UTF_8);
+	}
 	
 	/**
 	 * 读取资源内容,读取完毕后会关闭流<br>

+ 2 - 3
hutool-core/src/main/java/cn/hutool/core/io/resource/ResourceUtil.java

@@ -4,7 +4,6 @@ import cn.hutool.core.collection.CollUtil;
 import cn.hutool.core.collection.EnumerationIter;
 import cn.hutool.core.io.FileUtil;
 import cn.hutool.core.io.IORuntimeException;
-import cn.hutool.core.util.CharsetUtil;
 import cn.hutool.core.util.ClassLoaderUtil;
 import cn.hutool.core.util.StrUtil;
 import cn.hutool.core.util.URLUtil;
@@ -18,7 +17,7 @@ import java.util.Enumeration;
 import java.util.List;
 
 /**
- * ClassPath资源工具类
+ * Resource资源工具类
  * 
  * @author Looly
  *
@@ -33,7 +32,7 @@ public class ResourceUtil {
 	 * @since 3.1.1
 	 */
 	public static String readUtf8Str(String resource) {
-		return readStr(resource, CharsetUtil.CHARSET_UTF_8);
+		return getResourceObj(resource).readUtf8Str();
 	}
 
 	/**

+ 0 - 5
hutool-core/src/main/java/cn/hutool/core/io/resource/StringResource.java

@@ -83,11 +83,6 @@ public class StringResource implements Resource, Serializable {
 	}
 
 	@Override
-	public String readUtf8Str() throws IORuntimeException {
-		return this.data;
-	}
-
-	@Override
 	public byte[] readBytes() throws IORuntimeException {
 		return this.data.getBytes(this.charset);
 	}

+ 0 - 6
hutool-core/src/main/java/cn/hutool/core/io/resource/UrlResource.java

@@ -3,7 +3,6 @@ package cn.hutool.core.io.resource;
 import cn.hutool.core.io.FileUtil;
 import cn.hutool.core.io.IORuntimeException;
 import cn.hutool.core.io.IoUtil;
-import cn.hutool.core.util.CharsetUtil;
 import cn.hutool.core.util.ObjectUtil;
 import cn.hutool.core.util.URLUtil;
 
@@ -97,11 +96,6 @@ public class UrlResource implements Resource, Serializable{
 	}
 	
 	@Override
-	public String readUtf8Str() throws IORuntimeException{
-		return readStr(CharsetUtil.CHARSET_UTF_8);
-	}
-	
-	@Override
 	public byte[] readBytes() throws IORuntimeException{
 		InputStream in = null;
 		try {

+ 1 - 1
hutool-core/src/main/java/cn/hutool/core/net/url/UrlBuilder.java

@@ -71,7 +71,7 @@ public final class UrlBuilder implements Serializable {
 	}
 
 	/**
-	 * 使用URL字符串构建UrlBuilder
+	 * 使用URL字符串构建UrlBuilder,当传入的URL没有协议时,按照http协议对待。
 	 *
 	 * @param httpUrl URL字符串
 	 * @param charset 编码,用于URLEncode和URLDecode

+ 1 - 1
hutool-core/src/main/java/cn/hutool/core/net/url/UrlQuery.java

@@ -135,7 +135,7 @@ public class UrlQuery {
 				case '&'://键值对之间的分界符
 					addParam(name, queryStr.substring(pos, i), charset);
 					name = null;
-					if ("amp;".equals(queryStr.substring(i + 1, i + 5))) {
+					if (i+4 < len && "amp;".equals(queryStr.substring(i + 1, i + 5))) {
 						// issue#850@Github,"&amp;"转义为"&"
 						i+=4;
 					}

+ 1 - 1
hutool-core/src/main/java/cn/hutool/core/util/BooleanUtil.java

@@ -11,7 +11,7 @@ import cn.hutool.core.convert.Convert;
 public class BooleanUtil {
 
 	/** 表示为真的字符串 */
-	private static final String[] TRUE_ARRAY = { "true", "yes", "y", "t", "ok", "1", "on", "是", "对", "真", };
+	private static final String[] TRUE_ARRAY = { "true", "yes", "y", "t", "ok", "1", "on", "是", "对", "真", "對", "√"};
 
 	/**
 	 * 取相反值

+ 13 - 0
hutool-core/src/test/java/cn/hutool/core/io/resource/ResourceUtilTest.java

@@ -0,0 +1,13 @@
+package cn.hutool.core.io.resource;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+public class ResourceUtilTest {
+
+	@Test
+	public void readXmlTest(){
+		final String str = ResourceUtil.readUtf8Str("test.xml");
+		Assert.assertNotNull(str);
+	}
+}

+ 28 - 28
hutool-core/src/test/java/cn/hutool/core/net/UrlBuilderTest.java

@@ -9,112 +9,112 @@ public class UrlBuilderTest {
 
 	@Test
 	public void buildTest() {
-		String buildUrl = UrlBuilder.create().setHost("www.baidu.com").build();
-		Assert.assertEquals("http://www.baidu.com/", buildUrl);
+		String buildUrl = UrlBuilder.create().setHost("www.hutool.cn").build();
+		Assert.assertEquals("http://www.hutool.cn/", buildUrl);
 	}
 
 	@Test
 	public void testHost() {
 		String buildUrl = UrlBuilder.create()
 				.setScheme("https")
-				.setHost("www.baidu.com").build();
-		Assert.assertEquals("https://www.baidu.com/", buildUrl);
+				.setHost("www.hutool.cn").build();
+		Assert.assertEquals("https://www.hutool.cn/", buildUrl);
 	}
 
 	@Test
 	public void testHostPort() {
 		String buildUrl = UrlBuilder.create()
 				.setScheme("https")
-				.setHost("www.baidu.com")
+				.setHost("www.hutool.cn")
 				.setPort(8080)
 				.build();
-		Assert.assertEquals("https://www.baidu.com:8080/", buildUrl);
+		Assert.assertEquals("https://www.hutool.cn:8080/", buildUrl);
 	}
 
 	@Test
 	public void testPathAndQuery() {
 		final String buildUrl = UrlBuilder.create()
 				.setScheme("https")
-				.setHost("www.baidu.com")
+				.setHost("www.hutool.cn")
 				.addPath("/aaa").addPath("bbb")
 				.addQuery("ie", "UTF-8")
 				.addQuery("wd", "test")
 				.build();
 
-		Assert.assertEquals("https://www.baidu.com/aaa/bbb?ie=UTF-8&wd=test", buildUrl);
+		Assert.assertEquals("https://www.hutool.cn/aaa/bbb?ie=UTF-8&wd=test", buildUrl);
 	}
 
 	@Test
 	public void testQueryWithChinese() {
 		final String buildUrl = UrlBuilder.create()
 				.setScheme("https")
-				.setHost("www.baidu.com")
+				.setHost("www.hutool.cn")
 				.addPath("/aaa").addPath("bbb")
 				.addQuery("ie", "UTF-8")
 				.addQuery("wd", "测试")
 				.build();
 
-		Assert.assertEquals("https://www.baidu.com/aaa/bbb?ie=UTF-8&wd=%E6%B5%8B%E8%AF%95", buildUrl);
+		Assert.assertEquals("https://www.hutool.cn/aaa/bbb?ie=UTF-8&wd=%E6%B5%8B%E8%AF%95", buildUrl);
 	}
 
 	@Test
 	public void testMultiQueryWithChinese() {
 		final String buildUrl = UrlBuilder.create()
 				.setScheme("https")
-				.setHost("www.baidu.com")
+				.setHost("www.hutool.cn")
 				.addPath("/s")
 				.addQuery("ie", "UTF-8")
 				.addQuery("ie", "GBK")
 				.addQuery("wd", "测试")
 				.build();
 
-		Assert.assertEquals("https://www.baidu.com/s?ie=UTF-8&ie=GBK&wd=%E6%B5%8B%E8%AF%95", buildUrl);
+		Assert.assertEquals("https://www.hutool.cn/s?ie=UTF-8&ie=GBK&wd=%E6%B5%8B%E8%AF%95", buildUrl);
 	}
 
 	@Test
 	public void testFragment() {
 		String buildUrl = new UrlBuilder()
 				.setScheme("https")
-				.setHost("www.baidu.com")
+				.setHost("www.hutool.cn")
 				.setFragment("abc").build();
-		Assert.assertEquals("https://www.baidu.com/#abc", buildUrl);
+		Assert.assertEquals("https://www.hutool.cn/#abc", buildUrl);
 	}
 
 	@Test
 	public void testChineseFragment() {
 		String buildUrl = new UrlBuilder()
 				.setScheme("https")
-				.setHost("www.baidu.com")
+				.setHost("www.hutool.cn")
 				.setFragment("测试").build();
-		Assert.assertEquals("https://www.baidu.com/#%E6%B5%8B%E8%AF%95", buildUrl);
+		Assert.assertEquals("https://www.hutool.cn/#%E6%B5%8B%E8%AF%95", buildUrl);
 	}
 
 	@Test
 	public void testChineseFragmentWithPath() {
 		String buildUrl = new UrlBuilder()
 				.setScheme("https")
-				.setHost("www.baidu.com")
+				.setHost("www.hutool.cn")
 				.addPath("/s")
 				.setFragment("测试").build();
-		Assert.assertEquals("https://www.baidu.com/s#%E6%B5%8B%E8%AF%95", buildUrl);
+		Assert.assertEquals("https://www.hutool.cn/s#%E6%B5%8B%E8%AF%95", buildUrl);
 	}
 
 	@Test
 	public void testChineseFragmentWithPathAndQuery() {
 		String buildUrl = new UrlBuilder()
 				.setScheme("https")
-				.setHost("www.baidu.com")
+				.setHost("www.hutool.cn")
 				.addPath("/s")
 				.addQuery("wd", "test")
 				.setFragment("测试").build();
-		Assert.assertEquals("https://www.baidu.com/s?wd=test#%E6%B5%8B%E8%AF%95", buildUrl);
+		Assert.assertEquals("https://www.hutool.cn/s?wd=test#%E6%B5%8B%E8%AF%95", buildUrl);
 	}
 
 	@Test
 	public void ofTest() {
-		final UrlBuilder builder = UrlBuilder.of("http://www.baidu.com/aaa/bbb/?a=1&b=2#frag1", CharsetUtil.CHARSET_UTF_8);
+		final UrlBuilder builder = UrlBuilder.of("http://www.hutool.cn/aaa/bbb/?a=1&b=2#frag1", CharsetUtil.CHARSET_UTF_8);
 		Assert.assertEquals("http", builder.getScheme());
-		Assert.assertEquals("www.baidu.com", builder.getHost());
+		Assert.assertEquals("www.hutool.cn", builder.getHost());
 
 		Assert.assertEquals("aaa", builder.getPath().getSegment(0));
 		Assert.assertEquals("bbb", builder.getPath().getSegment(1));
@@ -127,9 +127,9 @@ public class UrlBuilderTest {
 
 	@Test
 	public void ofWithChineseTest() {
-		final UrlBuilder builder = UrlBuilder.ofHttp("www.baidu.com/aaa/bbb/?a=张三&b=%e6%9d%8e%e5%9b%9b#frag1", CharsetUtil.CHARSET_UTF_8);
+		final UrlBuilder builder = UrlBuilder.ofHttp("www.hutool.cn/aaa/bbb/?a=张三&b=%e6%9d%8e%e5%9b%9b#frag1", CharsetUtil.CHARSET_UTF_8);
 		Assert.assertEquals("http", builder.getScheme());
-		Assert.assertEquals("www.baidu.com", builder.getHost());
+		Assert.assertEquals("www.hutool.cn", builder.getHost());
 
 		Assert.assertEquals("aaa", builder.getPath().getSegment(0));
 		Assert.assertEquals("bbb", builder.getPath().getSegment(1));
@@ -142,9 +142,9 @@ public class UrlBuilderTest {
 
 	@Test
 	public void ofWithBlankTest() {
-		final UrlBuilder builder = UrlBuilder.ofHttp(" www.baidu.com/aaa/bbb/?a=张三&b=%e6%9d%8e%e5%9b%9b#frag1", CharsetUtil.CHARSET_UTF_8);
+		final UrlBuilder builder = UrlBuilder.ofHttp(" www.hutool.cn/aaa/bbb/?a=张三&b=%e6%9d%8e%e5%9b%9b#frag1", CharsetUtil.CHARSET_UTF_8);
 		Assert.assertEquals("http", builder.getScheme());
-		Assert.assertEquals("www.baidu.com", builder.getHost());
+		Assert.assertEquals("www.hutool.cn", builder.getHost());
 
 		Assert.assertEquals("aaa", builder.getPath().getSegment(0));
 		Assert.assertEquals("bbb", builder.getPath().getSegment(1));
@@ -158,9 +158,9 @@ public class UrlBuilderTest {
 	@Test
 	public void ofSpecialTest() {
 		//测试不规范的或者无需解码的字符串是否成功解码
-		final UrlBuilder builder = UrlBuilder.ofHttp(" www.baidu.com/aaa/bbb/?a=张三&b=%%e5%9b%9b#frag1", CharsetUtil.CHARSET_UTF_8);
+		final UrlBuilder builder = UrlBuilder.ofHttp(" www.hutool.cn/aaa/bbb/?a=张三&b=%%e5%9b%9b#frag1", CharsetUtil.CHARSET_UTF_8);
 		Assert.assertEquals("http", builder.getScheme());
-		Assert.assertEquals("www.baidu.com", builder.getHost());
+		Assert.assertEquals("www.hutool.cn", builder.getHost());
 
 		Assert.assertEquals("aaa", builder.getPath().getSegment(0));
 		Assert.assertEquals("bbb", builder.getPath().getSegment(1));

+ 9 - 8
hutool-db/src/main/java/cn/hutool/db/sql/SqlBuilder.java

@@ -1,11 +1,5 @@
 package cn.hutool.db.sql;
 
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.List;
-import java.util.Map.Entry;
-
 import cn.hutool.core.builder.Builder;
 import cn.hutool.core.collection.CollectionUtil;
 import cn.hutool.core.util.ArrayUtil;
@@ -15,6 +9,12 @@ import cn.hutool.db.DbRuntimeException;
 import cn.hutool.db.Entity;
 import cn.hutool.db.dialect.DialectName;
 
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map.Entry;
+
 /**
  * SQL构建器<br>
  * 首先拼接SQL语句,值使用 ? 占位<br>
@@ -404,12 +404,13 @@ public class SqlBuilder implements Builder<String>{
 		}
 
 		sql.append(" ORDER BY ");
-		String field = null;
+		String field;
 		boolean isFirst = true;
 		for (Order order : orders) {
+			field = order.getField();
 			if (null != wrapper) {
 				// 包装字段名
-				field = wrapper.wrap(order.getField());
+				field = wrapper.wrap(field);
 			}
 			if (StrUtil.isBlank(field)) {
 				continue;

+ 12 - 0
hutool-db/src/test/java/cn/hutool/db/sql/SqlBuilderTest.java

@@ -19,4 +19,16 @@ public class SqlBuilderTest {
 		SqlBuilder builder4 = SqlBuilder.create().select().from("user").where(LogicalOperator.AND, new Condition("name", "is not null"));
 		Assert.assertEquals("SELECT * FROM user WHERE name IS NOT NULL", builder4.build());
 	}
+
+	@Test
+	public void orderByTest(){
+		SqlBuilder builder = SqlBuilder.create().select("id", "username").from("user")
+				.join("role", SqlBuilder.Join.INNER)
+				.on("user.id = role.user_id")
+				.where(new Condition("age", ">=", 18),
+						new Condition("username", "abc", Condition.LikeType.Contains)
+				).orderBy(new Order("id"));
+
+		Assert.assertEquals("SELECT id,username FROM user INNER JOIN role ON user.id = role.user_id WHERE age >= ? AND username LIKE ? ORDER BY id", builder.build());
+	}
 }