This commit is contained in:
Looly 2020-05-01 22:20:27 +08:00
parent c697de539f
commit be65a142b4
18 changed files with 173 additions and 75 deletions

View File

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

View File

@ -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();
}
}

View File

@ -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);
}
}

View File

@ -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

View File

@ -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
@ -70,11 +69,6 @@ public class BytesResource implements Resource, Serializable {
return StrUtil.str(this.bytes, charset);
}
@Override
public String readUtf8Str() throws IORuntimeException {
return readStr(CharsetUtil.CHARSET_UTF_8);
}
@Override
public byte[] readBytes() throws IORuntimeException {
return this.bytes;

View File

@ -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;
@ -74,11 +73,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;

View File

@ -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;
}

View File

@ -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>
* 资源可以是文件URLClassPath中的文件亦或者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>

View File

@ -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();
}
/**

View File

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

View File

@ -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;
@ -96,11 +95,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;

View File

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

View File

@ -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;
}

View File

@ -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", "", "", "", "", ""};
/**
* 取相反值

View File

@ -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);
}
}

View File

@ -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));

View File

@ -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;

View File

@ -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());
}
}