Prechádzať zdrojové kódy

【NEW】新增集成个推,推送消息。业务要推送消息,直接向表bus_push_msg插入记录即可,计划任务AppMsgPushTask来完成推送,计划任务的时间cron和开启open可在表sys_scheduled_task设置。个推的相关参数在sys_config设置。

fenghao 4 rokov pred
rodič
commit
6664a84720
19 zmenil súbory, kde vykonal 1281 pridanie a 3 odobranie
  1. 12 0
      pom.xml
  2. 2 0
      railway-admin/src/main/java/com/railway/RailwayApplication.java
  3. 69 0
      railway-admin/src/main/java/com/railway/web/controller/business/push/BusPushMsgController.java
  4. 15 3
      railway-business/pom.xml
  5. 60 0
      railway-business/src/main/java/com/railway/business/push/domain/BusPushMsg.java
  6. 28 0
      railway-business/src/main/java/com/railway/business/push/enums/PushEnum.java
  7. 53 0
      railway-business/src/main/java/com/railway/business/push/mapper/BusPushMsgMapper.java
  8. 46 0
      railway-business/src/main/java/com/railway/business/push/service/IBusPushMsgService.java
  9. 290 0
      railway-business/src/main/java/com/railway/business/push/service/impl/BusPushMsgServiceImpl.java
  10. 79 0
      railway-business/src/main/java/com/railway/business/push/task/AppMsgPushTask.java
  11. 15 0
      railway-business/src/main/java/com/railway/business/push/vo/GeTuiVo.java
  12. 212 0
      railway-business/src/main/resources/mapper/push/BusPushMsgMapper.xml
  13. 75 0
      railway-framework/src/main/java/com/railway/framework/config/ConfigurerSchedulingTask.java
  14. 35 0
      railway-system/src/main/java/com/railway/system/domain/SysScheduledTask.java
  15. 44 0
      railway-system/src/main/java/com/railway/system/mapper/SysScheduledTaskMapper.java
  16. 40 0
      railway-system/src/main/java/com/railway/system/service/ISysScheduledTaskService.java
  17. 75 0
      railway-system/src/main/java/com/railway/system/service/impl/SysScheduledTaskServiceImpl.java
  18. 96 0
      railway-system/src/main/resources/mapper/system/SysScheduledTaskMapper.xml
  19. 35 0
      sql/getui.sql

+ 12 - 0
pom.xml

@@ -45,6 +45,7 @@
     <jwt.version>0.9.1</jwt.version>
     <tobato.version>1.27.2</tobato.version>
     <minio.version>8.2.2</minio.version>
+    <getui.version>4.1.0.5</getui.version>
   </properties>
 
   <!-- 依赖声明 -->
@@ -196,6 +197,13 @@
         <version>${lombok.version}</version>
       </dependency>
 
+      <!-- 个推 -->
+      <dependency>
+        <groupId>com.gexin.platform</groupId>
+        <artifactId>gexin-rp-sdk-http</artifactId>
+        <version>${getui.version}</version>
+      </dependency>
+
       <!-- 核心模块-->
       <dependency>
         <groupId>com.railway</groupId>
@@ -251,6 +259,10 @@
         <enabled>true</enabled>
       </releases>
     </repository>
+    <repository>
+      <id>getui-nexus</id>
+      <url>http://mvn.gt.getui.com/nexus/content/repositories/releases/</url>
+    </repository>
   </repositories>
 
   <pluginRepositories>

+ 2 - 0
railway-admin/src/main/java/com/railway/RailwayApplication.java

@@ -3,6 +3,7 @@ package com.railway;
 import org.springframework.boot.SpringApplication;
 import org.springframework.boot.autoconfigure.SpringBootApplication;
 import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
+import org.springframework.scheduling.annotation.EnableScheduling;
 import springfox.documentation.oas.annotations.EnableOpenApi;
 
 /**
@@ -11,6 +12,7 @@ import springfox.documentation.oas.annotations.EnableOpenApi;
  * @author railway
  */
 @EnableOpenApi
