use of com.terran4j.commons.util.error.BusinessException in project commons by terran4j.
the class AsymmetricKeys method decrypt.
/**
* 用私钥解密
* @param cipherText 密文
* @return 明文
* @throws BusinessException 解密过程中的异常信息
*/
public String decrypt(String cipherText) throws BusinessException {
try {
byte[] data = Strings.fromHexString(cipherText);
byte[] decryptedData = decrypt(data);
String result = new String(decryptedData, Encoding.UTF8.getName());
return result;
} catch (Exception e) {
throw new BusinessException(CommonErrorCode.INVALID_PARAM, e).put("cipherText", cipherText).setMessage("非法的密文");
}
}
use of com.terran4j.commons.util.error.BusinessException in project commons by terran4j.
the class AsymmetricKeys method initCipher.
private Cipher initCipher(RSAPublicKey publicKey) throws BusinessException {
try {
Cipher cipher = Cipher.getInstance(ALGORITHM_RSA, new BouncyCastleProvider());
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
return cipher;
} catch (NoSuchAlgorithmException e) {
throw new BusinessException(CommonErrorCode.INTERNAL_ERROR, e).put("algorithm", ALGORITHM_RSA).setMessage("No Such Algorithm: ${algorithm}");
} catch (NoSuchPaddingException e) {
throw new BusinessException(CommonErrorCode.INTERNAL_ERROR, e).setMessage("No Such Padding");
} catch (InvalidKeyException e) {
throw new BusinessException(CommonErrorCode.INTERNAL_ERROR, e).setMessage("加密公私非法,请检查");
}
}
use of com.terran4j.commons.util.error.BusinessException in project commons by terran4j.
the class DSchedulingAspect method doDistributedScheduling.
@Around("distributedScheduling()")
public Object doDistributedScheduling(ProceedingJoinPoint point) throws Throwable {
// JobExeInfo 用于记录任务信息。
JobExeInfo jobExeInfo = new JobExeInfo();
long beginTime = System.currentTimeMillis();
jobExeInfo.setBeginTime(beginTime);
jobExeInfo.setInstanceId(instanceId);
Object targetObject = point.getTarget();
Class<?> targetClass = Classes.getTargetClass(targetObject);
String className = targetClass.getName();
String methodName = point.getSignature().getName();
jobExeInfo.setClassName(className);
jobExeInfo.setMethodName(methodName);
final Logger log = LoggerFactory.getLogger(targetClass);
// 只有用 @DScheduling 修饰的方法,才会使用并发控制。
Object[] args = point.getArgs();
Method method = Classes.getMethod(targetClass, methodName, args, DScheduling.class);
if (method == null) {
log.error("method not found, className = {}, methodName = {}", className, methodName);
return point.proceed(args);
}
DScheduling distributedScheduling = method.getAnnotation(DScheduling.class);
if (distributedScheduling == null) {
log.error("@DistributedScheduling not found, className = {}, methodName = {}", className, methodName);
return point.proceed(args);
}
// 还得要 @Scheduled 修饰。
Scheduled scheduled = method.getAnnotation(Scheduled.class);
if (scheduled == null) {
String msg = String.format("${className}.${methodName}方法" + "上有 %s 注解但没有 %s 注解。", DScheduling.class, Scheduled.class);
throw new BusinessException(ErrorCodes.INTERNAL_ERROR).put("className", className).put("methodName", methodName).setMessage(msg);
}
// 被加上 Scheduled 注解的方法,都是没有参数的,
// 因此可以用“类名 + 方法名”唯一标识一个任务。
// 但是“类名 + 方法名”很长,有的类是动态类,类名不一定一样,
// 应用方需要自己设置distributedScheduling 的唯一标识。
String value = distributedScheduling.value();
checkValue(value, method);
if (log.isInfoEnabled()) {
log.info("start to DistributedScheduling '{}' at: {}", value, DateTimes.toString(new Date()));
}
// 尝试从 redis 中获取分布式锁,如果没有获取到锁,就不执行本次调度。
String jobInfoKey = "hedis.schedule.jobInfo-" + value;
String lockKey = "hedis.schedule.lock-" + value;
long lockExpired = distributedScheduling.lockExpiredSecond() * 1000;
// 任务信息保存时间要比锁长,目前设置为 2 倍。
long jobInfoExpired = lockExpired * 2;
boolean locked = cacheService.setObjectIfAbsent(lockKey, instanceId, lockExpired);
if (!locked) {
// 没有取到锁,不执行任务。
if (log.isInfoEnabled()) {
JobExeInfo lastInfo = cacheService.getObject(jobInfoKey, JobExeInfo.class);
log.info("job is executing by other instance, lastInfo:\n{}", lastInfo);
}
return null;
} else {
if (log.isInfoEnabled()) {
log.info("get the lock by instance: {}", instanceId);
}
}
// 查看上次的执行时间,如果没到这次的执行时间,也应该避免。
JobExeInfo lastInfo = cacheService.getObject(jobInfoKey, JobExeInfo.class);
if (lastInfo != null) {
if (!isValidTime(lastInfo, scheduled, distributedScheduling, log)) {
if (log.isInfoEnabled()) {
log.info("job is executed by other instance, but next " + "executing not coming, lastInfo: \n{}", lastInfo);
}
// 释放锁。
cacheService.remove(lockKey);
return null;
}
}
Object result = null;
try {
if (log.isInfoEnabled()) {
log.info("now begin to executing the job.");
}
// 执行任务之前,先写入任务的执行信息。
jobExeInfo.setRunning(true);
cacheService.setObject(jobInfoKey, jobExeInfo, jobInfoExpired);
// 真正执行任务。
result = point.proceed(args);
if (log.isInfoEnabled()) {
log.info("execute job done, args: {}, result: {}", args, result);
}
jobExeInfo.setResultCode("SUCCESS");
if (log.isInfoEnabled()) {
log.info("executing the job done.");
}
} catch (BusinessException e) {
jobExeInfo.setResultCode(e.getErrorCode().getName());
jobExeInfo.setMessage(e.getMessage());
if (log.isInfoEnabled()) {
log.info("executing the job error: {}", e.getMessage());
}
} catch (Throwable e) {
jobExeInfo.setResultCode(ErrorCodes.UNKNOWN_ERROR);
jobExeInfo.setMessage(e.getMessage());
if (log.isInfoEnabled()) {
log.info("executing the job error: {}", e.getMessage());
}
} finally {
// 保存本次任务的执行信息。
long endTime = System.currentTimeMillis();
jobExeInfo.setEndTime(endTime);
jobExeInfo.setRunning(false);
cacheService.setObject(jobInfoKey, jobExeInfo, jobInfoExpired);
if (log.isInfoEnabled()) {
log.info("done DScheduling, jobExeInfo:\n{}", jobExeInfo);
}
// 释放锁。
cacheService.remove(lockKey);
}
if (log.isInfoEnabled()) {
log.info("end of DistributedScheduling '{}' at: {}", value, DateTimes.toString(new Date()));
}
return result;
}
use of com.terran4j.commons.util.error.BusinessException in project commons by terran4j.
the class DSchedulingAspect method checkValue.
void checkValue(String value, Method method) throws BusinessException {
if (method == null) {
throw new NullPointerException("method is null.");
}
if (StringUtils.isEmpty(value)) {
throw new BusinessException(ErrorCodes.INTERNAL_ERROR).put("value", value).put("className", method.getDeclaringClass().getName()).put("methodName", method.getName()).setMessage("@DistributedScheduling value can't be empty.");
}
boolean isDuplicate = false;
Method existedMethod = methods.get(value);
if (existedMethod == null) {
synchronized (this) {
existedMethod = methods.get(value);
if (existedMethod != null && existedMethod != method) {
isDuplicate = true;
} else if (existedMethod == null) {
methods.put(value, method);
}
}
} else if (isDuplicate || !existedMethod.equals(method)) {
String msg = "@DistributedScheduling(\"${value}\") is duplicated with another.";
throw new BusinessException(ErrorCodes.INTERNAL_ERROR).put("value", value).put("className", method.getDeclaringClass().getName()).put("methodName", method.getName()).put("existedClassName", existedMethod.getDeclaringClass().getName()).put("existedMethodName", existedMethod.getName()).setMessage(msg);
}
}
use of com.terran4j.commons.util.error.BusinessException in project commons by terran4j.
the class DSynchronizedAspect method doGetLockKey.
static String doGetLockKey(String keyEL, Object target, Method method, Object[] args) throws BusinessException {
String lockKey = null;
if (StringUtils.isEmpty(keyEL)) {
lockKey = Classes.toIdentify(method);
} else {
String[] params = getNamesByAnno(method);
Expression expression = getExpression(keyEL);
EvaluationContext context = new StandardEvaluationContext();
context.setVariable("target", target);
int length = params.length;
if (length > 0) {
for (int i = 0; i < length; i++) {
String key = params[i];
Object value = args[i];
if (StringUtils.isEmpty(key) || value == null) {
continue;
}
context.setVariable(key, value);
DSynchArgs.set(key, value);
}
}
lockKey = expression.getValue(context, String.class);
if (StringUtils.isEmpty(lockKey)) {
throw new BusinessException(ErrorCodes.CONFIG_ERROR).put("keyEL", keyEL).put("keyValue", lockKey).setMessage("@DSynchronized中定义锁表达式为空。");
}
}
return lockKey;
}
Aggregations