使用pringboot发起HTTPS post请求遇到的问题

这个项目是跟别的服务进行对接,需要定时向对方的服务器发送https post请求,定时的部分我使用了Quartz,一个是15分钟一次发送,一个是每天凌晨2点发送:

public void scheduleJobs() throws SchedulerException {
        Scheduler scheduler = schedulerFactoryBean.getScheduler();
        dailyJob(scheduler);
        dataCollectionJob(scheduler);
    }

    private void dataCollectionJob(Scheduler scheduler) throws SchedulerException{
        JobDetail jobDetail0 = JobBuilder.newJob(DataCollection.class)
                .withIdentity("job0", "group0").build();
        CronScheduleBuilder scheduleBuilder0 = CronScheduleBuilder.cronSchedule("0 0/15 * * * ?");
        CronTrigger cronTrigger0 = TriggerBuilder.newTrigger().withIdentity("trigger0", "group0")
                .withSchedule(scheduleBuilder0).build();
        scheduler.scheduleJob(jobDetail0,cronTrigger0);
    }

    private void dailyJob(Scheduler scheduler) throws SchedulerException{
        JobDetail jobDetail1 = JobBuilder.newJob(Daily.class)
                .withIdentity("job1", "group1").build();
        CronScheduleBuilder scheduleBuilder0 = CronScheduleBuilder.cronSchedule("0 0 2 * * ?");
        CronTrigger cronTrigger1 = TriggerBuilder.newTrigger().withIdentity("trigger1", "group1")
                .withSchedule(scheduleBuilder0).build();
        scheduler.scheduleJob(jobDetail1,cronTrigger1);
    }

DataCollection.class 和 Daily.class 里面的逻辑基本一致,都是把要发送的实体类进行赋值的操作,然后就是发送数据:

public static Boolean UploadData(Object data,String url){
        try{
            HttpsURLConnection.setDefaultHostnameVerifier(new HttpsUtils().new NullHostNameVerifier());
            SSLContext sc = SSLContext.getInstance("TLS");
            sc.init(null, trustAllCerts, new SecureRandom());
            HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());

            URL serverUrl = new URL(url);
            HttpsURLConnection conn = (HttpsURLConnection) serverUrl.openConnection();
            conn.setRequestMethod("POST");
            conn.setRequestProperty("Content-type", "application/json");
            conn.setRequestProperty("Accept", "application/json");
            conn.setDoInput(true);
            conn.setDoOutput(true);
            conn.connect();

            OutputStreamWriter out = new OutputStreamWriter(conn.getOutputStream(),"UTF-8");
            out.write(data.toString());
            out.flush();
            out.close();

            String result = getReturn(conn);

            JSONObject jsonObj = JSONObject.parseObject(result);
            if(jsonObj.get("responseCode").equals("0")){
                System.out.println("post response: "+result);
                return true;
            }else{
                System.out.println(result);
                return false;
            }
        }catch(Exception e){
            e.printStackTrace();
            return false;
        }
    }

其中的 getReturn() 方法如下:

/*请求url获取返回的内容*/
    private static String getReturn(HttpURLConnection connection) throws IOException {
        StringBuffer buffer = new StringBuffer();
        //将返回的输入流转换成字符串
        try{
            InputStream inputStream = connection.getInputStream();
            InputStreamReader inputStreamReader = new InputStreamReader(inputStream, UTF_8);
            BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
            String str = null;
            while ((str = bufferedReader.readLine()) != null) {
                buffer.append(str);
            }
            String result = buffer.toString();
            return result;
        }catch (Exception e){
            e.printStackTrace();
            return null;
        }
    }

15分钟发送一次的和1天一次的发送都是走的这个 UploadData() 方法,现在遇到的问题是:15分钟一次的这个,我发送后对方接收到一次数据,这是正常的,但是1天一次这个对方在数据库中有两个1天的这个数据。
曾经怀疑过是对方的问题,比如接收到数据后处理不当导致在数据库里存了两遍这种情况,但是我用 postman 测试发了一次,发现对方数据库里只有一次的数据,所以现在只能是我这边找问题,我排查了很久没找到问题,有大佬可以根据这些代码推测一下吗?

我建议换一个http客户端试试看,jdk自带的这个不建议用。可以用okhttp,apache-httpclient。而且记录每一次发送请求的详细日志。当这个问题再次出现的问题根据日志定位问题。

每天两点执行的时候,15分钟的是不是刚好也是到了两点? 这样就触发了两次啊

1 个赞

15分钟和1天一次传的数据不一样,能看出来

那我先试一下apache-httpclient吧,换一个http客户端是什么意思呀?是要换另一个测试工具代替postman嘛?是的话有推荐的工具吗?

1 个赞

用 RestTemplate或者fegin

一天的定时任务重复执行是必现的么?

是必定的,但不知道是不是重复执行,因为只要上传成功,对方会给我回传,我看打印出来的日志对方给我的回传只有一次,但对方数据库里就是有两条一模一样的数据

有没有可能时并发问题,你可以试试 这个@DisallowConcurrentExecution注解

并发的话相当于发了多次post请求吧?但是对方对我的post请求回传信息就一次,感觉大概率不是并发