+@EnableScheduling
 @SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})
 public class RailwayApplication {
 

+ 69 - 0
railway-admin/src/main/java/com/railway/web/controller/business/push/BusPushMsgController.java

@@ -0,0 +1,69 @@
+package com.railway.web.controller.business.push;
+
+import com.railway.business.push.domain.BusPushMsg;
+import com.railway.business.push.service.IBusPushMsgService;
+import com.railway.common.core.controller.BaseController;
+import com.railway.common.core.domain.AjaxResult;
+import com.railway.common.core.page.TableDataInfo;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+import javax.validation.Valid;
+import java.util.List;
+
+@Api(value = "rest/push/bus/push/msg", tags = "个推消息表")
+@RestController
+@Validated
+@RequestMapping(value = "business/push/bus/push/msg")
+public class BusPushMsgController extends BaseController {
+    @Autowired
+    private IBusPushMsgService busPushMsgService;
+
+    @ApiOperation(value = "新增")
+    @PostMapping("/add")
+    public AjaxResult add(@Validated @RequestBody BusPushMsg busPushMsg) {
+        return toAjax(busPushMsgService.create(busPushMsg));
+    }
+
+    @ApiOperation(value = "删除")
+    @DeleteMapping("/{ids}")
+    public AjaxResult delete(@PathVariable(value = "ids") String[] ids) {
+        return toAjax(busPushMsgService.delete(ids));
+    }
+
+    @ApiOperation(value = "更新")
+    @PutMapping("/update")
+    public AjaxResult update(@RequestBody @Valid BusPushMsg busPushMsg) {
+        return toAjax(busPushMsgService.update(busPushMsg));
+    }
+
+    @ApiOperation(value = "单个")
+    @GetMapping(value = {"/", "/{id}"})
+    public AjaxResult getInfo(@PathVariable(value = "id") String id) {
+        BusPushMsg info = busPushMsgService.getInfo(id);
+        AjaxResult ajax = AjaxResult.success();
+        ajax.put("info",info);
+        return ajax;
+    }
+
+    @ApiOperation(value = "列表")
+    @GetMapping(value = "list")
+    public TableDataInfo getList(BusPushMsg busPushMsg) {
+        startPage();
+        List<BusPushMsg> list = busPushMsgService.getList(busPushMsg);
+        return getDataTable(list);
+    }
+
+    @ApiOperation(value = "最近的5条消息")
+    @GetMapping(value = "getListTop5")
+    public AjaxResult getListTop5(BusPushMsg busPushMsg) {
+        List<BusPushMsg> list = busPushMsgService.getListTop5(busPushMsg);
+        AjaxResult ajax = AjaxResult.success();
+        ajax.put("rows",list);
+        return ajax;
+    }
+
+}

+ 15 - 3
railway-business/pom.xml

@@ -35,11 +35,23 @@
             <groupId>io.swagger</groupId>
             <artifactId>swagger-annotations</artifactId>
         </dependency>
+        <dependency>
+            <groupId>com.gexin.platform</groupId>
+            <artifactId>gexin-rp-sdk-http</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.railway</groupId>
+            <artifactId>railway-system</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.railway</groupId>
+            <artifactId>railway-framework</artifactId>
+        </dependency>
     </dependencies>
 
     <properties>
-    <maven.compiler.source>8</maven.compiler.source>
-    <maven.compiler.target>8</maven.compiler.target>
-  </properties>
+        <maven.compiler.source>8</maven.compiler.source>
+        <maven.compiler.target>8</maven.compiler.target>
+      </properties>
 
 </project>

+ 60 - 0
railway-business/src/main/java/com/railway/business/push/domain/BusPushMsg.java

@@ -0,0 +1,60 @@
+package com.railway.business.push.domain;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.railway.common.core.domain.BaseEntity;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import org.hibernate.validator.constraints.Length;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import java.util.Date;
+/**
+ * 个推消息表
+ * @author author 2021-11-22
+ */
+@Data
+@ApiModel("个推消息表")
+@EqualsAndHashCode(callSuper = true)
+public class BusPushMsg extends BaseEntity{
+
+    @ApiModelProperty(value = "主键", hidden = true)
+    private Long id;
+
+    @ApiModelProperty(value = "用户id")
+    private Long userId;
+
+    @ApiModelProperty(value = "客户端id,app端提供")
+    private String clientId;
+
+    @ApiModelProperty(value = "客户端类型:0-android;1-ios")
+    private Integer clientType;
+
+    @ApiModelProperty(value = "消息标题")
+    private String title;
+
+    @ApiModelProperty(value = "消息内容")
+    private String content;
+
+    @ApiModelProperty(value = "ios专用")
+    private String iosAlertMsg;
+
+    @ApiModelProperty(value = "推送时间")
+    @DateTimeFormat(pattern = "yyyy-MM-dd")
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private Date pushTime;
+
+    @ApiModelProperty(value = "推送状态:0-未推送;1-推送成功;2-推送失败;3-服务器响应异常;")
+    private String pushStatus;
+
+    @ApiModelProperty(value = "推送结果说明")
+    private String pushResultDesc;
+
+    @ApiModelProperty(value = "推送轮数")
+    private Integer pushLoop;
+
+    public BusPushMsg() {
+    }
+
+}

+ 28 - 0
railway-business/src/main/java/com/railway/business/push/enums/PushEnum.java

@@ -0,0 +1,28 @@
+package com.railway.business.push.enums;
+
+public enum PushEnum {
+
+    /** 推送状态 */
+    GE_TUI_OK("ok", "成功"),
+    PUSH_STATUS_NOT("0","未推送"),
+    PUSH_STATUS_SUCCES("1", "推送成功"),
+    PUSH_STATUS_ERROR_PUSH("2", "推送失败"),
+    PUSH_STATUS_ERROR_SERVE("3", "服务器响应异常"),
+    ;
+
+    private final String code;
+    private final String info;
+
+    PushEnum(String code, String info) {
+        this.code = code;
+        this.info = info;
+    }
+
+    public String getCode() {
+        return code;
+    }
+
+    public String getInfo() {
+        return info;
+    }
+}

+ 53 - 0
railway-business/src/main/java/com/railway/business/push/mapper/BusPushMsgMapper.java

@@ -0,0 +1,53 @@
+package com.railway.business.push.mapper;
+
+import com.github.pagehelper.Page;
+import com.railway.business.push.domain.BusPushMsg;
+import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
+import org.springframework.stereotype.Repository;
+
+import java.util.List;
+
+/**
+* 个推消息表
+* @author author
+* @date 2021/11/16
+*/
+@Mapper
+@Repository
+public interface BusPushMsgMapper {
+
+    /**
+    * 新增
+    */
+    int insert(BusPushMsg busPushMsg);
+
+    /**
+    * 删除
+    */
+    int delete(@Param("id") String id);
+
+    /**
+    * 更新
+    */
+    int update(BusPushMsg busPushMsg);
+
+    /**
+    * 获取单个
+    */
+    BusPushMsg getInfo(@Param("id") String id);
+
+    /**
+    * 查询列表
+    */
+    Page<BusPushMsg> getList(BusPushMsg busPushMsg);
+
+    List<BusPushMsg> selectAppMsg();
+
+    /**
+     * 查询最近5条
+     * @param busPushMsg
+     * @return
+     */
+    Page<BusPushMsg> getListTop5(BusPushMsg busPushMsg);
+}

+ 46 - 0
railway-business/src/main/java/com/railway/business/push/service/IBusPushMsgService.java

@@ -0,0 +1,46 @@
+package com.railway.business.push.service;
+
+import com.railway.business.push.domain.BusPushMsg;
+import java.util.List;
+/**
+* 个推消息表
+* @author author
+* @date 2021/11/16
+*/
+public interface IBusPushMsgService{
+
+    /**
+    * 新增
+    */
+    int create(BusPushMsg busPushMsg);
+
+    /**
+    * 删除
+    */
+    int delete(String[] ids);
+
+    /**
+    * 更新
+    */
+    int update(BusPushMsg busPushMsg);
+
+    /**
+    * 获取单个
+    */
+    BusPushMsg getInfo(String id);
+
+    /**
+    * 查询列表
+    */
+    List<BusPushMsg> getList(BusPushMsg busPushMsg);
+
+    List<BusPushMsg> selectAppMsg();
+
+    List<BusPushMsg> getListTop5(BusPushMsg busPushMsg);
+
+    String pushToSingle(BusPushMsg busPushMsg);
+
+    void pushToSingleBatch(List<BusPushMsg> msgPos);
+
+    void updateBatch(List<BusPushMsg> msgPos);
+}

+ 290 - 0
railway-business/src/main/java/com/railway/business/push/service/impl/BusPushMsgServiceImpl.java

@@ -0,0 +1,290 @@
+package com.railway.business.push.service.impl;
+
+import com.gexin.fastjson.JSONObject;
+import com.gexin.rp.sdk.base.IBatch;
+import com.gexin.rp.sdk.base.IPushResult;
+import com.gexin.rp.sdk.base.impl.SingleMessage;
+import com.gexin.rp.sdk.base.impl.Target;
+import com.gexin.rp.sdk.exceptions.RequestException;
+import com.gexin.rp.sdk.http.IGtPush;
+import com.gexin.rp.sdk.template.AbstractTemplate;
+import com.gexin.rp.sdk.template.NotificationTemplate;
+import com.gexin.rp.sdk.template.TransmissionTemplate;
+import com.gexin.rp.sdk.template.style.Style0;
+import com.railway.business.push.domain.BusPushMsg;
+import com.railway.business.push.enums.PushEnum;
+import com.railway.business.push.mapper.BusPushMsgMapper;
+import com.railway.business.push.service.IBusPushMsgService;
+import com.railway.common.utils.SecurityUtils;
+import com.railway.system.service.ISysConfigService;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.io.IOException;
+import java.util.Date;
+import java.util.List;
+/**
+* 个推消息表
+* @author author
+* @date 2021/11/16
+*/
+@Slf4j
+@Service
+@Transactional(readOnly = true)
+public class BusPushMsgServiceImpl implements IBusPushMsgService{
+
+	private final ISysConfigService configService;
+	private BusPushMsgMapper busPushMsgMapper;
+
+	/**
+	 * 每个应用都对应一个唯一的AppID
+	 */
+	private String appId;
+	/**
+	 * SDK 与服务器端通过 Appkey 互相识别
+	 */
+	private  String appKey;
+	/**
+	 * 服务端API鉴权码
+	 */
+	private String masterSecret;
+
+	/**
+	 * 批量单传使用
+	 */
+	private IGtPush push;
+
+	public BusPushMsgServiceImpl(ISysConfigService configService, BusPushMsgMapper busPushMsgMapper) {
+		this.configService = configService;
+		this.busPushMsgMapper = busPushMsgMapper;
+		this.appId = this.configService.selectConfigByKey("getui.appId");
+		this.appKey = this.configService.selectConfigByKey("getui.appKey");
+		this.masterSecret = this.configService.selectConfigByKey("getui.masterSecret");
+
+		push = new IGtPush(appKey, masterSecret);
+	}
+
+	/**
+	* 新增
+	*/
+	@Transactional(rollbackFor = Exception.class)
+	public int create(BusPushMsg busPushMsg) {
+	    busPushMsg.setCreateTime(new Date());
+        busPushMsg.setCreateBy(SecurityUtils.getUsername());
+		busPushMsg.setPushStatus("0");
+		busPushMsg.setPushLoop(0);
+		return busPushMsgMapper.insert(busPushMsg);
+	}
+
+	/**
+	* 删除
+	*/
+	@Transactional(rollbackFor = Exception.class)
+	public int delete(String[] ids) {
+		int r =0;
+		for (String id : ids) {
+			int j= busPushMsgMapper.delete(id);
+			r = r + j;
+		}
+		return	r;
+	}
+
+	/**
+	* 更新
+	*/
+	@Transactional(rollbackFor = Exception.class)
+	public int update(BusPushMsg busPushMsg) {
+		busPushMsg.setUpdateTime(new Date());
+    	busPushMsg.setUpdateBy(SecurityUtils.getUsername());
+		return busPushMsgMapper.update(busPushMsg);
+	}
+
+	/**
+	* 获取单个
+	*/
+	public BusPushMsg getInfo(String id) {
+		return busPushMsgMapper.getInfo(id);
+	}
+
+	/**
+	* 查询列表
+	*/
+	public List<BusPushMsg> getList(BusPushMsg busPushMsg) {
+		return busPushMsgMapper.getList(busPushMsg);
+	}
+
+	@Override
+	public List<BusPushMsg> selectAppMsg() {
+		return busPushMsgMapper.selectAppMsg();
+	}
+
+	@Override
+	public List<BusPushMsg> getListTop5(BusPushMsg busPushMsg) {
+		// 查询已推送的
+		busPushMsg.setPushStatus(PushEnum.PUSH_STATUS_SUCCES.getCode());
+		return busPushMsgMapper.getListTop5(busPushMsg);
+	}
+
+	@Override
+	@Transactional(rollbackFor = Exception.class)
+	public void updateBatch(List<BusPushMsg> msgPos) {
+		for (BusPushMsg msg : msgPos) {
+			busPushMsgMapper.update(msg);
+		}
+	}
+
+	/**
+	 * 对单个用户推送消息
+	 *
+	 * @return
+	 */
+	@Override
+	public String pushToSingle(BusPushMsg msgPo) {
+		AbstractTemplate template = getTransmissionTemplate(msgPo.getContent());
+		// 单推消息类型
+		SingleMessage message = getSingleMessage(template);
+		Target target = new Target();
+		target.setAppId(appId);
+		target.setClientId(msgPo.getClientId());
+		IPushResult ret = null;
+		try {
+			if (push != null) {
+				ret = push.pushMessageToSingle(message, target);
+			}
+			else {
+				return "个推服务IGtPush创建异常";
+			}
+		} catch (RequestException e) {
+			log.error("消息发送失败,尝试1次重发", e);
+			ret = push.pushMessageToSingle(message, target, e.getRequestId());
+		}
+		if (ret != null) {
+			JSONObject jsonObject = new JSONObject();
+			jsonObject.putAll(ret.getResponse());
+			return jsonObject.toJSONString();
+		} else {
+			return "服务器响应异常";
+		}
+	}
+
+	/**
+	 * 透传消息,消息传递到客户端只有消息内容,展现形式由客户端自行定义
+	 * 注:ios端只支持透传消息
+	 *
+	 * @param content
+	 * @return
+	 */
+	private TransmissionTemplate getTransmissionTemplate(String content) {
+		TransmissionTemplate template = new TransmissionTemplate();
+		template.setAppId(appId);
+		template.setAppkey(appKey);
+		//透传消息设置,1为强制启动应用,客户端接收到消息后就会立即启动应用;2为等待应用启动
+		template.setTransmissionType(1);
+		template.setTransmissionContent(content);
+		return template;
+	}
+
+	/**
+	 * 通知模板
+	 * @param title
+	 * @param text
+	 * @return
+	 */
+	private NotificationTemplate getNotificationTemplate(String title, String text) {
+		Style0 style = new Style0();
+		// 设置推送标题、推送内容
+		style.setTitle(title);
+		style.setText(text);
+		// style.setLogo("push.png");  // 设置推送图标
+		// 设置响铃、震动等推送效果
+		style.setRing(true);  // 设置响铃
+		style.setVibrate(true);  // 设置震动
+
+		// 选择通知模板
+		NotificationTemplate template = new NotificationTemplate();
+		template.setAppId(appId);
+		template.setAppkey(appKey);
+		template.setStyle(style);
+		return template;
+	}
+
+	private SingleMessage getSingleMessage(AbstractTemplate template) {
+		SingleMessage message = new SingleMessage();
+		message.setData(template);
+		// 设置消息离线,并设置离线时间
+		message.setOffline(true);
+		// 离线有效时间,单位为毫秒
+		message.setOfflineExpireTime(72 * 3600 * 1000);
+		message.setPriority(1);
+		// 判断客户端是否wifi环境下推送。1为仅在wifi环境下推送,0为不限制网络环境,默认不限
+		message.setPushNetWorkType(0);
+		return message;
+	}
+
+	/**
+	 * 批量单推
+	 * <p>
+	 * 当单推任务较多时,推荐使用该接口,可以减少与服务端的交互次数。
+	 */
+	@Override
+	public void pushToSingleBatch(List<BusPushMsg> msgPos) {
+		IBatch batch = push.getBatch();
+		IPushResult ret = null;
+		try {
+			//构建客户a的透传消息a
+			for (BusPushMsg msgPo : msgPos) {
+				constructClientTransMsg(msgPo.getClientId(), batch, msgPo.getContent());
+			}
+			ret = batch.submit();
+		} catch (Exception e) {
+			e.printStackTrace();
+			try {
+				ret = batch.retry();
+			} catch (IOException ex) {
+				ex.printStackTrace();
+			}
+		}
+		if (ret != null) {
+			log.info(ret.getResponse().toString());
+		} else {
+			log.info("服务器响应异常");
+		}
+	}
+
+	private void constructClientTransMsg(String cid, IBatch batch, String content) throws Exception {
+		AbstractTemplate template = getTransmissionTemplate(content);
+		SingleMessage message = getSingleMessage(template);
+		// 设置推送目标,填入appid和clientId
+		Target target = new Target();
+		target.setAppId(appId);
+		target.setClientId(cid);
+		batch.add(message, target);
+	}
+
+	/**
+
+	 public BusPushMsgServiceImpl() {
+
+	 }
+
+	 public BusPushMsgServiceImpl(String appId, String appKey, String masterSecret, boolean enable) {
+		 this.appId = appId;
+		 this.appKey = appKey;
+		 this.masterSecret = masterSecret;
+		 this.enable = enable;
+		 push = new IGtPush(appKey, masterSecret);
+	 }
+
+	public static void main(String[] args) {
+		BusPushMsgServiceImpl push = new BusPushMsgServiceImpl("Y3xRJmer116Bb1HhqnZav7","N2oftDIHyC9o1Ue73Cx3fA","OZhDEZbGTZ9tc8P8IQ3Mk3",true);
+		BusPushMsg msgPo = new BusPushMsg();
+		msgPo.setClientId("d2a737569978aa43f42b2a8c562f69b1");
+		msgPo.setContent("测试服务器端push内容main");
+		String result = push.pushToSingle(msgPo);
+		System.out.println(result);
+	}
+	 */
+
+}

+ 79 - 0
railway-business/src/main/java/com/railway/business/push/task/AppMsgPushTask.java

@@ -0,0 +1,79 @@
+package com.railway.business.push.task;
+
+import com.gexin.fastjson.JSONObject;
+import com.railway.business.push.domain.BusPushMsg;
+import com.railway.business.push.enums.PushEnum;
+import com.railway.business.push.service.IBusPushMsgService;
+import com.railway.business.push.vo.GeTuiVo;
+import com.railway.framework.config.ConfigurerSchedulingTask;
+import com.railway.system.service.ISysConfigService;
+import com.railway.system.service.ISysScheduledTaskService;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.context.annotation.Configuration;
+
+import java.util.Date;
+import java.util.List;
+
+@Slf4j
+@Configuration
+public class AppMsgPushTask extends ConfigurerSchedulingTask {
+
+    private final ISysConfigService configService;
+    private final IBusPushMsgService busPushMsgService;
+    private final ISysScheduledTaskService sysScheduledTaskService;
+
+    public AppMsgPushTask(ISysConfigService configService, IBusPushMsgService busPushMsgService,
+                          ISysScheduledTaskService sysScheduledTaskService) {
+        this.configService = configService;
+        this.busPushMsgService = busPushMsgService;
+        this.sysScheduledTaskService = sysScheduledTaskService;
+    }
+
+    @Override
+    public void taskService() {
+        log.debug("个推task开始......");
+        Integer open = this.getOpen();
+        log.debug("个推开关 {}", open == 1);
+        // 个推开关
+        if (1 == open) {
+            // 查询需要发送的消息(未推送/推送失败且小于6轮)
+            List<BusPushMsg> msgPos = busPushMsgService.selectAppMsg();
+            if (msgPos.size() == 0) {
+                return;
+            }
+            Date curTime = new Date();
+            for (BusPushMsg msgPo : msgPos) {
+                msgPo.setPushLoop((msgPo.getPushLoop() + 1));
+                msgPo.setPushTime(curTime);
+                try {
+                    String result = busPushMsgService.pushToSingle(msgPo);
+                    //保存 解析 个推服务器的响应
+                    msgPo.setPushResultDesc(result);
+                    GeTuiVo geTuiVo = JSONObject.parseObject(result, GeTuiVo.class);
+                    if (geTuiVo != null) {
+                        if (PushEnum.GE_TUI_OK.getCode().equals(geTuiVo.getResult())) {
+                            msgPo.setPushStatus(PushEnum.PUSH_STATUS_SUCCES.getCode());
+                        } else {
+                            msgPo.setPushStatus(PushEnum.PUSH_STATUS_ERROR_PUSH.getCode());
+                        }
+                    }
+                } catch (Exception e) {
+                    msgPo.setPushStatus(PushEnum.PUSH_STATUS_ERROR_SERVE.getCode());
+                    msgPo.setPushResultDesc("个推服务器出错");
+                    log.error("个推服务器出错", e);
+                }
+            }
+            busPushMsgService.updateBatch(msgPos);
+        }
+        log.debug("个推task结束......");
+    }
+
+    @Override
+    public String getCron() {
+        return sysScheduledTaskService.getInfoByName("getui").getCron();
+    }
+
+    public Integer getOpen() {
+        return sysScheduledTaskService.getInfoByName("getui").getOpen();
+    }
+}

+ 15 - 0
railway-business/src/main/java/com/railway/business/push/vo/GeTuiVo.java

@@ -0,0 +1,15 @@
+package com.railway.business.push.vo;
+
+import lombok.Data;
+
+import java.io.Serializable;
+
+@Data
+public class GeTuiVo implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    private String result;
+    private String taskId;
+    private String status;
+}

