Quartz自动化配置定时任务
在业务中,我们经常需要编写定时任务,通过每个周期来定时统计一些聚合类信息,比如银行类业务实现每天日终实现对账、生成统计报表等等,这些非实时计算的任务都可以放在系统非繁忙时段来执行。今天我们来使用Quartz来实现可配置的定时任务,把cron表达式配置到数据库中,这样可以在页面上动态修改。
1.引入 jar包依赖
org.springframework.boot
spring-boot-starter-quartz
commons-io
commons-io
2.6
org.apache.commons
commons-lang3
commons-lang
commons-lang
2.4
2.定义实体类
/**
* 定时任务调度日志表
*/
@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
public class QuartzJobLog implements Serializable {
/** 主键 **/
private String id;
/** 任务名称 **/
private String jobName;
/** 任务组名 **/
private String jobGroup;
/** 调用目标字符串 **/
private String invokeTarget;
/** 日志信息 **/
private String jobMessage;
/** 执行状态(0正常 1失败) **/
private Integer status;
/** 异常信息 **/
private String exceptionInfo;
/** 开始时间 **/
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone="GMT+8")
private Date startTime;
/** 结束时间 **/
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone="GMT+8")
private Date endTime;
}
/**
* 定时任务调度表,可以和数据库表结构对应
*/
@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
public class QuartzJob implements Serializable {
//任务id
private String id;
//任务名称
private String jobName;
//任务组名
private String jobGroup;
// 调用目标字符串
private String invokeTarget;
// cron执行表达式
private String cronExpression;
//cron 计划策略
private String misfirePolicy;
// 是否并发执行 (0 允许 1 禁止)
private String concurrent;
// 任务状态 (0 正常 1 暂停)
private Integer status;
}
2.定义常量类
/**
* 任务调度通用常量
*/
public class ScheduleConstants {
public static final String TASK_CLASS_NAME = "TASK_CLASS_NAME";
//执行目标key
public static final String TASK_PROPERTIES = "TASK_PROPERTIES";
// 默认
public static final Integer MISFIRE_DEFAULT = 0;
// 立即触发执行
public static final Integer MISFIRE_IGNORE_MISFIRES = 1;
// 触发一次执行
public static final Integer MISFIRE_FIRE_AND_PROCEED = 2;
// 不触发理解执行
public static final Integer MISFIRE_DO_NOTHING = 3;
//失败状态
public static final Integer FAIL_STATUS = 1;
// 成功状态
public static final Integer SUCCESS_STATUS = 0;
// 任务的关闭的状态
public static final Integer STOP_STATUS = 2;
public enum Status
{
// 正常
NORMAL(0),
// 暂停
PAUSE(1);
private Integer value;
private Status(Integer value)
{
this.value = value;
}
public Integer getValue()
{
return value;
}
}
}
3.定义抽象任务类
public abstract class AbstractQuartzJob implements Job {
private static final Logger log = LoggerFactory.getLogger(AbstractQuartzJob.class);
//线程本地变量
private static ThreadLocal threadLocal = new ThreadLocal<>();
@Override
public void execute(JobExecutionContext context) throws JobExecutionException {
QuartzJob quartzJob = new QuartzJob();
BeanUtils.copyProperties(context.getMergedJobDataMap().get(ScheduleConstants.TASK_PROPERTIES),quartzJob);
try{
before(context,quartzJob);
if(quartzJob != null) {
doExecute(context,quartzJob);
}
after(context,quartzJob,null);
}catch (Exception e) {
log.error("任务执行异常 - : ",e);
after(context,quartzJob,e);
}
}
// 子类去实现,模板方法模式
public abstract void doExecute(JobExecutionContext context, QuartzJob quartzJob) throws Exception;
/**
* 执行前
* @param context 工作执行上下文对象
* @param quartzJob 系统计划任务
*/
private void before(JobExecutionContext context, QuartzJob quartzJob) {
threadLocal.set(new Date());
}
/**
* 执行后
* @param context 工作执行上下文对象
* @param quartzJob 系统计划任务
* @param e
*/
private void after(JobExecutionContext context, QuartzJob quartzJob, Exception e) {
Date startTime = threadLocal.get();
threadLocal.remove();
final QuartzJobLog jobLog = new QuartzJobLog();
jobLog.setJobName(quartzJob.getJobName());
jobLog.setJobGroup(quartzJob.getJobGroup());
jobLog.setInvokeTarget(quartzJob.getInvokeTarget());
jobLog.setStartTime(startTime);
jobLog.setEndTime(new Date());
long runMs = jobLog.getEndTime().getTime() - jobLog.getStartTime().getTime();
jobLog.setJobMessage(jobLog.getJobName() + " 总共耗时:" + runMs + "毫秒");
if (e != null)
{
jobLog.setStatus(ScheduleConstants.FAIL_STATUS);
String errorMsg = StringUtils.substring(ExceptionUtil.getMessage(e), 0, 2000);
jobLog.setExceptionInfo(errorMsg);
}
else
{
jobLog.setStatus(ScheduleConstants.SUCCESS_STATUS);
}
// 这里获取service然后插入库中
// SpringUtils.getBean(QuartzJobLogService.class).insertSelective(sysJobLog);
}
}
4. 定义反射工具类来执行目标任务
/**
* 任务执行工具
*/
@Slf4j
public class JobInvokeUtil {
/**
* 执行方法
* @param quartzJob 系统任务
*/
public static void invokeMethod(QuartzJob quartzJob) throws Exception {
String invokeTarget = quartzJob.getInvokeTarget();
String beanName = getBeanName(invokeTarget);
String methodName = getMethodName(invokeTarget);
List
5.定义配置类
/**
* Quartz配置类
*/
@Configuration
public class QuartzConfig {
@Bean
public Scheduler scheduler() throws SchedulerException {
SchedulerFactory schedulerFactoryBean = new StdSchedulerFactory();
return schedulerFactoryBean.getScheduler();
}
}
6.定义任务实现类
/**
* 定时任务处理(禁止并发执行)
*/
@DisallowConcurrentExecution
public class QuartzDisallowConcurrentExecution extends AbstractQuartzJob {
@Override
public void doExecute(JobExecutionContext context, QuartzJob quartzJob) throws Exception {
JobInvokeUtil.invokeMethod(quartzJob);
}
}
/**
* 定时任务处理(允许并发执行)
*/
public class QuartzJobExecution extends AbstractQuartzJob {
@Override
public void doExecute(JobExecutionContext context, QuartzJob quartzJob) throws Exception {
JobInvokeUtil.invokeMethod(quartzJob);
}
}
7. 定义任务工具接口类
/**
* Quartz配置类
*/
@Configuration
@Slf4j
public class QuartzSchedulerUtil {
@Autowired
private Scheduler scheduler;
//可以放在配置文件中
// cron表达式一分钟执行一次
private final String TEST_CRON = "0 0/1 * * * ?";
/**
* 容器初始化时执行此方法
* 也就是类初始化的时候
*/
@PostConstruct
public void init() {
// 查询数据库所有的(可以按照条件) 调度器
List quartzJobs = new ArrayList<>();
QuartzJob quartzJob1 = new QuartzJob();
quartzJob1.setId("332182389491109888");
quartzJob1.setJobName("v2Task2");
quartzJob1.setJobGroup("SYSTEM");
quartzJob1.setInvokeTarget("v2Task.runTask2(1,2l,'asa',true,2D)");
// quartzJob1.setInvokeTarget("v2Task.runTask1()");
quartzJob1.setCronExpression("*/10 * * * * ?");
quartzJob1.setMisfirePolicy("12");
quartzJob1.setConcurrent("0");
quartzJob1.setStatus(0);
quartzJobs.add(quartzJob1);
for(QuartzJob job : quartzJobs) {
try {
//防止因为数据问题重复创建
if(checkJobExists(job)) {
deleteJob(job);
}
createSchedule(job);
}catch (SchedulerException e) {
e.printStackTrace();
}
}
start();
}
/**
* 启动定时器
*/
private void start() {
try {
scheduler.start();
} catch (SchedulerException e) {
e.printStackTrace();
log.error("定时任务执行失败");
}
}
/**
* 创建一个定时任务
* @param job
*/
private void createSchedule(QuartzJob job) throws SchedulerException {
if(!checkJobExists(job)) {
//获取指定的job工作类
Class extends Job> jobClass = getQuartzJobClass(job);
// 通过JobBuidler构建JobDetail实例,JobDetail规定只能是实现Job接口的实例
// JobDetail是具体Job实例
JobDetail jobDetail = JobBuilder.newJob(jobClass).withIdentity(ScheduleConstants.TASK_CLASS_NAME+job.getId(),
job.getJobGroup()).build();
//基于表达式构建触发器
CronScheduleBuilder cronScheduleBuilder = null;
if(StringUtils.isNotEmpty(job.getCronExpression())) {
cronScheduleBuilder = CronScheduleBuilder.cronSchedule(job.getCronExpression());
}else {
cronScheduleBuilder= CronScheduleBuilder.cronSchedule(TEST_CRON);
}
// CronTrigger表达式触发器继承于 Trigger // cronSchedulerBuilder.withMisfireHandlingInstructionDoNothing()错过
// 60分钟后不在补偿,拉下的执行次数
// TriggerBuilder 用于构建触发器实例
CronTrigger cronTrigger = TriggerBuilder.newTrigger().withIdentity(ScheduleConstants.TASK_CLASS_NAME+job.getId(),job.getJobGroup())
.withSchedule(cronScheduleBuilder.withMisfireHandlingInstructionDoNothing()).build();
//放入参数,运行时的方法可以获取
jobDetail.getJobDataMap().put(ScheduleConstants.TASK_PROPERTIES,job);
scheduler.scheduleJob(jobDetail,cronTrigger);
//如果这个工作的状态为1
if(job.getStatus().equals(1)) {
pauseJob(job);
}
}
}
/**
* 继续执行定时任务
* @param job
* @return
*/
public boolean resumeJob(QuartzJob job) {
boolean bl = false;
try {
//JobKey定义了job的名称和组别
JobKey jobKey = JobKey.jobKey(ScheduleConstants.TASK_CLASS_NAME+job.getId(), job.getJobGroup());
if (jobKey != null) {
//继续任务
scheduler.resumeJob(jobKey);
bl = true;
}
} catch (SchedulerException e) {
System.out.println("继续调度任务异常:" + e);
} catch (Exception e) {
System.out.println("继续调度任务异常:" + e);
}
return bl;
}
/**
* 暂停任务
* @param job
*/
private boolean pauseJob(QuartzJob job) {
boolean flag = false;
try {
//JobKey定义了job的名称和组别
JobKey jobKey = JobKey.jobKey(ScheduleConstants.TASK_CLASS_NAME+job.getId(), job.getJobGroup());
//暂停任务
if (jobKey != null) {
scheduler.pauseJob(jobKey);
flag = true;
}
} catch (SchedulerException e) {
System.out.println("暂停调度任务异常:" + e);
} catch (Exception e) {
System.out.println("暂停调度任务异常:"+ e);
}
return flag;
}
/**
* 获取定时任务的具体执行类
* @param job
* @return
*/
private Class extends Job> getQuartzJobClass(QuartzJob job) {
boolean isConcurrent = "0".equals(job.getConcurrent());
return isConcurrent ? QuartzJobExecution.class :QuartzDisallowConcurrentExecution.class;
}
/**
* 删除定时任务
* @param job
*/
private boolean deleteJob(QuartzJob job) {
boolean flag = false;
try{
// JobKey定义了job的名称和组名
JobKey jobKey = JobKey.jobKey(ScheduleConstants.TASK_CLASS_NAME + job.getId(),job.getJobGroup());
if(jobKey != null) {
//删除定时任务
scheduler.deleteJob(jobKey);
flag = true;
}
}catch (SchedulerException e) {
log.error("删除调度任务异常: " + e);
}catch (Exception e) {
log.error("删除调度任务异常: " + e);
}
return flag;
}
/**
* 判断定时任务是否已经存在
* @param job
* @return
*/
private boolean checkJobExists(QuartzJob job) throws SchedulerException {
TriggerKey triggerKey = TriggerKey.triggerKey(ScheduleConstants.TASK_CLASS_NAME+job.getId(),job.getJobGroup());
return scheduler.checkExists(triggerKey);
}
/**
* 立即执行任务
* @param job
*/
public void run(QuartzJob job) throws SchedulerException {
// 参数
JobDataMap dataMap = new JobDataMap();
dataMap.put(ScheduleConstants.TASK_PROPERTIES,job);
scheduler.triggerJob(getJobKey(job),dataMap);
}
/**
* 获取jobkey
* @param job
* @return
*/
private JobKey getJobKey(QuartzJob job) {
return JobKey.jobKey(ScheduleConstants.TASK_CLASS_NAME+job.getId(),job.getJobGroup());
}
}
8.Spring获取上下文工具类
@Component
public final class SpringUtils implements BeanFactoryPostProcessor
{
/** Spring应用上下文环境 */
private static ConfigurableListableBeanFactory beanFactory;
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException
{
SpringUtils.beanFactory = beanFactory;
}
/**
* 获取对象
*
* @param name
* @return Object 一个以所给名字注册的bean的实例
* @throws org.springframework.beans.BeansException
*
*/
@SuppressWarnings("unchecked")
public static T getBean(String name) throws BeansException
{
return (T) beanFactory.getBean(name);
}
/**
* 获取类型为requiredType的对象
*
* @param clz
* @return
* @throws org.springframework.beans.BeansException
*
*/
public static T getBean(Class 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 org.springframework.beans.factory.NoSuchBeanDefinitionException
*
*/
public static boolean isSingleton(String name) throws NoSuchBeanDefinitionException
{
return beanFactory.isSingleton(name);
}
/**
* @param name
* @return Class 注册对象的类型
* @throws org.springframework.beans.factory.NoSuchBeanDefinitionException
*
*/
public static Class> getType(String name) throws NoSuchBeanDefinitionException
{
return beanFactory.getType(name);
}
/**
* 如果给定的bean名字在bean定义中有别名,则返回这些别名
*
* @param name
* @return
* @throws org.springframework.beans.factory.NoSuchBeanDefinitionException
*
*/
public static String[] getAliases(String name) throws NoSuchBeanDefinitionException
{
return beanFactory.getAliases(name);
}
/**
* 获取aop代理对象
*
* @param invoker
* @return
*/
@SuppressWarnings("unchecked")
public static T getAopProxy(T invoker)
{
return (T) AopContext.currentProxy();
}
}
9.编写待执行目标任务类
/**
* 定时调度具体工作类
*/
@Component("v2Task")
@Slf4j
public class V2Task {
/**
* 无参的任务
*/
public void runTask1() {
log.info("正在执行定时任务,无参方法");
}
/**
* 有参任务
* 目前仅执行常见的数据类型 Integer Long 带L string 带 '' bool Double 带 d
* @param a
* @param b
*/
public void runTask2(Integer a,Long b,String c,Boolean d,Double e) {
log.info("正在执行定时任务,带多个参数的方法"+a+" "+b+" "+c+" "+d+" "+e+"执行时间:"+new Date().toLocaleString());
}
}
6.常用工具类
/**
* 字符集工具类
*
* @author fc
*
*/
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();
}
}
10.类型转换器
/**
* 类型转换器
*
* @author fc
*
*/
public class Convert
{
/**
* 转换为字符串
* 如果给定的值为null,或者转换失败,返回默认值
* 转换失败不会报错
*
* @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();
}
/**
* 转换为字符串
* 如果给定的值为null
,或者转换失败,返回默认值null
* 转换失败不会报错
*
* @param value 被转换的值
* @return 结果
*/
public static String toStr(Object value)
{
return toStr(value, null);
}
/**
* 转换为字符
* 如果给定的值为null,或者转换失败,返回默认值
* 转换失败不会报错
*
* @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);
}
/**
* 转换为字符
* 如果给定的值为null
,或者转换失败,返回默认值null
* 转换失败不会报错
*
* @param value 被转换的值
* @return 结果
*/
public static Character toChar(Object value)
{
return toChar(value, null);
}
/**
* 转换为byte
* 如果给定的值为null
,或者转换失败,返回默认值
* 转换失败不会报错
*
* @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
* 如果给定的值为null
,或者转换失败,返回默认值null
* 转换失败不会报错
*
* @param value 被转换的值
* @return 结果
*/
public static Byte toByte(Object value)
{
return toByte(value, null);
}
/**
* 转换为Short
* 如果给定的值为null
,或者转换失败,返回默认值
* 转换失败不会报错
*
* @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
* 如果给定的值为null
,或者转换失败,返回默认值null
* 转换失败不会报错
*
* @param value 被转换的值
* @return 结果
*/
public static Short toShort(Object value)
{
return toShort(value, null);
}
/**
* 转换为Number
* 如果给定的值为空,或者转换失败,返回默认值
* 转换失败不会报错
*
* @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
* 如果给定的值为空,或者转换失败,返回默认值null
* 转换失败不会报错
*
* @param value 被转换的值
* @return 结果
*/
public static Number toNumber(Object value)
{
return toNumber(value, null);
}
/**
* 转换为int
* 如果给定的值为空,或者转换失败,返回默认值
* 转换失败不会报错
*
* @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
* 如果给定的值为null
,或者转换失败,返回默认值null
* 转换失败不会报错
*
* @param value 被转换的值
* @return 结果
*/
public static Integer toInt(Object value)
{
return toInt(value, null);
}
/**
* 转换为Integer数组
*
* @param split 被转换的值
* @return 结果
*/
public static Integer[] toIntArray(String str)
{
return toIntArray(",", str);
}
/**
* 转换为List数组
*
* @param split 被转换的值
* @return 结果
*/
public static List toListStrArray(String str){
String[] stringArray= toStrArray(str);
List stringB = Arrays.asList(stringArray);
return stringB;
}
/**
* 转换为Long数组
*
* @param split 被转换的值
* @return 结果
*/
public static Long[] toLongArray(String str)
{
return toLongArray(",", str);
}
/**
* 转换为Integer数组
*
* @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数组
*
* @param isIgnoreConvertError 是否忽略转换错误,忽略则给值null
* @param values 被转换的值
* @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数组
*
* @param split 被转换的值
* @return 结果
*/
public static String[] toStrArray(String str)
{
return toStrArray(",", str);
}
/**
* 转换为String数组
*
* @param split 分隔符
* @param split 被转换的值
* @return 结果
*/
public static String[] toStrArray(String split, String str)
{
return str.split(split);
}
/**
* 转换为long
* 如果给定的值为空,或者转换失败,返回默认值
* 转换失败不会报错
*
* @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
* 如果给定的值为null
,或者转换失败,返回默认值null
* 转换失败不会报错
*
* @param value 被转换的值
* @return 结果
*/
public static Long toLong(Object value)
{
return toLong(value, null);
}
/**
* 转换为double
* 如果给定的值为空,或者转换失败,返回默认值
* 转换失败不会报错
*
* @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
* 如果给定的值为空,或者转换失败,返回默认值null
* 转换失败不会报错
*
* @param value 被转换的值
* @return 结果
*/
public static Double toDouble(Object value)
{
return toDouble(value, null);
}
/**
* 转换为Float
* 如果给定的值为空,或者转换失败,返回默认值
* 转换失败不会报错
*
* @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
* 如果给定的值为空,或者转换失败,返回默认值null
* 转换失败不会报错
*
* @param value 被转换的值
* @return 结果
*/
public static Float toFloat(Object value)
{
return toFloat(value, null);
}
/**
* 转换为boolean
* String支持的值为:true、false、yes、ok、no,1,0 如果给定的值为空,或者转换失败,返回默认值
* 转换失败不会报错
*
* @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
* 如果给定的值为空,或者转换失败,返回默认值null
* 转换失败不会报错
*
* @param value 被转换的值
* @return 结果
*/
public static Boolean toBool(Object value)
{
return toBool(value, null);
}
/**
* 转换为Enum对象
* 如果给定的值为空,或者转换失败,返回默认值
*
* @param clazz Enum的Class
* @param value 值
* @param defaultValue 默认值
* @return Enum
*/
public static > E toEnum(Class 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对象
* 如果给定的值为空,或者转换失败,返回默认值null
*
* @param clazz Enum的Class
* @param value 值
* @return Enum
*/
public static > E toEnum(Class clazz, Object value)
{
return toEnum(clazz, value, null);
}
/**
* 转换为BigInteger
* 如果给定的值为空,或者转换失败,返回默认值
* 转换失败不会报错
*
* @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
* 如果给定的值为空,或者转换失败,返回默认值null
* 转换失败不会报错
*
* @param value 被转换的值
* @return 结果
*/
public static BigInteger toBigInteger(Object value)
{
return toBigInteger(value, null);
}
/**
* 转换为BigDecimal
* 如果给定的值为空,或者转换失败,返回默认值
* 转换失败不会报错
*
* @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
* 如果给定的值为空,或者转换失败,返回默认值
* 转换失败不会报错
*
* @param value 被转换的值
* @return 结果
*/
public static BigDecimal toBigDecimal(Object value)
{
return toBigDecimal(value, null);
}
/**
* 将对象转为字符串
* 1、Byte数组和ByteBuffer会被转换为对应字符串的数组 2、对象数组会调用Arrays.toString方法
*
* @param obj 对象
* @return 字符串
*/
public static String utf8Str(Object obj)
{
return str(obj, CharsetKit.CHARSET_UTF_8);
}
/**
* 将对象转为字符串
* 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));
}
/**
* 将对象转为字符串
* 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 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 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("^整$",
"零元整");
}
}
11.字符串格式化
/**
* 字符串格式化
*
* @author fc
*/
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 = '}';
/**
* 格式化字符串
* 此方法只是简单将占位符 {} 按照顺序替换为参数
* 如果想输出 {} 使用 \\转义 { 即可,如果想输出 {} 之前的 \ 使用双转义符 \\\\ 即可
* 例:
* 通常使用:format("this is {} for {}", "a", "b") -> this is a for b
* 转义{}: format("this is \\{} for {}", "a", "b") -> this is \{} for a
* 转义\: format("this is \\\\{} for {}", "a", "b") -> this is \a for b
*
* @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;
}
}
}
// append the characters following the last {} pair.
// 加入最后一个占位符后所有的字符
sbuf.append(strPattern, handledPosition, strPattern.length());
return sbuf.toString();
}
}
- 字符串工具类
/**
* 字符串工具类
*
* @author fc
*/
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 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);
}
/**
* 格式化文本, {} 表示占位符
* 此方法只是简单将占位符 {} 按照顺序替换为参数
* 如果想输出 {} 使用 \\转义 { 即可,如果想输出 {} 之前的 \ 使用双转义符 \\\\ 即可
* 例:
* 通常使用:format("this is {} for {}", "a", "b") -> this is a for b
* 转义{}: format("this is \\{} for {}", "a", "b") -> this is \{} for a
* 转义\: format("this is \\\\{} for {}", "a", "b") -> this is \a for b
*
* @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);
}
/**
* 驼峰首字符小写 NameVc>>nameVc
*/
public static String uncapitalize(String str)
{
int strLen;
if (str == null || (strLen = str.length()) == 0)
{
return str;
}
return new StrBuilder(strLen).append(Character.toLowerCase(str.charAt(0))).append(str.substring(1)).toString();
}
/**
* 驼峰命名转下划线 nameVc>>name_vc
*/
public static String toUnderScoreCase(String s)
{
if (s == null)
{
return null;
}
StringBuilder sb = new StringBuilder();
boolean upperCase = false;
for (int i = 0; i < s.length(); i++)
{
char c = s.charAt(i);
boolean nextUpperCase = true;
if (i < (s.length() - 1))
{
nextUpperCase = Character.isUpperCase(s.charAt(i + 1));
}
if ((i > 0) && Character.isUpperCase(c))
{
if (!upperCase || !nextUpperCase)
{
sb.append(SEPARATOR);
}
upperCase = true;
}
else
{
upperCase = false;
}
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();
}
/**
* 首字母大写
*
* @param name
* @return
*/
public static String firstUpperCase(String name) {
name = name.substring(0, 1).toUpperCase() + name.substring(1);
return name;
}
/**
* 首字母小写
*
* @param name
* @return
*/
public static String firstLowerCase(String name) {
name = name.substring(0, 1).toLowerCase() + name.substring(1);
return name;
}
/**
* 将下划线转化为大写
*
* @param name
* @param firstCase 首字母是否大写 true:大写 false;小写
* @return
*/
public static String upperCase_(String name, boolean firstCase) {
if(isEmpty(name)){
return "";
}
String[] s = name.split("_");
StringBuffer stringBuffer = new StringBuffer();
for (String s1 : s) {
stringBuffer.append(s1.substring(0, 1).toUpperCase() + s1.substring(1));
}
if(!firstCase){
return firstLowerCase(stringBuffer.toString());
}
return stringBuffer.toString();
}
/**
* get方法名字转成 t_b_abc>>tBAbc
* @param str
* @return
* @author fuce
* @Date 2020年1月30日 下午11:55:54
*/
public static String toFUNName(String str) {
StringBuffer buffer=new StringBuffer();
String name=str;
if(name.contains("_")) {
// 用下划线将原始字符串分割
String[] camels = name.split("_");
boolean b=true;
for (String str1 : camels) {
if(str1.length()==1&&b) {
b=false;
buffer.append(str1);
}else {
buffer.append(StringUtils.firstUpperCase(str1));
}
}
}else {
buffer.append(StringUtils.firstUpperCase(name));
}
return buffer.toString();
}
/**
* 列名转换成Java属性名
*/
public static String columnToJava(String columnName) {
return WordUtils.capitalizeFully(columnName, new char[]{'_'}).replace("_", "" );
}
/**
* 表名转换成Java类名
*/
public static String tableToJava(String tableName, String tablePrefix) {
if (StringUtils.isNotBlank(tablePrefix)) {
tableName = tableName.replaceFirst(tablePrefix, "" );
}
return columnToJava(tableName);
}
}