初始化
This commit is contained in:
128
ordermallGateway/src/main/java/com/yxt/ordermall/AuthFilter.java
Normal file
128
ordermallGateway/src/main/java/com/yxt/ordermall/AuthFilter.java
Normal file
@@ -0,0 +1,128 @@
|
||||
package com.yxt.ordermall;//package com.yxt.wms;
|
||||
//
|
||||
//import com.alibaba.fastjson.JSON;
|
||||
//import com.yxt.wms.utils.*;
|
||||
//import org.reactivestreams.Publisher;
|
||||
//import org.slf4j.Logger;
|
||||
//import org.slf4j.LoggerFactory;
|
||||
//import org.springframework.beans.factory.annotation.Autowired;
|
||||
//import org.springframework.cloud.gateway.filter.GatewayFilterChain;
|
||||
//import org.springframework.cloud.gateway.filter.GlobalFilter;
|
||||
//import org.springframework.core.Ordered;
|
||||
//import org.springframework.core.io.buffer.DataBuffer;
|
||||
//import org.springframework.core.io.buffer.DataBufferFactory;
|
||||
//import org.springframework.core.io.buffer.DataBufferUtils;
|
||||
//import org.springframework.http.HttpStatus;
|
||||
//import org.springframework.http.MediaType;
|
||||
//import org.springframework.http.server.reactive.ServerHttpRequest;
|
||||
//import org.springframework.http.server.reactive.ServerHttpResponse;
|
||||
//import org.springframework.stereotype.Component;
|
||||
//import org.springframework.util.MultiValueMap;
|
||||
//import org.springframework.web.server.ServerWebExchange;
|
||||
//import reactor.core.publisher.Mono;
|
||||
//
|
||||
//import static com.yxt.wms.utils.HttpStatus.OVERDUE;
|
||||
//
|
||||
///**
|
||||
// * @author dimengzhe
|
||||
// * @date 2020/12/2 9:52
|
||||
// * @description 网关鉴权
|
||||
// * 1.某些接口不需要不进行登录验证,如登录,注册,获取验证码等接口。(uri白名单)
|
||||
// * 2.某些接口需要登录验证,但是不需要刷新token有效时间,如客户端轮询请求的接口。
|
||||
// * 3.特定场景下IP黑、白名单。
|
||||
// * 4.处于安全考虑的接口流量控制。
|
||||
// */
|
||||
//@Component
|
||||
//public class AuthFilter implements GlobalFilter, Ordered {
|
||||
//
|
||||
// private static final Logger log = LoggerFactory.getLogger(AuthFilter.class);
|
||||
// //过期时间设置为4小时
|
||||
// private final static long EXPIRE_TIME = Constants.TOKEN_EXPIRE * 60;
|
||||
// private final static long EXPIRE_TIME_APP = Constants.TOKEN_EXPIRE_APP * 60;
|
||||
//
|
||||
// // 排除过滤的 uri 地址,nacos自行添加
|
||||
// @Autowired
|
||||
// private IgnoreWhiteProperties ignoreWhite;
|
||||
// @Autowired
|
||||
// private RedisUtil redisUtil;
|
||||
// /*
|
||||
// redis中数据存储结构为两个键值对
|
||||
// 键为用户ID,值为用户token,可以通过用户ID查询用户token,实现立刻失效用户token功能。
|
||||
// 键为用户token,值为用户数据,实现token有效性,用户数据缓存功能。
|
||||
// */
|
||||
//
|
||||
// @Override
|
||||
// public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
|
||||
// String url = exchange.getRequest().getURI().getPath();
|
||||
// //1.uri白名单。 跳过不需要验证的路径
|
||||
// if (StringUtils.matches(url, ignoreWhite.getWhites())) {
|
||||
// return chain.filter(exchange);
|
||||
// } else if (StringUtils.matchesTwo(url, ignoreWhite.getWhitesTwo())) {
|
||||
// return chain.filter(exchange);
|
||||
// }
|
||||
// //2.验证有无令牌。 从请求的header中获取token
|
||||
// String token = getToken(exchange.getRequest());
|
||||
// if (StringUtils.isBlank(token)) {
|
||||
// return setUnauthorizedResponse(exchange, "令牌不能为空");
|
||||
// }
|
||||
// //3.验证token是否有效。(a.验证token是否合法 b.验证token是否过期)
|
||||
// //从redis缓存中获取key对应的内容
|
||||
// String userName = redisUtil.get(token);
|
||||
//
|
||||
// if (StringUtils.isBlank(userName)) {
|
||||
//
|
||||
// return setUnauthorizedResponse(exchange, "登录状态已过期");
|
||||
// }
|
||||
// //验签:需要验证token中的签名是否与用户sid一致,后台用密钥+userSid+token除签名以外的内容,重新生成签名,与token中的签名进行比较
|
||||
//
|
||||
// //刷新token过期日期
|
||||
// if (token.contains("App")) {
|
||||
// redisUtil.expire(token, EXPIRE_TIME_APP);
|
||||
// } else {
|
||||
// redisUtil.expire(token, EXPIRE_TIME);
|
||||
// }
|
||||
//
|
||||
// // 在请求中增加用户信息
|
||||
// ServerHttpRequest mutableReq = exchange.getRequest().mutate()
|
||||
// .header(CacheConstants.DETAILS_USERNAME, userName).build();
|
||||
// ServerWebExchange mutableExchange = exchange.mutate().request(mutableReq).build();
|
||||
// return chain.filter(mutableExchange);
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * 鉴权异常处理
|
||||
// *
|
||||
// * @param exchange
|
||||
// * @param msg
|
||||
// * @return
|
||||
// */
|
||||
// private Mono<Void> setUnauthorizedResponse(ServerWebExchange exchange, String msg) {
|
||||
// ServerHttpResponse response = exchange.getResponse();
|
||||
// response.getHeaders().setContentType(MediaType.APPLICATION_JSON);
|
||||
// response.setStatusCode(HttpStatus.OK);
|
||||
//
|
||||
// log.error("[鉴权异常处理]请求路径:{}", exchange.getRequest().getPath());
|
||||
//
|
||||
// return response.writeWith(Mono.fromSupplier(() -> {
|
||||
// DataBufferFactory bufferFactory = response.bufferFactory();
|
||||
//// return bufferFactory.wrap(JSON.toJSONBytes(com.yxt.anrui.utils.HttpStatus.OVERDUE));
|
||||
// return bufferFactory.wrap(JSON.toJSONBytes(ResultBean.fireFail().setCode(OVERDUE).setMsg(msg)));
|
||||
// }));
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * 获取请求token
|
||||
// */
|
||||
// private String getToken(ServerHttpRequest request) {
|
||||
// String token = request.getHeaders().getFirst(CacheConstants.HEADER);
|
||||
//// if (StringUtils.isNotEmpty(token) && token.startsWith(CacheConstants.TOKEN_PREFIX)) {
|
||||
//// token = token.replace(CacheConstants.TOKEN_PREFIX, "");
|
||||
//// }
|
||||
// return token;
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public int getOrder() {
|
||||
// return 0;
|
||||
// }
|
||||
//}
|
||||
@@ -0,0 +1,18 @@
|
||||
package com.yxt.ordermall;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
|
||||
|
||||
/**
|
||||
* @author wangpengfei
|
||||
* @date ${DATE} ${TIME}
|
||||
*/
|
||||
@SpringBootApplication(scanBasePackages = {
|
||||
"com.yxt.ordermall"
|
||||
})
|
||||
@EnableDiscoveryClient
|
||||
public class GatewayApplication {
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(GatewayApplication.class, args);
|
||||
}}
|
||||
300
ordermallGateway/src/main/java/com/yxt/ordermall/RedisUtil.java
Normal file
300
ordermallGateway/src/main/java/com/yxt/ordermall/RedisUtil.java
Normal file
@@ -0,0 +1,300 @@
|
||||
package com.yxt.ordermall;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.dao.DataAccessException;
|
||||
import org.springframework.data.redis.connection.RedisConnection;
|
||||
import org.springframework.data.redis.connection.RedisStringCommands;
|
||||
import org.springframework.data.redis.core.*;
|
||||
import org.springframework.data.redis.core.types.Expiration;
|
||||
import org.springframework.data.redis.serializer.RedisSerializer;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* @author dimengzhe
|
||||
* @date 2020/9/9 17:35
|
||||
* @description redis工具类
|
||||
*/
|
||||
@Service
|
||||
public class RedisUtil {
|
||||
|
||||
@Autowired
|
||||
private RedisTemplate redisTemplate;
|
||||
|
||||
|
||||
/**
|
||||
* 字符串类型:根据key设置value值,如果key中的value存在,那么返回false
|
||||
*
|
||||
* @param key
|
||||
* @param value
|
||||
* @return
|
||||
*/
|
||||
public Boolean setnx(final String key, final String value, final long expration, final TimeUnit timeUnit) {
|
||||
return (Boolean) redisTemplate.execute(new RedisCallback<Boolean>() {
|
||||
@Override
|
||||
public Boolean doInRedis(RedisConnection redisConnection) throws DataAccessException {
|
||||
RedisSerializer<String> redisSerializer = redisTemplate.getStringSerializer();
|
||||
byte keys[] = redisSerializer.serialize(key);
|
||||
byte values[] = redisSerializer.serialize(value);
|
||||
return redisConnection.set(keys, values, Expiration.from(expration, timeUnit), RedisStringCommands.SetOption.SET_IF_ABSENT);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 写入缓存
|
||||
*
|
||||
* @param key
|
||||
* @param value
|
||||
* @return
|
||||
*/
|
||||
public boolean set(final String key, final String value) {
|
||||
|
||||
boolean result = (boolean) redisTemplate.execute(new RedisCallback<Boolean>() {
|
||||
@Override
|
||||
public Boolean doInRedis(RedisConnection connection) throws DataAccessException {
|
||||
RedisSerializer<String> serializer = redisTemplate.getStringSerializer();
|
||||
connection.set(serializer.serialize(key), serializer.serialize(value));
|
||||
return true;
|
||||
}
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 写入缓存设置时效时间
|
||||
*
|
||||
* @param key
|
||||
* @param value
|
||||
* @return
|
||||
*/
|
||||
public boolean set(final String key, Object value, Long expireTime) {
|
||||
boolean result = false;
|
||||
try {
|
||||
ValueOperations<Serializable, Object> operations = redisTemplate.opsForValue();
|
||||
operations.set(key, value);
|
||||
redisTemplate.expire(key, expireTime, TimeUnit.SECONDS);
|
||||
result = true;
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
/**
|
||||
* 刷新缓存到期时间
|
||||
* @param key
|
||||
* @param expire
|
||||
* @return
|
||||
*/
|
||||
public boolean expire(String key, long expire) {
|
||||
return redisTemplate.expire(key, expire, TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
/**
|
||||
* 读取缓存
|
||||
*
|
||||
* @param key
|
||||
* @return
|
||||
*/
|
||||
public String get(final String key) {
|
||||
String result = (String) redisTemplate.execute(new RedisCallback<String>() {
|
||||
@Override
|
||||
public String doInRedis(RedisConnection connection) throws DataAccessException {
|
||||
RedisSerializer<String> serializer = redisTemplate.getStringSerializer();
|
||||
byte[] value = connection.get(serializer.serialize(key));
|
||||
return serializer.deserialize(value);
|
||||
}
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 正则获取key集合
|
||||
*
|
||||
* @param pattern
|
||||
* @return
|
||||
*/
|
||||
public Set<String> keys(String pattern) {
|
||||
Set<String> keys = redisTemplate.keys(pattern);
|
||||
return keys;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 批量删除对应的value
|
||||
*
|
||||
* @param keys
|
||||
*/
|
||||
public void remove(final String... keys) {
|
||||
for (String key : keys) {
|
||||
remove(key);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量删除key
|
||||
*
|
||||
* @param pattern
|
||||
*/
|
||||
public void removePattern(final String pattern) {
|
||||
Set<Serializable> keys = redisTemplate.keys(pattern);
|
||||
if (keys.size() > 0) {
|
||||
redisTemplate.delete(keys);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
public Long remove(final String key) {
|
||||
return (Long) redisTemplate.execute(new RedisCallback<Long>() {
|
||||
@Override
|
||||
public Long doInRedis(RedisConnection redisConnection) throws DataAccessException {
|
||||
RedisSerializer<String> serializer = redisTemplate.getStringSerializer();
|
||||
byte keys[] = serializer.serialize(key);
|
||||
return redisConnection.del(keys);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 判断缓存中是否有对应的value
|
||||
*
|
||||
* @param key
|
||||
* @return
|
||||
*/
|
||||
public boolean exists(final String key) {
|
||||
return redisTemplate.hasKey(key);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 哈希 添加
|
||||
*
|
||||
* @param key
|
||||
* @param hashKey
|
||||
* @param value
|
||||
*/
|
||||
public void hmSet(String key, Object hashKey, Object value) {
|
||||
HashOperations<String, Object, Object> hash = redisTemplate.opsForHash();
|
||||
hash.put(key, hashKey, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* 哈希获取数据
|
||||
*
|
||||
* @param key
|
||||
* @param hashKey
|
||||
* @return
|
||||
*/
|
||||
public String hmGet(String key, Object hashKey) {
|
||||
HashOperations<String, String, String> hash = redisTemplate.opsForHash();
|
||||
return hash.get(key, hashKey);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取哈希 keys
|
||||
*
|
||||
* @param key
|
||||
* @return
|
||||
*/
|
||||
public Set<String> hmGetKeys(String key) {
|
||||
HashOperations<String, String, String> hash = redisTemplate.opsForHash();
|
||||
return hash.keys(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除集合中的key
|
||||
*
|
||||
* @param key
|
||||
* @param hashKey
|
||||
*/
|
||||
public void hmDelete(String key, Object hashKey) {
|
||||
HashOperations<String, Object, Object> hash = redisTemplate.opsForHash();
|
||||
hash.delete(key, hashKey);
|
||||
}
|
||||
|
||||
/**
|
||||
* 列表添加
|
||||
*
|
||||
* @param k
|
||||
* @param v
|
||||
*/
|
||||
public void lPush(String k, Object v) {
|
||||
ListOperations<String, Object> list = redisTemplate.opsForList();
|
||||
list.rightPush(k, v);
|
||||
}
|
||||
|
||||
/**
|
||||
* 列表获取
|
||||
*
|
||||
* @param k
|
||||
* @param l
|
||||
* @param l1
|
||||
* @return
|
||||
*/
|
||||
public List<Object> lRange(String k, long l, long l1) {
|
||||
ListOperations<String, Object> list = redisTemplate.opsForList();
|
||||
return list.range(k, l, l1);
|
||||
}
|
||||
|
||||
/**
|
||||
* 集合添加
|
||||
*
|
||||
* @param key
|
||||
* @param value
|
||||
*/
|
||||
public void add(String key, Object value) {
|
||||
SetOperations<String, Object> set = redisTemplate.opsForSet();
|
||||
set.add(key, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* 集合获取
|
||||
*
|
||||
* @param key
|
||||
* @return
|
||||
*/
|
||||
public Set<Object> setMembers(String key) {
|
||||
SetOperations<String, Object> set = redisTemplate.opsForSet();
|
||||
return set.members(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* 有序集合添加
|
||||
*
|
||||
* @param key
|
||||
* @param value
|
||||
* @param scoure
|
||||
*/
|
||||
public void zAdd(String key, Object value, double scoure) {
|
||||
ZSetOperations<String, Object> zset = redisTemplate.opsForZSet();
|
||||
zset.add(key, value, scoure);
|
||||
}
|
||||
|
||||
/**
|
||||
* 有序集合获取
|
||||
*
|
||||
* @param key
|
||||
* @param scoure
|
||||
* @param scoure1
|
||||
* @return
|
||||
*/
|
||||
public Set<Object> rangeByScore(String key, double scoure, double scoure1) {
|
||||
ZSetOperations<String, Object> zset = redisTemplate.opsForZSet();
|
||||
return zset.rangeByScore(key, scoure, scoure1);
|
||||
}
|
||||
|
||||
/**
|
||||
* 实现命令:TTL key 以秒为单位,返回给定key的剩余生存时间
|
||||
* @param key
|
||||
* @return
|
||||
*/
|
||||
public long ttl(String key) {
|
||||
return redisTemplate.getExpire(key);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package com.yxt.ordermall.utils;
|
||||
|
||||
/**
|
||||
* @author dimengzhe
|
||||
* @date 2020/12/2 9:58
|
||||
* @description 缓存的key 常量
|
||||
*/
|
||||
|
||||
public class CacheConstants {
|
||||
|
||||
/**
|
||||
* 令牌自定义标识
|
||||
*/
|
||||
public static final String HEADER = "token";
|
||||
|
||||
/**
|
||||
* 令牌前缀
|
||||
*/
|
||||
public static final String TOKEN_PREFIX = "Bearer ";
|
||||
|
||||
/**
|
||||
* 用户名字段
|
||||
*/
|
||||
public static final String DETAILS_USERNAME = "userName";
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
package com.yxt.ordermall.utils;
|
||||
|
||||
import java.nio.charset.Charset;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
/**
|
||||
* @author dimengzhe
|
||||
* @date 2020/12/2 10:02
|
||||
* @description
|
||||
*/
|
||||
|
||||
public class CharsetKit {
|
||||
|
||||
/** ISO-8859-1 */
|
||||
public static final String ISO_8859_1 = "ISO-8859-1";
|
||||
/** UTF-8 */
|
||||
public static final String UTF_8 = "UTF-8";
|
||||
/** GBK */
|
||||
public static final String GBK = "GBK";
|
||||
|
||||
/** ISO-8859-1 */
|
||||
public static final Charset CHARSET_ISO_8859_1 = Charset.forName(ISO_8859_1);
|
||||
/** UTF-8 */
|
||||
public static final Charset CHARSET_UTF_8 = Charset.forName(UTF_8);
|
||||
/** GBK */
|
||||
public static final Charset CHARSET_GBK = Charset.forName(GBK);
|
||||
|
||||
/**
|
||||
* 转换为Charset对象
|
||||
*
|
||||
* @param charset 字符集,为空则返回默认字符集
|
||||
* @return Charset
|
||||
*/
|
||||
public static Charset charset(String charset)
|
||||
{
|
||||
return StringUtils.isEmpty(charset) ? Charset.defaultCharset() : Charset.forName(charset);
|
||||
}
|
||||
|
||||
/**
|
||||
* 转换字符串的字符集编码
|
||||
*
|
||||
* @param source 字符串
|
||||
* @param srcCharset 源字符集,默认ISO-8859-1
|
||||
* @param destCharset 目标字符集,默认UTF-8
|
||||
* @return 转换后的字符集
|
||||
*/
|
||||
public static String convert(String source, String srcCharset, String destCharset)
|
||||
{
|
||||
return convert(source, Charset.forName(srcCharset), Charset.forName(destCharset));
|
||||
}
|
||||
|
||||
/**
|
||||
* 转换字符串的字符集编码
|
||||
*
|
||||
* @param source 字符串
|
||||
* @param srcCharset 源字符集,默认ISO-8859-1
|
||||
* @param destCharset 目标字符集,默认UTF-8
|
||||
* @return 转换后的字符集
|
||||
*/
|
||||
public static String convert(String source, Charset srcCharset, Charset destCharset)
|
||||
{
|
||||
if (null == srcCharset)
|
||||
{
|
||||
srcCharset = StandardCharsets.ISO_8859_1;
|
||||
}
|
||||
|
||||
if (null == destCharset)
|
||||
{
|
||||
destCharset = StandardCharsets.UTF_8;
|
||||
}
|
||||
|
||||
if (StringUtils.isEmpty(source) || srcCharset.equals(destCharset))
|
||||
{
|
||||
return source;
|
||||
}
|
||||
return new String(source.getBytes(srcCharset), destCharset);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return 系统字符集编码
|
||||
*/
|
||||
public static String systemCharset()
|
||||
{
|
||||
return Charset.defaultCharset().name();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package com.yxt.ordermall.utils;
|
||||
|
||||
/**
|
||||
* @author dimengzhe
|
||||
* @date 2020/12/2 9:56
|
||||
* @description 通用常量信息
|
||||
*/
|
||||
|
||||
public class Constants {
|
||||
|
||||
/**
|
||||
* 成功标记
|
||||
*/
|
||||
public static final Integer SUCCESS = 200;
|
||||
|
||||
/**
|
||||
* 失败标记
|
||||
*/
|
||||
public static final Integer FAIL = 5000;
|
||||
|
||||
public static final boolean fail = false;
|
||||
public static final boolean success = true;
|
||||
|
||||
/**
|
||||
* 令牌有效期(分钟)
|
||||
*/
|
||||
public final static long TOKEN_EXPIRE = 4*60;
|
||||
public final static long TOKEN_EXPIRE_APP = 15*24*60;
|
||||
}
|
||||
@@ -0,0 +1,999 @@
|
||||
package com.yxt.ordermall.utils;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.math.BigInteger;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.charset.Charset;
|
||||
import java.text.NumberFormat;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* @author dimengzhe
|
||||
* @date 2020/12/2 10:01
|
||||
* @description
|
||||
*/
|
||||
|
||||
public class Convert {
|
||||
|
||||
/**
|
||||
* 转换为字符串<br>
|
||||
* 如果给定的值为null,或者转换失败,返回默认值<br>
|
||||
* 转换失败不会报错
|
||||
*
|
||||
* @param value 被转换的值
|
||||
* @param defaultValue 转换错误时的默认值
|
||||
* @return 结果
|
||||
*/
|
||||
public static String toStr(Object value, String defaultValue)
|
||||
{
|
||||
if (null == value)
|
||||
{
|
||||
return defaultValue;
|
||||
}
|
||||
if (value instanceof String)
|
||||
{
|
||||
return (String) value;
|
||||
}
|
||||
return value.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 转换为字符串<br>
|
||||
* 如果给定的值为<code>null</code>,或者转换失败,返回默认值<code>null</code><br>
|
||||
* 转换失败不会报错
|
||||
*
|
||||
* @param value 被转换的值
|
||||
* @return 结果
|
||||
*/
|
||||
public static String toStr(Object value)
|
||||
{
|
||||
return toStr(value, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 转换为字符<br>
|
||||
* 如果给定的值为null,或者转换失败,返回默认值<br>
|
||||
* 转换失败不会报错
|
||||
*
|
||||
* @param value 被转换的值
|
||||
* @param defaultValue 转换错误时的默认值
|
||||
* @return 结果
|
||||
*/
|
||||
public static Character toChar(Object value, Character defaultValue)
|
||||
{
|
||||
if (null == value)
|
||||
{
|
||||
return defaultValue;
|
||||
}
|
||||
if (value instanceof Character)
|
||||
{
|
||||
return (Character) value;
|
||||
}
|
||||
|
||||
final String valueStr = toStr(value, null);
|
||||
return StringUtils.isEmpty(valueStr) ? defaultValue : valueStr.charAt(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* 转换为字符<br>
|
||||
* 如果给定的值为<code>null</code>,或者转换失败,返回默认值<code>null</code><br>
|
||||
* 转换失败不会报错
|
||||
*
|
||||
* @param value 被转换的值
|
||||
* @return 结果
|
||||
*/
|
||||
public static Character toChar(Object value)
|
||||
{
|
||||
return toChar(value, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 转换为byte<br>
|
||||
* 如果给定的值为<code>null</code>,或者转换失败,返回默认值<br>
|
||||
* 转换失败不会报错
|
||||
*
|
||||
* @param value 被转换的值
|
||||
* @param defaultValue 转换错误时的默认值
|
||||
* @return 结果
|
||||
*/
|
||||
public static Byte toByte(Object value, Byte defaultValue)
|
||||
{
|
||||
if (value == null)
|
||||
{
|
||||
return defaultValue;
|
||||
}
|
||||
if (value instanceof Byte)
|
||||
{
|
||||
return (Byte) value;
|
||||
}
|
||||
if (value instanceof Number)
|
||||
{
|
||||
return ((Number) value).byteValue();
|
||||
}
|
||||
final String valueStr = toStr(value, null);
|
||||
if (StringUtils.isEmpty(valueStr))
|
||||
{
|
||||
return defaultValue;
|
||||
}
|
||||
try
|
||||
{
|
||||
return Byte.parseByte(valueStr);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
return defaultValue;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 转换为byte<br>
|
||||
* 如果给定的值为<code>null</code>,或者转换失败,返回默认值<code>null</code><br>
|
||||
* 转换失败不会报错
|
||||
*
|
||||
* @param value 被转换的值
|
||||
* @return 结果
|
||||
*/
|
||||
public static Byte toByte(Object value)
|
||||
{
|
||||
return toByte(value, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 转换为Short<br>
|
||||
* 如果给定的值为<code>null</code>,或者转换失败,返回默认值<br>
|
||||
* 转换失败不会报错
|
||||
*
|
||||
* @param value 被转换的值
|
||||
* @param defaultValue 转换错误时的默认值
|
||||
* @return 结果
|
||||
*/
|
||||
public static Short toShort(Object value, Short defaultValue)
|
||||
{
|
||||
if (value == null)
|
||||
{
|
||||
return defaultValue;
|
||||
}
|
||||
if (value instanceof Short)
|
||||
{
|
||||
return (Short) value;
|
||||
}
|
||||
if (value instanceof Number)
|
||||
{
|
||||
return ((Number) value).shortValue();
|
||||
}
|
||||
final String valueStr = toStr(value, null);
|
||||
if (StringUtils.isEmpty(valueStr))
|
||||
{
|
||||
return defaultValue;
|
||||
}
|
||||
try
|
||||
{
|
||||
return Short.parseShort(valueStr.trim());
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
return defaultValue;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 转换为Short<br>
|
||||
* 如果给定的值为<code>null</code>,或者转换失败,返回默认值<code>null</code><br>
|
||||
* 转换失败不会报错
|
||||
*
|
||||
* @param value 被转换的值
|
||||
* @return 结果
|
||||
*/
|
||||
public static Short toShort(Object value)
|
||||
{
|
||||
return toShort(value, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 转换为Number<br>
|
||||
* 如果给定的值为空,或者转换失败,返回默认值<br>
|
||||
* 转换失败不会报错
|
||||
*
|
||||
* @param value 被转换的值
|
||||
* @param defaultValue 转换错误时的默认值
|
||||
* @return 结果
|
||||
*/
|
||||
public static Number toNumber(Object value, Number defaultValue)
|
||||
{
|
||||
if (value == null)
|
||||
{
|
||||
return defaultValue;
|
||||
}
|
||||
if (value instanceof Number)
|
||||
{
|
||||
return (Number) value;
|
||||
}
|
||||
final String valueStr = toStr(value, null);
|
||||
if (StringUtils.isEmpty(valueStr))
|
||||
{
|
||||
return defaultValue;
|
||||
}
|
||||
try
|
||||
{
|
||||
return NumberFormat.getInstance().parse(valueStr);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
return defaultValue;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 转换为Number<br>
|
||||
* 如果给定的值为空,或者转换失败,返回默认值<code>null</code><br>
|
||||
* 转换失败不会报错
|
||||
*
|
||||
* @param value 被转换的值
|
||||
* @return 结果
|
||||
*/
|
||||
public static Number toNumber(Object value)
|
||||
{
|
||||
return toNumber(value, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 转换为int<br>
|
||||
* 如果给定的值为空,或者转换失败,返回默认值<br>
|
||||
* 转换失败不会报错
|
||||
*
|
||||
* @param value 被转换的值
|
||||
* @param defaultValue 转换错误时的默认值
|
||||
* @return 结果
|
||||
*/
|
||||
public static Integer toInt(Object value, Integer defaultValue)
|
||||
{
|
||||
if (value == null)
|
||||
{
|
||||
return defaultValue;
|
||||
}
|
||||
if (value instanceof Integer)
|
||||
{
|
||||
return (Integer) value;
|
||||
}
|
||||
if (value instanceof Number)
|
||||
{
|
||||
return ((Number) value).intValue();
|
||||
}
|
||||
final String valueStr = toStr(value, null);
|
||||
if (StringUtils.isEmpty(valueStr))
|
||||
{
|
||||
return defaultValue;
|
||||
}
|
||||
try
|
||||
{
|
||||
return Integer.parseInt(valueStr.trim());
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
return defaultValue;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 转换为int<br>
|
||||
* 如果给定的值为<code>null</code>,或者转换失败,返回默认值<code>null</code><br>
|
||||
* 转换失败不会报错
|
||||
*
|
||||
* @param value 被转换的值
|
||||
* @return 结果
|
||||
*/
|
||||
public static Integer toInt(Object value)
|
||||
{
|
||||
return toInt(value, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 转换为Integer数组<br>
|
||||
*
|
||||
* @param str 被转换的值
|
||||
* @return 结果
|
||||
*/
|
||||
public static Integer[] toIntArray(String str)
|
||||
{
|
||||
return toIntArray(",", str);
|
||||
}
|
||||
|
||||
/**
|
||||
* 转换为Long数组<br>
|
||||
*
|
||||
* @param str 被转换的值
|
||||
* @return 结果
|
||||
*/
|
||||
public static Long[] toLongArray(String str)
|
||||
{
|
||||
return toLongArray(",", str);
|
||||
}
|
||||
|
||||
/**
|
||||
* 转换为Integer数组<br>
|
||||
*
|
||||
* @param split 分隔符
|
||||
* @param split 被转换的值
|
||||
* @return 结果
|
||||
*/
|
||||
public static Integer[] toIntArray(String split, String str)
|
||||
{
|
||||
if (StringUtils.isEmpty(str))
|
||||
{
|
||||
return new Integer[] {};
|
||||
}
|
||||
String[] arr = str.split(split);
|
||||
final Integer[] ints = new Integer[arr.length];
|
||||
for (int i = 0; i < arr.length; i++)
|
||||
{
|
||||
final Integer v = toInt(arr[i], 0);
|
||||
ints[i] = v;
|
||||
}
|
||||
return ints;
|
||||
}
|
||||
|
||||
/**
|
||||
* 转换为Long数组<br>
|
||||
*
|
||||
* @param split 分隔符
|
||||
* @param str 被转换的值
|
||||
* @return 结果
|
||||
*/
|
||||
public static Long[] toLongArray(String split, String str)
|
||||
{
|
||||
if (StringUtils.isEmpty(str))
|
||||
{
|
||||
return new Long[] {};
|
||||
}
|
||||
String[] arr = str.split(split);
|
||||
final Long[] longs = new Long[arr.length];
|
||||
for (int i = 0; i < arr.length; i++)
|
||||
{
|
||||
final Long v = toLong(arr[i], null);
|
||||
longs[i] = v;
|
||||
}
|
||||
return longs;
|
||||
}
|
||||
|
||||
/**
|
||||
* 转换为String数组<br>
|
||||
*
|
||||
* @param str 被转换的值
|
||||
* @return 结果
|
||||
*/
|
||||
public static String[] toStrArray(String str)
|
||||
{
|
||||
return toStrArray(",", str);
|
||||
}
|
||||
|
||||
/**
|
||||
* 转换为String数组<br>
|
||||
*
|
||||
* @param split 分隔符
|
||||
* @param split 被转换的值
|
||||
* @return 结果
|
||||
*/
|
||||
public static String[] toStrArray(String split, String str)
|
||||
{
|
||||
return str.split(split);
|
||||
}
|
||||
|
||||
/**
|
||||
* 转换为long<br>
|
||||
* 如果给定的值为空,或者转换失败,返回默认值<br>
|
||||
* 转换失败不会报错
|
||||
*
|
||||
* @param value 被转换的值
|
||||
* @param defaultValue 转换错误时的默认值
|
||||
* @return 结果
|
||||
*/
|
||||
public static Long toLong(Object value, Long defaultValue)
|
||||
{
|
||||
if (value == null)
|
||||
{
|
||||
return defaultValue;
|
||||
}
|
||||
if (value instanceof Long)
|
||||
{
|
||||
return (Long) value;
|
||||
}
|
||||
if (value instanceof Number)
|
||||
{
|
||||
return ((Number) value).longValue();
|
||||
}
|
||||
final String valueStr = toStr(value, null);
|
||||
if (StringUtils.isEmpty(valueStr))
|
||||
{
|
||||
return defaultValue;
|
||||
}
|
||||
try
|
||||
{
|
||||
// 支持科学计数法
|
||||
return new BigDecimal(valueStr.trim()).longValue();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
return defaultValue;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 转换为long<br>
|
||||
* 如果给定的值为<code>null</code>,或者转换失败,返回默认值<code>null</code><br>
|
||||
* 转换失败不会报错
|
||||
*
|
||||
* @param value 被转换的值
|
||||
* @return 结果
|
||||
*/
|
||||
public static Long toLong(Object value)
|
||||
{
|
||||
return toLong(value, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 转换为double<br>
|
||||
* 如果给定的值为空,或者转换失败,返回默认值<br>
|
||||
* 转换失败不会报错
|
||||
*
|
||||
* @param value 被转换的值
|
||||
* @param defaultValue 转换错误时的默认值
|
||||
* @return 结果
|
||||
*/
|
||||
public static Double toDouble(Object value, Double defaultValue)
|
||||
{
|
||||
if (value == null)
|
||||
{
|
||||
return defaultValue;
|
||||
}
|
||||
if (value instanceof Double)
|
||||
{
|
||||
return (Double) value;
|
||||
}
|
||||
if (value instanceof Number)
|
||||
{
|
||||
return ((Number) value).doubleValue();
|
||||
}
|
||||
final String valueStr = toStr(value, null);
|
||||
if (StringUtils.isEmpty(valueStr))
|
||||
{
|
||||
return defaultValue;
|
||||
}
|
||||
try
|
||||
{
|
||||
// 支持科学计数法
|
||||
return new BigDecimal(valueStr.trim()).doubleValue();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
return defaultValue;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 转换为double<br>
|
||||
* 如果给定的值为空,或者转换失败,返回默认值<code>null</code><br>
|
||||
* 转换失败不会报错
|
||||
*
|
||||
* @param value 被转换的值
|
||||
* @return 结果
|
||||
*/
|
||||
public static Double toDouble(Object value)
|
||||
{
|
||||
return toDouble(value, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 转换为Float<br>
|
||||
* 如果给定的值为空,或者转换失败,返回默认值<br>
|
||||
* 转换失败不会报错
|
||||
*
|
||||
* @param value 被转换的值
|
||||
* @param defaultValue 转换错误时的默认值
|
||||
* @return 结果
|
||||
*/
|
||||
public static Float toFloat(Object value, Float defaultValue)
|
||||
{
|
||||
if (value == null)
|
||||
{
|
||||
return defaultValue;
|
||||
}
|
||||
if (value instanceof Float)
|
||||
{
|
||||
return (Float) value;
|
||||
}
|
||||
if (value instanceof Number)
|
||||
{
|
||||
return ((Number) value).floatValue();
|
||||
}
|
||||
final String valueStr = toStr(value, null);
|
||||
if (StringUtils.isEmpty(valueStr))
|
||||
{
|
||||
return defaultValue;
|
||||
}
|
||||
try
|
||||
{
|
||||
return Float.parseFloat(valueStr.trim());
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
return defaultValue;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 转换为Float<br>
|
||||
* 如果给定的值为空,或者转换失败,返回默认值<code>null</code><br>
|
||||
* 转换失败不会报错
|
||||
*
|
||||
* @param value 被转换的值
|
||||
* @return 结果
|
||||
*/
|
||||
public static Float toFloat(Object value)
|
||||
{
|
||||
return toFloat(value, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 转换为boolean<br>
|
||||
* String支持的值为:true、false、yes、ok、no,1,0 如果给定的值为空,或者转换失败,返回默认值<br>
|
||||
* 转换失败不会报错
|
||||
*
|
||||
* @param value 被转换的值
|
||||
* @param defaultValue 转换错误时的默认值
|
||||
* @return 结果
|
||||
*/
|
||||
public static Boolean toBool(Object value, Boolean defaultValue)
|
||||
{
|
||||
if (value == null)
|
||||
{
|
||||
return defaultValue;
|
||||
}
|
||||
if (value instanceof Boolean)
|
||||
{
|
||||
return (Boolean) value;
|
||||
}
|
||||
String valueStr = toStr(value, null);
|
||||
if (StringUtils.isEmpty(valueStr))
|
||||
{
|
||||
return defaultValue;
|
||||
}
|
||||
valueStr = valueStr.trim().toLowerCase();
|
||||
switch (valueStr)
|
||||
{
|
||||
case "true":
|
||||
return true;
|
||||
case "false":
|
||||
return false;
|
||||
case "yes":
|
||||
return true;
|
||||
case "ok":
|
||||
return true;
|
||||
case "no":
|
||||
return false;
|
||||
case "1":
|
||||
return true;
|
||||
case "0":
|
||||
return false;
|
||||
default:
|
||||
return defaultValue;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 转换为boolean<br>
|
||||
* 如果给定的值为空,或者转换失败,返回默认值<code>null</code><br>
|
||||
* 转换失败不会报错
|
||||
*
|
||||
* @param value 被转换的值
|
||||
* @return 结果
|
||||
*/
|
||||
public static Boolean toBool(Object value)
|
||||
{
|
||||
return toBool(value, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 转换为Enum对象<br>
|
||||
* 如果给定的值为空,或者转换失败,返回默认值<br>
|
||||
*
|
||||
* @param clazz Enum的Class
|
||||
* @param value 值
|
||||
* @param defaultValue 默认值
|
||||
* @return Enum
|
||||
*/
|
||||
public static <E extends Enum<E>> E toEnum(Class<E> clazz, Object value, E defaultValue)
|
||||
{
|
||||
if (value == null)
|
||||
{
|
||||
return defaultValue;
|
||||
}
|
||||
if (clazz.isAssignableFrom(value.getClass()))
|
||||
{
|
||||
@SuppressWarnings("unchecked")
|
||||
E myE = (E) value;
|
||||
return myE;
|
||||
}
|
||||
final String valueStr = toStr(value, null);
|
||||
if (StringUtils.isEmpty(valueStr))
|
||||
{
|
||||
return defaultValue;
|
||||
}
|
||||
try
|
||||
{
|
||||
return Enum.valueOf(clazz, valueStr);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
return defaultValue;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 转换为Enum对象<br>
|
||||
* 如果给定的值为空,或者转换失败,返回默认值<code>null</code><br>
|
||||
*
|
||||
* @param clazz Enum的Class
|
||||
* @param value 值
|
||||
* @return Enum
|
||||
*/
|
||||
public static <E extends Enum<E>> E toEnum(Class<E> clazz, Object value)
|
||||
{
|
||||
return toEnum(clazz, value, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 转换为BigInteger<br>
|
||||
* 如果给定的值为空,或者转换失败,返回默认值<br>
|
||||
* 转换失败不会报错
|
||||
*
|
||||
* @param value 被转换的值
|
||||
* @param defaultValue 转换错误时的默认值
|
||||
* @return 结果
|
||||
*/
|
||||
public static BigInteger toBigInteger(Object value, BigInteger defaultValue)
|
||||
{
|
||||
if (value == null)
|
||||
{
|
||||
return defaultValue;
|
||||
}
|
||||
if (value instanceof BigInteger)
|
||||
{
|
||||
return (BigInteger) value;
|
||||
}
|
||||
if (value instanceof Long)
|
||||
{
|
||||
return BigInteger.valueOf((Long) value);
|
||||
}
|
||||
final String valueStr = toStr(value, null);
|
||||
if (StringUtils.isEmpty(valueStr))
|
||||
{
|
||||
return defaultValue;
|
||||
}
|
||||
try
|
||||
{
|
||||
return new BigInteger(valueStr);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
return defaultValue;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 转换为BigInteger<br>
|
||||
* 如果给定的值为空,或者转换失败,返回默认值<code>null</code><br>
|
||||
* 转换失败不会报错
|
||||
*
|
||||
* @param value 被转换的值
|
||||
* @return 结果
|
||||
*/
|
||||
public static BigInteger toBigInteger(Object value)
|
||||
{
|
||||
return toBigInteger(value, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 转换为BigDecimal<br>
|
||||
* 如果给定的值为空,或者转换失败,返回默认值<br>
|
||||
* 转换失败不会报错
|
||||
*
|
||||
* @param value 被转换的值
|
||||
* @param defaultValue 转换错误时的默认值
|
||||
* @return 结果
|
||||
*/
|
||||
public static BigDecimal toBigDecimal(Object value, BigDecimal defaultValue)
|
||||
{
|
||||
if (value == null)
|
||||
{
|
||||
return defaultValue;
|
||||
}
|
||||
if (value instanceof BigDecimal)
|
||||
{
|
||||
return (BigDecimal) value;
|
||||
}
|
||||
if (value instanceof Long)
|
||||
{
|
||||
return new BigDecimal((Long) value);
|
||||
}
|
||||
if (value instanceof Double)
|
||||
{
|
||||
return new BigDecimal((Double) value);
|
||||
}
|
||||
if (value instanceof Integer)
|
||||
{
|
||||
return new BigDecimal((Integer) value);
|
||||
}
|
||||
final String valueStr = toStr(value, null);
|
||||
if (StringUtils.isEmpty(valueStr))
|
||||
{
|
||||
return defaultValue;
|
||||
}
|
||||
try
|
||||
{
|
||||
return new BigDecimal(valueStr);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
return defaultValue;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 转换为BigDecimal<br>
|
||||
* 如果给定的值为空,或者转换失败,返回默认值<br>
|
||||
* 转换失败不会报错
|
||||
*
|
||||
* @param value 被转换的值
|
||||
* @return 结果
|
||||
*/
|
||||
public static BigDecimal toBigDecimal(Object value)
|
||||
{
|
||||
return toBigDecimal(value, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 将对象转为字符串<br>
|
||||
* 1、Byte数组和ByteBuffer会被转换为对应字符串的数组 2、对象数组会调用Arrays.toString方法
|
||||
*
|
||||
* @param obj 对象
|
||||
* @return 字符串
|
||||
*/
|
||||
public static String utf8Str(Object obj)
|
||||
{
|
||||
return str(obj, CharsetKit.CHARSET_UTF_8);
|
||||
}
|
||||
|
||||
/**
|
||||
* 将对象转为字符串<br>
|
||||
* 1、Byte数组和ByteBuffer会被转换为对应字符串的数组 2、对象数组会调用Arrays.toString方法
|
||||
*
|
||||
* @param obj 对象
|
||||
* @param charsetName 字符集
|
||||
* @return 字符串
|
||||
*/
|
||||
public static String str(Object obj, String charsetName)
|
||||
{
|
||||
return str(obj, Charset.forName(charsetName));
|
||||
}
|
||||
|
||||
/**
|
||||
* 将对象转为字符串<br>
|
||||
* 1、Byte数组和ByteBuffer会被转换为对应字符串的数组 2、对象数组会调用Arrays.toString方法
|
||||
*
|
||||
* @param obj 对象
|
||||
* @param charset 字符集
|
||||
* @return 字符串
|
||||
*/
|
||||
public static String str(Object obj, Charset charset)
|
||||
{
|
||||
if (null == obj)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
if (obj instanceof String)
|
||||
{
|
||||
return (String) obj;
|
||||
}
|
||||
else if (obj instanceof byte[] || obj instanceof Byte[])
|
||||
{
|
||||
return str((Byte[]) obj, charset);
|
||||
}
|
||||
else if (obj instanceof ByteBuffer)
|
||||
{
|
||||
return str((ByteBuffer) obj, charset);
|
||||
}
|
||||
return obj.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 将byte数组转为字符串
|
||||
*
|
||||
* @param bytes byte数组
|
||||
* @param charset 字符集
|
||||
* @return 字符串
|
||||
*/
|
||||
public static String str(byte[] bytes, String charset)
|
||||
{
|
||||
return str(bytes, StringUtils.isEmpty(charset) ? Charset.defaultCharset() : Charset.forName(charset));
|
||||
}
|
||||
|
||||
/**
|
||||
* 解码字节码
|
||||
*
|
||||
* @param data 字符串
|
||||
* @param charset 字符集,如果此字段为空,则解码的结果取决于平台
|
||||
* @return 解码后的字符串
|
||||
*/
|
||||
public static String str(byte[] data, Charset charset)
|
||||
{
|
||||
if (data == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
if (null == charset)
|
||||
{
|
||||
return new String(data);
|
||||
}
|
||||
return new String(data, charset);
|
||||
}
|
||||
|
||||
/**
|
||||
* 将编码的byteBuffer数据转换为字符串
|
||||
*
|
||||
* @param data 数据
|
||||
* @param charset 字符集,如果为空使用当前系统字符集
|
||||
* @return 字符串
|
||||
*/
|
||||
public static String str(ByteBuffer data, String charset)
|
||||
{
|
||||
if (data == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return str(data, Charset.forName(charset));
|
||||
}
|
||||
|
||||
/**
|
||||
* 将编码的byteBuffer数据转换为字符串
|
||||
*
|
||||
* @param data 数据
|
||||
* @param charset 字符集,如果为空使用当前系统字符集
|
||||
* @return 字符串
|
||||
*/
|
||||
public static String str(ByteBuffer data, Charset charset)
|
||||
{
|
||||
if (null == charset)
|
||||
{
|
||||
charset = Charset.defaultCharset();
|
||||
}
|
||||
return charset.decode(data).toString();
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------- 全角半角转换
|
||||
/**
|
||||
* 半角转全角
|
||||
*
|
||||
* @param input String.
|
||||
* @return 全角字符串.
|
||||
*/
|
||||
public static String toSBC(String input)
|
||||
{
|
||||
return toSBC(input, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 半角转全角
|
||||
*
|
||||
* @param input String
|
||||
* @param notConvertSet 不替换的字符集合
|
||||
* @return 全角字符串.
|
||||
*/
|
||||
public static String toSBC(String input, Set<Character> notConvertSet)
|
||||
{
|
||||
char c[] = input.toCharArray();
|
||||
for (int i = 0; i < c.length; i++)
|
||||
{
|
||||
if (null != notConvertSet && notConvertSet.contains(c[i]))
|
||||
{
|
||||
// 跳过不替换的字符
|
||||
continue;
|
||||
}
|
||||
|
||||
if (c[i] == ' ')
|
||||
{
|
||||
c[i] = '\u3000';
|
||||
}
|
||||
else if (c[i] < '\177')
|
||||
{
|
||||
c[i] = (char) (c[i] + 65248);
|
||||
|
||||
}
|
||||
}
|
||||
return new String(c);
|
||||
}
|
||||
|
||||
/**
|
||||
* 全角转半角
|
||||
*
|
||||
* @param input String.
|
||||
* @return 半角字符串
|
||||
*/
|
||||
public static String toDBC(String input)
|
||||
{
|
||||
return toDBC(input, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 替换全角为半角
|
||||
*
|
||||
* @param text 文本
|
||||
* @param notConvertSet 不替换的字符集合
|
||||
* @return 替换后的字符
|
||||
*/
|
||||
public static String toDBC(String text, Set<Character> notConvertSet)
|
||||
{
|
||||
char c[] = text.toCharArray();
|
||||
for (int i = 0; i < c.length; i++)
|
||||
{
|
||||
if (null != notConvertSet && notConvertSet.contains(c[i]))
|
||||
{
|
||||
// 跳过不替换的字符
|
||||
continue;
|
||||
}
|
||||
|
||||
if (c[i] == '\u3000')
|
||||
{
|
||||
c[i] = ' ';
|
||||
}
|
||||
else if (c[i] > '\uFF00' && c[i] < '\uFF5F')
|
||||
{
|
||||
c[i] = (char) (c[i] - 65248);
|
||||
}
|
||||
}
|
||||
String returnString = new String(c);
|
||||
|
||||
return returnString;
|
||||
}
|
||||
|
||||
/**
|
||||
* 数字金额大写转换 先写个完整的然后将如零拾替换成零
|
||||
*
|
||||
* @param n 数字
|
||||
* @return 中文大写数字
|
||||
*/
|
||||
public static String digitUppercase(double n)
|
||||
{
|
||||
String[] fraction = { "角", "分" };
|
||||
String[] digit = { "零", "壹", "贰", "叁", "肆", "伍", "陆", "柒", "捌", "玖" };
|
||||
String[][] unit = { { "元", "万", "亿" }, { "", "拾", "佰", "仟" } };
|
||||
|
||||
String head = n < 0 ? "负" : "";
|
||||
n = Math.abs(n);
|
||||
|
||||
String s = "";
|
||||
for (int i = 0; i < fraction.length; i++)
|
||||
{
|
||||
s += (digit[(int) (Math.floor(n * 10 * Math.pow(10, i)) % 10)] + fraction[i]).replaceAll("(零.)+", "");
|
||||
}
|
||||
if (s.length() < 1)
|
||||
{
|
||||
s = "整";
|
||||
}
|
||||
int integerPart = (int) Math.floor(n);
|
||||
|
||||
for (int i = 0; i < unit[0].length && integerPart > 0; i++)
|
||||
{
|
||||
String p = "";
|
||||
for (int j = 0; j < unit[1].length && n > 0; j++)
|
||||
{
|
||||
p = digit[integerPart % 10] + unit[1][j] + p;
|
||||
integerPart = integerPart / 10;
|
||||
}
|
||||
s = p.replaceAll("(零.)*零$", "").replaceAll("^$", "零") + unit[0][i] + s;
|
||||
}
|
||||
return head + s.replaceAll("(零.)*零元", "元").replaceFirst("(零.)+", "").replaceAll("(零.)+", "零").replaceAll("^整$", "零元整");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package com.yxt.ordermall.utils;
|
||||
|
||||
/**
|
||||
* @author dimengzhe
|
||||
* @date 2021/6/16 10:50
|
||||
* @description
|
||||
*/
|
||||
|
||||
public class HttpStatus {
|
||||
|
||||
/**
|
||||
* 操作成功
|
||||
*/
|
||||
public static final int SUCCESS = 200;
|
||||
|
||||
/**
|
||||
* 系统内部错误
|
||||
*/
|
||||
public static final int ERROR = 500;
|
||||
|
||||
public static final String OVERDUE = "5000";
|
||||
|
||||
}
|
||||
@@ -0,0 +1,167 @@
|
||||
package com.yxt.ordermall.utils;
|
||||
|
||||
import org.apache.http.Consts;
|
||||
import org.apache.http.HttpEntity;
|
||||
import org.apache.http.NameValuePair;
|
||||
import org.apache.http.client.entity.UrlEncodedFormEntity;
|
||||
import org.apache.http.client.methods.CloseableHttpResponse;
|
||||
import org.apache.http.client.methods.HttpGet;
|
||||
import org.apache.http.client.methods.HttpPost;
|
||||
import org.apache.http.entity.StringEntity;
|
||||
import org.apache.http.impl.client.CloseableHttpClient;
|
||||
import org.apache.http.impl.client.HttpClients;
|
||||
import org.apache.http.message.BasicNameValuePair;
|
||||
import org.apache.http.util.EntityUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class HttpUtils {
|
||||
private static final Logger log = LoggerFactory.getLogger(HttpUtils.class);
|
||||
private static final CloseableHttpClient httpclient = HttpClients.createDefault();
|
||||
private static final String userAgent = "Mozilla/5.0 (Windows NT 6.2; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.87 Safari/537.36";
|
||||
|
||||
/**
|
||||
* 发送HttpGet请求 * * @param url * 请求地址 * @return 返回字符串
|
||||
*/
|
||||
public static String sendGet(String url, String token) {
|
||||
String result = null;
|
||||
CloseableHttpResponse response = null;
|
||||
try {
|
||||
HttpGet httpGet = new HttpGet(url);
|
||||
httpGet.setHeader("User-Agent", userAgent);
|
||||
httpGet.setHeader("Authorization", "token " + token);
|
||||
response = httpclient.execute(httpGet);
|
||||
HttpEntity entity = response.getEntity();
|
||||
if (entity != null) {
|
||||
result = EntityUtils.toString(entity);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("处理失败 {}" + e);
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
if (response != null) {
|
||||
try {
|
||||
response.close();
|
||||
} catch (IOException e) {
|
||||
log.error(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送HttpPost请求,参数为map * * @param url * 请求地址 * @param map * 请求参数 * @return 返回字符串
|
||||
*/
|
||||
public static String sendPost(String url, Map<String, String> map) {
|
||||
// 设置参数
|
||||
List<NameValuePair> formparams = new ArrayList<NameValuePair>();
|
||||
for (Map.Entry<String, String> entry : map.entrySet()) {
|
||||
formparams.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));
|
||||
}
|
||||
// 编码
|
||||
UrlEncodedFormEntity formEntity = new UrlEncodedFormEntity(formparams, Consts.UTF_8);
|
||||
// 取得HttpPost对象
|
||||
HttpPost httpPost = new HttpPost(url);
|
||||
// 防止被当成攻击添加的
|
||||
httpPost.setHeader("User-Agent", userAgent);
|
||||
// 参数放入Entity
|
||||
httpPost.setEntity(formEntity);
|
||||
CloseableHttpResponse response = null;
|
||||
String result = null;
|
||||
try {
|
||||
// 执行post请求
|
||||
response = httpclient.execute(httpPost);
|
||||
// 得到entity
|
||||
HttpEntity entity = response.getEntity();
|
||||
// 得到字符串
|
||||
result = EntityUtils.toString(entity);
|
||||
} catch (IOException e) {
|
||||
log.error(e.getMessage());
|
||||
} finally {
|
||||
if (response != null) {
|
||||
try {
|
||||
response.close();
|
||||
} catch (IOException e) {
|
||||
log.error(e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 发送HttpPost请求,参数为json字符串 * * @param url * @param jsonStr * @return
|
||||
*/
|
||||
public static String sendPost(String url, String jsonStr) {
|
||||
String result = null;
|
||||
// 字符串编码
|
||||
StringEntity entity = new StringEntity(jsonStr, Consts.UTF_8);
|
||||
// 设置content-type
|
||||
entity.setContentType("application/json");
|
||||
HttpPost httpPost = new HttpPost(url);
|
||||
// 防止被当成攻击添加的
|
||||
httpPost.setHeader("User-Agent", userAgent);
|
||||
// 接收参数设置
|
||||
httpPost.setHeader("Accept", "application/json");
|
||||
httpPost.setEntity(entity);
|
||||
CloseableHttpResponse response = null;
|
||||
try {
|
||||
response = httpclient.execute(httpPost);
|
||||
HttpEntity httpEntity = response.getEntity();
|
||||
result = EntityUtils.toString(httpEntity);
|
||||
} catch (IOException e) {
|
||||
log.error(e.getMessage());
|
||||
} finally {
|
||||
// 关闭CloseableHttpResponse
|
||||
if (response != null) {
|
||||
try {
|
||||
response.close();
|
||||
} catch (IOException e) {
|
||||
log.error(e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送不带参数的HttpPost请求 * * @param url * @return
|
||||
*/
|
||||
public static String sendPost(String url) {
|
||||
String result = null;
|
||||
// 得到一个HttpPost对象
|
||||
HttpPost httpPost = new HttpPost(url);
|
||||
// 防止被当成攻击添加的
|
||||
httpPost.setHeader("User-Agent", userAgent);
|
||||
CloseableHttpResponse response = null;
|
||||
try {
|
||||
// 执行HttpPost请求,并得到一个CloseableHttpResponse
|
||||
response = httpclient.execute(httpPost);
|
||||
// 从CloseableHttpResponse中拿到HttpEntity
|
||||
HttpEntity entity = response.getEntity();
|
||||
// 将HttpEntity转换为字符串
|
||||
result = EntityUtils.toString(entity);
|
||||
} catch (IOException e) {
|
||||
log.error(e.getMessage());
|
||||
} finally {
|
||||
// 关闭CloseableHttpResponse
|
||||
if (response != null) {
|
||||
try {
|
||||
response.close();
|
||||
} catch (IOException e) {
|
||||
log.error(e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
/*********************************************************
|
||||
*********************************************************
|
||||
******************** *******************
|
||||
************* ************
|
||||
******* _oo0oo_ *******
|
||||
*** o8888888o ***
|
||||
* 88" . "88 *
|
||||
* (| -_- |) *
|
||||
* 0\ = /0 *
|
||||
* ___/`---'\___ *
|
||||
* .' \\| |// '. *
|
||||
* / \\||| : |||// \ *
|
||||
* / _||||| -:- |||||- \ *
|
||||
* | | \\\ - /// | | *
|
||||
* | \_| ''\---/'' |_/ | *
|
||||
* \ .-\__ '-' ___/-. / *
|
||||
* ___'. .' /--.--\ `. .'___ *
|
||||
* ."" '< `.___\_<|>_/___.' >' "". *
|
||||
* | | : `- \`.;`\ _ /`;.`/ - ` : | | *
|
||||
* \ \ `_. \_ __\ /__ _/ .-` / / *
|
||||
* =====`-.____`.___ \_____/___.-`___.-'===== *
|
||||
* `=---=' *
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ *
|
||||
*********__佛祖保佑__永无BUG__验收通过__钞票多多__*********
|
||||
*********************************************************/
|
||||
package com.yxt.ordermall.utils;
|
||||
|
||||
/**
|
||||
* Project: yxt-common <br/>
|
||||
* File: IResultCodeMsg.java <br/>
|
||||
* Class: com.yxt.common.core.result.IResultCodeMsg <br/>
|
||||
* Description: <描述类的功能>. <br/>
|
||||
* Copyright: Copyright (c) 2011 <br/>
|
||||
* Company: https://gitee.com/liuzp315 <br/>
|
||||
* Makedate: 2021/9/11 下午11:00 <br/>
|
||||
*
|
||||
* @author popo
|
||||
* @version 1.0
|
||||
* @since 1.0
|
||||
*/
|
||||
public interface IResultCodeMsg {
|
||||
String getCode();
|
||||
String getMsg();
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
package com.yxt.ordermall.utils;
|
||||
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.cloud.context.config.annotation.RefreshScope;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author dimengzhe
|
||||
* @date 2020/12/2 9:54
|
||||
* @description 放行白名单配置
|
||||
*/
|
||||
@Configuration
|
||||
@RefreshScope
|
||||
@ConfigurationProperties(prefix = "ignore")
|
||||
public class IgnoreWhiteProperties {
|
||||
|
||||
/**
|
||||
* 放行白名单配置,网关不校验此处的白名单
|
||||
*/
|
||||
private List<String> whites = new ArrayList<>();
|
||||
|
||||
public List<String> getWhites() {
|
||||
return whites;
|
||||
}
|
||||
|
||||
public void setWhites(List<String> whites) {
|
||||
this.whites = whites;
|
||||
}
|
||||
|
||||
private List<String> whitesTwo = new ArrayList<>();
|
||||
|
||||
public List<String> getWhitesTwo() {
|
||||
return whitesTwo;
|
||||
}
|
||||
|
||||
public void setWhitesTwo(List<String> whitesTwo) {
|
||||
this.whitesTwo = whitesTwo;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,191 @@
|
||||
package com.yxt.ordermall.utils;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* Project: yxt-common-core <br/>
|
||||
* File: ResultBean.java <br/>
|
||||
* Class: com.yxt.common.core.result.ResultBean <br/>
|
||||
* Description: 通过接口、Rest、逻辑处理执行后的结果信息. <br/>
|
||||
* Copyright: Copyright (c) 2011 <br/>
|
||||
* Company: https://gitee.com/liuzp315 <br/>
|
||||
* Makedate: 2020/8/4 0:51 <br/>
|
||||
*
|
||||
* @author liupopo
|
||||
* @version 1.0
|
||||
* @since 1.0
|
||||
*/
|
||||
public class ResultBean<T> implements Serializable {
|
||||
private static final long serialVersionUID = 4529658978692424234L;
|
||||
|
||||
private long timestamp = System.currentTimeMillis();
|
||||
|
||||
public long getTimestamp() {
|
||||
return timestamp;
|
||||
}
|
||||
|
||||
// 是否成功
|
||||
private boolean success;
|
||||
|
||||
// 消息 返回结果的说明
|
||||
private String msg;
|
||||
|
||||
// 结果状态码
|
||||
private String code;
|
||||
|
||||
// 数据
|
||||
private T data;
|
||||
|
||||
private String message;
|
||||
|
||||
public String getMessage() {
|
||||
return message;
|
||||
}
|
||||
|
||||
public ResultBean<T> setMessage(String message) {
|
||||
this.message = message;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ResultBean() {
|
||||
}
|
||||
|
||||
public ResultBean(boolean success) {
|
||||
this.success = success;
|
||||
}
|
||||
|
||||
public ResultBean(boolean success, String msg) {
|
||||
this.success = success;
|
||||
this.msg = msg;
|
||||
}
|
||||
|
||||
public ResultBean(boolean success, String msg, String code) {
|
||||
this.success = success;
|
||||
this.msg = msg;
|
||||
this.code = code;
|
||||
}
|
||||
|
||||
public ResultBean(T data) {
|
||||
this.success = true;
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
public ResultBean(String code, T data) {
|
||||
this.success = true;
|
||||
this.code = code;
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
public ResultBean(String code, String msg, T data) {
|
||||
this.success = true;
|
||||
this.code = code;
|
||||
this.msg = msg;
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
public boolean getSuccess() {
|
||||
return success;
|
||||
}
|
||||
|
||||
public ResultBean<T> setSuccess(boolean success) {
|
||||
this.success = success;
|
||||
return this;
|
||||
}
|
||||
|
||||
public String getMsg() {
|
||||
return msg;
|
||||
}
|
||||
|
||||
public ResultBean<T> setMsg(String msg) {
|
||||
this.msg = msg;
|
||||
return this;
|
||||
}
|
||||
|
||||
public String getCode() {
|
||||
return code;
|
||||
}
|
||||
|
||||
public ResultBean<T> setCode(String code) {
|
||||
this.code = code;
|
||||
return this;
|
||||
}
|
||||
|
||||
public T getData() {
|
||||
return data;
|
||||
}
|
||||
|
||||
public ResultBean<T> setData(T data) {
|
||||
this.data = data;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ResultBean<T> successOne() {
|
||||
this.setSuccess(true);
|
||||
this.setCode("0");
|
||||
this.setMessage("成功!");
|
||||
return this;
|
||||
}
|
||||
|
||||
public ResultBean<T> failOne() {
|
||||
this.setSuccess(false);
|
||||
this.setCode(String.valueOf(HttpStatus.ERROR));
|
||||
this.setMessage("操作失败!");
|
||||
return this;
|
||||
}
|
||||
|
||||
public ResultBean<T> success() {
|
||||
this.setSuccess(true);
|
||||
this.setCode(String.valueOf(HttpStatus.SUCCESS));
|
||||
this.setMsg("操作成功!");
|
||||
return this;
|
||||
}
|
||||
|
||||
public ResultBean<T> fail() {
|
||||
this.setSuccess(false);
|
||||
this.setCode(String.valueOf(HttpStatus.ERROR));
|
||||
this.setMsg("操作失败!");
|
||||
return this;
|
||||
}
|
||||
|
||||
public static <T> ResultBean<T> fireSuccess() {
|
||||
ResultBean<T> rb = new ResultBean<T>();
|
||||
rb.setSuccess(true);
|
||||
rb.setCode(String.valueOf(HttpStatus.SUCCESS));
|
||||
rb.setMsg("操作成功!");
|
||||
return rb;
|
||||
}
|
||||
|
||||
public static <T> ResultBean<T> fireFail() {
|
||||
ResultBean<T> rb = new ResultBean<T>();
|
||||
rb.setSuccess(false);
|
||||
rb.setCode(String.valueOf(HttpStatus.ERROR));
|
||||
rb.setMsg("操作失败!");
|
||||
return rb;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置返回code及msg
|
||||
*
|
||||
* @param codeMsg Code和Msg的枚举
|
||||
* @return
|
||||
*/
|
||||
public ResultBean<T> setCode(IResultCodeMsg codeMsg) {
|
||||
this.code = codeMsg.getCode();
|
||||
this.msg = codeMsg.getMsg();
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回失败信息,并指定结果code
|
||||
*
|
||||
* @param codeMsg Code和Msg的枚举
|
||||
* @return
|
||||
*/
|
||||
public ResultBean<T> fail(IResultCodeMsg codeMsg) {
|
||||
this.setSuccess(false);
|
||||
this.code = codeMsg.getCode();
|
||||
this.msg = codeMsg.getMsg();
|
||||
return this;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
package com.yxt.ordermall.utils;
|
||||
|
||||
/**
|
||||
* @author dimengzhe
|
||||
* @date 2020/12/2 10:00
|
||||
* @description
|
||||
*/
|
||||
|
||||
public class StrFormatter {
|
||||
|
||||
public static final String EMPTY_JSON = "{}";
|
||||
public static final char C_BACKSLASH = '\\';
|
||||
public static final char C_DELIM_START = '{';
|
||||
public static final char C_DELIM_END = '}';
|
||||
|
||||
/**
|
||||
* 格式化字符串<br>
|
||||
* 此方法只是简单将占位符 {} 按照顺序替换为参数<br>
|
||||
* 如果想输出 {} 使用 \\转义 { 即可,如果想输出 {} 之前的 \ 使用双转义符 \\\\ 即可<br>
|
||||
* 例:<br>
|
||||
* 通常使用:format("this is {} for {}", "a", "b") -> this is a for b<br>
|
||||
* 转义{}: format("this is \\{} for {}", "a", "b") -> this is \{} for a<br>
|
||||
* 转义\: format("this is \\\\{} for {}", "a", "b") -> this is \a for b<br>
|
||||
*
|
||||
* @param strPattern 字符串模板
|
||||
* @param argArray 参数列表
|
||||
* @return 结果
|
||||
*/
|
||||
public static String format(final String strPattern, final Object... argArray)
|
||||
{
|
||||
if (StringUtils.isEmpty(strPattern) || StringUtils.isEmpty(argArray))
|
||||
{
|
||||
return strPattern;
|
||||
}
|
||||
final int strPatternLength = strPattern.length();
|
||||
|
||||
// 初始化定义好的长度以获得更好的性能
|
||||
StringBuilder sbuf = new StringBuilder(strPatternLength + 50);
|
||||
|
||||
int handledPosition = 0;
|
||||
int delimIndex;// 占位符所在位置
|
||||
for (int argIndex = 0; argIndex < argArray.length; argIndex++)
|
||||
{
|
||||
delimIndex = strPattern.indexOf(EMPTY_JSON, handledPosition);
|
||||
if (delimIndex == -1)
|
||||
{
|
||||
if (handledPosition == 0)
|
||||
{
|
||||
return strPattern;
|
||||
}
|
||||
else
|
||||
{ // 字符串模板剩余部分不再包含占位符,加入剩余部分后返回结果
|
||||
sbuf.append(strPattern, handledPosition, strPatternLength);
|
||||
return sbuf.toString();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (delimIndex > 0 && strPattern.charAt(delimIndex - 1) == C_BACKSLASH)
|
||||
{
|
||||
if (delimIndex > 1 && strPattern.charAt(delimIndex - 2) == C_BACKSLASH)
|
||||
{
|
||||
// 转义符之前还有一个转义符,占位符依旧有效
|
||||
sbuf.append(strPattern, handledPosition, delimIndex - 1);
|
||||
sbuf.append(Convert.utf8Str(argArray[argIndex]));
|
||||
handledPosition = delimIndex + 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
// 占位符被转义
|
||||
argIndex--;
|
||||
sbuf.append(strPattern, handledPosition, delimIndex - 1);
|
||||
sbuf.append(C_DELIM_START);
|
||||
handledPosition = delimIndex + 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// 正常占位符
|
||||
sbuf.append(strPattern, handledPosition, delimIndex);
|
||||
sbuf.append(Convert.utf8Str(argArray[argIndex]));
|
||||
handledPosition = delimIndex + 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
// 加入最后一个占位符后所有的字符
|
||||
sbuf.append(strPattern, handledPosition, strPattern.length());
|
||||
|
||||
return sbuf.toString();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,526 @@
|
||||
package com.yxt.ordermall.utils;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author dimengzhe
|
||||
* @date 2020/12/2 9:59
|
||||
* @description
|
||||
*/
|
||||
|
||||
public class StringUtils extends org.apache.commons.lang3.StringUtils {
|
||||
|
||||
/**
|
||||
* 空字符串
|
||||
*/
|
||||
private static final String NULLSTR = "";
|
||||
|
||||
/**
|
||||
* 下划线
|
||||
*/
|
||||
private static final char SEPARATOR = '_';
|
||||
|
||||
/**
|
||||
* 星号
|
||||
*/
|
||||
private static final String START = "*";
|
||||
|
||||
/**
|
||||
* 获取参数不为空值
|
||||
*
|
||||
* @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 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);
|
||||
}
|
||||
|
||||
/**
|
||||
* 格式化文本, {} 表示占位符<br>
|
||||
* 此方法只是简单将占位符 {} 按照顺序替换为参数<br>
|
||||
* 如果想输出 {} 使用 \\转义 { 即可,如果想输出 {} 之前的 \ 使用双转义符 \\\\ 即可<br>
|
||||
* 例:<br>
|
||||
* 通常使用:format("this is {} for {}", "a", "b") -> this is a for b<br>
|
||||
* 转义{}: format("this is \\{} for {}", "a", "b") -> this is \{} for a<br>
|
||||
* 转义\: format("this is \\\\{} for {}", "a", "b") -> this is \a for b<br>
|
||||
*
|
||||
* @param template 文本模板,被替换的部分用 {} 表示
|
||||
* @param params 参数值
|
||||
* @return 格式化后的文本
|
||||
*/
|
||||
public static String format(String template, Object... params) {
|
||||
if (isEmpty(params) || isEmpty(template)) {
|
||||
return template;
|
||||
}
|
||||
return StrFormatter.format(template, params);
|
||||
}
|
||||
|
||||
/**
|
||||
* 下划线转驼峰命名
|
||||
*/
|
||||
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;
|
||||
}
|
||||
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 matchesTwo(String str, List<String> strs) {
|
||||
if (isEmpty(str) || isEmpty(strs)) {
|
||||
return false;
|
||||
}
|
||||
for (String testStr : strs) {
|
||||
if (matchesTwo(str, testStr)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static boolean matches(String str, List<String> strs) {
|
||||
if (isEmpty(str) || isEmpty(strs)) {
|
||||
return false;
|
||||
}
|
||||
for (String testStr : strs) {
|
||||
if (matches(str, testStr)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 查找指定字符串是否匹配指定字符串数组中的任意一个字符串
|
||||
*
|
||||
* @param str 指定字符串
|
||||
* @param strs 需要检查的字符串数组
|
||||
* @return 是否匹配
|
||||
*/
|
||||
public static boolean matches(String str, String... strs) {
|
||||
if (isEmpty(str) || isEmpty(strs)) {
|
||||
return false;
|
||||
}
|
||||
for (String testStr : strs) {
|
||||
if (matches(str, testStr)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static boolean matches(String str, String pattern) {
|
||||
if (isEmpty(pattern) || isEmpty(str)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
pattern = pattern.replaceAll("\\s*", ""); // 替换空格
|
||||
int beginOffset = 0; // pattern截取开始位置
|
||||
int formerStarOffset = -1; // 前星号的偏移位置
|
||||
int latterStarOffset = -1; // 后星号的偏移位置
|
||||
|
||||
String remainingURI = str;
|
||||
String prefixPattern = "";
|
||||
String suffixPattern = "";
|
||||
|
||||
boolean result = false;
|
||||
do {
|
||||
formerStarOffset = indexOf(pattern, START, beginOffset);
|
||||
prefixPattern = substring(pattern, beginOffset, formerStarOffset > -1 ? formerStarOffset : pattern.length());
|
||||
|
||||
// 匹配前缀Pattern
|
||||
result = remainingURI.equals(prefixPattern);
|
||||
// 已经没有星号,直接返回
|
||||
if (formerStarOffset == -1) {
|
||||
return result;
|
||||
}
|
||||
|
||||
// 匹配失败,直接返回
|
||||
if (!result){
|
||||
return false;
|
||||
}
|
||||
if (!isEmpty(prefixPattern)) {
|
||||
remainingURI = substringAfter(str, prefixPattern);
|
||||
}
|
||||
|
||||
// 匹配后缀Pattern
|
||||
latterStarOffset = indexOf(pattern, START, formerStarOffset + 1);
|
||||
suffixPattern = substring(pattern, formerStarOffset + 1, latterStarOffset > -1 ? latterStarOffset : pattern.length());
|
||||
|
||||
result = remainingURI.equals(suffixPattern);
|
||||
// 匹配失败,直接返回
|
||||
if (!result){
|
||||
return false;
|
||||
}
|
||||
if (!isEmpty(suffixPattern)) {
|
||||
remainingURI = substringAfter(str, suffixPattern);
|
||||
}
|
||||
|
||||
// 移动指针
|
||||
beginOffset = latterStarOffset + 1;
|
||||
|
||||
}
|
||||
while (!isEmpty(suffixPattern) && !isEmpty(remainingURI));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 查找指定字符串是否匹配
|
||||
*
|
||||
* @param str 指定字符串
|
||||
* @param pattern 需要检查的字符串
|
||||
* @return 是否匹配
|
||||
*/
|
||||
public static boolean matchesTwo(String str, String pattern) {
|
||||
if (isEmpty(pattern) || isEmpty(str)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
pattern = pattern.replaceAll("\\s*", ""); // 替换空格
|
||||
int beginOffset = 0; // pattern截取开始位置
|
||||
int formerStarOffset = -1; // 前星号的偏移位置
|
||||
int latterStarOffset = -1; // 后星号的偏移位置
|
||||
|
||||
String remainingURI = str;
|
||||
String prefixPattern = "";
|
||||
String suffixPattern = "";
|
||||
|
||||
boolean result = false;
|
||||
do {
|
||||
formerStarOffset = indexOf(pattern, START, beginOffset);
|
||||
prefixPattern = substring(pattern, beginOffset, formerStarOffset > -1 ? formerStarOffset : pattern.length());
|
||||
|
||||
// 匹配前缀Pattern
|
||||
result = remainingURI.contains(prefixPattern);
|
||||
// 已经没有星号,直接返回
|
||||
if (formerStarOffset == -1) {
|
||||
return result;
|
||||
}
|
||||
|
||||
// 匹配失败,直接返回
|
||||
if (!result){
|
||||
return false;
|
||||
}
|
||||
if (!isEmpty(prefixPattern)) {
|
||||
remainingURI = substringAfter(str, prefixPattern);
|
||||
}
|
||||
|
||||
// 匹配后缀Pattern
|
||||
latterStarOffset = indexOf(pattern, START, formerStarOffset + 1);
|
||||
suffixPattern = substring(pattern, formerStarOffset + 1, latterStarOffset > -1 ? latterStarOffset : pattern.length());
|
||||
|
||||
result = remainingURI.contains(suffixPattern);
|
||||
// 匹配失败,直接返回
|
||||
if (!result){
|
||||
return false;
|
||||
}
|
||||
if (!isEmpty(suffixPattern)) {
|
||||
remainingURI = substringAfter(str, suffixPattern);
|
||||
}
|
||||
|
||||
// 移动指针
|
||||
beginOffset = latterStarOffset + 1;
|
||||
|
||||
}
|
||||
while (!isEmpty(suffixPattern) && !isEmpty(remainingURI));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <T> T cast(Object obj) {
|
||||
return (T) obj;
|
||||
}
|
||||
}
|
||||
20
ordermallGateway/src/main/resources/application-dev.yml
Normal file
20
ordermallGateway/src/main/resources/application-dev.yml
Normal file
@@ -0,0 +1,20 @@
|
||||
spring:
|
||||
resources:
|
||||
static-locations: file:D://supervise
|
||||
cloud:
|
||||
nacos:
|
||||
discovery:
|
||||
# namespace: supervise
|
||||
server-addr: 127.0.0.1:8848
|
||||
redis:
|
||||
database: 3 # Redis数据库索引(默认为0)
|
||||
host: 127.0.0.1
|
||||
jedis:
|
||||
pool:
|
||||
max-active: -1 #连接池最大连接数(使用负值表示没有限制)
|
||||
max-idle: 8 #连接池中的最大空闲连接
|
||||
max-wait: -1 # 连接池最大阻塞等待时间(使用负值表示没有限制)
|
||||
min-idle: 0 # 连接池中的最小空闲连接
|
||||
password:
|
||||
port: 6379
|
||||
timeout: 0 # 连接超时时间(毫秒)
|
||||
20
ordermallGateway/src/main/resources/application-pro.yml
Normal file
20
ordermallGateway/src/main/resources/application-pro.yml
Normal file
@@ -0,0 +1,20 @@
|
||||
spring:
|
||||
resources:
|
||||
static-locations: file:D://supervise
|
||||
cloud:
|
||||
nacos:
|
||||
discovery:
|
||||
# namespace: supervise
|
||||
server-addr: 127.0.0.1:8848
|
||||
redis:
|
||||
database: 3 # Redis数据库索引(默认为0)
|
||||
host: 127.0.0.1
|
||||
jedis:
|
||||
pool:
|
||||
max-active: -1 #连接池最大连接数(使用负值表示没有限制)
|
||||
max-idle: 8 #连接池中的最大空闲连接
|
||||
max-wait: -1 # 连接池最大阻塞等待时间(使用负值表示没有限制)
|
||||
min-idle: 0 # 连接池中的最小空闲连接
|
||||
password:
|
||||
port: 6379
|
||||
timeout: 0 # 连接超时时间(毫秒)
|
||||
1
ordermallGateway/src/main/resources/application-test.yml
Normal file
1
ordermallGateway/src/main/resources/application-test.yml
Normal file
@@ -0,0 +1 @@
|
||||
|
||||
41
ordermallGateway/src/main/resources/application.yml
Normal file
41
ordermallGateway/src/main/resources/application.yml
Normal file
@@ -0,0 +1,41 @@
|
||||
hystrix:
|
||||
command:
|
||||
default:
|
||||
execution:
|
||||
isolation:
|
||||
strategy: SEMAPHORE
|
||||
thread:
|
||||
timeoutInMilliseconds: 300000
|
||||
server:
|
||||
port: 8114
|
||||
spring:
|
||||
application:
|
||||
name: gateway
|
||||
profiles:
|
||||
active: dev
|
||||
# active: pro
|
||||
cloud:
|
||||
gateway:
|
||||
routes:
|
||||
- id: ordermall-biz
|
||||
predicates:
|
||||
- Path= /mall/**
|
||||
uri: lb://ordermall-biz
|
||||
filters:
|
||||
- StripPrefix=1
|
||||
|
||||
ignore:
|
||||
whites:
|
||||
- /mall/apiadmin/sysuser/login #pc端登录
|
||||
- /mall/apiadmin/sysuser/register #pc端登录
|
||||
- /mall/apiadmin/sysuser/sendMessageCode/** #发送验证码
|
||||
- /mall/apiadmin/sysuser/sendMessageLogin/** #发送验证码
|
||||
- /mall/apiadmin/sysuser/sendMessageUpdate/** #发送验证码
|
||||
- /mall/apiadmin/sysuser/bindOrganization #绑定组织
|
||||
- /mall/apiadmin/sysuser/selOrganization #绑定组织
|
||||
|
||||
|
||||
|
||||
|
||||
whitesTwo: #包含所有
|
||||
- /upload/**
|
||||
Reference in New Issue
Block a user