+ 212 - 0
railway-business/src/main/resources/mapper/push/BusPushMsgMapper.xml

@@ -0,0 +1,212 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.railway.business.push.mapper.BusPushMsgMapper">
+
+    <resultMap id="BaseResultMap" type="com.railway.business.push.domain.BusPushMsg">
+        <result column="id" property="id"/>
+        <result column="user_id" property="userId"/>
+        <result column="client_id" property="clientId"/>
+        <result column="client_type" property="clientType"/>
+        <result column="title" property="title"/>
+        <result column="content" property="content"/>
+        <result column="ios_alert_msg" property="iosAlertMsg"/>
+        <result column="create_time" property="createTime"/>
+        <result column="push_time" property="pushTime"/>
+        <result column="push_status" property="pushStatus"/>
+        <result column="push_result_desc" property="pushResultDesc"/>
+        <result column="push_loop" property="pushLoop"/>
+    </resultMap>
+
+    <sql id="Base_Column_List">
+        id,
+                user_id,
+                client_id,
+                client_type,
+                title,
+                content,
+                ios_alert_msg,
+                create_time,
+                push_time,
+                push_status,
+                push_result_desc,
+                push_loop
+    </sql>
+
+    <insert id="insert" parameterType="com.railway.business.push.domain.BusPushMsg">
+        <selectKey keyProperty="id" order="AFTER" resultType="Long">
+            select @@IDENTITY as id
+        </selectKey>
+        INSERT INTO bus_push_msg
+        <trim prefix="(" suffix=")" suffixOverrides=",">
+            <if test ='null != userId'>
+                user_id,
+            </if>
+            <if test ='null != clientId'>
+                client_id,
+            </if>
+            <if test ='null != clientType'>
+                client_type,
+            </if>
+            <if test ='null != title'>
+                title,
+            </if>
+            <if test ='null != content'>
+                content,
+            </if>
+            <if test ='null != iosAlertMsg'>
+                ios_alert_msg,
+            </if>
+            <if test ='null != createTime'>
+                create_time,
+            </if>
+            <if test ='null != pushTime'>
+                push_time,
+            </if>
+            <if test ='null != pushStatus'>
+                push_status,
+            </if>
+            <if test ='null != pushResultDesc'>
+                push_result_desc,
+            </if>
+            <if test ='null != pushLoop'>
+                push_loop
+            </if>
+        </trim>
+        <trim prefix="values (" suffix=")" suffixOverrides=",">
+            <if test ='null != userId'>
+                #{userId},
+            </if>
+            <if test ='null != clientId'>
+                #{clientId},
+            </if>
+            <if test ='null != clientType'>
+                #{clientType},
+            </if>
+            <if test ='null != title'>
+                #{title},
+            </if>
+            <if test ='null != content'>
+                #{content},
+            </if>
+            <if test ='null != iosAlertMsg'>
+                #{iosAlertMsg},
+            </if>
+            <if test ='null != createTime'>
+                #{createTime},
+            </if>
+            <if test ='null != pushTime'>
+                #{pushTime},
+            </if>
+            <if test ='null != pushStatus'>
+                #{pushStatus},
+            </if>
+            <if test ='null != pushResultDesc'>
+                #{pushResultDesc},
+            </if>
+            <if test ='null != pushLoop'>
+                #{pushLoop}
+            </if>
+        </trim>
+    </insert>
+
+    <delete id="delete">
+        DELETE FROM bus_push_msg
+        WHERE id = #{id}
+    </delete>
+
+    <update id="update" parameterType="com.railway.business.push.domain.BusPushMsg">
+        UPDATE bus_push_msg
+        <set>
+            <if test ='null != userId'>user_id = #{userId},</if>
+            <if test ='null != clientId'>client_id = #{clientId},</if>
+            <if test ='null != clientType'>client_type = #{clientType},</if>
+            <if test ='null != title'>title = #{title},</if>
+            <if test ='null != content'>content = #{content},</if>
+            <if test ='null != iosAlertMsg'>ios_alert_msg = #{iosAlertMsg},</if>
+            <if test ='null != createTime'>create_time = #{createTime},</if>
+            <if test ='null != pushTime'>push_time = #{pushTime},</if>
+            <if test ='null != pushStatus'>push_status = #{pushStatus},</if>
+            <if test ='null != pushResultDesc'>push_result_desc = #{pushResultDesc},</if>
+            <if test ='null != pushLoop'>push_loop = #{pushLoop}</if>
+        </set>
+        WHERE id = #{id}
+    </update>
+
+
+    <select id="getInfo" resultMap="BaseResultMap">
+        SELECT
+        <include refid="Base_Column_List"/>
+        FROM bus_push_msg
+        WHERE id = #{id}
+
+    </select>
+
+    <select id="getList" resultMap="BaseResultMap">
+        SELECT
+        <include refid="Base_Column_List"/>
+        FROM bus_push_msg
+        <where>
+            <if test="userId!=null and userId!=''">
+                and user_id=#{userId}
+            </if>
+            <if test="clientId!=null and clientId!=''">
+                and client_id=#{clientId}
+            </if>
+            <if test="clientType!=null and clientType!=''">
+                and client_type=#{clientType}
+            </if>
+            <if test="title!=null and title!=''">
+                and title=#{title}
+            </if>
+            <if test="content!=null and content!=''">
+                and content=#{content}
+            </if>
+            <if test="iosAlertMsg!=null and iosAlertMsg!=''">
+                and ios_alert_msg=#{iosAlertMsg}
+            </if>
+            <if test="createTime!=null">
+                and DATE_FORMAT(t.create_time, '%Y-%m-%d') = #{createTime}
+            </if>
+            <if test="pushTime!=null">
+                and DATE_FORMAT(t.push_time, '%Y-%m-%d') = #{pushTime}
+            </if>
+            <if test="pushStatus!=null and pushStatus!=''">
+                and push_status=#{pushStatus}
+            </if>
+            <if test="pushResultDesc!=null and pushResultDesc!=''">
+                and push_result_desc=#{pushResultDesc}
+            </if>
+            <if test="pushLoop!=null and pushLoop!=''">
+                and push_loop=#{pushLoop}
+            </if>
+        </where>
+    </select>
+
+    <select id="selectAppMsg" resultMap="BaseResultMap">
+        SELECT
+        <include refid="Base_Column_List"/>
+        FROM bus_push_msg
+        where (push_status = '0' or push_status = '2')
+        <![CDATA[
+            and push_loop < 6
+        ]]>
+    </select>
+
+    <select id="getListTop5" resultMap="BaseResultMap">
+        SELECT
+        <include refid="Base_Column_List"/>
+        FROM bus_push_msg
+        <where>
+            <if test="userId!=null and userId!=''">
+                and user_id=#{userId}
+            </if>
+            <if test="pushStatus!=null and pushStatus!=''">
+                and push_status=#{pushStatus}
+            </if>
+        </where>
+        ORDER BY push_time DESC
+        LIMIT 5
+    </select>
+
+</mapper>

