Quellcode durchsuchen

钉钉微应用-英语单词考试完全版后端

Eric vor 2 Jahren
Ursprung
Commit
63cbe8becd

+ 10 - 0
backend/pom.xml

@@ -93,6 +93,16 @@
             <artifactId>mybatis-spring</artifactId>
             <version>2.0.1</version>
         </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-quartz</artifactId>
+            <version>2.7.0</version>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework</groupId>
+            <artifactId>spring-context-support</artifactId>
+            <version>5.1.9.RELEASE</version>
+        </dependency>
     </dependencies>
 
     <build>

+ 8 - 4
backend/src/main/java/com/dingtalk/h5app/quickstart/Application.java

@@ -1,10 +1,12 @@
 package com.dingtalk.h5app.quickstart;
 
-import org.mybatis.spring.annotation.MapperScan;
+
+import org.quartz.*;
+import org.quartz.impl.StdSchedulerFactory;
 import org.springframework.boot.SpringApplication;
 import org.springframework.boot.autoconfigure.SpringBootApplication;
-import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
-import org.springframework.context.annotation.ComponentScan;
+import org.springframework.scheduling.annotation.EnableAsync;
+import org.springframework.scheduling.annotation.EnableScheduling;
 
 /**
  * 启动入口
@@ -12,9 +14,11 @@ import org.springframework.context.annotation.ComponentScan;
  * @author openapi@dingtalk
  * @date 2020/2/4
  */
