精华内容
下载资源
问答
  • 《Spring MVC 实现原理与源码解析 —— 精品合集》 《Spring Boot 实现原理与源码解析 —— 精品合集》 《数据库实体设计合集》 《Java 面试题 —— 精品合集》 《Java 学习指南 —— 精品合集》 定时任务实现的几种...
    • 使用Timer
    • 使用ScheduledExecutorService
    • 使用Spring Task
    • 整合Quartz
    • 最后

    • 《Netty 实现原理与源码解析 —— 精品合集》
    • 《Spring 实现原理与源码解析 —— 精品合集》
    • 《MyBatis 实现原理与源码解析 —— 精品合集》
    • 《Spring MVC 实现原理与源码解析 —— 精品合集》
    • 《Spring Boot 实现原理与源码解析 —— 精品合集》
    • 《数据库实体设计合集》
    • 《Java 面试题 —— 精品合集》
    • 《Java 学习指南 —— 精品合集》

    定时任务实现的几种方式:

    • Timer:这是java自带的java.util.Timer类,这个类允许你调度一个java.util.TimerTask任务。使用这种方式可以让你的程序按照某一个频度执行,但不能在指定时间运行。一般用的较少。
    • ScheduledExecutorService:也jdk自带的一个类;是基于线程池设计的定时任务类,每个调度任务都会分配到线程池中的一个线程去执行,也就是说,任务是并发执行,互不影响。
    • Spring Task:Spring3.0以后自带的task,可以将它看成一个轻量级的Quartz,而且使用起来比Quartz简单许多。
    • Quartz:这是一个功能比较强大的的调度器,可以让你的程序在指定时间执行,也可以按照某一个频度执行,配置起来稍显复杂。

    使用Timer

    这个目前在项目中用的较少,直接贴demo代码。具体的介绍可以查看api

    public class TestTimer {
        public static void main(String[] args) {
            TimerTask timerTask = new TimerTask() {
                @Override
                public void run() {
                    System.out.println("task  run:"+ new Date());
                }
            };
            Timer timer = new Timer();
            //安排指定的任务在指定的时间开始进行重复的固定延迟执行。这里是每3秒执行一次
            timer.schedule(timerTask,10,3000);
        }
    }
    

    使用ScheduledExecutorService

    该方法跟Timer类似,直接看demo:

    public class TestScheduledExecutorService {
        public static void main(String[] args) {
            ScheduledExecutorService service = Executors.newSingleThreadScheduledExecutor();
            // 参数:1、任务体 2、首次执行的延时时间
            //      3、任务执行间隔 4、间隔时间单位
            service.scheduleAtFixedRate(()->System.out.println("task ScheduledExecutorService "+new Date()), 0, 3, TimeUnit.SECONDS);
        }
    }
    

    使用Spring Task

    简单的定时任务

    在SpringBoot项目中,我们可以很优雅的使用注解来实现定时任务,首先创建项目,导入依赖:

    <dependencies>
      <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
      </dependency>
      <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter</artifactId>
      </dependency>
      <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <optional>true</optional>
      </dependency>
      <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
      </dependency>
    </dependencies>
    

    创建任务类:

    @Slf4j
    @Component
    public class ScheduledService {
        @Scheduled(cron = "0/5 * * * * *")
        public void scheduled(){
            log.info("=====>>>>>使用cron  {}",System.currentTimeMillis());
        }
        @Scheduled(fixedRate = 5000)
        public void scheduled1() {
            log.info("=====>>>>>使用fixedRate{}", System.currentTimeMillis());
        }
        @Scheduled(fixedDelay = 5000)
        public void scheduled2() {
            log.info("=====>>>>>fixedDelay{}",System.currentTimeMillis());
        }
    }
    

    在主类上使用@EnableScheduling注解开启对定时任务的支持,然后启动项目

    可以看到三个定时任务都已经执行,并且使同一个线程中串行执行,如果只有一个定时任务,这样做肯定没问题,当定时任务增多,如果一个任务卡死,会导致其他任务也无法执行。

    多线程执行

    在传统的Spring项目中,我们可以在xml配置文件添加task的配置,而在SpringBoot项目中一般使用config配置类的方式添加配置,所以新建一个AsyncConfig类

    @Configuration
    @EnableAsync
    public class AsyncConfig {
         /*
        此处成员变量应该使用@Value从配置中读取
         */
        private int corePoolSize = 10;
        private int maxPoolSize = 200;
        private int queueCapacity = 10;
        @Bean
        public Executor taskExecutor() {
            ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
            executor.setCorePoolSize(corePoolSize);
            executor.setMaxPoolSize(maxPoolSize);
            executor.setQueueCapacity(queueCapacity);
            executor.initialize();
            return executor;
        }
    }
    

    @Configuration:表明该类是一个配置类@EnableAsync:开启异步事件的支持

    然后在定时任务的类或者方法上添加@Async 。最后重启项目,每一个任务都是在不同的线程中

    执行时间的配置

    在上面的定时任务中,我们在方法上使用@Scheduled注解来设置任务的执行时间,并且使用三种属性配置方式:

    1. fixedRate:定义一个按一定频率执行的定时任务
    2. fixedDelay:定义一个按一定频率执行的定时任务,与上面不同的是,改属性可以配合initialDelay, 定义该任务延迟执行时间。
    3. cron:通过表达式来配置任务执行时间

    cron表达式详解

    一个cron表达式有至少6个(也可能7个)有空格分隔的时间元素。按顺序依次为:

    • 秒(0~59)
    • 分钟(0~59)
    • 3 小时(0~23)
    • 4 天(0~31)
    • 5 月(0~11)
    • 6 星期(1~7 1=SUN 或 SUN,MON,TUE,WED,THU,FRI,SAT)
    • 年份(1970-2099)

    其中每个元素可以是一个值(如6),一个连续区间(9-12),一个间隔时间(8-18/4)(/表示每隔4小时),一个列表(1,3,5),通配符。由于”月份中的日期”和”星期中的日期”这两个元素互斥的,必须要对其中一个设置。配置实例:

    • 每隔5秒执行一次:/5 * ?
    • 每隔1分钟执行一次:0 /1 ?
    • 0 0 10,14,16 ? 每天上午10点,下午2点,4点
    • 0 0/30 9-17 ? 朝九晚五工作时间内每半小时
    • 0 0 12 ? * WED 表示每个星期三中午12点
    • “0 0 12 ?” 每天中午12点触发
    • “0 15 10 ? “ 每天上午10:15触发
    • “0 15 10 ?” 每天上午10:15触发
    • “0 15 10 ? *” 每天上午10:15触发
    • “0 15 10 ? 2005” 2005年的每天上午10:15触发
    • “0 14 * ?” 在每天下午2点到下午2:59期间的每1分钟触发
    • “0 0/5 14 ?” 在每天下午2点到下午2:55期间的每5分钟触发
    • “0 0/5 14,18 ?” 在每天下午2点到2:55期间和下午6点到6:55期间的每5分钟触发
    • “0 0-5 14 ?” 在每天下午2点到下午2:05期间的每1分钟触发
    • “0 10,44 14 ? 3 WED” 每年三月的星期三的下午2:10和2:44触发
    • “0 15 10 ? * MON-FRI” 周一至周五的上午10:15触发
    • “0 15 10 15 * ?” 每月15日上午10:15触发
    • “0 15 10 L * ?” 每月最后一日的上午10:15触发
    • “0 15 10 ? * 6L” 每月的最后一个星期五上午10:15触发
    • “0 15 10 ? * 6L 2002-2005” 2002年至2005年的每月的最后一个星期五上午10:15触发
    • “0 15 10 ? * 6#3” 每月的第三个星期五上午10:15触发

    有些子表达式能包含一些范围或列表

    例如:子表达式(天(星期))可以为 “MON-FRI”,“MON,WED,FRI”,“MON-WED,SAT”

    “*”字符代表所有可能的值
    “/”字符用来指定数值的增量

    例如:在子表达式(分钟)里的“0/15”表示从第0分钟开始,每15分钟
    在子表达式(分钟)里的“3/20”表示从第3分钟开始,每20分钟(它和“3,23,43”)的含义一样

    “?”字符仅被用于天(月)和天(星期)两个子表达式,表示不指定值
    当2个子表达式其中之一被指定了值以后,为了避免冲突,需要将另一个子表达式的值设为“?”

    “L” 字符仅被用于天(月)和天(星期)两个子表达式,它是单词“last”的缩写
    如果在“L”前有具体的内容,它就具有其他的含义了。

    例如:“6L”表示这个月的倒数第6天
    注意:在使用“L”参数时,不要指定列表或范围,因为这会导致问题

    W 字符代表着平日(Mon-Fri),并且仅能用于日域中。它用来指定离指定日的最近的一个平日。大部分的商业处理都是基于工作周的,所以 W 字符可能是非常重要的。

    例如,日域中的 15W 意味着 “离该月15号的最近一个平日。” 假如15号是星期六,那么 trigger 会在14号(星期五)触发,因为星期四比星期一离15号更近。

    C:代表“Calendar”的意思。它的意思是计划所关联的日期,如果日期没有被关联,则相当于日历中所有日期。

    例如5C在日期字段中就相当于日历5日以后的第一天。1C在星期字段中相当于星期日后的第一天。

    字段允许值允许的特殊字符秒0~59, - * /分0~59, - * /小时0~23, - * /日期1-31, - * ? / L W C月份1~12或者JAN~DEC, - * /星期1~7或者SUN~SAT, - * ? / L C #年(可选)留空,1970~2099, - * /

    在线cron表达式生成:http://qqe2.com/cron/index

    整合Quartz

    • 添加依赖

    如果SpringBoot版本是2.0.0以后的,则在spring-boot-starter中已经包含了quart的依赖,则可以直接使用spring-boot-starter-quartz依赖:

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-quartz</artifactId>
    </dependency>
    

    如果是1.5.9则要使用以下添加依赖:

    <dependency>
      <groupId>org.quartz-scheduler</groupId>
      <artifactId>quartz</artifactId>
      <version>2.3.0</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-context-support</artifactId>
    </dependency>
    

    这里我使用SpringBoot版本是2.0.0.BUILD-SNAPSHOT ,该版本开始集成了Quartz,所以事实现起来很方便。其它好像比较麻烦,这里就不介绍,以后有时间再详细深入了解Quartz。

    • 创建任务类TestQuartz,该类主要是继承了QuartzJobBean
    public class TestQuartz extends QuartzJobBean {
        /**
         * 执行定时任务
         * @param jobExecutionContext
         * @throws JobExecutionException
         */
        @Override
        protected void executeInternal(JobExecutionContext jobExecutionContext) throws JobExecutionException {
            System.out.println("quartz task "+new Date());
        }
    }
    
    • 创建配置类QuartzConfig
    @Configuration
    public class QuartzConfig {
        @Bean
        public JobDetail teatQuartzDetail(){
            return JobBuilder.newJob(TestQuartz.class).withIdentity("testQuartz").storeDurably().build();
        }
    
        @Bean
        public Trigger testQuartzTrigger(){
            SimpleScheduleBuilder scheduleBuilder = SimpleScheduleBuilder.simpleSchedule()
                    .withIntervalInSeconds(10)  //设置时间周期单位秒
                    .repeatForever();
            return TriggerBuilder.newTrigger().forJob(teatQuartzDetail())
                    .withIdentity("testQuartz")
                    .withSchedule(scheduleBuilder)
                    .build();
        }
    }
    
    • 启动项目

    最后

    上面都是简单的介绍了关于SpringBoot定时任务的处理,直接使用SpringTask注解的方式应该是最方便的,而使用Quartz从2.0开始也变得很方便。对于这两种方式,应该说各有长处吧,按需选择。另外关于Quartz的详细内容可以查看官方文档:传送门

    来源:http://t.cn/EKj1aqJ

    展开全文
  • 极光推送在众多的消息推送里...极光推送官方SDK文档:https://docs.jiguang.cn/jpush/server/sdk/java_sdk/ 错误码信息:https://docs.jiguang.cn/jpush/server/push/rest_api_v3_push/#_19 工具类: import ja...

    极光推送在众多的消息推送里,口碑算是很好的,项目中我负责的是这一块,就整理了这篇博客帮助记忆;

    极光推送官方SDK文档:https://docs.jiguang.cn/jpush/server/sdk/java_sdk/

    错误码信息:https://docs.jiguang.cn/jpush/server/push/rest_api_v3_push/#_19

    工具类:

    import java.util.ArrayList;
    import java.util.List;
    
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    
    import cn.jiguang.common.resp.APIConnectionException;
    import cn.jiguang.common.resp.APIRequestException;
    import cn.jpush.api.JPushClient;
    import cn.jpush.api.push.PushResult;
    import cn.jpush.api.push.model.Message;
    import cn.jpush.api.push.model.Options;
    import cn.jpush.api.push.model.Platform;
    import cn.jpush.api.push.model.PushPayload;
    import cn.jpush.api.push.model.audience.Audience;
    import cn.jpush.api.push.model.notification.AndroidNotification;
    import cn.jpush.api.push.model.notification.IosNotification;
    import cn.jpush.api.push.model.notification.Notification;
    import cn.jpush.api.schedule.ScheduleResult;
    
    /**
     * @author Zhang
     * @date 2018年11月14日
     * @description: 极光推送工具类
     */ 
    public class JpushClientUtil {
    	
    	private static Logger logger = LoggerFactory.getLogger(JpushClientUtil.class);
     
        private final static String APPKER = "************";
     
        private final static String MASTERSECRET = "**********";
     
        private static JPushClient jPushClient = new JPushClient(MASTERSECRET,APPKER);
        
        private JpushClientUtil() {
            throw new AssertionError("不能产生该对象");
        }
        /*
        public static void main(String[] args) {
        	List<String> alias = new ArrayList<String>();
        	alias.add("276");
        	alias.add("231");
        	sendToRegistrationId(alias, "测试", "测试信息", "测试信息", "https://www.baidu.com");
    //    	sendToRegistrationId2(alias, "测试", "测试信息", "测试信息", "https://www.baidu.com","2018-11-23 17:05:25");
    //    	sendToAllAndroid("测试", "测试信息", "测试信息", "https://www.baidu.com");
    //    	sendToAllIos("测试", "测试信息", "测试信息", "https://www.baidu.com");
    	}
        */
        /**
         * 推送给设备标识参数的用户
         * @param alias 设备标识
         * @param notification_title 通知内容标题
         * @param msg_title 消息内容标题
         * @param msg_content 消息内容
         * @param extrasparam 扩展字段(通常传跳转的链接)
         * @return 0推送失败,1推送成功
         */
        public static int sendToRegistrationId( List<String> alias,String notification_title, String msg_title, String msg_content, String extrasparam) {
        	JPushClient jPushClient = new JPushClient(MASTERSECRET,APPKER);
            int result = 0;
            try {
                PushPayload pushPayload= JpushClientUtil.buildPushObject_all_alias_alertWithTitle(alias,notification_title,msg_title,msg_content,extrasparam);
                PushResult pushResult=jPushClient.sendPush(pushPayload);
                if(pushResult.getResponseCode()==200){
                    result=1;
                }
                logger.info("[极光推送]PushResult result is " + pushResult);
            } catch (APIConnectionException e) {
            	logger.error("[极光推送]Connection error. Should retry later. ", e);
            } catch (APIRequestException e) {
            	logger.error("[极光推送]Error response from JPush server. Should review and fix it. ", e);
            	logger.info("[极光推送]HTTP Status: " + e.getStatus());
            	logger.info("[极光推送]Error Code: " + e.getErrorCode());
            	logger.info("[极光推送]Error Message: " + e.getErrorMessage());
            }
     
             return result;
        }
     
        /**
         * 推送给设备标识参数的用户(定时)
         * @param alias 设备标识
         * @param notification_title 通知内容标题
         * @param msg_title 消息内容标题
         * @param msg_content 消息内容
         * @param extrasparam 扩展字段
         * @param time 格式:yyyy-MM-dd HH:mm:ss
         * @return 0推送失败,1推送成功
         */
        public static int sendToRegistrationId2( List<String> alias,String notification_title, String msg_title, String msg_content, String extrasparam, String time) {
        	JPushClient jPushClient = new JPushClient(MASTERSECRET,APPKER);
            int result = 0;
            try {
                PushPayload pushPayload= JpushClientUtil.buildPushObject_all_alias_alertWithTitle(alias,notification_title,msg_title,msg_content,extrasparam);
                ScheduleResult scheduleResult=jPushClient.createSingleSchedule("点呗生活", time, pushPayload);
                if(scheduleResult.getResponseCode()==200){
                    result=1;
                }
                logger.info("[极光推送]ScheduleResult result is " + scheduleResult);
            } catch (APIConnectionException e) {
            	logger.error("[极光推送]Connection error. Should retry later. ", e);
            } catch (APIRequestException e) {
            	logger.error("[极光推送]Error response from JPush server. Should review and fix it. ", e);
            	logger.info("[极光推送]HTTP Status: " + e.getStatus());
            	logger.info("[极光推送]Error Code: " + e.getErrorCode());
            	logger.info("[极光推送]Error Message: " + e.getErrorMessage());
            }
     
             return result;
        }    
        
        /**
         * 发送给所有安卓用户
         * @param notification_title 通知内容标题
         * @param msg_title 消息内容标题
         * @param msg_content 消息内容
         * @param extrasparam 扩展字段
         * @return 0推送失败,1推送成功
         */
        public static int sendToAllAndroid( String notification_title, String msg_title, String msg_content, String extrasparam) {
            int result = 0;
            try {
                PushPayload pushPayload= JpushClientUtil.buildPushObject_android_all_alertWithTitle(notification_title,msg_title,msg_content,extrasparam);
                PushResult pushResult=jPushClient.sendPush(pushPayload);
                if(pushResult.getResponseCode()==200){
                    result=1;
                }
                logger.info("[极光推送]PushResult result is " + pushResult);
            } catch (APIConnectionException e) {
            	logger.error("[极光推送]Connection error. Should retry later. ", e);
            } catch (APIRequestException e) {
            	logger.error("[极光推送]Error response from JPush server. Should review and fix it. ", e);
            	logger.info("[极光推送]HTTP Status: " + e.getStatus());
            	logger.info("[极光推送]Error Code: " + e.getErrorCode());
            	logger.info("[极光推送]Error Message: " + e.getErrorMessage());
            }
     
             return result;
        }
     
        /**
         * 发送给所有IOS用户
         * @param notification_title 通知内容标题
         * @param msg_title 消息内容标题
         * @param msg_content 消息内容
         * @param extrasparam 扩展字段
         * @return 0推送失败,1推送成功
         */
        public static int sendToAllIos(String notification_title, String msg_title, String msg_content, String extrasparam) {
            int result = 0;
            try {
                PushPayload pushPayload= JpushClientUtil.buildPushObject_ios_all_alertWithTitle(notification_title,msg_title,msg_content,extrasparam);
                PushResult pushResult=jPushClient.sendPush(pushPayload);
                if(pushResult.getResponseCode()==200){
                    result=1;
                }
                logger.info("[极光推送]PushResult result is " + pushResult);
            } catch (APIConnectionException e) {
            	logger.error("[极光推送]Connection error. Should retry later. ", e);
            } catch (APIRequestException e) {
            	logger.error("[极光推送]Error response from JPush server. Should review and fix it. ", e);
            	logger.info("[极光推送]HTTP Status: " + e.getStatus());
            	logger.info("[极光推送]Error Code: " + e.getErrorCode());
            	logger.info("[极光推送]Error Message: " + e.getErrorMessage());
            }
     
             return result;
        }
     
        /**
         * 发送给所有用户
         * @param notification_title 通知内容标题
         * @param msg_title 消息内容标题
         * @param msg_content 消息内容
         * @param extrasparam 扩展字段
         * @return 0推送失败,1推送成功
         */
        public static int sendToAll( String notification_title, String msg_title, String msg_content, String extrasparam) {
            int result = 0;
            try {
                PushPayload pushPayload= JpushClientUtil.buildPushObject_android_and_ios(notification_title,msg_title,msg_content,extrasparam);
                PushResult pushResult=jPushClient.sendPush(pushPayload);
                if(pushResult.getResponseCode()==200){
                    result=1;
                }
                logger.info("[极光推送]PushResult result is " + pushResult);
            } catch (APIConnectionException e) {
            	logger.error("[极光推送]Connection error. Should retry later. ", e);
            } catch (APIRequestException e) {
            	logger.error("[极光推送]Error response from JPush server. Should review and fix it. ", e);
            	logger.info("[极光推送]HTTP Status: " + e.getStatus());
            	logger.info("[极光推送]Error Code: " + e.getErrorCode());
            	logger.info("[极光推送]Error Message: " + e.getErrorMessage());
            }
     
            return result;
        }
        
        /**
         * 发送给所有用户(定时推送)
         * @param notification_title 通知内容标题
         * @param msg_title 消息内容标题
         * @param msg_content 消息内容
         * @param extrasparam 扩展字段
         * @param time 格式:yyyy-MM-dd HH:mm:ss
         * @return 0推送失败,1推送成功
         */
        public static int sendToAll2( String notification_title, String msg_title, String msg_content, String extrasparam, String time) {
            int result = 0;
            try {
                PushPayload pushPayload= JpushClientUtil2.buildPushObject_android_and_ios(notification_title,msg_title,msg_content,extrasparam);
                ScheduleResult scheduleResult=jPushClient.createSingleSchedule("测试", time, pushPayload);
                if(scheduleResult.getResponseCode()==200){
                    result=1;
                }
                logger.info("[极光推送]scheduleResult result is " + scheduleResult);
            } catch (APIConnectionException e) {
            	logger.error("[极光推送]Connection error. Should retry later. ", e);
            } catch (APIRequestException e) {
            	logger.error("[极光推送]Error response from JPush server. Should review and fix it. ", e);
            	logger.info("[极光推送]HTTP Status: " + e.getStatus());
            	logger.info("[极光推送]Error Code: " + e.getErrorCode());
            	logger.info("[极光推送]Error Message: " + e.getErrorMessage());
            }
     
            return result;
        }
     
     
        public static PushPayload buildPushObject_android_and_ios(String notification_title, String msg_title, String msg_content, String extrasparam) {
            return PushPayload.newBuilder()
                    .setPlatform(Platform.android_ios())
                    .setAudience(Audience.all())
                    .setNotification(Notification.newBuilder()
                            .setAlert(msg_content)
                            .addPlatformNotification(AndroidNotification.newBuilder()
                                    .setAlert(msg_content)
                                    .setTitle(notification_title)
                                    //此字段为透传字段,不会显示在通知栏。用户可以通过此字段来做一些定制需求,如特定的key传要指定跳转的页面(value)
                                    .addExtra("url",extrasparam)
                                    .build()
                            )
                            .addPlatformNotification(IosNotification.newBuilder()
                                    //传一个IosAlert对象,指定apns title、title、subtitle等
                                    .setAlert(msg_content)
                                    //直接传alert
                                    //此项是指定此推送的badge自动加1
                                    .incrBadge(1)
                                    //此字段的值default表示系统默认声音;传sound.caf表示此推送以项目里面打包的sound.caf声音来提醒,
                                    // 如果系统没有此音频则以系统默认声音提醒;此字段如果传空字符串,iOS9及以上的系统是无声音提醒,以下的系统是默认声音
                                    .setSound("sound.caf")
                                    //此字段为透传字段,不会显示在通知栏。用户可以通过此字段来做一些定制需求,如特定的key传要指定跳转的页面(value)
                                    .addExtra("url",extrasparam)
                                    //此项说明此推送是一个background推送,想了解background看:http://docs.jpush.io/client/ios_tutorials/#ios-7-background-remote-notification
                                    // .setContentAvailable(true)
     
                                    .build()
                            )
                            .build()
                    )
                    //Platform指定了哪些平台就会像指定平台中符合推送条件的设备进行推送。 jpush的自定义消息,
                    // sdk默认不做任何处理,不会有通知提示。建议看文档http://docs.jpush.io/guideline/faq/的
                    // [通知与自定义消息有什么区别?]了解通知和自定义消息的区别
                    .setMessage(Message.newBuilder()
                            .setMsgContent(msg_content)
                            .setTitle(msg_title)
                            .addExtra("url",extrasparam)
                            .build())
     
                    .setOptions(Options.newBuilder()
                            //此字段的值是用来指定本推送要推送的apns环境,false表示开发,true表示生产;对android和自定义消息无意义
                            .setApnsProduction(true)
                            //此字段是给开发者自己给推送编号,方便推送者分辨推送记录
                            .setSendno(1)
                            //此字段的值是用来指定本推送的离线保存时长,如果不传此字段则默认保存一天,最多指定保留十天,单位为秒
                            .setTimeToLive(86400)
                            .build()
                    )
                    .build();
        }
     
        private static PushPayload buildPushObject_all_alias_alertWithTitle(List<String> alias,String notification_title, String msg_title, String msg_content, String extrasparam) {
            //创建一个IosAlert对象,可指定APNs的alert、title等字段
            //IosAlert iosAlert =  IosAlert.newBuilder().setTitleAndBody("title", "alert body").build();
     
            return PushPayload.newBuilder()
                    //指定要推送的平台,all代表当前应用配置了的所有平台,也可以传android等具体平台
                    .setPlatform(Platform.all())
                    //指定推送的接收对象,all代表所有人,也可以指定已经设置成功的tag或alias或该应应用客户端调用接口获取到的registration id
                    .setAudience(Audience.alias(alias))
    //                .setAudience(Audience.registrationId(registrationId))
                    //jpush的通知,android的由jpush直接下发,iOS的由apns服务器下发,Winphone的由mpns下发
                    .setNotification(Notification.newBuilder()
                            //指定当前推送的android通知
                            .addPlatformNotification(AndroidNotification.newBuilder()
                            			
                                    .setAlert(msg_content)
                                    .setTitle(notification_title)
                                    //此字段为透传字段,不会显示在通知栏。用户可以通过此字段来做一些定制需求,如特定的key传要指定跳转的页面(value)
                                    .addExtra("url",extrasparam)
     
                                    .build())
                            //指定当前推送的iOS通知
                            .addPlatformNotification(IosNotification.newBuilder()
                                    //传一个IosAlert对象,指定apns title、title、subtitle等
                                    .setAlert(msg_content)
                                    //直接传alert
                                    //此项是指定此推送的badge自动加1
                                    .incrBadge(1)
                                    //此字段的值default表示系统默认声音;传sound.caf表示此推送以项目里面打包的sound.caf声音来提醒,
                                    // 如果系统没有此音频则以系统默认声音提醒;此字段如果传空字符串,iOS9及以上的系统是无声音提醒,以下的系统是默认声音
                                    .setSound("sound.caf")
                                    //此字段为透传字段,不会显示在通知栏。用户可以通过此字段来做一些定制需求,如特定的key传要指定跳转的页面(value)
                                    .addExtra("url",extrasparam)
                                    //此项说明此推送是一个background推送,想了解background看:http://docs.jpush.io/client/ios_tutorials/#ios-7-background-remote-notification
                                    //取消此注释,消息推送时ios将无法在锁屏情况接收
                                    // .setContentAvailable(true)
     
                                    .build())
     
     
                            .build())
                    //Platform指定了哪些平台就会像指定平台中符合推送条件的设备进行推送。 jpush的自定义消息,
                    // sdk默认不做任何处理,不会有通知提示。建议看文档http://docs.jpush.io/guideline/faq/的
                    // [通知与自定义消息有什么区别?]了解通知和自定义消息的区别
                    .setMessage(Message.newBuilder()
     
                            .setMsgContent(msg_content)
     
                            .setTitle(msg_title)
     
                            .addExtra("url",extrasparam)
     
                            .build())
     
                    .setOptions(Options.newBuilder()
                            //此字段的值是用来指定本推送要推送的apns环境,false表示开发,true表示生产;对android和自定义消息无意义
                            .setApnsProduction(true)
                            //此字段是给开发者自己给推送编号,方便推送者分辨推送记录
                            .setSendno(1)
                            //此字段的值是用来指定本推送的离线保存时长,如果不传此字段则默认保存一天,最多指定保留十天;
                            .setTimeToLive(86400)
     
                            .build())
     
                    .build();
     
        }
     
        private static PushPayload buildPushObject_android_all_alertWithTitle(String notification_title, String msg_title, String msg_content, String extrasparam) {
            return PushPayload.newBuilder()
                    //指定要推送的平台,all代表当前应用配置了的所有平台,也可以传android等具体平台
                    .setPlatform(Platform.android())
                    //指定推送的接收对象,all代表所有人,也可以指定已经设置成功的tag或alias或该应应用客户端调用接口获取到的registration id
                    .setAudience(Audience.all())
                    //jpush的通知,android的由jpush直接下发,iOS的由apns服务器下发,Winphone的由mpns下发
                    .setNotification(Notification.newBuilder()
                            //指定当前推送的android通知
                            .addPlatformNotification(AndroidNotification.newBuilder()
                                    .setAlert(msg_content)
                                    .setTitle(notification_title)
                                    //此字段为透传字段,不会显示在通知栏。用户可以通过此字段来做一些定制需求,如特定的key传要指定跳转的页面(value)
                                    .addExtra("url",extrasparam)
                                    .build())
                            .build()
                    )
                    //Platform指定了哪些平台就会像指定平台中符合推送条件的设备进行推送。 jpush的自定义消息,
                    // sdk默认不做任何处理,不会有通知提示。建议看文档http://docs.jpush.io/guideline/faq/的
                    // [通知与自定义消息有什么区别?]了解通知和自定义消息的区别
                    .setMessage(Message.newBuilder()
                            .setMsgContent(msg_content)
                            .setTitle(msg_title)
                            .addExtra("url",extrasparam)
                            .build())
     
                    .setOptions(Options.newBuilder()
                            //此字段的值是用来指定本推送要推送的apns环境,false表示开发,true表示生产;对android和自定义消息无意义
                            .setApnsProduction(true)
                            //此字段是给开发者自己给推送编号,方便推送者分辨推送记录
                            .setSendno(1)
                            //此字段的值是用来指定本推送的离线保存时长,如果不传此字段则默认保存一天,最多指定保留十天,单位为秒
                            .setTimeToLive(86400)
                            .build())
                    .build();
        }
     
        private static PushPayload buildPushObject_ios_all_alertWithTitle( String notification_title, String msg_title, String msg_content, String extrasparam) {
            return PushPayload.newBuilder()
                    //指定要推送的平台,all代表当前应用配置了的所有平台,也可以传android等具体平台
                    .setPlatform(Platform.ios())
                    //指定推送的接收对象,all代表所有人,也可以指定已经设置成功的tag或alias或该应应用客户端调用接口获取到的registration id
                    .setAudience(Audience.all())
                    //jpush的通知,android的由jpush直接下发,iOS的由apns服务器下发,Winphone的由mpns下发
                    .setNotification(Notification.newBuilder()
                            //指定当前推送的android通知
                            .addPlatformNotification(IosNotification.newBuilder()
                                    //传一个IosAlert对象,指定apns title、title、subtitle等
                                    .setAlert(msg_content)
                                    //直接传alert
                                    //此项是指定此推送的badge自动加1
                                    .incrBadge(1)
                                    //此字段的值default表示系统默认声音;传sound.caf表示此推送以项目里面打包的sound.caf声音来提醒,
                                    // 如果系统没有此音频则以系统默认声音提醒;此字段如果传空字符串,iOS9及以上的系统是无声音提醒,以下的系统是默认声音
                                    .setSound("sound.caf")
                                    //此字段为透传字段,不会显示在通知栏。用户可以通过此字段来做一些定制需求,如特定的key传要指定跳转的页面(value)
                                    .addExtra("url",extrasparam)
                                    //此项说明此推送是一个background推送,想了解background看:http://docs.jpush.io/client/ios_tutorials/#ios-7-background-remote-notification
                                   // .setContentAvailable(true)
     
                                    .build())
                            .build()
                    )
                    //Platform指定了哪些平台就会像指定平台中符合推送条件的设备进行推送。 jpush的自定义消息,
                    // sdk默认不做任何处理,不会有通知提示。建议看文档http://docs.jpush.io/guideline/faq/的
                    // [通知与自定义消息有什么区别?]了解通知和自定义消息的区别
                    .setMessage(Message.newBuilder()
                            .setMsgContent(msg_content)
                            .setTitle(msg_title)
                            .addExtra("url",extrasparam)
                            .build())
     
                    .setOptions(Options.newBuilder()
                            //此字段的值是用来指定本推送要推送的apns环境,false表示开发,true表示生产;对android和自定义消息无意义
                            .setApnsProduction(true)
                            //此字段是给开发者自己给推送编号,方便推送者分辨推送记录
                            .setSendno(1)
                            //此字段的值是用来指定本推送的离线保存时长,如果不传此字段则默认保存一天,最多指定保留十天,单位为秒
                            .setTimeToLive(86400)
                            .build())
                    .build();
        }
     
    }

    推送成功返回:

     

    推送失败返回(大多的推送失败返回,都是1011找不到指定的目标用户):

     

    展开全文
  • @EnableScheduling // 开启对定时任务支持 @SpringBootApplication public class DmsAdminApplication{ public static void main(String[] args) { SpringApplication.run(DmsAdminApplication.class, args); } }
  • 功能:向后台发送tcp请求,如果失败(超时或者其他原因),隔5s、15s、35s相继推送三次 问题:1.如何高并发处理? 2.相隔时间怎么控制?
  • JAVA-向页面定时推送信息

    千次阅读 2019-03-07 15:25:52
    使用Quartz触发器加dwr推送技术(服务器推送技术,Server push)完成,直接用实例说明: 1、先看配置: &lt;?xml version="1.0" encoding="UTF-8"?&gt; &lt;beans xmlns="...

    使用Quartz触发器加dwr推送技术(服务器推送技术,Server push)完成,直接用实例说明:

    1、先看配置:

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd">

        <!-- 设定自动执行任务的方法体 -->

       <!-- warnEventPushScanAction是Spring配置的java类名,scanWarnEvent为类里面的方法 -->

        <bean id="warnEventPushScanJob"
            class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
            <property name="targetObject" ref="
    warnEventPushScanAction" />
            <property name="targetMethod" value="
    scanWarnEvent" />
            <property name="concurrent" value="false" />
    <!--将并发设置,false为执行完本次任务再执行下一次的任务-->
        </bean>
        <!-- 设定自动执行任务的时间 每到一个时间点运行 -->
        <bean id="warnEventPushScanTrigger" class="org.springframework.scheduling.quartz.CronTriggerBean">
            <property name="jobDetail" ref="
    warnEventPushScanJob" />
            <property name="cronExpression" value="
    0/5 * * * * ?" />
        </bean>

        
         <!-- 进行动态的任务注册和调度 -->
         <bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean" >
            <property name="triggers">
                <list>
                    <ref bean="
    warnEventPushScanTrigger" />
                </list>
            </property>
        </bean> 
    </beans>

    2、看进入的方法及数据推送

    public class WarnEventPushScanAction extends QueryManageAction { 

     private AlarmVideoCirculateAction alarmVideoCirculateAction;  

     public void scanWarnEvent() {

    /*这里是你的逻辑*/

                alarmVideoCirculateAction.callDWRPageJSFunctionForIndexPage(list);

     }

    }

    public class AlarmVideoCirculateAction extends WebPushAction{
        @SuppressWarnings("deprecation")
        public static int callDWRPageJSFunctionForIndexPage(List smsJsons) {

    //参数1是接收数据的页面,参数2是页面的js方法,参数三是传过去的数据
            callDWRPageJSFunction("monitorVideo/HCVSM/alarmVideoCirculateH.jsp", "setAlarmVideoData", smsJsons);
            return 0;
        }
        /**
         * pushPage为推送的页面
         * callBackMethod为js方法
         * @param pushPage
         * @param callBackMethod
         * @param smsJsons
         * @return
         */
        @SuppressWarnings("deprecation")
        public static int callDWRPageJSFunction(String pushPage, String callBackMethod, List smsJsons) {
            int result = -1;
            if (contex != null) {
                //得到要推送到 的页面 dwr3为项目名称 , 一定要加上。
                if (projectName == null || projectName.equals("")) {
                    projectName = getProjectName();
                }
                String page = projectName + pushPage;
                Collection<ScriptSession> sessions = contex.getScriptSessionsByPage(page);    
                Iterator it = sessions.iterator(); 
                while (it.hasNext()) {
                    ScriptSession session = (ScriptSession) it.next();
                    Util util = new Util(session);
                 
       //回调js方法,callBackMethod:方法名,callBackParameter:回调参数
                    util.addFunctionCall(callBackMethod, smsJsons);
                }
                result = 1;
            }
            return result;
        }    

        }

     

    展开全文
  • public class ScheduledThreadPoolTest { public static void main(String[] args) throws InterruptedException { final TimerTask task1 = new TimerTask() { @Override public void run() { ...
  • 微信公众号 模板消息 定时推送 java

    千次阅读 2018-05-18 18:29:00
    前提:业务需要,要做一个关于月报的微信消息推送。即每个月定时自动发送一条消息 给关注 公众号的人 用的是 公众号的测试账号(实际开发需要认证的公众号) 微信官网的 模板消息接口规则: 1、所有服务号都可以...

    前提:业务需要,要做一个关于月报的微信消息推送。即每个月定时自动发送一条消息 给关注 公众号的人 

    用的是 公众号的测试账号(实际开发需要认证的公众号)

    微信官网的 模板消息接口规则:

    1、所有服务号都可以在功能->添加功能插件处看到申请模板消息功能的入口,但只有认证后的服务号才可以申请模板消息的使用权限并获得该权限;
    2、需要选择公众账号服务所处的2个行业,每月可更改1次所选行业;
    3、在所选择行业的模板库中选用已有的模板进行调用;
    4、每个账号可以同时使用25个模板。
    5、当前每个账号的模板消息的日调用上限为10万次,单个模板没有特殊限制。【2014年11月18日将接口调用频率从默认的日1万次提升为日10万次,可在MP登录后的开发者中心查看】。当账号粉丝数超过10W/100W/1000W时,模板消息的日调用上限会相应提升,以公众号MP后台开发者中心页面中标明的数字为准。

    注意点:
    1、模板消息调用时主要需要模板ID和模板中各参数的赋值内容;
    2、模板中参数内容必须以".DATA"结尾,否则视为保留字;
    3、模板保留符号"{{ }}"。

    我说下 大致思路:首先 根据 appid,appsecret 去调用 "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid="+APPID+"&secret="+APPSecret;
    返回 accessToken,这个accessToken是以后我们获取的凭证。 其次:获取所有关注人的openid 去调用 "https://api.weixin.qq.com/cgi-bin/user/get?access_token="+accessToken+"&next_openid="+next_openid;
    返回所有用户的openid(注意是数组)最后:向每一个openid的用户发消息咯 调用的接口:"https://api.weixin.qq.com/cgi-bin/message/template/send?access_token="+accessToken;
    注意:这里有post数据,官网有详细说明(json格式,其实是你的传入参数){
               "touser":"OPENID",
    "template_id":"tamplate_id,
    "url":"你需要跳转你服务器的地址",
    "data":{
    "first": {
    "value":"亲爱的童鞋,你好!",
    "color":"#173177"
    },
    "remark":{
    "value":"上月月报已到达,请查收!",
    "color":"#173177"
    }
    }
    }


    在测试的公众号 有自己的 appid,appsecret, 有关注公众号的所有人的openid,还要建立自己的一个消息模板

     
     
    如何连微信服务器:代码如下:(前面讲的获取acceToken,openid都是调用此方法获取的得到)
    //MSG为:上面post的数据

    public JSONObject HTTPURLUtil(String url,String MSG) {

    URL urlGet = null;
    JSONObject object = null;

    try {
    urlGet = new URL(url);
    HttpURLConnection http = (HttpURLConnection) urlGet.openConnection();
    http.setRequestMethod("GET"); //必须get方式请求
    http.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
    http.setDoOutput(true);
    http.setDoInput(true);
    System.setProperty("sun.net.client.defaultConnectTimeout", "30000");// 连接超时30秒
    System.setProperty("sun.net.client.defaultReadTimeout", "30000"); // 读取超时30秒
    http.connect();

    OutputStream os =null;

    if(!MSG.equals("") ) { //写消息数据
    os = http.getOutputStream();
    os.write(MSG.getBytes("UTF-8")); //传入参数
    }

    InputStream is = http.getInputStream();
    int size = is.available();
    byte[] jsonBytes = new byte[ size ];
    is.read(jsonBytes);
    String message = new String(jsonBytes, "UTF-8");
    object = JSONObject.parseObject(message);

    //关闭流
    if(!MSG.equals("")) {
    os.flush();
    os.close();
    }
    is.close();

    } catch (Exception e) {
    e.printStackTrace();
    }

    return object;
    }

    可以去微信官网查看返回json对象的参数来查看是否成功

    最后 给出 测试成功 的截图:

     

    点击详情:查看月报:(这里的地址为 post 数据里面url参数的地址  需要你自己有服务器,或者有端口映射 )

     

      这里涉及公司的 保密 暂时不放源码,如需要,请联系我 微信号:wxb909355285  共同交流

     

    转载于:https://www.cnblogs.com/xuanbo/p/9057442.html

    展开全文
  • 我要用 selenium-java + phantomjs 爬取某网页上\下的内容,这个\是一个系统消息推送节点,特点如下: 1、打开网页后,这个最初 div节点是空的(应该是通过class做了js事件监听) 2、保持网页不刷新,这个...
  • 邮件定时推送

    2019-06-10 01:11:30
    NULL 博文链接:https://lbovinl.iteye.com/blog/2337899
  • 用GoEasy推送实现Java实时推送

    千次阅读 2016-10-28 14:21:24
    用GoEasy推送实现Java实时推送 2015-12-09 11:52 by Xiqincai, 908 阅读, 3 评论, 收藏, 编辑 前段时间客户有个需求他希望他在后台管理页面发布一个消息,所有用这个系统的用户无论在哪个页面都能及时...
  • Java调用极光推送推送消息

    千次阅读 2017-02-25 17:37:30
    极光推送

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 23,508
精华内容 9,403
关键字:

java定时推送

java 订阅