+ 75 - 0
railway-framework/src/main/java/com/railway/framework/config/ConfigurerSchedulingTask.java

@@ -0,0 +1,75 @@
+package com.railway.framework.config;
+
+import com.google.common.util.concurrent.ThreadFactoryBuilder;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.scheduling.annotation.EnableScheduling;
+import org.springframework.scheduling.annotation.SchedulingConfigurer;
+import org.springframework.scheduling.config.ScheduledTaskRegistrar;
+import org.springframework.scheduling.support.CronTrigger;
+
+import java.util.concurrent.Executor;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ThreadFactory;
+
+/**
+ * @Description: 基于接口SchedulingConfigurer的动态定时任务
+ * @Author:
+ */
+@Configuration
+@EnableScheduling
+public abstract class ConfigurerSchedulingTask implements SchedulingConfigurer {
+
+  //定时任务周期表达式
+  private String cron;
+  /**
+   * @Description:  重写配置定时任务的方法
+   * @param: scheduledTaskRegistrar
+   * @return: void
+   * @Author:
+   */
+  @Override
+  public void configureTasks(ScheduledTaskRegistrar scheduledTaskRegistrar) {
+    scheduledTaskRegistrar.setScheduler(taskScheduler());
+    scheduledTaskRegistrar.addTriggerTask(
+            //执行定时任务
+            () ->
+            {
+              taskService();
+            },
+            //设置触发器
+            triggerContext -> {
+
+              cron = getCron();//获取定时任务周期表达式
+
+              CronTrigger trigger = new CronTrigger(cron);
+
+              return trigger.nextExecutionTime(triggerContext);
+            }
+    );
+
+  }
+
+  public Executor taskScheduler() {
+    //设置线程名称
+    ThreadFactory namedThreadFactory = new ThreadFactoryBuilder().setNameFormat("demo-pool-%d").build();
+    //创建线程池
+    return Executors.newScheduledThreadPool(5, namedThreadFactory);
+  }
+
+  /**
+   * @Description: 执行定时任务
+   * @param:
+   * @return: void
+   * @Author:
+   */
+  public abstract void taskService();
+
+  /**
+   * @Description: 获取定时任务周期表达式
+   * @param:
+   * @return: java.lang.String
+   * @Author:
+   */
+  public abstract String getCron();
+
+}