+@EnableScheduling
+@EnableAsync
 @SpringBootApplication
 public class Application {
-    public static void main(String[] args) {
+    public static void main(String[] args) throws SchedulerException {
         SpringApplication.run(Application.class, args);
     }
 }

+ 0 - 1
backend/src/main/java/com/dingtalk/h5app/quickstart/controller/AuthController.java

@@ -72,7 +72,6 @@ public class AuthController {
     @PostMapping("/login")
     public ServiceResult<UserDTO> login(@RequestParam String authCode) {
         String accessToken;
-
         // 获取accessToken
         ServiceResult<String> accessTokenSr = tokenService.getAccessToken();
         if (!accessTokenSr.isSuccess()) {

+ 113 - 2
backend/src/main/java/com/dingtalk/h5app/quickstart/controller/CiKuController.java

@@ -1,12 +1,24 @@
 package com.dingtalk.h5app.quickstart.controller;
 
+
+import com.dingtalk.h5app.quickstart.domain.ServiceResult;
 import com.dingtalk.h5app.quickstart.entity.Grade;
+import com.dingtalk.h5app.quickstart.mapper.CronMapper;
 import com.dingtalk.h5app.quickstart.service.CiKuService;
+import com.dingtalk.h5app.quickstart.service.QuartzService;
+import com.dingtalk.h5app.quickstart.service.TokenService;
 import com.dingtalk.h5app.quickstart.vo.CiKuVO;
+import org.junit.Test;
+import org.quartz.JobKey;
+import org.quartz.Scheduler;
+import org.quartz.SchedulerException;
+import org.quartz.TriggerKey;
+import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.*;
-
 import javax.annotation.Resource;
-import java.util.List;
+import java.sql.SQLException;
+import java.util.*;
+
 
 @RestController
 @CrossOrigin
@@ -15,6 +27,18 @@ public class CiKuController {
     @Resource
     private CiKuService ciKuService;
 
+    @Resource
+    private QuartzService quartzService;
+
+    @Autowired
+    private TokenService tokenService;
+
+    @Autowired
+    private CronMapper cronMapper;
+
+    @Autowired
+    private Scheduler scheduler;
+
     @GetMapping("/findByRandom")
     public List<CiKuVO> findByRandom() {
         return ciKuService.findByRandom();
@@ -30,4 +54,91 @@ public class CiKuController {
         return ciKuService.getGrade(name);
     }
 
+    @PostMapping("/setTimer")
+    public ServiceResult serTimer(@RequestParam("pinlv") String pinlv, @RequestParam("time") String time, @RequestParam("userid") String userid){
+//        System.out.println(pinlv);
+//        System.out.println(userid);
+        String accessToken;
+//        System.out.println(file);
+        // 获取accessToken
+        ServiceResult<String> accessTokenSr = tokenService.getAccessToken();
+        if (!accessTokenSr.isSuccess()) {
+            return ServiceResult.failure(accessTokenSr.getCode(), accessTokenSr.getMessage());
+        }
+        List<Integer> a = new ArrayList<>();
+
+        accessToken = accessTokenSr.getResult();
+        String cron = "";
+        if ("day".equals(pinlv)){
+            if(time.charAt(0) == '0'&& time.charAt(3) == '0'){
+                cron = "0 " + time.charAt(4) + " " + time.charAt(1) + " * * ?";
+            }else if (time.charAt(0) == '0'&& time.charAt(3) != '0'){
+                cron = "0 " + time.substring(3,5) + " " + time.charAt(1) + " * * ?";
+            }else if(time.charAt(0) != '0'&& time.charAt(3) == '0'){
+                cron = "0 " + time.charAt(4) + " " + time.substring(0,2) + " * * ?";
+            }else if(time.charAt(0) != '0'&& time.charAt(3) != '0'){
+                cron = "0 " + time.substring(3,5) + " " + time.substring(0,2) + " * * ?";
+            }
+        }else{
+            if ("00".equals(time.substring(3,5))){
+                if("0".equals(time.substring(0,1))){
+                    cron = "0 0 "+ time.charAt(1) +" ? * "+pinlv;
+                }else{
+                    cron = "0 0 "+ time.substring(0,2) +" ? * "+pinlv;
+                }
+            }else{
+                if("0".equals(time.substring(0,1))){
+                    if ("0".equals(time.substring(3,4))){
+                        cron = "0 "+time.charAt(4)+" "+ time.charAt(1) +" ? * " +pinlv;
+                    }else {
+                        cron = "0 "+time.substring(3,5)+" "+ time.charAt(1) +" ? * " +pinlv;
+                    }
+                }else {
+                    if ("0".equals(time.substring(3,4))){
+                        cron = "0 "+time.charAt(4)+" "+ time.substring(0,2) +" ? * " +pinlv;
+                    }else {
+                        cron = "0 "+time.substring(3,5)+" "+ time.substring(0,2) +" ? * " +pinlv;
+                    }
+                }
+            }
+        }
+        try {
+
+            if("success".equals(quartzService.insertQuartz(userid, cron, accessToken,pinlv+"|"+time))){
+                return ServiceResult.success("成功");
+            }else {
+                return ServiceResult.failure("失败");
+            }
+        } catch (SchedulerException | SQLException e) {
+            return ServiceResult.failure(e.getMessage());
+        }
+    }
+
+    @PostMapping("/selectTimer")
+    public ServiceResult selectTimer(@RequestParam("userid") String userid){
+        return ServiceResult.success(cronMapper.selectCron(userid));
+    }
+
+    @PostMapping("/deleteTimer")
+    public ServiceResult deleteTimer(@RequestParam("userid") String userid,@RequestParam("frequency") String frequency) throws SchedulerException {
+        String jobID = cronMapper.getJobID(userid, frequency);
+//        System.out.println(jobID);
+        try {
+            JobKey jobKey = new JobKey(jobID,userid);
+            if (!scheduler.checkExists(jobKey)) {
+                System.out.println("job not exists, job name: "+jobKey.getName()+", group name: "+ jobKey.getGroup());
+                return ServiceResult.failure("200");
+            }
+            TriggerKey triggerKey = TriggerKey.triggerKey(jobID,userid);
+            scheduler.pauseTrigger(triggerKey);
+            scheduler.unscheduleJob(triggerKey);
+            boolean b = scheduler.deleteJob(jobKey);
+            System.out.println(b);
+        } catch (Exception e) {
+            System.out.println(e.getMessage());
+        }
+//        System.out.println(b);
+        return ServiceResult.success(cronMapper.deleteTimer(userid,frequency));
+    }
+
 }

+ 27 - 0
backend/src/main/java/com/dingtalk/h5app/quickstart/mapper/CronMapper.java

@@ -0,0 +1,27 @@
+package com.dingtalk.h5app.quickstart.mapper;
+
+import org.apache.ibatis.annotations.Delete;
+import org.apache.ibatis.annotations.Insert;
+import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Select;
+
+import java.util.List;
+
+/**
+ * @author Shawn
+ */
+@Mapper
+public interface CronMapper {
+
+        @Insert("insert into english_job(JobID,cron,userid,frequency) values(#{JobID},#{cron},#{userid},#{frequency})")
+        int addCron(String JobID,String cron,String userid,String frequency);
+
+        @Select("select frequency from english_job where userid = #{userid}")
+        List<String> selectCron(String userid);
+
+        @Select("select JobID from english_job where userid = #{userid} and frequency = #{frequency}")
+        String getJobID(String userid,String frequency);
+
+        @Delete("delete from english_job where userid = #{userid} and frequency = #{frequency}")
+        int deleteTimer(String userid,String frequency);
+}

+ 48 - 0
backend/src/main/java/com/dingtalk/h5app/quickstart/quartz/MyJob.java

@@ -0,0 +1,48 @@
+package com.dingtalk.h5app.quickstart.quartz;
+
+import com.dingtalk.api.DefaultDingTalkClient;
+import com.dingtalk.api.DingTalkClient;
+import com.dingtalk.api.request.OapiMessageCorpconversationAsyncsendV2Request;
+import com.dingtalk.api.response.OapiMessageCorpconversationAsyncsendV2Response;
+import com.taobao.api.ApiException;
+import org.quartz.Job;
+import org.quartz.JobExecutionContext;
+import org.quartz.JobExecutionException;
+
+/**
+ * @author Shawn
+ */
+public class MyJob implements Job {
+
+    @Override
+    public void execute(JobExecutionContext context) throws JobExecutionException {
+
+        try {
+            DingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/topapi/message/corpconversation/asyncsend_v2");
+            OapiMessageCorpconversationAsyncsendV2Request req = new OapiMessageCorpconversationAsyncsendV2Request();
+            req.setAgentId(1661857171L);
+            req.setUseridList(context.getJobDetail().getJobDataMap().getString("userid"));
+//            req.setDeptIdList(deptlist);
+            OapiMessageCorpconversationAsyncsendV2Request.Msg obj1 = new OapiMessageCorpconversationAsyncsendV2Request.Msg();
+            obj1.setMsgtype("action_card");
+            OapiMessageCorpconversationAsyncsendV2Request.Link obj2 = new OapiMessageCorpconversationAsyncsendV2Request.Link();
+            obj2.setTitle("速来学英语");
+            obj1.setLink(obj2);
+            OapiMessageCorpconversationAsyncsendV2Request.Markdown obj3 = new OapiMessageCorpconversationAsyncsendV2Request.Markdown();
+            obj3.setTitle("速来学英语");
+            obj1.setMarkdown(obj3);
+            OapiMessageCorpconversationAsyncsendV2Request.ActionCard obj4 = new OapiMessageCorpconversationAsyncsendV2Request.ActionCard();
+            obj4.setSingleUrl("http://101.204.146.11:8081/#/");
+            obj4.setSingleTitle(context.getJobDetail().getJobDataMap().getString("frequency")+"速来学英语");
+            obj4.setMarkdown("![](https://img1.baidu.com/it/u=908218778,3362502617&fm=253&fmt=auto&app=120&f=JPEG?w=1057&h=800)");
+            obj4.setTitle("速来学英语");
+            obj1.setActionCard(obj4);
+            req.setMsg(obj1);
+            OapiMessageCorpconversationAsyncsendV2Response rsp = client.execute(req, context.getJobDetail().getJobDataMap().getString("token"));
+            System.out.println(rsp.getBody());
+        } catch (ApiException e) {
+            e.printStackTrace();
+        }
+
+    }
+}

+ 13 - 0
backend/src/main/java/com/dingtalk/h5app/quickstart/service/QuartzService.java

@@ -0,0 +1,13 @@
+package com.dingtalk.h5app.quickstart.service;
+
+import org.quartz.SchedulerException;
+
+import java.sql.SQLException;
+
+/**
+ * @author Shawn
+ */
+public interface QuartzService {
+
+    String insertQuartz(String userid,String cron,String token,String frequency) throws SchedulerException, SQLException;
+}

+ 41 - 6
backend/src/main/java/com/dingtalk/h5app/quickstart/service/TokenService.java

@@ -11,11 +11,23 @@ import com.dingtalk.h5app.quickstart.config.AppConfig;
 import com.dingtalk.h5app.quickstart.domain.ServiceResult;
 import com.dingtalk.h5app.quickstart.util.FileUtil;
 import com.taobao.api.ApiException;
+import org.quartz.Job;
+import org.quartz.JobExecutionContext;
+import org.quartz.JobExecutionException;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.scheduling.annotation.Async;
+import org.springframework.scheduling.annotation.EnableAsync;
+import org.springframework.scheduling.annotation.EnableScheduling;
+import org.springframework.scheduling.annotation.Scheduled;
 import org.springframework.stereotype.Service;
 
+import javax.xml.crypto.Data;
+
+import java.util.Date;
+
 import static com.dingtalk.h5app.quickstart.config.UrlConstant.URL_GET_JSTICKET;
 import static com.dingtalk.h5app.quickstart.config.UrlConstant.URL_GET_TOKEN;
 
@@ -26,14 +38,17 @@ import static com.dingtalk.h5app.quickstart.config.UrlConstant.URL_GET_TOKEN;
  * @date 2020/2/4
  */
 @Service
-public class TokenService {
-    private static final Logger log = LoggerFactory.getLogger(TokenService.class);
+@Configuration
+@EnableAsync
+@EnableScheduling
+public class TokenService{
+    private final Logger log = LoggerFactory.getLogger(TokenService.class);
     /**
-     * 缓存时间:一小时50分钟
+     * 缓存时间:一小时50分钟,最大时间是俩小时,早几分钟留出更新token的时间
      */
-    private static final long CACHE_TTL = 60 * 55 * 2 * 1000;
+    public static final long CACHE_TTL = 60 * 56 * 2 * 1000;
 
-    private AppConfig appConfig;
+    public AppConfig appConfig;
 
     @Autowired
     public TokenService(AppConfig appConfig) {
@@ -128,7 +143,7 @@ public class TokenService {
      * @param field   token字段名
      * @return token值 或 null (过期或未查到)
      */
-    private String getFromCache(String section, String field) {
+    public String getFromCache(String section, String field) {
         JSONObject o = (JSONObject) FileUtil.getValue(section, appConfig.getAppKey());
         if (o != null && System.currentTimeMillis() - o.getLong("begin_time") <= CACHE_TTL) {
             return o.getString(field);
@@ -145,4 +160,24 @@ public class TokenService {
 
         FileUtil.write2File(wrapperObj, section);
     }
+
+    @Scheduled(cron = "*/30 * * * * ?")
+    @Async
+    public void execute(){
+        System.out.println("\n--例行检查token--"+new Date().toLocaleString());
+        if(getFromCache("accessToken", "access_token") == null){
+            System.out.println("--token已经过期,现在更新--");
+            this.getAccessToken();
+        }else{
+//            System.out.println("token未过期");
+        }
+
+        System.out.println("--例行检查jsTicket--"+new Date().toLocaleString());
+        if(getFromCache("jsticket", "ticket") == null){
+            System.out.println("--jsticket已经过期,现在更新--");
+            this.getJsTicket();
+        }else{
+//            System.out.println("jsticket未过期\n");
+        }
+    }
 }

+ 1 - 0
backend/src/main/java/com/dingtalk/h5app/quickstart/service/impl/CiKuServiceImpl.java

@@ -23,6 +23,7 @@ public class CiKuServiceImpl implements CiKuService {
     @Autowired
     private CiKuMapper ciKuMapper;
 
+
     @Override
     public List<CiKuVO> findByRandom() {
 

+ 49 - 0
backend/src/main/java/com/dingtalk/h5app/quickstart/service/impl/QuartzServiceImpl.java

@@ -0,0 +1,49 @@
+package com.dingtalk.h5app.quickstart.service.impl;
+
+import com.dingtalk.h5app.quickstart.mapper.CronMapper;
+import com.dingtalk.h5app.quickstart.quartz.MyJob;
+import com.dingtalk.h5app.quickstart.service.QuartzService;
+import org.quartz.*;
+import org.quartz.impl.StdSchedulerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.sql.SQLException;
+
+/**
+ * @author Shawn
+ */
+@Service
+public class QuartzServiceImpl implements QuartzService {
+
+    @Autowired
+    private CronMapper cronMapper;
+
+    @Autowired
+    Scheduler scheduler;
+
+    @Override
+    public String insertQuartz(String userid, String cron,String token,String frequency) throws SchedulerException,SQLException {
+
+
+            if (cronMapper.addCron(userid + cron, cron, userid,frequency) == 1){
+                JobDetail jobDetail = JobBuilder.newJob(MyJob.class)
+                        .withIdentity(JobKey.jobKey(userid + cron,userid))
+                        .usingJobData("userid",userid)
+                        .usingJobData("frequency",frequency)
+                        .usingJobData("token",token)
+                        .build();
+                System.out.println("jobName:*"+userid + cron+"*");
+                System.out.println("group:*"+userid+"*");
+                Trigger trigger = TriggerBuilder.newTrigger().withIdentity(TriggerKey.triggerKey(userid + cron,userid))
+                        .withSchedule(CronScheduleBuilder.cronSchedule(cron)).build();
+
+                scheduler.scheduleJob(jobDetail,trigger);
+                scheduler.start();
+                return "success";
+            }else {
+                return "error";
+            }
+
+    }
+}

+ 2 - 0
backend/src/main/resources/application.properties

@@ -7,3 +7,5 @@ spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
 spring.datasource.url=jdbc:mysql://125.71.216.35:3306/db_test_eng?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=UTC
 spring.datasource.username=engstuser
 spring.datasource.password=581hbr%$!
+
+server.port=8082