SpringBoot定时任务
在项目开发过程中,我们经常需要执行具有周期性的任务。通过定时任务可以很好的帮助我们实现。
spring项目启动后想对一些数据做同步,一些表数据要不定时统计,一些业务报表的汇总和生成,大量数据导入后台处理,一般都是用定时任务去处理,对于太占资源的任务需要后台处理,越复杂的系统定时任务也越多,需要监控的东西也很多。
而在springBoot提供了简单的定时任务支持,由于Spring Schedule包含在spring-boot-starter基础模块中了,所有不需要增加额外的依赖。
操作步骤
- 初始化项目之后,我们需要在spring boot的入口类Application.java中,允许支持schedule
@SpringBootApplication @EnableScheduling public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } }
- 然后,新建一个执行类Jobs.java
@Component public class Jobs { public final static long ONE_Minute = 60 * 1000; private SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); @Scheduled(fixedDelay=ONE_Minute) public void fixedDelayJob(){ System.out.println(sdf.format(new Date()) +" >>fixedDelay执行...."); } @Scheduled(fixedRate=ONE_Minute) public void fixedRateJob(){ System.out.println(sdf.format(new Date())+" >>fixedRate执行...."); } @Scheduled(cron="0 15 7 * * ?") public void cronJob(){ System.out.println(sdf.format(new Date())+" >>cron执行...."); } }
@Scheduled参数说明:
- fixedDelay和fixedRate是最简单的2种方式,多少分钟执行一次,单位是毫秒,所以1分钟就是60秒×1000。
- 他们的区别在于,fixedRate就是每多次分钟一次,不论你业务执行花费了多少时间。我都是1分钟执行1次,而fixedDelay是当任务执行完毕后1分钟在执行。所以根据实际业务不同,我们会选择不同的方式。
而还有一类定时任务,比如是每天的7点15分执行,那么我们就需要用另外一种方式:cron表达式 - cron表达式,有专门的语法(Linux中的定时任务也是使用cron),而且感觉有点绕人,不过简单来说,大家记住一些常用的用法即可,特殊的语法可以单独去查。
cron一共有7位,但是最后一位是年,可以留空,所以我们可以写6位:
* 第一位,表示秒,取值0-59 * 第二位,表示分,取值0-59 * 第三位,表示小时,取值0-23 * 第四位,日期天/日,取值1-31 * 第五位,日期月份,取值1-12 * 第六位,星期,取值1-7,星期一,星期二...,注:不是第1周,第二周的意思 另外:1表示星期天,2表示星期一。 * 第7为,年份,可以留空,取值1970-2099
cron中,还有一些特殊的符号,含义如下:
(*)星号:可以理解为每的意思,每秒,每分,每天,每月,每年... (?)问号:问号只能出现在日期和星期这两个位置,表示这个位置的值不确定,每天3点执行,所以第六位星期的位置,我们是不需要关注的,就是不确定的值。同时:日期和星期是两个相互排斥的元素,通过问号来表明不指定值。比如,1月10日,比如是星期1,如果在星期的位置是另指定星期二,就前后冲突矛盾了。 (-)减号:表达一个范围,如在小时字段中使用“10-12”,则表示从10到12点,即10,11,12 (,)逗号:表达一个列表值,如在星期字段中使用“1,2,4”,则表示星期一,星期二,星期四 (/)斜杠:如:x/y,x是开始值,y是步长,比如在第一位(秒) 0/15就是,从0秒开始,每15秒,最后就是0,15,30,45,60 另:*/y,等同于0/y
下面列举几个例子来验证:
0 0 3 * * ? 每天3点执行 0 5 3 * * ? 每天3点5分执行 0 5 3 ? * * 每天3点5分执行,与上面作用相同 0 5/10 3 * * ? 每天3点的 5分,15分,25分,35分,45分,55分这几个时间点执行 0 10 3 ? * 1 每周星期天,3点10分 执行,注:1表示星期天 0 10 3 ? * 1#3 每个月的第三个星期,星期天 执行,#号只能出现在星期的位置
SpringBoot中发送请求和Gson使用
java中发送请求:
参考一:https://www.cnblogs.com/leeego-123/p/12144525.html
参考二(我之前的博客):http://qkongtao.cn/?p=569#i
Gson的使用
我们来测试一个比较复杂的接口数据
使用高德地图提供的天气预报接口服务:
官方文档:https://lbs.amap.com/api/webservice/guide/api/weatherinfo
具体申请key和怎么使用该天气接口可以参看官方文档来实现
申请完接口之后,使用如下:
https://restapi.amap.com/v3/weather/weatherInfo?key=你的key&extensions=all&city=330100
是get请求,可以直接使用浏览器访问:
结果如下
里面的数据又杂又多,在Java后端返回回来的是json字符串,无法像js那样直接转换为json对象直接访问。这个时候我们就可以用到Google提供的Gson工具来很方便的处理这些数据。
比如我们处理日期为 2021-07-22 的天气:
Gson使用步骤
- 导入pom.xml依赖
<dependency> <groupId>com.google.code.gson</groupId> <artifactId>gson</artifactId> <version>2.8.3</version> </dependency>
- 新建 GetEmailInfosUtil.java 工具类
/** * @author tao * @date 2021-07-21 22:06 * 概要: */ public class GetEmailInfosUtil { /*获取天气*/ public static String getWeather() { RestTemplate restTemplate = new RestTemplate(); ResponseEntity<String> responseEntity = restTemplate.getForEntity("https://restapi.amap.com/v3/weather/weatherInfo?key=你的KEY&extensions=all&city=330100", String.class); //城市名,天气现象(白天,晚上),实时气温白天,晚上,风向描述,风力级别,数据发布的时间 String city, dayweather, nightweather, nighttemp, daytemp, winddirection, windpower, reporttime, forecasts; String result = responseEntity.getBody(); JsonParser jp = new JsonParser(); //将json字符串转化成json对象 JsonObject resultJo = jp.parse(result).getAsJsonObject(); JsonElement jsonElement = resultJo.get("forecasts").getAsJsonArray().get(0); forecasts = jsonElement.toString(); //System.out.println("forecasts=" + forecasts); JsonObject forecastsJo = jp.parse(forecasts).getAsJsonObject(); JsonElement jsonElementCasts = forecastsJo.get("casts").getAsJsonArray().get(0); JsonObject castsJo = jp.parse(jsonElementCasts.toString()).getAsJsonObject(); //获取对应的值 city = forecastsJo.get("city").getAsString(); reporttime = forecastsJo.get("reporttime").getAsString(); dayweather = castsJo.get("dayweather").getAsString(); nightweather = castsJo.get("nightweather").getAsString(); nighttemp = castsJo.get("nighttemp").getAsString(); daytemp = castsJo.get("daytemp").getAsString(); winddirection = castsJo.get("daywind").getAsString(); windpower = castsJo.get("daypower").getAsString(); String weatherText = "小黑天气预报来啦^_^:今日" + city + "天气" + dayweather + (dayweather.equals(nightweather) ? "" : "nightweather") + ";气温是" + nighttemp + "到" + daytemp + "度;风向是" + winddirection + "风,强度是" + windpower + "级。预报时间:" + reporttime + "。"; return weatherText; } }
- 测试方法
@Test void getWeather() { String weather = GetEmailInfosUtil.getWeather(); System.out.println(weather); }
- 结果如下
- Gson的使用说明
* 通过RestTemplate发送请求数据接口获取json的字符串
* new 一个 JsonParser 对象
* jp.parse(result).getAsJsonObject()获取json对象JsonObject
* 如果对象中的元素是字符串,则可以直接使用JsonObject对象.get("city").getAsString();获取字符串
* 如果对象中的元素是数组,则可以使用JsonObject对象.get("casts").getAsJsonArray();获取jsonArray数组
Date一些常用的工具方法
1. 获取指定日期加上天数后的日期
/** * 指定日期加上天数后的日期 * * @param num 为增加的天数 * @param newDate 创建时间 * @return * @throws ParseException */ public static String plusDay(int num, String newDate) throws ParseException { SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); Date currdate = format.parse(newDate); Calendar ca = Calendar.getInstance(); ca.setTime(currdate); ca.add(Calendar.DATE, num);// num为增加的天数,可以改变的 currdate = ca.getTime(); String enddate = format.format(currdate); return enddate; }
2. 字符串的日期格式的计算两个日期相差的天数
/* * 字符串的日期格式的计算 * @param smdate 时间1 * @param bdate 时间2 * @return 时间2 - 时间1 * @throws ParseException */ public static int daysBetween(String smdate, String bdate) throws ParseException { SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); Calendar cal = Calendar.getInstance(); cal.setTime(sdf.parse(smdate)); long time1 = cal.getTimeInMillis(); cal.setTime(sdf.parse(bdate)); long time2 = cal.getTimeInMillis(); long between_days = (time2 - time1) / (1000 * 3600 * 24); return Integer.parseInt(String.valueOf(between_days)); }
任意进制的转换
使用 new java.math.BigInteger(要转换的数, 源数的进制).toString(要转换成的进制);可以实现实现任意数、任意进制的转换。
以下是两个示例:
1. 10进制转32进制的方法
/** * 10进制转32进制的方法 * num 要转换的数 from源数的进制 to要转换成的进制 * * @param num 10进制(字符串) * @return 转换结果的32进制字符串 */ public static String change10To32(String num) { int from = 10; int to = 32; return new java.math.BigInteger(num, from).toString(to); }
2. 32进制转10进制的方法
/** * 32进制转10进制的方法 * num 要转换的数 from源数的进制 to要转换成的进制 * * @param num 10进制(字符串) * @return 转换结果的10进制字符串 */ public static String change32To10(String num) { int f = 32; int t = 10; return new java.math.BigInteger(num, f).toString(t); }
测试结果
1.10进制转32进制的方法
2. 32进制转10进制的方法