+ 35 - 0
railway-system/src/main/java/com/railway/system/domain/SysScheduledTask.java

@@ -0,0 +1,35 @@
+package com.railway.system.domain;
+
+import com.railway.common.core.domain.BaseEntity;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import org.hibernate.validator.constraints.Length;
+/**
+ * 系统计划任务表
+ * @author author 2021-12-09
+ */
+@Data
+@ApiModel("系统计划任务表")
+@EqualsAndHashCode(callSuper = true)
+public class SysScheduledTask extends BaseEntity{
+
+    @ApiModelProperty(value = "主键", hidden = true)
+    private Long id;
+
+    @ApiModelProperty(value = "任务名称")
+    @Length(min = 1, max = 50, message = "【任务名称】长度必须介于 {min} 和 {max} 之间")
+    private String name;
+
+    @ApiModelProperty(value = "任务cron")
+    @Length(min = 1, max = 30, message = "【任务cron】长度必须介于 {min} 和 {max} 之间")
+    private String cron;
+
+    @ApiModelProperty(value = "1开启,0关闭")
+    private Integer open;
+
+    public SysScheduledTask() {
+    }
+
+}

+ 44 - 0
railway-system/src/main/java/com/railway/system/mapper/SysScheduledTaskMapper.java

@@ -0,0 +1,44 @@
+package com.railway.system.mapper;
+
+import com.github.pagehelper.Page;
+import com.railway.system.domain.SysScheduledTask;
+import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
+import org.springframework.stereotype.Repository;
+
+/**
+* 系统计划任务表
+* @author author
+* @date 2021/12/09
+*/
+@Mapper
+@Repository
+public interface SysScheduledTaskMapper {
+
+    /**
+    * 新增
+    */
+    int insert(SysScheduledTask sysScheduledTask);
+
+    /**
+    * 删除
+    */
+    int delete(@Param("id") String id);
+
+    /**
+    * 更新
+    */
+    int update(SysScheduledTask sysScheduledTask);
+
+    /**
+    * 获取单个
+    */
+    SysScheduledTask getInfo(@Param("id") String id);
+
+    SysScheduledTask getInfoByName(@Param("name") String name);
+    /**
+    * 查询列表
+    */
+    Page<SysScheduledTask> getList(SysScheduledTask sysScheduledTask);
+
+}

