马府强
2 years ago
90 changed files with 4313 additions and 0 deletions
@ -0,0 +1,7 @@ |
|||
<?xml version="1.0" encoding="UTF-8"?> |
|||
<project version="4"> |
|||
<component name="Encoding"> |
|||
<file url="file://$PROJECT_DIR$/src/main/java" charset="UTF-8" /> |
|||
<file url="file://$PROJECT_DIR$/src/main/resources" charset="UTF-8" /> |
|||
</component> |
|||
</project> |
@ -0,0 +1,46 @@ |
|||
/* |
|||
* Copyright (C), 2019-2020 dingyong |
|||
* FileName: ApiCall |
|||
* Author: dingyong |
|||
* Date: 2021/1/22 |
|||
* Description: //描述
|
|||
* History: //修改记录
|
|||
* <author> <time> <version> <desc> |
|||
* 修改人姓名 修改时间 版本号 描述 |
|||
*/ |
|||
package org.example.redislimater; |
|||
|
|||
import java.lang.annotation.*; |
|||
import java.util.concurrent.TimeUnit; |
|||
|
|||
/** |
|||
* @author dingyong |
|||
* @Description: 接口调用监控及限流 |
|||
* 限制每个ip对每个方法的访问限制,加上时间限制 |
|||
* @Date 2021/1/22 |
|||
* @see [相关类/方法](可选) |
|||
* @since [产品/模块版本] (可选) |
|||
*/ |
|||
@Target(ElementType.METHOD) |
|||
@Retention(RetentionPolicy.RUNTIME) |
|||
@Documented |
|||
public @interface ApiCall { |
|||
|
|||
/** |
|||
* 单位时间内能访问多少次,默认不限次 |
|||
* @return 调用次数 |
|||
*/ |
|||
long limitCount() default 1000000000; |
|||
|
|||
/** |
|||
* 多长时间内限制,默认 60 |
|||
* @return 时间 |
|||
*/ |
|||
long time() default 60; |
|||
|
|||
/** |
|||
* 时间类型,默认毫秒 |
|||
* @return 时间类型 |
|||
*/ |
|||
TimeUnit timeUnit() default TimeUnit.MILLISECONDS ; |
|||
} |
@ -0,0 +1,204 @@ |
|||
/* |
|||
* Copyright (C), 2019-2020 dingyong |
|||
* FileName: ApiCallAdvice |
|||
* Author: dingyong |
|||
* Date: 2021/1/22 |
|||
* Description: //描述
|
|||
* History: //修改记录
|
|||
* <author> <time> <version> <desc> |
|||
* 修改人姓名 修改时间 版本号 描述 |
|||
*/ |
|||
package org.example.redislimater; |
|||
|
|||
import com.alibaba.fastjson.JSON; |
|||
import org.aspectj.lang.ProceedingJoinPoint; |
|||
import org.aspectj.lang.annotation.*; |
|||
import org.aspectj.lang.reflect.MethodSignature; |
|||
import org.example.redislimater.exception.ApiCallException; |
|||
import org.example.redislimater.exception.BusinessException; |
|||
import org.example.redislimater.utils.IpUtils; |
|||
import org.example.redislimater.utils.Recode; |
|||
import org.slf4j.Logger; |
|||
import org.slf4j.LoggerFactory; |
|||
import org.springframework.stereotype.Component; |
|||
import org.springframework.web.context.request.RequestContextHolder; |
|||
import org.springframework.web.context.request.ServletRequestAttributes; |
|||
|
|||
import javax.annotation.Resource; |
|||
import javax.servlet.http.HttpServletRequest; |
|||
import java.text.SimpleDateFormat; |
|||
import java.util.Arrays; |
|||
import java.util.Date; |
|||
import java.util.concurrent.TimeUnit; |
|||
|
|||
/** |
|||
* @author dingyong |
|||
* @Description: 接口调用情况监控<br/> |
|||
* 1、监控单个接口一天内的调用次数<br/> |
|||
* 2、如果抛出异常,则记录异常信息及发生时间<br/> |
|||
* 3、对单个IP进行限流,每天对每个接口的调用次数有限<br/> |
|||
* @Date 2021/1/22 |
|||
* @see [相关类/方法](可选) |
|||
* @since [产品/模块版本] (可选) |
|||
*/ |
|||
@Aspect |
|||
@Component |
|||
public class ApiCallAdvice { |
|||
|
|||
private static final Logger interfaceLog = LoggerFactory.getLogger("interfaceLog"); |
|||
|
|||
@Resource |
|||
private RedisUtils redisUtils; |
|||
|
|||
private static final String FORMAT_PATTERN_DAY = "yyyy-MM-dd"; |
|||
private static final String FORMAT_PATTERN_MILLS = "yyyy-MM-dd HH:mm:ss:SSS"; |
|||
|
|||
// 配置织入点
|
|||
@Pointcut("@annotation(org.example.redislimater.ApiCall)") |
|||
public void apiCall() |
|||
{ |
|||
} |
|||
|
|||
/** |
|||
* |
|||
* @param pjp |
|||
* @return |
|||
*/ |
|||
@Around(value = "apiCall())") |
|||
public Object requestLimitAround(ProceedingJoinPoint pjp) { |
|||
MethodSignature methodSignature = (MethodSignature)pjp.getSignature(); |
|||
ApiCall apiCall = methodSignature.getMethod().getAnnotation(ApiCall.class); |
|||
// 限制访问次数
|
|||
long limitCount = apiCall.limitCount(); |
|||
|
|||
// 获取 request , 然后获取访问 ip
|
|||
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); |
|||
String requestIp = IpUtils.getIpAddr(request); |
|||
if(StringUtils.isEmpty(requestIp)) { |
|||
interfaceLog.error("execute api {} error, ip is empty",methodSignature.getMethod().getName()); |
|||
throw new ApiCallException(Recode.IP_ERROR.getCode(),Recode.IP_ERROR.getDesc()); |
|||
} |
|||
|
|||
//获取uri
|
|||
String uri = request.getRequestURI(); |
|||
String key = "API_LIMIT:" + uri + "_" + requestIp +"_"; |
|||
int size = redisUtils.keys(key + "*").size(); |
|||
if( size > limitCount ){ |
|||
interfaceLog.error("execute api {} error, ip exceed max call limit!, IP is {}",methodSignature.getMethod().getName(),requestIp); |
|||
throw new ApiCallException(Recode.LIMIT_ERROR.getCode(),Recode.LIMIT_ERROR.getDesc()); |
|||
} |
|||
|
|||
// 将访问存进缓存
|
|||
redisUtils.set(key+System.currentTimeMillis(), "1", apiCall.time(), apiCall.timeUnit()); |
|||
|
|||
//获取传入目标方法的参数
|
|||
Object[] args = pjp.getArgs(); |
|||
try { |
|||
// 执行访问并返回数据
|
|||
//方法参数
|
|||
String param; |
|||
if (args.length == 1){ |
|||
param = JSON.toJSONString(args[0]); |
|||
}else{ |
|||
param = Arrays.toString(pjp.getArgs()); |
|||
} |
|||
//耗时
|
|||
long beginTime = System.nanoTime(); |
|||
//执行结果
|
|||
Object result = pjp.proceed(args); |
|||
long endTime =System.nanoTime(); |
|||
String resultJson = JSON.toJSONString(result); |
|||
//日志打印
|
|||
interfaceLog.info("execute api : {},param: {},result:{},cost:{}ms", |
|||
methodSignature.getMethod().getName(),param,resultJson,(endTime-beginTime)/1000000); |
|||
return result; |
|||
} catch (Throwable throwable) { |
|||
//throwable.printStackTrace();
|
|||
//interfaceLog.error("execute api:{}error, cause by {}", methodSignature.getMethod().getName(),throwable.getMessage());
|
|||
interfaceLog.error("execute api:{}error, cause by {}, ip is{}", methodSignature.getMethod().getName(),throwable.getMessage(),requestIp); |
|||
throw new BusinessException("系统异常"); |
|||
} |
|||
} |
|||
|
|||
/** |
|||
* 真正执行业务操作前先进行总的限流的验证 |
|||
* 限制维度为:一天内单个IP的访问次数 |
|||
* key = URI + IP + date(精确到天) |
|||
* value = 调用次数 |
|||
*/ |
|||
@Before("apiCall()") |
|||
public void before() { |
|||
// 接收到请求,记录请求内容
|
|||
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); |
|||
//获取请求的request
|
|||
HttpServletRequest request = attributes.getRequest(); |
|||
|
|||
String uri = request.getRequestURI(); |
|||
String date = dateFormat(FORMAT_PATTERN_DAY); |
|||
String ip = IpUtils.getIpAddr(request); |
|||
|
|||
if (StringUtils.isEmpty(ip)) { |
|||
interfaceLog.error("execute uri {} error, Unauthorized access!ip cannot empty!",uri); |
|||
throw new ApiCallException(Recode.IP_ERROR.getCode(),Recode.IP_ERROR.getDesc()); |
|||
} |
|||
// URI+IP+日期 构成以天为维度的key
|
|||
String ipKey = "API_LIMIT_DAY:"+uri + "_" + ip + "_" + date; |
|||
if (redisUtils.hasKey(ipKey)) { |
|||
if (Integer.parseInt(redisUtils.get(ipKey).toString()) > 10000) { |
|||
interfaceLog.error("execute uri {} error, exceed max call limit!,IP is :{}",uri,ip); |
|||
throw new ApiCallException(Recode.LIMIT_ERROR.getCode(),Recode.LIMIT_ERROR.getDesc()); |
|||
} |
|||
redisUtils.incr(ipKey, 1); |
|||
} else { |
|||
redisUtils.set(ipKey, 1, 1L, TimeUnit.DAYS); |
|||
} |
|||
} |
|||
|
|||
/** |
|||
* 如果有返回结果,代表一次调用,则对应接口的调用次数加一,统计维度为天 |
|||
* (Redis使用Hash结构) |
|||
* key = URI |
|||
* key = date (精确到天) |
|||
* value = 调用次数 |
|||
*/ |
|||
@AfterReturning("apiCall()") |
|||
public void afterReturning() { |
|||
// 接收到请求,记录请求内容
|
|||
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); |
|||
//获取请求的request
|
|||
HttpServletRequest request = attributes.getRequest(); |
|||
|
|||
String uri = request.getRequestURI(); |
|||
String date = dateFormat(FORMAT_PATTERN_DAY); |
|||
if (redisUtils.hasKey(uri)) { |
|||
redisUtils.boundHashOpsIncrement(uri,date, 1); |
|||
} else { |
|||
redisUtils.boundHashOpsPut(uri,date, 1); |
|||
} |
|||
} |
|||
|
|||
/** |
|||
* 如果调用抛出异常,则缓存异常信息(Redis使用Hash结构) |
|||
* key = URI + “_exception” |
|||
* key = time (精确到毫秒的时间) |
|||
* value = exception 异常信息 |
|||
* |
|||
* @param ex 异常信息 |
|||
*/ |
|||
@AfterThrowing(value = "apiCall()", throwing = "ex") |
|||
public void afterThrowing(Exception ex) { |
|||
//ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
|
|||
// HttpServletRequest request = attributes.getRequest();
|
|||
//String uri = request.getRequestURI() + "_exception";
|
|||
//String time = dateFormat(FORMAT_PATTERN_MILLS);
|
|||
//redisTemplate.boundHashOps(uri).put(time, exception);
|
|||
interfaceLog.error("execute api error, cause by {}",ex.getMessage()); |
|||
} |
|||
|
|||
|
|||
private String dateFormat(String pattern) { |
|||
SimpleDateFormat dateFormat = new SimpleDateFormat(pattern); |
|||
return dateFormat.format(new Date()); |
|||
} |
|||
|
|||
} |
@ -0,0 +1,719 @@ |
|||
/* |
|||
* Copyright (C), 2019-2020 dingyong |
|||
* FileName: RedisUtils |
|||
* Author: dingyong |
|||
* Date: 2020/10/7 |
|||
* Description: //描述
|
|||
* History: //修改记录
|
|||
* <author> <time> <version> <desc> |
|||
* 修改人姓名 修改时间 版本号 描述 |
|||
*/ |
|||
package org.example.redislimater; |
|||
|
|||
import org.springframework.beans.factory.annotation.Autowired; |
|||
import org.springframework.data.redis.connection.RedisStringCommands; |
|||
import org.springframework.data.redis.connection.ReturnType; |
|||
import org.springframework.data.redis.core.*; |
|||
import org.springframework.data.redis.core.types.Expiration; |
|||
import org.springframework.stereotype.Component; |
|||
import org.springframework.util.CollectionUtils; |
|||
|
|||
import java.nio.charset.Charset; |
|||
import java.util.*; |
|||
import java.util.concurrent.TimeUnit; |
|||
|
|||
/** |
|||
* @author dingyong |
|||
* @Description: redis工具类 |
|||
* @Date 2020/10/7 |
|||
* @see [相关类/方法](可选) |
|||
* @since [产品/模块版本] (可选) |
|||
*/ |
|||
@Component |
|||
public class RedisUtils { |
|||
|
|||
@Autowired |
|||
private RedisTemplate<String, Object> redisTemplate; |
|||
|
|||
//因为spring自动注入管理了bean容器,直接用@Autowired取即可
|
|||
@Autowired |
|||
private StringRedisTemplate stringRedisTemplate; |
|||
|
|||
public RedisUtils(RedisTemplate<String, Object> redisTemplate) { |
|||
this.redisTemplate = redisTemplate; |
|||
} |
|||
|
|||
/** |
|||
* 指定缓存失效时间 |
|||
* @param key 键 |
|||
* @param time 时间(秒) |
|||
* @return |
|||
*/ |
|||
public boolean expire(String key,long time){ |
|||
try { |
|||
if(time>0){ |
|||
redisTemplate.expire(key, time, TimeUnit.SECONDS); |
|||
} |
|||
return true; |
|||
} catch (Exception e) { |
|||
e.printStackTrace(); |
|||
return false; |
|||
} |
|||
} |
|||
|
|||
/** |
|||
* 根据key 获取过期时间 |
|||
* @param key 键 不能为null |
|||
* @return 时间(秒) 返回0代表为永久有效 |
|||
*/ |
|||
public long getExpire(String key){ |
|||
return redisTemplate.getExpire(key,TimeUnit.SECONDS); |
|||
} |
|||
|
|||
/** |
|||
* 判断key是否存在 |
|||
* @param key 键 |
|||
* @return true 存在 false不存在 |
|||
*/ |
|||
public boolean hasKey(String key){ |
|||
try { |
|||
return redisTemplate.hasKey(key); |
|||
} catch (Exception e) { |
|||
e.printStackTrace(); |
|||
return false; |
|||
} |
|||
} |
|||
|
|||
/** |
|||
* 删除缓存 |
|||
* @param key 可以传一个值 或多个 |
|||
*/ |
|||
@SuppressWarnings("unchecked") |
|||
public void del(String ... key){ |
|||
if(key!=null&&key.length>0){ |
|||
if(key.length==1){ |
|||
redisTemplate.delete(key[0]); |
|||
}else{ |
|||
redisTemplate.delete(CollectionUtils.arrayToList(key)); |
|||
} |
|||
} |
|||
} |
|||
|
|||
//============================String=============================
|
|||
/** |
|||
* 普通缓存获取 |
|||
* @param key 键 |
|||
* @return 值 |
|||
*/ |
|||
public Object get(String key){ |
|||
return key==null?null:redisTemplate.opsForValue().get(key); |
|||
} |
|||
|
|||
/** |
|||
* 普通缓存放入 |
|||
* @param key 键 |
|||
* @param value 值 |
|||
* @return true成功 false失败 |
|||
*/ |
|||
public boolean set(String key,Object value) { |
|||
try { |
|||
redisTemplate.opsForValue().set(key, value); |
|||
return true; |
|||
} catch (Exception e) { |
|||
e.printStackTrace(); |
|||
return false; |
|||
} |
|||
} |
|||
|
|||
/** |
|||
* 普通缓存放入并设置时间 |
|||
* @param key 键 |
|||
* @param value 值 |
|||
* @param time 时间(秒) time要大于0 如果time小于等于0 将设置无限期 |
|||
* @return true成功 false 失败 |
|||
*/ |
|||
public boolean set(String key,Object value,long time){ |
|||
try { |
|||
if(time>0){ |
|||
redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS); |
|||
}else{ |
|||
set(key, value); |
|||
} |
|||
return true; |
|||
} catch (Exception e) { |
|||
e.printStackTrace(); |
|||
return false; |
|||
} |
|||
} |
|||
|
|||
/** |
|||
* 普通缓存放入并设置时间 |
|||
* @param key 键 |
|||
* @param value 值 |
|||
* @param time 时间(秒) time要大于0 如果time小于等于0 将设置无限期 |
|||
* @return true成功 false 失败 |
|||
*/ |
|||
public boolean set(String key,Object value,long time,TimeUnit timeUnit){ |
|||
try { |
|||
if(time>0){ |
|||
redisTemplate.opsForValue().set(key, value, time, timeUnit); |
|||
}else{ |
|||
set(key, value); |
|||
} |
|||
return true; |
|||
} catch (Exception e) { |
|||
e.printStackTrace(); |
|||
return false; |
|||
} |
|||
} |
|||
|
|||
public Boolean lock(String key,String value, Long timeout, TimeUnit timeUnit) { |
|||
Boolean lockStat = stringRedisTemplate.execute((RedisCallback<Boolean>) connection -> |
|||
connection.set(key.getBytes(Charset.forName("UTF-8")), value.getBytes(Charset.forName("UTF-8")), |
|||
Expiration.from(timeout, timeUnit), RedisStringCommands.SetOption.SET_IF_ABSENT)); |
|||
return lockStat; |
|||
} |
|||
|
|||
public Boolean unLock(String key,String value) { |
|||
String script = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end"; |
|||
boolean unLockStat = stringRedisTemplate.execute((RedisCallback<Boolean>) connection -> |
|||
connection.eval(script.getBytes(), ReturnType.BOOLEAN, 1, |
|||
key.getBytes(Charset.forName("UTF-8")), value.getBytes(Charset.forName("UTF-8")))); |
|||
return unLockStat; |
|||
} |
|||
/* |
|||
|
|||
public boolean tryLock(String key,String value,long expire){ |
|||
boolean result; |
|||
RedisConnectionFactory factory = redisTemplate.getConnectionFactory(); |
|||
assert factory != null; |
|||
RedisConnection conn = factory.getConnection(); |
|||
try { |
|||
result = conn.set(key.getBytes(Charset.forName("UTF-8")), value.getBytes(Charset.forName("UTF-8")), |
|||
Expiration.from(expire, TimeUnit.MILLISECONDS), RedisStringCommands.SetOption.SET_IF_ABSENT); |
|||
} finally { |
|||
RedisConnectionUtils.releaseConnection(conn, factory); |
|||
} |
|||
return result; |
|||
} |
|||
|
|||
public void execDelLuaScript(String key, String value,String script){ |
|||
byte[][] keysAndArgs = new byte[2][]; |
|||
keysAndArgs[0] = key.getBytes(Charset.forName("UTF-8")); |
|||
keysAndArgs[1] = value.getBytes(Charset.forName("UTF-8")); |
|||
RedisConnectionFactory factory = redisTemplate.getConnectionFactory(); |
|||
RedisConnection conn = factory.getConnection(); |
|||
try { |
|||
conn.scriptingCommands().eval(script.getBytes(Charset.forName("UTF-8")), ReturnType.INTEGER, 1, keysAndArgs); |
|||
} finally { |
|||
RedisConnectionUtils.releaseConnection(conn, factory); |
|||
} |
|||
} |
|||
*/ |
|||
|
|||
/** |
|||
* 递增 |
|||
* @param key 键 |
|||
* @param delta 要增加几(大于0) |
|||
* @return |
|||
*/ |
|||
public long incr(String key, long delta){ |
|||
if(delta<0){ |
|||
throw new RuntimeException("递增因子必须大于0"); |
|||
} |
|||
return redisTemplate.opsForValue().increment(key, delta); |
|||
} |
|||
|
|||
/** |
|||
* 递减 |
|||
* @param key 键 |
|||
* @param delta 要减少几(小于0) |
|||
* @return |
|||
*/ |
|||
public long decr(String key, long delta){ |
|||
if(delta<0){ |
|||
throw new RuntimeException("递减因子必须大于0"); |
|||
} |
|||
return redisTemplate.opsForValue().increment(key, -delta); |
|||
} |
|||
|
|||
//================================Map=================================
|
|||
/** |
|||
* HashGet |
|||
* @param key 键 不能为null |
|||
* @param item 项 不能为null |
|||
* @return 值 |
|||
*/ |
|||
public Object hget(String key,String item){ |
|||
return redisTemplate.opsForHash().get(key, item); |
|||
} |
|||
|
|||
/** |
|||
* 获取hashKey对应的所有键值 |
|||
* @param key 键 |
|||
* @return 对应的多个键值 |
|||
*/ |
|||
public Map<Object,Object> hmget(String key){ |
|||
return redisTemplate.opsForHash().entries(key); |
|||
} |
|||
|
|||
/** |
|||
* HashSet |
|||
* @param key 键 |
|||
* @param map 对应多个键值 |
|||
* @return true 成功 false 失败 |
|||
*/ |
|||
public boolean hmset(String key, Map<String,Object> map){ |
|||
try { |
|||
redisTemplate.opsForHash().putAll(key, map); |
|||
return true; |
|||
} catch (Exception e) { |
|||
e.printStackTrace(); |
|||
return false; |
|||
} |
|||
} |
|||
|
|||
/** |
|||
* HashSet 并设置时间 |
|||
* @param key 键 |
|||
* @param map 对应多个键值 |
|||
* @param time 时间(秒) |
|||
* @return true成功 false失败 |
|||
*/ |
|||
public boolean hmset(String key, Map<String,Object> map, long time){ |
|||
try { |
|||
redisTemplate.opsForHash().putAll(key, map); |
|||
if(time>0){ |
|||
expire(key, time); |
|||
} |
|||
return true; |
|||
} catch (Exception e) { |
|||
e.printStackTrace(); |
|||
return false; |
|||
} |
|||
} |
|||
|
|||
/** |
|||
* 向一张hash表中放入数据,如果不存在将创建 |
|||
* @param key 键 |
|||
* @param item 项 |
|||
* @param value 值 |
|||
* @return true 成功 false失败 |
|||
*/ |
|||
public boolean hset(String key,String item,Object value) { |
|||
try { |
|||
redisTemplate.opsForHash().put(key, item, value); |
|||
return true; |
|||
} catch (Exception e) { |
|||
e.printStackTrace(); |
|||
return false; |
|||
} |
|||
} |
|||
|
|||
/** |
|||
* 向一张hash表中放入数据,如果不存在将创建 |
|||
* @param key 键 |
|||
* @param item 项 |
|||
* @param value 值 |
|||
* @param time 时间(秒) 注意:如果已存在的hash表有时间,这里将会替换原有的时间 |
|||
* @return true 成功 false失败 |
|||
*/ |
|||
public boolean hset(String key,String item,Object value,long time) { |
|||
try { |
|||
redisTemplate.opsForHash().put(key, item, value); |
|||
if(time>0){ |
|||
expire(key, time); |
|||
} |
|||
return true; |
|||
} catch (Exception e) { |
|||
e.printStackTrace(); |
|||
return false; |
|||
} |
|||
} |
|||
|
|||
/** |
|||
* 删除hash表中的值 |
|||
* @param key 键 不能为null |
|||
* @param item 项 可以使多个 不能为null |
|||
*/ |
|||
public void hdel(String key, Object... item){ |
|||
redisTemplate.opsForHash().delete(key,item); |
|||
} |
|||
|
|||
/** |
|||
* 判断hash表中是否有该项的值 |
|||
* @param key 键 不能为null |
|||
* @param item 项 不能为null |
|||
* @return true 存在 false不存在 |
|||
*/ |
|||
public boolean hHasKey(String key, String item){ |
|||
return redisTemplate.opsForHash().hasKey(key, item); |
|||
} |
|||
|
|||
/** |
|||
* hash递增 如果不存在,就会创建一个 并把新增后的值返回 |
|||
* @param key 键 |
|||
* @param item 项 |
|||
* @param by 要增加几(大于0) |
|||
* @return |
|||
*/ |
|||
public double hincr(String key, String item,double by){ |
|||
return redisTemplate.opsForHash().increment(key, item, by); |
|||
} |
|||
|
|||
/** |
|||
* hash递减 |
|||
* @param key 键 |
|||
* @param item 项 |
|||
* @param by 要减少记(小于0) |
|||
*/ |
|||
public double hdecr(String key, String item,double by){ |
|||
return redisTemplate.opsForHash().increment(key, item,-by); |
|||
} |
|||
|
|||
//============================set=============================
|
|||
/** |
|||
* 根据key获取Set中的所有值 |
|||
* @param key 键 |
|||
* @return |
|||
*/ |
|||
public Set<Object> sGet(String key){ |
|||
try { |
|||
return redisTemplate.opsForSet().members(key); |
|||
} catch (Exception e) { |
|||
e.printStackTrace(); |
|||
return null; |
|||
} |
|||
} |
|||
|
|||
/** |
|||
* 根据value从一个set中查询,是否存在 |
|||
* @param key 键 |
|||
* @param value 值 |
|||
* @return true 存在 false不存在 |
|||
*/ |
|||
public boolean sHasKey(String key,Object value){ |
|||
try { |
|||
return redisTemplate.opsForSet().isMember(key, value); |
|||
} catch (Exception e) { |
|||
e.printStackTrace(); |
|||
return false; |
|||
} |
|||
} |
|||
|
|||
/** |
|||
* 将数据放入set缓存 |
|||
* @param key 键 |
|||
* @param values 值 可以是多个 |
|||
* @return 成功个数 |
|||
*/ |
|||
public long sSet(String key, Object...values) { |
|||
try { |
|||
return redisTemplate.opsForSet().add(key, values); |
|||
} catch (Exception e) { |
|||
e.printStackTrace(); |
|||
return 0; |
|||
} |
|||
} |
|||
|
|||
/** |
|||
* 将set数据放入缓存 |
|||
* @param key 键 |
|||
* @param time 时间(秒) |
|||
* @param values 值 可以是多个 |
|||
* @return 成功个数 |
|||
*/ |
|||
public long sSetAndTime(String key,long time,Object...values) { |
|||
try { |
|||
Long count = redisTemplate.opsForSet().add(key, values); |
|||
if(time>0) { |
|||
expire(key, time); |
|||
} |
|||
return count; |
|||
} catch (Exception e) { |
|||
e.printStackTrace(); |
|||
return 0; |
|||
} |
|||
} |
|||
|
|||
/** |
|||
* 获取set缓存的长度 |
|||
* @param key 键 |
|||
* @return |
|||
*/ |
|||
public long sGetSetSize(String key){ |
|||
try { |
|||
return redisTemplate.opsForSet().size(key); |
|||
} catch (Exception e) { |
|||
e.printStackTrace(); |
|||
return 0; |
|||
} |
|||
} |
|||
|
|||
/** |
|||
* 移除值为value的 |
|||
* @param key 键 |
|||
* @param values 值 可以是多个 |
|||
* @return 移除的个数 |
|||
*/ |
|||
public long setRemove(String key, Object ...values) { |
|||
try { |
|||
Long count = redisTemplate.opsForSet().remove(key, values); |
|||
return count; |
|||
} catch (Exception e) { |
|||
e.printStackTrace(); |
|||
return 0; |
|||
} |
|||
} |
|||
//===============================list=================================
|
|||
|
|||
/** |
|||
* 获取list缓存的内容 |
|||
* @param key 键 |
|||
* @param start 开始 |
|||
* @param end 结束 0 到 -1代表所有值 |
|||
* @return |
|||
*/ |
|||
public List<Object> lGet(String key, long start, long end){ |
|||
try { |
|||
return redisTemplate.opsForList().range(key, start, end); |
|||
} catch (Exception e) { |
|||
e.printStackTrace(); |
|||
return null; |
|||
} |
|||
} |
|||
|
|||
/** |
|||
* 获取list缓存的长度 |
|||
* @param key 键 |
|||
* @return |
|||
*/ |
|||
public long lGetListSize(String key){ |
|||
try { |
|||
return redisTemplate.opsForList().size(key); |
|||
} catch (Exception e) { |
|||
e.printStackTrace(); |
|||
return 0; |
|||
} |
|||
} |
|||
|
|||
/** |
|||
* 通过索引 获取list中的值 |
|||
* @param key 键 |
|||
* @param index 索引 index>=0时, 0 表头,1 第二个元素,依次类推;index<0时,-1,表尾,-2倒数第二个元素,依次类推 |
|||
* @return |
|||
*/ |
|||
public Object lGetIndex(String key,long index){ |
|||
try { |
|||
return redisTemplate.opsForList().index(key, index); |
|||
} catch (Exception e) { |
|||
e.printStackTrace(); |
|||
return null; |
|||
} |
|||
} |
|||
|
|||
/** |
|||
* 将list放入缓存 |
|||
* @param key 键 |
|||
* @param value 值 |
|||
* @return |
|||
*/ |
|||
public boolean lSet(String key, Object value) { |
|||
try { |
|||
redisTemplate.opsForList().rightPush(key, value); |
|||
return true; |
|||
} catch (Exception e) { |
|||
e.printStackTrace(); |
|||
return false; |
|||
} |
|||
} |
|||
|
|||
/** |
|||
* 将list放入缓存 |
|||
* @param key 键 |
|||
* @param value 值 |
|||
* @param time 时间(秒) |
|||
* @return |
|||
*/ |
|||
public boolean lSet(String key, Object value, long time) { |
|||
try { |
|||
redisTemplate.opsForList().rightPush(key, value); |
|||
if (time > 0) { |
|||
expire(key, time); |
|||
} |
|||
return true; |
|||
} catch (Exception e) { |
|||
e.printStackTrace(); |
|||
return false; |
|||
} |
|||
} |
|||
|
|||
/** |
|||
* 将list放入缓存 |
|||
* @param key 键 |
|||
* @param value 值 |
|||
* @return |
|||
*/ |
|||
public boolean lSet(String key, List<Object> value) { |
|||
try { |
|||
redisTemplate.opsForList().rightPushAll(key, value); |
|||
return true; |
|||
} catch (Exception e) { |
|||
e.printStackTrace(); |
|||
return false; |
|||
} |
|||
} |
|||
|
|||
/** |
|||
* 将list放入缓存 |
|||
* @param key 键 |
|||
* @param value 值 |
|||
* @param time 时间(秒) |
|||
* @return |
|||
*/ |
|||
public boolean lSet(String key, List<Object> value, long time) { |
|||
try { |
|||
redisTemplate.opsForList().rightPushAll(key, value); |
|||
if (time > 0) { |
|||
expire(key, time); |
|||
} |
|||
return true; |
|||
} catch (Exception e) { |
|||
e.printStackTrace(); |
|||
return false; |
|||
} |
|||
} |
|||
|
|||
/** |
|||
* 根据索引修改list中的某条数据 |
|||
* @param key 键 |
|||
* @param index 索引 |
|||
* @param value 值 |
|||
* @return |
|||
*/ |
|||
public boolean lUpdateIndex(String key, long index,Object value) { |
|||
try { |
|||
redisTemplate.opsForList().set(key, index, value); |
|||
return true; |
|||
} catch (Exception e) { |
|||
e.printStackTrace(); |
|||
return false; |
|||
} |
|||
} |
|||
|
|||
/** |
|||
* 移除N个值为value |
|||
* @param key 键 |
|||
* @param count 移除多少个 |
|||
* @param value 值 |
|||
* @return 移除的个数 |
|||
*/ |
|||
public long lRemove(String key,long count,Object value) { |
|||
try { |
|||
Long remove = redisTemplate.opsForList().remove(key, count, value); |
|||
return remove; |
|||
} catch (Exception e) { |
|||
e.printStackTrace(); |
|||
return 0; |
|||
} |
|||
} |
|||
|
|||
/** |
|||
* 模糊查询获取key值 |
|||
* @param pattern |
|||
* @return |
|||
*/ |
|||
public Set keys(String pattern){ |
|||
return redisTemplate.keys(pattern); |
|||
} |
|||
|
|||
/** |
|||
* 使用Redis的消息队列 |
|||
* @param channel |
|||
* @param message 消息内容 |
|||
*/ |
|||
public void convertAndSend(String channel, Object message){ |
|||
redisTemplate.convertAndSend(channel,message); |
|||
} |
|||
|
|||
|
|||
|
|||
/** |
|||
* 根据起始结束序号遍历Redis中的list |
|||
* @param listKey |
|||
* @param start 起始序号 |
|||
* @param end 结束序号 |
|||
* @return |
|||
*/ |
|||
public List<Object> rangeList(String listKey, long start, long end) { |
|||
//绑定操作
|
|||
BoundListOperations<String, Object> boundValueOperations = redisTemplate.boundListOps(listKey); |
|||
//查询数据
|
|||
return boundValueOperations.range(start, end); |
|||
} |
|||
/** |
|||
* 弹出右边的值 --- 并且移除这个值 |
|||
* @param listKey |
|||
*/ |
|||
public Object rifhtPop(String listKey){ |
|||
//绑定操作
|
|||
BoundListOperations<String, Object> boundValueOperations = redisTemplate.boundListOps(listKey); |
|||
return boundValueOperations.rightPop(); |
|||
} |
|||
|
|||
//=========BoundListOperations 用法 End============
|
|||
|
|||
public void incrementStar(String starIdKey,String fansId,Integer supportValue){ |
|||
try { |
|||
redisTemplate.opsForZSet().add(starIdKey,fansId,supportValue); |
|||
} catch (Exception e) { |
|||
return; |
|||
} |
|||
} |
|||
|
|||
public List<Map<String,Object>> getIncrementStar(String starIdKey){ |
|||
Set<ZSetOperations.TypedTuple<Object>> typedTuples = redisTemplate.opsForZSet() |
|||
.reverseRangeByScoreWithScores(starIdKey, 0, 99999, 0, 100);//只取前100条
|
|||
int index = 0; |
|||
List<Map<String,Object>> rank = new ArrayList<>(); |
|||
for(ZSetOperations.TypedTuple typle:typedTuples){ |
|||
Map<String, Object> map = new HashMap<>(); |
|||
map.put("fansId",typle.getValue()); |
|||
map.put("count",typle.getScore().intValue()); |
|||
map.put("rank",++index); |
|||
rank.add(map); |
|||
} |
|||
return rank; |
|||
} |
|||
|
|||
|
|||
public void boundHashOpsIncrement(String var,String var1, long var2){ |
|||
redisTemplate.boundHashOps(var).increment(var1, var2); |
|||
} |
|||
|
|||
public void boundHashOpsPut(String var,String var1, long var2){ |
|||
redisTemplate.boundHashOps(var).put(var1, var2); |
|||
} |
|||
|
|||
|
|||
/** |
|||
* 次数限制 |
|||
* @param key key |
|||
* @param limitSeconds key有效期 |
|||
* @param limitTimes 限制次数 |
|||
* @return -1表示超过限制 |
|||
*/ |
|||
public Long limitIncr(final String key, final int limitSeconds, final int limitTimes) { |
|||
if(StringUtils.isEmpty(key)) { |
|||
return 0L; |
|||
} |
|||
Long ret = 1L; |
|||
if (!redisTemplate.hasKey(key)) { |
|||
redisTemplate.opsForValue().increment(key, 1); |
|||
redisTemplate.expire(key, limitSeconds, TimeUnit.SECONDS); |
|||
return ret; |
|||
} |
|||
ret = redisTemplate.opsForValue().increment(key, 1); |
|||
return ret > limitTimes ? -1L : ret; |
|||
} |
|||
} |
@ -0,0 +1,410 @@ |
|||
package org.example.redislimater; |
|||
|
|||
|
|||
import org.example.redislimater.utils.StrFormatter; |
|||
|
|||
import java.util.Collection; |
|||
import java.util.Map; |
|||
|
|||
/** |
|||
* 字符串工具类 |
|||
* |
|||
* @author pangu |
|||
*/ |
|||
public class StringUtils extends org.apache.commons.lang3.StringUtils |
|||
{ |
|||
/** 空字符串 */ |
|||
private static final String NULLSTR = ""; |
|||
|
|||
/** 下划线 */ |
|||
private static final char SEPARATOR = '_'; |
|||
|
|||
/** |
|||
* 获取参数不为空值 |
|||
* |
|||
* @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; |
|||
} |
|||
if (s.indexOf(SEPARATOR) == -1) |
|||
{ |
|||
return s; |
|||
} |
|||
s = s.toLowerCase(); |
|||
StringBuilder sb = new StringBuilder(s.length()); |
|||
boolean upperCase = false; |
|||
for (int i = 0; i < s.length(); i++) |
|||
{ |
|||
char c = s.charAt(i); |
|||
|
|||
if (c == SEPARATOR) |
|||
{ |
|||
upperCase = true; |
|||
} |
|||
else if (upperCase) |
|||
{ |
|||
sb.append(Character.toUpperCase(c)); |
|||
upperCase = false; |
|||
} |
|||
else |
|||
{ |
|||
sb.append(c); |
|||
} |
|||
} |
|||
return sb.toString(); |
|||
} |
|||
|
|||
@SuppressWarnings("unchecked") |
|||
public static <T> T cast(Object obj) |
|||
{ |
|||
return (T) obj; |
|||
} |
|||
} |
@ -0,0 +1,23 @@ |
|||
package org.example.redislimater.controller; |
|||
|
|||
|
|||
import org.example.redislimater.ApiCall; |
|||
import org.springframework.validation.annotation.Validated; |
|||
import org.springframework.web.bind.annotation.GetMapping; |
|||
import org.springframework.web.bind.annotation.RequestMapping; |
|||
import org.springframework.web.bind.annotation.RestController; |
|||
|
|||
import java.util.concurrent.TimeUnit; |
|||
|
|||
@RestController |
|||
@RequestMapping("/api/cricle") |
|||
@Validated |
|||
public class TestController { |
|||
|
|||
@ApiCall(time = 1,limitCount = 100,timeUnit = TimeUnit.SECONDS) |
|||
@GetMapping("/queryAllCricles") |
|||
public String queryAllCricles(String req) |
|||
{ |
|||
return null; |
|||
} |
|||
} |
@ -0,0 +1,33 @@ |
|||
/* |
|||
* Copyright (C), 2019-2020 dingyong |
|||
* FileName: ApiCallException |
|||
* Author: dingyong |
|||
* Date: 2021/1/22 |
|||
* Description: //描述
|
|||
* History: //修改记录
|
|||
* <author> <time> <version> <desc> |
|||
* 修改人姓名 修改时间 版本号 描述 |
|||
*/ |
|||
package org.example.redislimater.exception; |
|||
|
|||
/** |
|||
* @author dingyong |
|||
* @Description: TODO |
|||
* @Date 2021/1/22 |
|||
* @see [相关类/方法](可选) |
|||
* @since [产品/模块版本] (可选) |
|||
*/ |
|||
public class ApiCallException extends RuntimeException { |
|||
|
|||
private static final long serialVersionUID = 4721703562003091668L; |
|||
private final Integer errorCode; |
|||
|
|||
public ApiCallException(int errorCode, String message) { |
|||
super(message); |
|||
this.errorCode = errorCode; |
|||
} |
|||
|
|||
public Integer getErrorCode() { |
|||
return errorCode; |
|||
} |
|||
} |
@ -0,0 +1,30 @@ |
|||
package org.example.redislimater.exception; |
|||
|
|||
/** |
|||
* 业务异常 |
|||
* |
|||
* @author pangu |
|||
*/ |
|||
public class BusinessException extends RuntimeException |
|||
{ |
|||
private static final long serialVersionUID = 1L; |
|||
|
|||
protected final String message; |
|||
|
|||
public BusinessException(String message) |
|||
{ |
|||
this.message = message; |
|||
} |
|||
|
|||
public BusinessException(String message, Throwable e) |
|||
{ |
|||
super(message, e); |
|||
this.message = message; |
|||
} |
|||
|
|||
@Override |
|||
public String getMessage() |
|||
{ |
|||
return message; |
|||
} |
|||
} |
@ -0,0 +1,15 @@ |
|||
package org.example.redislimater.exception; |
|||
|
|||
/** |
|||
* 演示模式异常 |
|||
* |
|||
* @author pangu |
|||
*/ |
|||
public class DemoModeException extends RuntimeException |
|||
{ |
|||
private static final long serialVersionUID = 1L; |
|||
|
|||
public DemoModeException() |
|||
{ |
|||
} |
|||
} |
@ -0,0 +1,57 @@ |
|||
/* |
|||
* Copyright (C), 2019-2020 dingyong |
|||
* FileName: PGException |
|||
* Author: dingyong |
|||
* Date: 2020/12/8 |
|||
* Description: //描述
|
|||
* History: //修改记录
|
|||
* <author> <time> <version> <desc> |
|||
* 修改人姓名 修改时间 版本号 描述 |
|||
*/ |
|||
package org.example.redislimater.exception; |
|||
|
|||
import com.alibaba.fastjson.JSON; |
|||
|
|||
/** |
|||
* @author dingyong |
|||
* @Description: TODO |
|||
* @Date 2020/12/8 |
|||
* @see [相关类/方法](可选) |
|||
* @since [产品/模块版本] (可选) |
|||
*/ |
|||
public class PGException extends RuntimeException{ |
|||
|
|||
private static final long serialVersionUID = 8368117911051585269L; |
|||
private final String errorCode; |
|||
|
|||
public PGException(String errorCode) { |
|||
super(); |
|||
this.errorCode = errorCode; |
|||
} |
|||
|
|||
public PGException(String errorCode, String message) { |
|||
super(message); |
|||
this.errorCode = errorCode; |
|||
} |
|||
|
|||
public PGException(String errorCode, Throwable cause) { |
|||
super(cause); |
|||
this.errorCode = errorCode; |
|||
} |
|||
|
|||
public PGException(String errorCode, String message, Throwable cause) { |
|||
super(message, cause); |
|||
this.errorCode = errorCode; |
|||
} |
|||
|
|||
public String getErrorCode() { |
|||
return errorCode; |
|||
} |
|||
|
|||
|
|||
@Override |
|||
public String toString() { |
|||
return JSON.toJSONString(this); |
|||
} |
|||
|
|||
} |
@ -0,0 +1,63 @@ |
|||
/* |
|||
* Copyright (C), 2019-2020 dingyong |
|||
* FileName: ServiceException |
|||
* Author: dingyong |
|||
* Date: 2020/12/7 |
|||
* Description: //描述
|
|||
* History: //修改记录
|
|||
* <author> <time> <version> <desc> |
|||
* 修改人姓名 修改时间 版本号 描述 |
|||
*/ |
|||
package org.example.redislimater.exception; |
|||
|
|||
|
|||
import org.example.redislimater.utils.ErrorCodeEnum; |
|||
|
|||
/** |
|||
* @author dingyong |
|||
* @Description: TODO |
|||
* @Date 2020/12/7 |
|||
* @see [相关类/方法](可选) |
|||
* @since [产品/模块版本] (可选) |
|||
*/ |
|||
public class ServiceException extends RuntimeException { |
|||
private String code; |
|||
|
|||
public ServiceException(String code, String message) { |
|||
super(message); |
|||
this.code = code; |
|||
} |
|||
|
|||
public ServiceException(String code, Throwable ex) { |
|||
super(ex); |
|||
this.code = code; |
|||
} |
|||
|
|||
public ServiceException(String code, String message, Throwable ex) { |
|||
super(message, ex); |
|||
this.code = code; |
|||
} |
|||
|
|||
public ServiceException(ErrorCodeEnum code) { |
|||
super(code.getValue()); |
|||
this.code = code.getCode(); |
|||
} |
|||
|
|||
public ServiceException(ErrorCodeEnum code, String message) { |
|||
super(message); |
|||
this.code = code.getCode(); |
|||
} |
|||
|
|||
public ServiceException(ErrorCodeEnum code, Throwable ex) { |
|||
this(code); |
|||
} |
|||
|
|||
public ServiceException(ErrorCodeEnum code, String message, Throwable ex) { |
|||
super(message, ex); |
|||
this.code = code.getCode(); |
|||
} |
|||
|
|||
public String getCode() { |
|||
return this.code; |
|||
} |
|||
} |
@ -0,0 +1,26 @@ |
|||
package org.example.redislimater.exception; |
|||
|
|||
/** |
|||
* 工具类异常 |
|||
* |
|||
* @author pangu |
|||
*/ |
|||
public class UtilException extends RuntimeException |
|||
{ |
|||
private static final long serialVersionUID = 8247610319171014183L; |
|||
|
|||
public UtilException(Throwable e) |
|||
{ |
|||
super(e.getMessage(), e); |
|||
} |
|||
|
|||
public UtilException(String message) |
|||
{ |
|||
super(message); |
|||
} |
|||
|
|||
public UtilException(String message, Throwable throwable) |
|||
{ |
|||
super(message, throwable); |
|||
} |
|||
} |
@ -0,0 +1,98 @@ |
|||
package org.example.redislimater.exception.base; |
|||
|
|||
|
|||
import org.example.redislimater.utils.MessageUtils; |
|||
import org.springframework.util.StringUtils; |
|||
|
|||
/** |
|||
* 基础异常 |
|||
* |
|||
* @author pangu |
|||
*/ |
|||
public class BaseException extends RuntimeException |
|||
{ |
|||
private static final long serialVersionUID = 1L; |
|||
|
|||
/** |
|||
* 所属模块 |
|||
*/ |
|||
private String module; |
|||
|
|||
/** |
|||
* 错误码 |
|||
*/ |
|||
private String code; |
|||
|
|||
/** |
|||
* 错误码对应的参数 |
|||
*/ |
|||
private Object[] args; |
|||
|
|||
/** |
|||
* 错误消息 |
|||
*/ |
|||
private String defaultMessage; |
|||
|
|||
public BaseException(String module, String code, Object[] args, String defaultMessage) |
|||
{ |
|||
this.module = module; |
|||
this.code = code; |
|||
this.args = args; |
|||
this.defaultMessage = defaultMessage; |
|||
} |
|||
|
|||
public BaseException(String module, String code, Object[] args) |
|||
{ |
|||
this(module, code, args, null); |
|||
} |
|||
|
|||
public BaseException(String module, String defaultMessage) |
|||
{ |
|||
this(module, null, null, defaultMessage); |
|||
} |
|||
|
|||
public BaseException(String code, Object[] args) |
|||
{ |
|||
this(null, code, args, null); |
|||
} |
|||
|
|||
public BaseException(String defaultMessage) |
|||
{ |
|||
this(null, null, null, defaultMessage); |
|||
} |
|||
|
|||
@Override |
|||
public String getMessage() |
|||
{ |
|||
String message = null; |
|||
if (!StringUtils.isEmpty(code)) |
|||
{ |
|||
message = MessageUtils.message(code, args); |
|||
} |
|||
if (message == null) |
|||
{ |
|||
message = defaultMessage; |
|||
} |
|||
return message; |
|||
} |
|||
|
|||
public String getModule() |
|||
{ |
|||
return module; |
|||
} |
|||
|
|||
public String getCode() |
|||
{ |
|||
return code; |
|||
} |
|||
|
|||
public Object[] getArgs() |
|||
{ |
|||
return args; |
|||
} |
|||
|
|||
public String getDefaultMessage() |
|||
{ |
|||
return defaultMessage; |
|||
} |
|||
} |
@ -0,0 +1,20 @@ |
|||
package org.example.redislimater.exception.file; |
|||
|
|||
|
|||
import org.example.redislimater.exception.base.BaseException; |
|||
|
|||
/** |
|||
* 文件信息异常类 |
|||
* |
|||
* @author pangu |
|||
*/ |
|||
public class FileException extends BaseException |
|||
{ |
|||
private static final long serialVersionUID = 1L; |
|||
|
|||
public FileException(String code, Object[] args) |
|||
{ |
|||
super("file", code, args, null); |
|||
} |
|||
|
|||
} |
@ -0,0 +1,16 @@ |
|||
package org.example.redislimater.exception.file; |
|||
|
|||
/** |
|||
* 文件名称超长限制异常类 |
|||
* |
|||
* @author pangu |
|||
*/ |
|||
public class FileNameLengthLimitExceededException extends FileException |
|||
{ |
|||
private static final long serialVersionUID = 1L; |
|||
|
|||
public FileNameLengthLimitExceededException(int defaultFileNameLength) |
|||
{ |
|||
super("upload.filename.exceed.length", new Object[] { defaultFileNameLength }); |
|||
} |
|||
} |
@ -0,0 +1,16 @@ |
|||
package org.example.redislimater.exception.file; |
|||
|
|||
/** |
|||
* 文件名大小限制异常类 |
|||
* |
|||
* @author pangu |
|||
*/ |
|||
public class FileSizeLimitExceededException extends FileException |
|||
{ |
|||
private static final long serialVersionUID = 1L; |
|||
|
|||
public FileSizeLimitExceededException(long defaultMaxSize) |
|||
{ |
|||
super("upload.exceed.maxSize", new Object[] { defaultMaxSize }); |
|||
} |
|||
} |
@ -0,0 +1,83 @@ |
|||
package org.example.redislimater.exception.file; |
|||
|
|||
|
|||
import org.apache.commons.fileupload.FileUploadException; |
|||
|
|||
import java.util.Arrays; |
|||
|
|||
/** |
|||
* 文件上传 误异常类 |
|||
* |
|||
* @author pangu |
|||
*/ |
|||
public class InvalidExtensionException extends FileUploadException |
|||
{ |
|||
private static final long serialVersionUID = 1L; |
|||
|
|||
private String[] allowedExtension; |
|||
private String extension; |
|||
private String filename; |
|||
|
|||
public InvalidExtensionException(String[] allowedExtension, String extension, String filename) |
|||
{ |
|||
super("filename : [" + filename + "], extension : [" + extension + "], allowed extension : [" + Arrays.toString(allowedExtension) + "]"); |
|||
this.allowedExtension = allowedExtension; |
|||
this.extension = extension; |
|||
this.filename = filename; |
|||
} |
|||
|
|||
public String[] getAllowedExtension() |
|||
{ |
|||
return allowedExtension; |
|||
} |
|||
|
|||
public String getExtension() |
|||
{ |
|||
return extension; |
|||
} |
|||
|
|||
public String getFilename() |
|||
{ |
|||
return filename; |
|||
} |
|||
|
|||
public static class InvalidImageExtensionException extends InvalidExtensionException |
|||
{ |
|||
private static final long serialVersionUID = 1L; |
|||
|
|||
public InvalidImageExtensionException(String[] allowedExtension, String extension, String filename) |
|||
{ |
|||
super(allowedExtension, extension, filename); |
|||
} |
|||
} |
|||
|
|||
public static class InvalidFlashExtensionException extends InvalidExtensionException |
|||
{ |
|||
private static final long serialVersionUID = 1L; |
|||
|
|||
public InvalidFlashExtensionException(String[] allowedExtension, String extension, String filename) |
|||
{ |
|||
super(allowedExtension, extension, filename); |
|||
} |
|||
} |
|||
|
|||
public static class InvalidMediaExtensionException extends InvalidExtensionException |
|||
{ |
|||
private static final long serialVersionUID = 1L; |
|||
|
|||
public InvalidMediaExtensionException(String[] allowedExtension, String extension, String filename) |
|||
{ |
|||
super(allowedExtension, extension, filename); |
|||
} |
|||
} |
|||
|
|||
public static class InvalidVideoExtensionException extends InvalidExtensionException |
|||
{ |
|||
private static final long serialVersionUID = 1L; |
|||
|
|||
public InvalidVideoExtensionException(String[] allowedExtension, String extension, String filename) |
|||
{ |
|||
super(allowedExtension, extension, filename); |
|||
} |
|||
} |
|||
} |
@ -0,0 +1,34 @@ |
|||
package org.example.redislimater.exception.job; |
|||
|
|||
/** |
|||
* 计划策略异常 |
|||
* |
|||
* @author pangu |
|||
*/ |
|||
public class TaskException extends Exception |
|||
{ |
|||
private static final long serialVersionUID = 1L; |
|||
|
|||
private Code code; |
|||
|
|||
public TaskException(String msg, Code code) |
|||
{ |
|||
this(msg, code, null); |
|||
} |
|||
|
|||
public TaskException(String msg, Code code, Exception nestedEx) |
|||
{ |
|||
super(msg, nestedEx); |
|||
this.code = code; |
|||
} |
|||
|
|||
public Code getCode() |
|||
{ |
|||
return code; |
|||
} |
|||
|
|||
public enum Code |
|||
{ |
|||
TASK_EXISTS, NO_TASK_EXISTS, TASK_ALREADY_STARTED, UNKNOWN, CONFIG_ERROR, TASK_NODE_NOT_AVAILABLE |
|||
} |
|||
} |
@ -0,0 +1,16 @@ |
|||
package org.example.redislimater.exception.user; |
|||
|
|||
/** |
|||
* 验证码错误异常类 |
|||
* |
|||
* @author pangu |
|||
*/ |
|||
public class CaptchaException extends UserException |
|||
{ |
|||
private static final long serialVersionUID = 1L; |
|||
|
|||
public CaptchaException() |
|||
{ |
|||
super("user.jcaptcha.error", null); |
|||
} |
|||
} |
@ -0,0 +1,16 @@ |
|||
package org.example.redislimater.exception.user; |
|||
|
|||
/** |
|||
* 角色锁定异常类 |
|||
* |
|||
* @author pangu |
|||
*/ |
|||
public class RoleBlockedException extends UserException |
|||
{ |
|||
private static final long serialVersionUID = 1L; |
|||
|
|||
public RoleBlockedException() |
|||
{ |
|||
super("role.blocked", null); |
|||
} |
|||
} |
@ -0,0 +1,16 @@ |
|||
package org.example.redislimater.exception.user; |
|||
|
|||
/** |
|||
* 用户锁定异常类 |
|||
* |
|||
* @author pangu |
|||
*/ |
|||
public class UserBlockedException extends UserException |
|||
{ |
|||
private static final long serialVersionUID = 1L; |
|||
|
|||
public UserBlockedException() |
|||
{ |
|||
super("user.blocked", null); |
|||
} |
|||
} |
@ -0,0 +1,16 @@ |
|||
package org.example.redislimater.exception.user; |
|||
|
|||
/** |
|||
* 用户账号已被删除 |
|||
* |
|||
* @author pangu |
|||
*/ |
|||
public class UserDeleteException extends UserException |
|||
{ |
|||
private static final long serialVersionUID = 1L; |
|||
|
|||
public UserDeleteException() |
|||
{ |
|||
super("user.password.delete", null); |
|||
} |
|||
} |
@ -0,0 +1,19 @@ |
|||
package org.example.redislimater.exception.user; |
|||
|
|||
|
|||
import org.example.redislimater.exception.base.BaseException; |
|||
|
|||
/** |
|||
* 用户信息异常类 |
|||
* |
|||
* @author pangu |
|||
*/ |
|||
public class UserException extends BaseException |
|||
{ |
|||
private static final long serialVersionUID = 1L; |
|||
|
|||
public UserException(String code, Object[] args) |
|||
{ |
|||
super("user", code, args, null); |
|||
} |
|||
} |
@ -0,0 +1,16 @@ |
|||
package org.example.redislimater.exception.user; |
|||
|
|||
/** |
|||
* 用户不存在异常类 |
|||
* |
|||
* @author pangu |
|||
*/ |
|||
public class UserNotExistsException extends UserException |
|||
{ |
|||
private static final long serialVersionUID = 1L; |
|||
|
|||
public UserNotExistsException() |
|||
{ |
|||
super("user.not.exists", null); |
|||
} |
|||
} |
@ -0,0 +1,16 @@ |
|||
package org.example.redislimater.exception.user; |
|||
|
|||
/** |
|||
* 用户密码不正确或不符合规范异常类 |
|||
* |
|||
* @author pangu |
|||
*/ |
|||
public class UserPasswordNotMatchException extends UserException |
|||
{ |
|||
private static final long serialVersionUID = 1L; |
|||
|
|||
public UserPasswordNotMatchException() |
|||
{ |
|||
super("user.password.not.match", null); |
|||
} |
|||
} |
@ -0,0 +1,16 @@ |
|||
package org.example.redislimater.exception.user; |
|||
|
|||
/** |
|||
* 用户错误记数异常类 |
|||
* |
|||
* @author pangu |
|||
*/ |
|||
public class UserPasswordRetryLimitCountException extends UserException |
|||
{ |
|||
private static final long serialVersionUID = 1L; |
|||
|
|||
public UserPasswordRetryLimitCountException(int retryLimitCount) |
|||
{ |
|||
super("user.password.retry.limit.count", new Object[] { retryLimitCount }); |
|||
} |
|||
} |
@ -0,0 +1,16 @@ |
|||
package org.example.redislimater.exception.user; |
|||
|
|||
/** |
|||
* 用户错误最大次数异常类 |
|||
* |
|||
* @author pangu |
|||
*/ |
|||
public class UserPasswordRetryLimitExceedException extends UserException |
|||
{ |
|||
private static final long serialVersionUID = 1L; |
|||
|
|||
public UserPasswordRetryLimitExceedException(int retryLimitCount) |
|||
{ |
|||
super("user.password.retry.limit.exceed", new Object[] { retryLimitCount }); |
|||
} |
|||
} |
@ -0,0 +1,88 @@ |
|||
package org.example.redislimater.utils; |
|||
|
|||
|
|||
import org.example.redislimater.StringUtils; |
|||
|
|||
import java.nio.charset.Charset; |
|||
import java.nio.charset.StandardCharsets; |
|||
|
|||
/** |
|||
* 字符集工具类 |
|||
* |
|||
* @author pangu |
|||
*/ |
|||
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) |
|||
{ |
|||
srcCharset = 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(); |
|||
} |
|||
} |
File diff suppressed because it is too large
@ -0,0 +1,63 @@ |
|||
/* |
|||
* Copyright (C), 2019-2020 dingyong |
|||
* FileName: ErrorCodeEnum |
|||
* Author: dingyong |
|||
* Date: 2020/12/7 |
|||
* Description: //描述
|
|||
* History: //修改记录
|
|||
* <author> <time> <version> <desc> |
|||
* 修改人姓名 修改时间 版本号 描述 |
|||
*/ |
|||
package org.example.redislimater.utils; |
|||
|
|||
/** |
|||
* @author dingyong |
|||
* @Description: TODO |
|||
* @Date 2020/12/7 |
|||
* @see [相关类/方法](可选) |
|||
* @since [产品/模块版本] (可选) |
|||
*/ |
|||
public enum ErrorCodeEnum { |
|||
SYSTOM_ERROR("100001","系统错误"), |
|||
|
|||
ERROR_200001("200001","接收数据失败"), |
|||
PARAM_ERROR("200002","参数不正确"), |
|||
|
|||
USER_NOT_EXIST("300001","用户不存在或者密码错误"), |
|||
USER_FORBID_ERROR("300003","账号已被禁用,请与管理员联系"), |
|||
|
|||
// 系统错误
|
|||
UNKNOWN("500","系统内部错误,请联系管理员"), |
|||
PATH_NOT_FOUND("404","路径不存在,请检查路径"), |
|||
NO_AUTH("403","没有权限,请联系管理员"), |
|||
DUPLICATE_KEY("501","数据库中已存在该记录"), |
|||
TOKEN_GENERATOR_ERROR("502","token生成失败"), |
|||
NO_UUID("503","uuid为空"), |
|||
SQL_ILLEGAL("504","sql非法"), |
|||
|
|||
//用户权限错误
|
|||
INVALID_TOKEN("1001","token不合法"), |
|||
|
|||
//七牛OSS错误
|
|||
OSS_CONFIG_ERROR("10050","七牛配置信息错误"), |
|||
OSS_UPLOAD_ERROR("10051","OSSBookNote上传失败"), |
|||
|
|||
; |
|||
|
|||
private String code; |
|||
private String value; |
|||
|
|||
|
|||
ErrorCodeEnum(String code, String value) { |
|||
this.code = code; |
|||
this.value = value; |
|||
} |
|||
|
|||
public String getCode() { |
|||
return this.code; |
|||
} |
|||
|
|||
public String getValue() { |
|||
return this.value; |
|||
} |
|||
} |
@ -0,0 +1,196 @@ |
|||
package org.example.redislimater.utils; |
|||
|
|||
import org.example.redislimater.StringUtils; |
|||
|
|||
import javax.servlet.http.HttpServletRequest; |
|||
import java.net.InetAddress; |
|||
import java.net.UnknownHostException; |
|||
|
|||
/** |
|||
* 获取IP方法 |
|||
* |
|||
* @author pangu |
|||
*/ |
|||
public class IpUtils |
|||
{ |
|||
public static String getIpAddr(HttpServletRequest request) |
|||
{ |
|||
if (request == null) |
|||
{ |
|||
return "unknown"; |
|||
} |
|||
String ip = request.getHeader("x-forwarded-for"); |
|||
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) |
|||
{ |
|||
ip = request.getHeader("Proxy-Client-IP"); |
|||
} |
|||
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) |
|||
{ |
|||
ip = request.getHeader("X-Forwarded-For"); |
|||
} |
|||
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) |
|||
{ |
|||
ip = request.getHeader("WL-Proxy-Client-IP"); |
|||
} |
|||
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) |
|||
{ |
|||
ip = request.getHeader("X-Real-IP"); |
|||
} |
|||
|
|||
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) |
|||
{ |
|||
ip = request.getRemoteAddr(); |
|||
} |
|||
|
|||
return "0:0:0:0:0:0:0:1".equals(ip) ? "127.0.0.1" : ip; |
|||
} |
|||
|
|||
public static boolean internalIp(String ip) |
|||
{ |
|||
byte[] addr = textToNumericFormatV4(ip); |
|||
return internalIp(addr) || "127.0.0.1".equals(ip); |
|||
} |
|||
|
|||
private static boolean internalIp(byte[] addr) |
|||
{ |
|||
if (StringUtils.isNull(addr) || addr.length < 2) |
|||
{ |
|||
return true; |
|||
} |
|||
final byte b0 = addr[0]; |
|||
final byte b1 = addr[1]; |
|||
// 10.x.x.x/8
|
|||
final byte SECTION_1 = 0x0A; |
|||
// 172.16.x.x/12
|
|||
final byte SECTION_2 = (byte) 0xAC; |
|||
final byte SECTION_3 = (byte) 0x10; |
|||
final byte SECTION_4 = (byte) 0x1F; |
|||
// 192.168.x.x/16
|
|||
final byte SECTION_5 = (byte) 0xC0; |
|||
final byte SECTION_6 = (byte) 0xA8; |
|||
switch (b0) |
|||
{ |
|||
case SECTION_1: |
|||
return true; |
|||
case SECTION_2: |
|||
if (b1 >= SECTION_3 && b1 <= SECTION_4) |
|||
{ |
|||
return true; |
|||
} |
|||
case SECTION_5: |
|||
switch (b1) |
|||
{ |
|||
case SECTION_6: |
|||
return true; |
|||
} |
|||
default: |
|||
return false; |
|||
} |
|||
} |
|||
|
|||
/** |
|||
* 将IPv4地址转换成字节 |
|||
* |
|||
* @param text IPv4地址 |
|||
* @return byte 字节 |
|||
*/ |
|||
public static byte[] textToNumericFormatV4(String text) |
|||
{ |
|||
if (text.length() == 0) |
|||
{ |
|||
return null; |
|||
} |
|||
|
|||
byte[] bytes = new byte[4]; |
|||
String[] elements = text.split("\\.", -1); |
|||
try |
|||
{ |
|||
long l; |
|||
int i; |
|||
switch (elements.length) |
|||
{ |
|||
case 1: |
|||
l = Long.parseLong(elements[0]); |
|||
if ((l < 0L) || (l > 4294967295L)) { |
|||
return null; |
|||
} |
|||
bytes[0] = (byte) (int) (l >> 24 & 0xFF); |
|||
bytes[1] = (byte) (int) ((l & 0xFFFFFF) >> 16 & 0xFF); |
|||
bytes[2] = (byte) (int) ((l & 0xFFFF) >> 8 & 0xFF); |
|||
bytes[3] = (byte) (int) (l & 0xFF); |
|||
break; |
|||
case 2: |
|||
l = Integer.parseInt(elements[0]); |
|||
if ((l < 0L) || (l > 255L)) { |
|||
return null; |
|||
} |
|||
bytes[0] = (byte) (int) (l & 0xFF); |
|||
l = Integer.parseInt(elements[1]); |
|||
if ((l < 0L) || (l > 16777215L)) { |
|||
return null; |
|||
} |
|||
bytes[1] = (byte) (int) (l >> 16 & 0xFF); |
|||
bytes[2] = (byte) (int) ((l & 0xFFFF) >> 8 & 0xFF); |
|||
bytes[3] = (byte) (int) (l & 0xFF); |
|||
break; |
|||
case 3: |
|||
for (i = 0; i < 2; ++i) |
|||
{ |
|||
l = Integer.parseInt(elements[i]); |
|||
if ((l < 0L) || (l > 255L)) { |
|||
return null; |
|||
} |
|||
bytes[i] = (byte) (int) (l & 0xFF); |
|||
} |
|||
l = Integer.parseInt(elements[2]); |
|||
if ((l < 0L) || (l > 65535L)) { |
|||
return null; |
|||
} |
|||
bytes[2] = (byte) (int) (l >> 8 & 0xFF); |
|||
bytes[3] = (byte) (int) (l & 0xFF); |
|||
break; |
|||
case 4: |
|||
for (i = 0; i < 4; ++i) |
|||
{ |
|||
l = Integer.parseInt(elements[i]); |
|||
if ((l < 0L) || (l > 255L)) { |
|||
return null; |
|||
} |
|||
bytes[i] = (byte) (int) (l & 0xFF); |
|||
} |
|||
break; |
|||
default: |
|||
return null; |
|||
} |
|||
} |
|||
catch (NumberFormatException e) |
|||
{ |
|||
return null; |
|||
} |
|||
return bytes; |
|||
} |
|||
|
|||
public static String getHostIp() |
|||
{ |
|||
try |
|||
{ |
|||
return InetAddress.getLocalHost().getHostAddress(); |
|||
} |
|||
catch (UnknownHostException e) |
|||
{ |
|||
} |
|||
return "127.0.0.1"; |
|||
} |
|||
|
|||
public static String getHostName() |
|||
{ |
|||
try |
|||
{ |
|||
return InetAddress.getLocalHost().getHostName(); |
|||
} |
|||
catch (UnknownHostException e) |
|||
{ |
|||
} |
|||
return "未知"; |
|||
} |
|||
} |
@ -0,0 +1,27 @@ |
|||
package org.example.redislimater.utils; |
|||
|
|||
|
|||
import org.example.redislimater.utils.spring.SpringUtils; |
|||
import org.springframework.context.MessageSource; |
|||
import org.springframework.context.i18n.LocaleContextHolder; |
|||
|
|||
/** |
|||
* 获取i18n资源文件 |
|||
* |
|||
* @author pangu |
|||
*/ |
|||
public class MessageUtils |
|||
{ |
|||
/** |
|||
* 根据消息键和参数 获取消息 委托给spring messageSource |
|||
* |
|||
* @param code 消息键 |
|||
* @param args 参数 |
|||
* @return 获取国际化翻译值 |
|||
*/ |
|||
public static String message(String code, Object... args) |
|||
{ |
|||
MessageSource messageSource = SpringUtils.getBean(MessageSource.class); |
|||
return messageSource.getMessage(code, args, LocaleContextHolder.getLocale()); |
|||
} |
|||
} |
@ -0,0 +1,44 @@ |
|||
/* |
|||
* Copyright (C), 2019-2020 dingyong |
|||
* FileName: Recode |
|||
* Author: dingyong |
|||
* Date: 2020/12/5 |
|||
* Description: //描述
|
|||
* History: //修改记录
|
|||
* <author> <time> <version> <desc> |
|||
* 修改人姓名 修改时间 版本号 描述 |
|||
*/ |
|||
package org.example.redislimater.utils; |
|||
|
|||
/** |
|||
* @author dingyong |
|||
* @Description: TODO |
|||
* @Date 2020/12/5 |
|||
* @see [相关类/方法](可选) |
|||
* @since [产品/模块版本] (可选) |
|||
*/ |
|||
public enum Recode { |
|||
SUCCESS(200,"成功"), |
|||
FAILUR(500,"失败"), |
|||
EMPTY(600,"空"), |
|||
LIMIT_ERROR(100001,"err:100001 访问失败!超过访问限制!"), |
|||
IP_ERROR(100002,"err:100002 IP为空 非法操作"), |
|||
PARAM_ERROR(100004,"err:100004 参数错误"), |
|||
CHOU_JIANG_LIMIT(100003,"抽奖次数不够"),; |
|||
|
|||
private Integer code; |
|||
private String desc; |
|||
|
|||
Recode(Integer code, String desc) { |
|||
this.code = code; |
|||
this.desc = desc; |
|||
} |
|||
|
|||
public Integer getCode() { |
|||
return code; |
|||
} |
|||
|
|||
public String getDesc() { |
|||
return desc; |
|||
} |
|||
} |
@ -0,0 +1,93 @@ |
|||
package org.example.redislimater.utils; |
|||
|
|||
|
|||
import org.example.redislimater.StringUtils; |
|||
|
|||
/** |
|||
* 字符串格式化 |
|||
* |
|||
* @author pangu |
|||
*/ |
|||
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,146 @@ |
|||
package org.example.redislimater.utils.spring; |
|||
|
|||
import org.example.redislimater.StringUtils; |
|||
import org.springframework.aop.framework.AopContext; |
|||
import org.springframework.beans.BeansException; |
|||
import org.springframework.beans.factory.NoSuchBeanDefinitionException; |
|||
import org.springframework.beans.factory.config.BeanFactoryPostProcessor; |
|||
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; |
|||
import org.springframework.context.ApplicationContext; |
|||
import org.springframework.context.ApplicationContextAware; |
|||
import org.springframework.stereotype.Component; |
|||
|
|||
/** |
|||
* spring工具类 方便在非spring管理环境中获取bean |
|||
* |
|||
* @author pangu |
|||
*/ |
|||
@Component |
|||
public final class SpringUtils implements BeanFactoryPostProcessor, ApplicationContextAware |
|||
{ |
|||
/** Spring应用上下文环境 */ |
|||
private static ConfigurableListableBeanFactory beanFactory; |
|||
|
|||
private static ApplicationContext applicationContext; |
|||
|
|||
@Override |
|||
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException |
|||
{ |
|||
SpringUtils.beanFactory = beanFactory; |
|||
} |
|||
|
|||
@Override |
|||
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException |
|||
{ |
|||
SpringUtils.applicationContext = applicationContext; |
|||
} |
|||
|
|||
/** |
|||
* 获取对象 |
|||
* |
|||
* @param name |
|||
* @return Object 一个以所给名字注册的bean的实例 |
|||
* @throws BeansException |
|||
* |
|||
*/ |
|||
@SuppressWarnings("unchecked") |
|||
public static <T> T getBean(String name) throws BeansException |
|||
{ |
|||
return (T) beanFactory.getBean(name); |
|||
} |
|||
|
|||
/** |
|||
* 获取类型为requiredType的对象 |
|||
* |
|||
* @param clz |
|||
* @return |
|||
* @throws BeansException |
|||
* |
|||
*/ |
|||
public static <T> T getBean(Class<T> clz) throws BeansException |
|||
{ |
|||
T result = (T) beanFactory.getBean(clz); |
|||
return result; |
|||
} |
|||
|
|||
/** |
|||
* 如果BeanFactory包含一个与所给名称匹配的bean定义,则返回true |
|||
* |
|||
* @param name |
|||
* @return boolean |
|||
*/ |
|||
public static boolean containsBean(String name) |
|||
{ |
|||
return beanFactory.containsBean(name); |
|||
} |
|||
|
|||
/** |
|||
* 判断以给定名字注册的bean定义是一个singleton还是一个prototype。 如果与给定名字相应的bean定义没有被找到,将会抛出一个异常(NoSuchBeanDefinitionException) |
|||
* |
|||
* @param name |
|||
* @return boolean |
|||
* @throws NoSuchBeanDefinitionException |
|||
* |
|||
*/ |
|||
public static boolean isSingleton(String name) throws NoSuchBeanDefinitionException |
|||
{ |
|||
return beanFactory.isSingleton(name); |
|||
} |
|||
|
|||
/** |
|||
* @param name |
|||
* @return Class 注册对象的类型 |
|||
* @throws NoSuchBeanDefinitionException |
|||
* |
|||
*/ |
|||
public static Class<?> getType(String name) throws NoSuchBeanDefinitionException |
|||
{ |
|||
return beanFactory.getType(name); |
|||
} |
|||
|
|||
/** |
|||
* 如果给定的bean名字在bean定义中有别名,则返回这些别名 |
|||
* |
|||
* @param name |
|||
* @return |
|||
* @throws NoSuchBeanDefinitionException |
|||
* |
|||
*/ |
|||
public static String[] getAliases(String name) throws NoSuchBeanDefinitionException |
|||
{ |
|||
return beanFactory.getAliases(name); |
|||
} |
|||
|
|||
/** |
|||
* 获取aop代理对象 |
|||
* |
|||
* @param invoker |
|||
* @return |
|||
*/ |
|||
@SuppressWarnings("unchecked") |
|||
public static <T> T getAopProxy(T invoker) |
|||
{ |
|||
return (T) AopContext.currentProxy(); |
|||
} |
|||
|
|||
/** |
|||
* 获取当前的环境配置,无配置返回null |
|||
* |
|||
* @return 当前的环境配置 |
|||
*/ |
|||
public static String[] getActiveProfiles() |
|||
{ |
|||
return applicationContext.getEnvironment().getActiveProfiles(); |
|||
} |
|||
|
|||
/** |
|||
* 获取当前的环境配置,当有多个环境配置时,只获取第一个 |
|||
* |
|||
* @return 当前的环境配置 |
|||
*/ |
|||
public static String getActiveProfile() |
|||
{ |
|||
final String[] activeProfiles = getActiveProfiles(); |
|||
return StringUtils.isNotEmpty(activeProfiles) ? activeProfiles[0] : null; |
|||
} |
|||
} |
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -0,0 +1,5 @@ |
|||
#Generated by Maven |
|||
#Wed Dec 21 00:45:43 CST 2022 |
|||
version=1.0-SNAPSHOT |
|||
groupId=org.example |
|||
artifactId=demodump |
@ -0,0 +1,47 @@ |
|||
org\example\redislimater\exception\ApiCallException.class |
|||
org\example\redislimater\exception\user\UserBlockedException.class |
|||
org\example\redislimater\exception\user\CaptchaException.class |
|||
org\example\redislimater\utils\spring\SpringUtils.class |
|||
org\example\redislimater\exception\file\FileSizeLimitExceededException.class |
|||
org\example\redislimater\exception\file\InvalidExtensionException$InvalidMediaExtensionException.class |
|||
org\example\redislimater\exception\user\UserPasswordRetryLimitExceedException.class |
|||
org\example\redislimater\StringUtils.class |
|||
org\example\redislimater\utils\MessageUtils.class |
|||
org\example\redislimater\exception\user\UserDeleteException.class |
|||
org\example\redislimater\exception\file\InvalidExtensionException$InvalidFlashExtensionException.class |
|||
org\example\redislimater\exception\user\RoleBlockedException.class |
|||
org\example\redislimater\RedisUtils.class |
|||
org\example\redislimater\exception\job\TaskException.class |
|||
org\example\redislimater\exception\PGException.class |
|||
org\example\redislimater\exception\file\InvalidExtensionException$InvalidVideoExtensionException.class |
|||
org\example\redislimater\exception\ServiceException.class |
|||
org\example\function\VUtils.class |
|||
org\example\function\PresentOrElseHandler.class |
|||
org\example\redislimater\utils\IpUtils.class |
|||
org\example\redislimater\ApiCallAdvice.class |
|||
org\example\redislimater\exception\base\BaseException.class |
|||
org\example\redislimater\ApiCall.class |
|||
org\example\redislimater\utils\ErrorCodeEnum.class |
|||
org\example\strategy\Program.class |
|||
org\example\function\BranchHandle.class |
|||
org\example\redislimater\exception\DemoModeException.class |
|||
org\example\redislimater\exception\user\UserPasswordNotMatchException.class |
|||
org\example\redislimater\utils\Convert.class |
|||
org\example\redislimater\exception\file\InvalidExtensionException$InvalidImageExtensionException.class |
|||
org\example\redislimater\exception\user\UserPasswordRetryLimitCountException.class |
|||
org\example\redislimater\exception\user\UserException.class |
|||
org\example\strategy\IDEA.class |
|||
org\example\redislimater\exception\user\UserNotExistsException.class |
|||
org\example\strategy\Programmer.class |
|||
org\example\redislimater\utils\CharsetKit.class |
|||
org\example\redislimater\exception\BusinessException.class |
|||
org\example\redislimater\exception\file\FileException.class |
|||
org\example\redislimater\exception\file\InvalidExtensionException.class |
|||
org\example\redislimater\utils\StrFormatter.class |
|||
org\example\function\ThrowExceptionFunction.class |
|||
org\example\redislimater\exception\job\TaskException$Code.class |
|||
org\example\redislimater\exception\UtilException.class |
|||
org\example\strategy\Eclipse.class |
|||
org\example\redislimater\exception\file\FileNameLengthLimitExceededException.class |
|||
org\example\redislimater\controller\TestController.class |
|||
org\example\redislimater\utils\Recode.class |
@ -0,0 +1,42 @@ |
|||
D:\demodump\src\main\java\org\example\function\BranchHandle.java |
|||
D:\demodump\src\main\java\org\example\redislimater\exception\user\CaptchaException.java |
|||
D:\demodump\src\main\java\org\example\redislimater\utils\IpUtils.java |
|||
D:\demodump\src\main\java\org\example\redislimater\utils\MessageUtils.java |
|||
D:\demodump\src\main\java\org\example\redislimater\exception\ServiceException.java |
|||
D:\demodump\src\main\java\org\example\function\VUtils.java |
|||
D:\demodump\src\main\java\org\example\redislimater\exception\user\UserDeleteException.java |
|||
D:\demodump\src\main\java\org\example\redislimater\exception\UtilException.java |
|||
D:\demodump\src\main\java\org\example\redislimater\exception\job\TaskException.java |
|||
D:\demodump\src\main\java\org\example\redislimater\exception\ApiCallException.java |
|||
D:\demodump\src\main\java\org\example\redislimater\exception\BusinessException.java |
|||
D:\demodump\src\main\java\org\example\redislimater\exception\user\RoleBlockedException.java |
|||
D:\demodump\src\main\java\org\example\redislimater\exception\file\FileException.java |
|||
D:\demodump\src\main\java\org\example\redislimater\utils\CharsetKit.java |
|||
D:\demodump\src\main\java\org\example\redislimater\exception\PGException.java |
|||
D:\demodump\src\main\java\org\example\redislimater\exception\user\UserPasswordRetryLimitCountException.java |
|||
D:\demodump\src\main\java\org\example\redislimater\exception\base\BaseException.java |
|||
D:\demodump\src\main\java\org\example\redislimater\exception\user\UserPasswordNotMatchException.java |
|||
D:\demodump\src\main\java\org\example\redislimater\exception\user\UserBlockedException.java |
|||
D:\demodump\src\main\java\org\example\redislimater\StringUtils.java |
|||
D:\demodump\src\main\java\org\example\redislimater\utils\Convert.java |
|||
D:\demodump\src\main\java\org\example\redislimater\ApiCallAdvice.java |
|||
D:\demodump\src\main\java\org\example\redislimater\utils\spring\SpringUtils.java |
|||
D:\demodump\src\main\java\org\example\strategy\Eclipse.java |
|||
D:\demodump\src\main\java\org\example\redislimater\exception\file\FileNameLengthLimitExceededException.java |
|||
D:\demodump\src\main\java\org\example\redislimater\exception\file\InvalidExtensionException.java |
|||
D:\demodump\src\main\java\org\example\redislimater\utils\Recode.java |
|||
D:\demodump\src\main\java\org\example\strategy\Program.java |
|||
D:\demodump\src\main\java\org\example\redislimater\exception\DemoModeException.java |
|||
D:\demodump\src\main\java\org\example\redislimater\RedisUtils.java |
|||
D:\demodump\src\main\java\org\example\redislimater\utils\StrFormatter.java |
|||
D:\demodump\src\main\java\org\example\redislimater\ApiCall.java |
|||
D:\demodump\src\main\java\org\example\redislimater\controller\TestController.java |
|||
D:\demodump\src\main\java\org\example\redislimater\exception\user\UserPasswordRetryLimitExceedException.java |
|||
D:\demodump\src\main\java\org\example\redislimater\exception\user\UserNotExistsException.java |
|||
D:\demodump\src\main\java\org\example\redislimater\exception\user\UserException.java |
|||
D:\demodump\src\main\java\org\example\strategy\IDEA.java |
|||
D:\demodump\src\main\java\org\example\function\ThrowExceptionFunction.java |
|||
D:\demodump\src\main\java\org\example\function\PresentOrElseHandler.java |
|||
D:\demodump\src\main\java\org\example\strategy\Programmer.java |
|||
D:\demodump\src\main\java\org\example\redislimater\exception\file\FileSizeLimitExceededException.java |
|||
D:\demodump\src\main\java\org\example\redislimater\utils\ErrorCodeEnum.java |
@ -0,0 +1 @@ |
|||
org\example\Test.class |
@ -0,0 +1 @@ |
|||
D:\demodump\src\test\java\org\example\Test.java |
Binary file not shown.
Loading…
Reference in new issue