- 浏览: 116496 次
- 性别:
- 来自: 广州
文章分类
最新评论
-
ron.luo:
干货,必须得顶。
JAXB使用经验总结 -
csdn_zuoqiang:
能否看下DWR的配置情况?谢谢
结合webservice实现dwr推送 -
友友水:
。。。。不好意思,无心之失,删不掉前一条评论
JAXB使用经验总结 -
友友水:
[/flash][/flash][/flash][/flash ...
JAXB使用经验总结 -
lihong11:
大哥,加加注释好不?看不懂唉
小玩dwr实现服务器推送
情景:
数据库中的数据需要根据formula在一定时间上计算得到相应的结果数据,就是说,根据formula去计算,得到相应结果保存在相应字段上,这个job是定时触发的,计算按照一定的事件类型。
代码:
这个类负责调用正确的cronJob去执行定时任务。我们可以看到,传过来相应的cronJobKey,首先从daily开始计算,只要成功,就会触发一系列的计算
接下来,我们看看DashboardDataCalculationService这个接口.
这个接口中定义了三个calculate方法,用于计算,再看看它的实现类中
public boolean calculate(String cronJobKey, PeriodType periodType, Date date);方法
看下这个方法,init()方法初始化了ThreadLocal变量中的参数,
接下来,systemCronJobService 负责去数据库拿到相应的SystemCronJob 对象,如果没拿到,则直跳出返回。
拿到SystemCronJob 对象后,通过它可以得到相应的需要计算的数据表对象,得到要计算的记录,分条执行calculateDef(periodType, calculateDate, def)。
在方法public boolean calculate(final String cronJobKey, final PeriodType periodType, final Date date) 调用 private void calculateDef(final PeriodType periodType, final Date calculateDate,
final DashboardDataDefinition def)方法,在此方法中,最终会调用
doCalculate()方法,所以,关键的计算在这里面。
这个方法中,首先把要计算的条件组成一个key,放在本地线程当中,其中有一个相应的计算结果,如果下次计算的条件与其相同,则不需要计算了,直接拿出结果就OK了,这样就节省了很多时间。
关键的计算是调用了spring的ExpressionParser及 Expression,让ExpressionParser去解析我们的formula,得到Expression 对象,最后有Expression对象调用它的getValue()方法得到计算结果。
当然,其中用到StandardEvaluationContext,PropertyAccessor,这些都是计算不可少的spring自带对象, DashboardDataAccessor以及FormulaMethod 都是自己编写的用于计算的条件对象,看名字应该知道它们是用来干什么的。
数据库中的数据需要根据formula在一定时间上计算得到相应的结果数据,就是说,根据formula去计算,得到相应结果保存在相应字段上,这个job是定时触发的,计算按照一定的事件类型。
代码:
public class DashboardDataCalculationJob { private final static Logger log = LoggerFactory.getLogger(DashboardDataCalculationJob.class); protected String cronJobKey; private DashboardDataCalculationService dashboardDataCalculationService; public void setCronJobKey(final String cronJobKey) { this.cronJobKey = cronJobKey; } public void setDashboardDataCalculationService( final DashboardDataCalculationService dashboardDataCalculationService) { this.dashboardDataCalculationService = dashboardDataCalculationService; } public void execute() { long start = System.currentTimeMillis(); Date date = new Date(); log.info("DashboardDataCalculationJob executing Daily..."); boolean success = dashboardDataCalculationService.calculate(cronJobKey, PeriodType.Daily, date); if (success) { log.info("DashboardDataCalculationJob executing Monthly..."); success = dashboardDataCalculationService.calculate(cronJobKey, PeriodType.Monthly, date); } if (success) { log.info("DashboardDataCalculationJob executing Yearly..."); dashboardDataCalculationService.calculate(cronJobKey, PeriodType.Yearly, date); } log.info("DashboardDataCalculationJob took {} ms.", System.currentTimeMillis() - start); } }
这个类负责调用正确的cronJob去执行定时任务。我们可以看到,传过来相应的cronJobKey,首先从daily开始计算,只要成功,就会触发一系列的计算
接下来,我们看看DashboardDataCalculationService这个接口.
@WebService public interface DashboardDataCalculationService { public boolean calculate(String cronJobKey, PeriodType periodType, Date date); public boolean calculateFields(List<String> fieldList, PeriodType periodType, Date date); public Double doCalculate(String formula, Date calculateDate, PeriodType periodType); }
这个接口中定义了三个calculate方法,用于计算,再看看它的实现类中
public boolean calculate(String cronJobKey, PeriodType periodType, Date date);方法
public boolean calculate(final String cronJobKey, final PeriodType periodType, final Date date) { try { init(); Date calculateDate = JobUtil.getCalculateDate(periodType, date); SystemCronJob systemCronJob = systemCronJobService.getSystemCronJobByJobKey(cronJobKey); if (systemCronJob == null) { log.error("SystemCronJob not found by cronJobKey: {}", cronJobKey); String subject = "SystemCronJob not found by cronJobKey: " + cronJobKey; String content = subject; try { emailService.sendEmail(subject, content); } catch (Exception e) { log.error(e.getMessage(), e); } return false; } List<DashboardDataDefinition> defList = systemCronJob.getDashboardDataDefinitions(); for (DashboardDataDefinition def : defList) { calculateDef(periodType, calculateDate, def); } return true; } catch (Exception ex) { log.error(ex.getMessage()); String subject = "DashboardDataCalculationService Failed: " + ex.getMessage(); StringWriter writer = new StringWriter(); ex.printStackTrace(new PrintWriter(writer)); String content = writer.toString(); try { emailService.sendEmail(subject, content); } catch (Exception e) { log.error(e.getMessage(), e); } return false; } finally { release(); } }
看下这个方法,init()方法初始化了ThreadLocal变量中的参数,
private static final ThreadLocal<Map<String, Double>> cachedValue = new ThreadLocal<Map<String, Double>>(); private static final ThreadLocal<Map<String, Boolean>> cachedValueSumLast = new ThreadLocal<Map<String, Boolean>>();
public void init() { cachedValue.set(new HashMap<String, Double>()); cachedValueSumLast.set(new HashMap<String, Boolean>()); }
接下来,systemCronJobService 负责去数据库拿到相应的SystemCronJob 对象,如果没拿到,则直跳出返回。
拿到SystemCronJob 对象后,通过它可以得到相应的需要计算的数据表对象,得到要计算的记录,分条执行calculateDef(periodType, calculateDate, def)。
private void calculateDef(final PeriodType periodType, final Date calculateDate, final DashboardDataDefinition def) { log.info("ChartField: {}, FormulaText: {}", def.getChartField(), def.getFormulaText()); String formula = def.getFormulaText(); if (StringUtils.isBlank(formula)) { log.warn("'{}' FormulaText is blank", def.getChartField()); return; } log.info("formula: {}={}", def.getChartField(), formula); Double value = doCalculate(formula, calculateDate, periodType);
在方法public boolean calculate(final String cronJobKey, final PeriodType periodType, final Date date) 调用 private void calculateDef(final PeriodType periodType, final Date calculateDate,
final DashboardDataDefinition def)方法,在此方法中,最终会调用
Double value = doCalculate(formula, calculateDate, periodType);
doCalculate()方法,所以,关键的计算在这里面。
public Double doCalculate(final String formula, final Date calculateDate, final PeriodType periodType) { String cacheKey = getCacheKey(formula, calculateDate, periodType); if (cachedValue.get() == null) { init(); } if (cachedValue.get().containsKey(cacheKey)) { Double cached = cachedValue.get().get(cacheKey); Boolean sumLastCal = cachedValueSumLast.get().get(cacheKey); if (sumLastCal != null && sumLastCal.booleanValue() == true) { FormulaMethod.sumLastCal.set(Boolean.TRUE); } log.info("use cached value {} :{}", formula, cached); return cached; } long start = System.currentTimeMillis(); log.info("calculateDate: {}", calculateDate); log.info("calculateDate.time: {}", calculateDate.getTime()); log.info("periodType: {}", periodType); ExpressionParser parser = new SpelExpressionParser(); Expression exp = parser.parseExpression(formula); StandardEvaluationContext context = new StandardEvaluationContext(); DashboardDataAccessor accessor = new DashboardDataAccessor(calculateDate, periodType); context.setRootObject(new FormulaMethod(calculateDate, periodType, accessor)); List<PropertyAccessor> propertyAccessors = new ArrayList<PropertyAccessor>(); propertyAccessors.add(accessor); context.setPropertyAccessors(propertyAccessors); Object value = exp.getValue(context); log.info("{} = {}", formula, value); log.info("took {} ms.", System.currentTimeMillis() - start); double v = Double.parseDouble(value.toString()); cachedValue.get().put(cacheKey, v); cachedValueSumLast.get().put(cacheKey, FormulaMethod.sumLastCal.get()); return v; }
这个方法中,首先把要计算的条件组成一个key,放在本地线程当中,其中有一个相应的计算结果,如果下次计算的条件与其相同,则不需要计算了,直接拿出结果就OK了,这样就节省了很多时间。
关键的计算是调用了spring的ExpressionParser及 Expression,让ExpressionParser去解析我们的formula,得到Expression 对象,最后有Expression对象调用它的getValue()方法得到计算结果。
当然,其中用到StandardEvaluationContext,PropertyAccessor,这些都是计算不可少的spring自带对象, DashboardDataAccessor以及FormulaMethod 都是自己编写的用于计算的条件对象,看名字应该知道它们是用来干什么的。
发表评论
-
动态多数据源实现
2019-12-18 12:58 458背景: 目前基于连接了mobile库 从库的 项目(sprin ... -
RPC调用之微博 motan
2018-02-23 16:42 1527这边文章将偏实战, 至于motan,可以去了解如何实现、比普通 ... -
push数据结构设计
2016-03-14 16:23 1749根据目前使用的极光推送, 设计一个合理的服务端,而且满足一 ... -
安全性,加密
2016-03-07 15:55 667/** * 随机字符串集 */ pri ... -
Myeclipse反向生成pojo及hibernate映射文件(由数据库表)
2013-03-18 14:38 1095在这之前请创建一个web工程,然后右键选择myeclipse- ... -
结合webservice实现dwr推送
2012-08-22 13:26 5328情景: 客户端需要实时提醒服务,比如某个日程已过期的提醒, ... -
项目中很强大的两个DAO
2011-12-02 11:37 1318直接贴代码了 public class DaoBase& ... -
Spring 定时任务quartz配置
2011-11-18 17:39 1644贴上xml文件, <?xml version= ... -
spring 与Hibernate集成的配置
2011-04-16 08:44 1709首先建个web项目,导入所需要的包,包名在这列出: hib ... -
spring 对jdbc的支持
2011-04-15 15:19 1410我写了个小测试,熟悉一下spring对JDBC的支持与配置过程 ... -
spring中配置国际化
2011-04-14 20:44 1106先写好几个.properties的资源文件放在classpat ... -
Spring 精华中aop的小测试
2011-04-14 20:01 1987对aop进行了小测试,动手才能看清真相! 首先,写个ao ... -
JNDI数据库连接池配置
2011-03-29 15:34 1349Tomcat 目录下conf中server.xml中配置: ... -
第一篇文章---收集数据库知识
2011-02-19 18:44 886以下是Oracle的一些命令: Sql代码 1、set ...
相关推荐
本篇文章将详细探讨如何在 Kubernetes (k8s) 集群环境中,结合 Spring Boot 应用程序和 Kubernetes CronJob 资源来配置定时任务。 首先,Spring Boot 是一个流行的 Java 框架,用于快速构建微服务应用。它提供了...
Spring框架提供了多种方式来实现定时任务,这使得开发者可以在不同场景下选择最适合的方案。本文主要探讨了Spring中实现定时任务的三种主要方法:Java的`java.util.Timer`、Quartz库以及Spring自身的Task调度器。 ...
结合Eclipse和Maven,创建Spring定时任务项目时,你需要: 1. 创建一个新的Maven项目,并添加Spring的相关依赖,如`spring-context`, `spring-context-support`(对于Spring Task),以及`quartz`和`spring-quartz`...
Spring框架提供了一系列工具来支持定时任务的实现,其中包括Spring自带的`spring-task`模块和第三方的Quartz库。下面我们将详细探讨这两种方式以及如何通过注解和非注解的方式进行配置。 首先,`spring-task`是...
在Java Spring框架中,动态配置定时任务是一项非常实用的功能,它允许我们根据需求灵活地更改或添加定时任务,而无需每次改动都重启应用。本文将深入探讨如何在Spring中实现这种动态配置,以及如何结合数据库来管理...
将Quartz2集成到Spring4中,可以方便地管理和执行定时任务,无需在代码中直接管理Scheduler实例,而是通过Spring配置来定义和控制Job。 集成Quartz2和Spring4的过程主要包括以下几个步骤: 1. **引入依赖**:首先...
Spring框架结合Quartz库,提供了一种强大而灵活的方式来管理这些定时任务。本项目旨在演示如何利用Spring和Quartz从数据库中动态加载定时任务,并实现对它们的增删改查功能。以下是关于这个主题的详细知识讲解。 ...
在Spring框架中,定时任务是实现自动化操作的重要手段,它允许开发者在特定时间点执行特定的任务,例如数据清理、报表生成等。本篇文章将详细探讨Spring中的定时...希望这些知识对您在实现Spring定时任务时有所帮助。
在Spring框架中,定时任务是实现周期性任务执行的关键特性,它允许开发者在特定时间间隔内执行特定的代码逻辑,而无需手动干预。本示例将深入探讨如何使用Spring的TaskScheduler或者Quartz Scheduler来创建和管理...
在Spring框架中,有三种主要的定时任务机制可供开发者选择,分别是基于Quartz的定时机制、Spring自己的`@Scheduled`注解以及Java的`java.util.Timer`类。在这篇文章中,我们将重点讨论基于Quartz的定时机制,因为它...
Spring 3.0版本引入了对定时任务的支持,这是一个非常实用的功能,可以帮助开发者实现定期执行的任务,如数据同步、报表生成等。本文将深入探讨Spring 3.0中的定时任务实现,并结合Quartz库来进一步扩展定时任务的...
Spring定时任务是企业级应用程序中常见的一种需求,用于在特定时间执行特定的任务,例如数据备份、清理、报表生成等。Quartz是Java领域一个强大的、开源的作业调度框架,它允许开发者灵活地定义任务和调度策略。这篇...
本资源"Spring整合Quartz后的简单定时任务示例"提供了如何将这两者结合使用的实例,旨在帮助开发者实现基于Spring的定时任务功能。 首先,我们要理解Spring对定时任务的支持。Spring框架通过`@Scheduled`注解提供了...
### Spring定时任务的几种实现 #### 一、定时任务实现技术分类 在Spring框架中,实现定时任务的主要技术方案有三种: 1. **Java自带的`java.util.Timer`类**:这种实现方式允许用户调度一个`java.util.TimerTask`...
在 "Quartz+spring定时任务demo" 中,我们首先需要了解如何配置和集成 Quartz 与 Spring。这通常包括以下步骤: 1. **引入依赖**:在项目中添加 Quartz 和 Spring 相关的 jar 包。描述中提到的 "1128266338845696....
本项目将Spring与Quartz相结合,实现了一个Web页面可配置的动态生成Spring定时任务的功能,并能持久化这些任务到数据库中,这在实际业务场景中非常实用。 首先,我们要理解Spring的定时任务是如何工作的。Spring...
在Spring框架中,定时任务是通过Spring的Task执行器或者Quartz库来实现的,用于在指定的时间间隔或特定时间点执行重复性任务。这里我们将深入讲解如何在Spring中配置和使用定时任务。 首先,Spring提供了两种定时...
在Spring Boot框架中,定时任务是一项非常重要的功能,它允许开发者在特定的时间间隔执行特定的任务。Spring Boot通过集成Spring Framework的Task Execution和Scheduling模块,提供了便捷的方式来管理和执行定时任务...
Spring 定时任务主要依赖于 Quartz 的 Job 和 Trigger 两个核心组件。其中,Job 代表了需要执行的任务,而 Trigger 用于控制任务何时以及如何执行。 ##### 2.2 实现步骤 1. **定义 Job**:首先,需要定义一个具体...
然而,如果需要更复杂的定时任务调度,如基于Cron表达式的定时,Spring推荐使用第三方的调度库,比如Quartz。 Quartz是一个功能强大的开源作业调度框架,它可以与Java应用程序无缝集成,用于执行计划任务。在Spring...