+ 40 - 0
railway-system/src/main/java/com/railway/system/service/ISysScheduledTaskService.java

@@ -0,0 +1,40 @@
+package com.railway.system.service;
+
+import com.railway.system.domain.SysScheduledTask;
+
+import java.util.List;
+/**
+* 系统计划任务表
+* @author author
+* @date 2021/12/09
+*/
+public interface ISysScheduledTaskService{
+
+    /**
+    * 新增
+    */
+    int create(SysScheduledTask sysScheduledTask);
+
+    /**
+    * 删除
+    */
+    int delete(String[] ids);
+
+    /**
+    * 更新
+    */
+    int update(SysScheduledTask sysScheduledTask);
+
+    /**
+    * 获取单个
+    */
+    SysScheduledTask getInfo(String id);
+
+    SysScheduledTask getInfoByName(String name);
+
+    /**
+    * 查询列表
+    */
+    List<SysScheduledTask> getList(SysScheduledTask sysScheduledTask);
+
+}

+ 75 - 0
railway-system/src/main/java/com/railway/system/service/impl/SysScheduledTaskServiceImpl.java

@@ -0,0 +1,75 @@
+package com.railway.system.service.impl;
+
+import com.railway.common.utils.SecurityUtils;
+import com.railway.system.domain.SysScheduledTask;
+import com.railway.system.mapper.SysScheduledTaskMapper;
+import com.railway.system.service.ISysScheduledTaskService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.util.Date;
+import java.util.List;
+/**
+* 系统计划任务表
+* @author author
+* @date 2021/12/09
+*/
+@Service
+@Transactional(readOnly = true)
+public class SysScheduledTaskServiceImpl implements ISysScheduledTaskService {
+@Autowired
+private SysScheduledTaskMapper sysScheduledTaskMapper;
+
+	/**
+	* 新增
+	*/
+	@Transactional(rollbackFor = Exception.class)
+	public int create(SysScheduledTask sysScheduledTask) {
+	    sysScheduledTask.setCreateTime(new Date());
+        sysScheduledTask.setCreateBy(SecurityUtils.getUsername());
+		return sysScheduledTaskMapper.insert(sysScheduledTask);
+	}
+
+	/**
+	* 删除
+	*/
+	@Transactional(rollbackFor = Exception.class)
+	public int delete(String[] ids) {
+		int r =0;
+		for (String id : ids) {
+			int j= sysScheduledTaskMapper.delete(id);
+			r = r + j;
+		}
+		return	r;
+	}
+
+	/**
+	* 更新
+	*/
+	@Transactional(rollbackFor = Exception.class)
+	public int update(SysScheduledTask sysScheduledTask) {
+		sysScheduledTask.setUpdateTime(new Date());
+    	sysScheduledTask.setUpdateBy(SecurityUtils.getUsername());
+		return sysScheduledTaskMapper.update(sysScheduledTask);
+	}
+
+	/**
+	* 获取单个
+	*/
+	public SysScheduledTask getInfo(String id) {
+		return sysScheduledTaskMapper.getInfo(id);
+	}
+
+	@Override
+	public SysScheduledTask getInfoByName(String name) {
+		return sysScheduledTaskMapper.getInfoByName(name);
+	}
+
+	/**
+	* 查询列表
+	*/
+	public List<SysScheduledTask> getList(SysScheduledTask sysScheduledTask) {
+		return sysScheduledTaskMapper.getList(sysScheduledTask);
+	}
+}

+ 96 - 0
railway-system/src/main/resources/mapper/system/SysScheduledTaskMapper.xml

@@ -0,0 +1,96 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.railway.system.mapper.SysScheduledTaskMapper">
+
+    <resultMap id="BaseResultMap" type="com.railway.system.domain.SysScheduledTask">
+                <result column="id" property="id"/>
+                <result column="name" property="name"/>
+                <result column="cron" property="cron"/>
+                <result column="open" property="open"/>
+    </resultMap>
+
+    <sql id="Base_Column_List">
+                id,
+                `name`,
+                cron,
+                `open`
+    </sql>
+
+    <insert id="insert" parameterType="com.railway.system.domain.SysScheduledTask">
+        <selectKey keyProperty="id" order="BEFORE" resultType="String">
+            select replace(uuid(), '-', '') from dual
+        </selectKey>
+        INSERT INTO sys_scheduled_task
+        <trim prefix="(" suffix=")" suffixOverrides=",">
+                    <if test ='null != name'>
+                        `name`,
+                    </if>
+                    <if test ='null != cron'>
+                        cron,
+                    </if>
+                    <if test ='null != open'>
+                        `open`
+                    </if>
+        </trim>
+        <trim prefix="values (" suffix=")" suffixOverrides=",">
+                    <if test ='null != name'>
+                    #{name},
+                    </if>
+                    <if test ='null != cron'>
+                    #{cron},
+                    </if>
+                    <if test ='null != open'>
+                    #{open}
+                    </if>
+        </trim>
+    </insert>
+
+    <delete id="delete">
+        delete from sys_scheduled_task
+        WHERE id = #{id}
+    </delete>
+
+    <update id="update" parameterType="com.railway.system.domain.SysScheduledTask">
+        UPDATE sys_scheduled_task
+        <set>
+                    <if test ='null != name'>`name` = #{name},</if>
+                    <if test ='null != cron'>cron = #{cron},</if>
+                    <if test ='null != open'>`open` = #{open}</if>
+        </set>
+        WHERE id = #{id}
+    </update>
+
+
+    <select id="getInfo" resultMap="BaseResultMap">
+        SELECT
+        <include refid="Base_Column_List"/>
+        FROM sys_scheduled_task
+        WHERE id = #{id}
+    </select>
+
+    <select id="getInfoByName" resultMap="BaseResultMap">
+        SELECT
+        <include refid="Base_Column_List"/>
+        FROM sys_scheduled_task
+        WHERE `name` = #{name}
+    </select>
+
+    <select id="getList" resultMap="BaseResultMap">
+        SELECT
+        <include refid="Base_Column_List"/>
+        FROM sys_scheduled_task
+        <where>
+                <if test="name!=null and name!=''">
+                    and `name`=#{name}
+                </if>
+                <if test="cron!=null and cron!=''">
+                    and cron=#{cron}
+                </if>
+                <if test="open!=null and open!=''">
+                    and `open`=#{open}
+                </if>
+        </where>
+    </select>
+
+</mapper>

+ 35 - 0
sql/getui.sql

@@ -0,0 +1,35 @@
+-- sys_config 插入个推参数
+INSERT INTO `sys_config` VALUES (6, '个推-appId', 'getui.appId', 'Y3xRJmer116Bb1HhqnZav7', 'N', 'admin', '2021-12-09 08:47:52', '', NULL, NULL);
+INSERT INTO `sys_config` VALUES (7, '个推-appKey', 'getui.appKey', 'N2oftDIHyC9o1Ue73Cx3fA', 'N', 'admin', '2021-12-09 08:48:34', '', NULL, NULL);
+INSERT INTO `sys_config` VALUES (8, '个推-appSecret', 'getui.appSecret', 'AxCTRofHoO6XY47mpP2Vs8', 'N', 'admin', '2021-12-09 08:49:10', '', NULL, NULL);
+INSERT INTO `sys_config` VALUES (9, '个推-masterSecret', 'getui.masterSecret', 'OZhDEZbGTZ9tc8P8IQ3Mk3', 'N', 'admin', '2021-12-09 08:49:41', '', NULL, NULL);
+
+-- 创建系统计划任务表,并插入个推task
+DROP TABLE IF EXISTS `sys_scheduled_task`;
+CREATE TABLE `sys_scheduled_task` (
+    `id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键',
+    `name` varchar(50) NOT NULL COMMENT '任务名称',
+    `cron` varchar(30) NOT NULL COMMENT '任务cron',
+    `open` tinyint(1) NOT NULL DEFAULT '0' COMMENT '1开启,0关闭',
+    PRIMARY KEY (`id`)
+) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8 COMMENT='系统计划任务表';
+
+INSERT INTO `sys_scheduled_task` VALUES (1, 'getui', '0/10 * * * * ? ', 1);
+
+-- 创建个推消息表
+DROP TABLE IF EXISTS `bus_push_msg`;
+CREATE TABLE `bus_push_msg` (
+    `id` int NOT NULL AUTO_INCREMENT,
+    `user_id` bigint NOT NULL COMMENT '用户id',
+    `client_id` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '客户端id,APP端提供',
+    `client_type` tinyint NOT NULL DEFAULT '0' COMMENT '客户端类型:0-android;1-ios',
+    `title` varchar(255) DEFAULT NULL COMMENT '消息标题',
+    `content` varchar(1000) NOT NULL DEFAULT '' COMMENT '消息内容',
+    `ios_alert_msg` varchar(128) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT '' COMMENT 'IOS专用',
+    `create_time` datetime NOT NULL COMMENT '创建时间',
+    `push_time` datetime DEFAULT NULL COMMENT '推送时间',
+    `push_status` char(1) NOT NULL DEFAULT '0' COMMENT '推送状态:0-未推送;1-推送成功;2-推送失败;3-服务器响应异常;',
+    `push_result_desc` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT '' COMMENT '推送结果说明',
+    `push_loop` tinyint NOT NULL DEFAULT '0' COMMENT '推送轮数',
+    PRIMARY KEY (`id`) USING BTREE
+) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='个推消息表';