springboot实现复杂业务下的更新操作

大家好,我是雄雄,欢迎关注微信公众号:雄雄的小课堂

前言

现在是2022年5月4日19:25:55!今天写了个这样的功能:

某用户在一天内有多个训练项目,比如:晨跑,有氧训练,跳绳这三个项目。这三个训练项目都在数据库中有记录,每个项目都有开始时间,结束时间以及状态。状态包含:未开始,进行中和已结束。

下图展示的就是训练项目

用户早上醒来之后,点击第一个晨跑的小卡片,那么就开始记录当前时间就是晨跑的开始时间。训练完之后,用户接着点击有氧训练的小卡片,那么此时,晨跑项目的结束时间就是当前时间,有氧训练的开始时间也是当前时间,此时的晨跑状态是已结束,有氧训练的状态是进行中

没明白的话多看几遍就明白了,哈哈哈,这儿有点绕。

因为这是两个系统,训练项目所属一个项目,调用的是另一个项目,下面说一下我的实现方式。

实现思路

  1. 在训练项目的系统上,只实现更新操作,传参:项目id,开始时间,结束时间,状态
  2. 在调用的系统上,编写业务代码块,一共有三个接口。
  3. 接口一:记录第一个训练项目的开始时间,将当前训练项目的id放在redis中。
  4. 接口二:从redis中获取上一个动作的id,传递动作的id,时间戳,然后修改上一个动作的结束时间是当前的时间戳,第一个动作的状态是【已结束】,当前动作的开始时间是当前的时间戳,状态是【训练中】,删除上一个动作的id,将当前动作的id放在redis里面
  5. 接口三:最后一个动作的结束:传递当前方案的id,动作的id,用户id,时间戳,然后修改当前动作的结束时间是时间戳,状态是【已结束】,删掉redis里面的用户id

说明:大家可以看到,我将第一个训练项目的id放在了redis中,这么放的目的就是下一个训练项目传过来之后,更好的知道上一个训练项目是哪个,因为我们需要更改它的状态和结束时间。之后还需要更改当前训练项目的开始时间和状态。以此类推,一直到最后一个。

接口三主要实现的功能就是更新最后一个训练项目的结束时间,这样我们就可以依次更改每个训练项目的开始时间、结束时间以及训练状态

上面还是有点绕,大家可以仔细的看看~

实现代码

下面我来介绍一下代码是怎么实现的。

首先是训练项目中的更新操作,这个方法就一个修改的操作,没啥特别复杂的,下面是代码:

        /*** 根据项目project的id,修改动作状态和开始时间,结束时间* 参数:动作id,状态,开始时间,结束时间*/@PostMapping(value = "/updateProjectById")public String updateProjectById(@RequestHeader("Authorization")String token,Long pid,int status,Long beginTime,Long endTime) {JSONObject jsonObject = new JSONObject();//1.验证tokenboolean isOk = TokenUtil.verify(token);if (!isOk) {jsonObject.put("code", 401);jsonObject.put("msg", "令牌失效");return jsonObject.toString();}SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");try {//查询Project project = projectService.getById(pid);//训练项目状态,0未开始,1进行中,2已完成project.setProjectStatus(status + "");//将时间戳转换成时间if (beginTime != null) {String kstime = DateParseUtils.getTimeChuo(beginTime);project.setBeginTime(format.parse(kstime));}//结束时间if (endTime != null) {String jstime = DateParseUtils.getTimeChuo(endTime);project.setEndTime(format.parse(jstime));}projectService.updateById(project);jsonObject.put("code",200);jsonObject.put("msg","操作成功");jsonObject.put("status",true);} catch (ParseException e) {jsonObject.put("code",500);jsonObject.put("msg","操作失败");jsonObject.put("status",false);e.printStackTrace();}return jsonObject.toJSONString();}

可以发现,开始时间和结束时间都不能是必填,因为在更新第一个训练项目的时候,我们只能知道当前的时间是开始时间,并不知道何时结束。同理,在更新第二个训练项目时,我们只需拿着当前时间更新上一个训练项目的结束时间就行。

下面是调用方的实现:

  1. 将参数封装成实体:
    package org.springblade.modules.system.vo;import io.swagger.annotations.ApiModel;
import lombok.Data;
import lombok.EqualsAndHashCode;/*** @author: muxiongxiong* @date: 2022年04月30日 20:34* 公众号:雄雄的小课堂* 博客:https://blog.csdn.net/qq_34137397* 个人站:http://www.穆雄雄.com* 个人站:http://www.muxiongxiong.cn* @Description: 类的描述*/@Data
@ApiModel(value = "TrainingVO对象", description = "TrainingVO对象")
public class TrainingVO {/*** 动作id*/private Long projectId;/*** 方案id*/private Long programmeId;/*** 用户id*/private Long userId;/*** 动作状态*/private Integer status;/*** 时间戳 接收前台传过来的时间戳*/private Long time;/*** 业务上处理的动作,开始时间*/private Long beginTime;/*** 业务上处理的动作,结束时间*/private Long endTime;}
  1. 公共接口,也就是更新的接口:
    /*** 公共的接口* 调用训练方案的* 更新动作的状态和时间** @param trainingVO* @return*/@Overridepublic R updateTrainingProgrammeAndProjectStatusAndTime(TrainingVO trainingVO) {//判断是否为空R rt = getToken();String token = "";if (rt != null) {JSONObject jsonObject = (JSONObject) rt.getData();if (jsonObject != null) {token = jsonObject.getStr("access_token");}} else {return R.fail(500, "获取token失败");}if (StringUtil.isEmpty(token)) {return R.fail(500, "获取token失败");}//请求接口地址String url = TrainingSchemeConstant.updateProjectById;Map paramMap = new HashMap();//动作idif (trainingVO.getProjectId() != null) {paramMap.put("pid", trainingVO.getProjectId());}//开始时间if (trainingVO.getBeginTime() != null) {paramMap.put("beginTime", trainingVO.getBeginTime());}//状态if (trainingVO.getStatus() != null) {paramMap.put("status", trainingVO.getStatus());}//结束时间if (trainingVO.getEndTime() != null) {paramMap.put("endTime", trainingVO.getEndTime());}try {String body = HttpUtil.createPost(url).header("Authorization", token).form(paramMap).execute().body();if (StringUtils.isBlank(body)) {return R.status(false);}JSONObject obj = JSONUtil.parseObj(body);if (obj == null) {return R.status(false);}boolean flag = Boolean.parseBoolean(obj.get("status").toString());return R.status(flag);} catch (Exception e) {e.printStackTrace();System.out.println(e.getMessage());return R.status(false);}}
  1. 接口一,更新第一个训练项目的开始时间状态:
    /*** 接口一:第一个动作的开始:* 1.当前动作的id,时间戳,然后将当前动作的开始时间修改,当前动作的状态该成 【训练中】* 2.将当前动做的id放在redis里面。* 参数:用户id,方案id,主要是放在redis的时候需要用** @param trainingVO* @return*/@PostMapping("/updateProjectBeginTime")@ApiOperationSupport(order = 3)@ApiOperation(value = "threePlant-第一个动作的更新", notes = "传入userId,programmeId,projectId,time")public R updateProjectBeginTime(@ApiParam(value = "训练方案业务对象", required = true) @RequestBody  TrainingVO trainingVO) {//第一个动作的开始时间trainingVO.setBeginTime(trainingVO.getTime());//第一个动作:训练中trainingVO.setStatus(1);//将第一个动作放在redis的缓存中bladeRedis.set("training:updateTrainingStatusAndTime:" +trainingVO.getUserId() + ":" +trainingVO.getProgrammeId(), trainingVO.getProjectId());//调用更新的借口return trainingSchemeUrlService.updateTrainingProgrammeAndProjectStatusAndTime(trainingVO);}
  1. 接口二,更新当前动作的开始时间,状态和上一个动作的结束时间、状态。
    /*** 接口二:中间的动作操作:* 1.从redis中获取上一个动作的id。* 2.传递动作的id,时间戳,然后修改上一个动作的结束时间是当前的时间戳,第一个动作的状态是【已结束】,当前动作的开始时间是当前的时间戳,状态是【训练中】* 3.删除上一个动作的id,将当前动作的id放在redis里面** @param trainingVO* @return*/@PostMapping("/updateProjectBeginTimeAndEndTime")@ApiOperationSupport(order = 3)@ApiOperation(value = "threePlant-中间动作的更新", notes = "传入userId,programmeId,projectId,time")public R updateProjectBeginTimeAndEndTime(@ApiParam(value = "训练方案业务对象", required = true) @RequestBody TrainingVO trainingVO) {TrainingVO trainingVONew = new TrainingVO();//先从redis中获取上一个动作的idLong beforePid = bladeRedis.get("training:updateTrainingStatusAndTime:" + trainingVO.getUserId() + ":" + trainingVO.getProgrammeId());//用完之后删掉redis里面的数据bladeRedis.del("training:updateTrainingStatusAndTime:" + trainingVO.getUserId() + ":" + trainingVO.getProgrammeId());//修改上个动作的结束时间是当前的时间戳trainingVONew.setEndTime(trainingVO.getTime());//上个动作的状态是已结束trainingVONew.setStatus(2);trainingVONew.setProjectId(beforePid);//调用更新的借口R resultR = trainingSchemeUrlService.updateTrainingProgrammeAndProjectStatusAndTime(trainingVONew);if (resultR.getCode() == 200) {//更新没啥问题//开始修改当前状态//状态是训练中trainingVO.setStatus(1);//开始时间是时间戳trainingVO.setBeginTime(trainingVO.getTime());//将当前的动作在放在redis里面bladeRedis.set("training:updateTrainingStatusAndTime:" +trainingVO.getUserId() + ":" +trainingVO.getProgrammeId(), trainingVO.getProjectId());//调用更新的方法return trainingSchemeUrlService.updateTrainingProgrammeAndProjectStatusAndTime(trainingVO);} else {return R.status(false);}}
  1. 接口三,更新最后一个训练项目的结束时间和训练状态:
    /*** 接口三:最后一个动作的结束:* 1.传递当前方案的id,动作的id,用户id,时间戳,然后修改当前动作的结束时间是时间戳,状态是【已结束】* 2.删掉redis里面的用户id** @param trainingVO* @return*/@PostMapping("/updateProjectEndTime")@ApiOperationSupport(order = 3)@ApiOperation(value = "threePlant-最后一个动作的更新", notes = "传入userId,programmeId,projectId,time")public R updateProjectEndTime(@ApiParam(value = "训练方案业务对象", required = true) @RequestBody TrainingVO trainingVO) {//最后一个动作的结束时间是时间戳trainingVO.setEndTime(trainingVO.getTime());//最后一个动作是已结束trainingVO.setStatus(2);//删掉redis中的动作idbladeRedis.del("training:updateTrainingStatusAndTime:" +trainingVO.getUserId() + ":" +trainingVO.getProgrammeId());return trainingSchemeUrlService.updateTrainingProgrammeAndProjectStatusAndTime(trainingVO);}trainingVO.setStatus(2);//删掉redis中的动作idbladeRedis.del("training:updateTrainingStatusAndTime:" +trainingVO.getUserId() + ":" +trainingVO.getProgrammeId());return trainingSchemeUrlService.updateTrainingProgrammeAndProjectStatusAndTime(trainingVO);}

以上就是整个流程的实现,其实写代码难的不是代码,而是业务,当你明白了业务是什么,随之而来的就是实现方式,所以,业务是重中之重的~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/323645.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

elementui解决el-dialog不清空内容的问题,el-dialog关闭时销毁子组件

大家好,我是雄雄,欢迎关注微信公众号:雄雄的小课堂 前言 现在是2022年5月5日22:48:21! 今天在使用element-ui中的el-dialog的时候遇到了个这样的问题:页面上点击添加的按钮,弹出el-dialog对话框&#xff…

MySQL 中的重做日志,回滚日志以及二进制日志的简单总结

转载自 MySQL 中的重做日志,回滚日志以及二进制日志的简单总结 MySQL中有六种日志文件,分别是:重做日志(redo log)、回滚日志(undo log)、二进制日志(binlog)、错误日志…

c语言分离三位数

#include<stdio.h> main(){ int k,l,m,n;printf("请输入一个三位数"); scanf("%d",&k);lk/100;mk/10%10;nk%10;printf("这个三位数的百位是:%d\n",l);printf("这个三位数的十位是:%d\n",m);printf("这个三位数的个位是…

分布式ID自增算法 Snowflake

近在尝试EF的多数据库移植&#xff0c;但是原始项目中主键用的Sqlserver的GUID。MySQL没法移植了。 其实发现GUID也没法保证数据的递增性&#xff0c;又不太想使用int递增主键&#xff0c;就开始探索别的ID形式。 后来发现twitter的Snowflake算法。 一开始我尝试过直接引用N…

java中,根据指定日期显示出前n天的日期

大家好&#xff0c;我是雄雄&#xff0c;欢迎关注微信公众号&#xff1a;雄雄的小课堂 今天分享的是&#xff1a;在java中&#xff0c;根据指定日期显示出前n天的日期 效果如下&#xff1a; 大家注意观察上面的时间&#xff0c;我传入的时间是&#xff1a;2022年5月9日21:28:…

jdbc实现批量给多个表中更新数据(解析Excel表数据插入到数据库中)

大家好&#xff0c;我是雄雄&#xff0c;欢迎关注微信公众号&#xff1a;雄雄的小课堂 前言 现在是&#xff1a;2022年5月19日08:01:51 今天遇到了个这样的需求&#xff0c;解析excel表中的数据&#xff0c;以JDBC的方式&#xff0c;将数据批量更新至不同的数据表中。注意&am…

.Net Core 全局配置读取管理方法 ConfigurationManager

最近在学习.Net Core的过程中&#xff0c;发现.Net Framework中常用的ConfigurationManager在Core中竟然被干掉了。 也能理解。Core中使用的配置文件全是Json&#xff0c;不像Framework使用的XML&#xff0c;暂时不支持也是能理解的&#xff0c;但是毕竟全局配置文件这种东西还…

Http 持久连接与 HttpClient 连接池

转载自 Http 持久连接与 HttpClient 连接池 一、背景 HTTP协议是无状态的协议&#xff0c;即每一次请求都是互相独立的。因此它的最初实现是&#xff0c;每一个http请求都会打开一个tcp socket连接&#xff0c;当交互完毕后会关闭这个连接。 HTTP协议是全双工的协议&#x…

jdbc解析excel文件,批量插入数据至库中

“大家好&#xff0c;我是雄雄&#xff0c;欢迎关注微信公众号&#xff1a;雄雄的小课堂”前言现在是&#xff1a;2022年5月20日09:32:38今天遇到了个这样的需求&#xff0c;解析excel表中的数据&#xff0c;以JDBC的方式&#xff0c;将数据批量更新至不同的数据表中。注意&…

线程2

public class test{/*** 测试延迟继承* param args*/public static void main(String[] args) {Cat catnew Cat();cat.start();//启动线程&#xff0c;会导致run函数的运行Dog dognew Dog();//创建一个线程对象Thread tnew Thread(dog);t.start();}} //继承Thread创建线程 clas…

.NET及.NET Core系统架构

.NET 官方架构指南 Microservices and Docker Containers Web Applications with ASP.NET 官网地址&#xff1a;https://www.microsoft.com/net/learn/architecture 三层及多层架构 Multitier Architecture ASP.NET N-Tier Architecture Schema Visual Studio N-Tier Examp…

Spring Boot 自动配置的 “魔法” 是如何实现的?

转载自 Spring Boot 自动配置的 “魔法” 是如何实现的&#xff1f; Spring Boot是Spring旗下众多的子项目之一&#xff0c;其理念是约定优于配置&#xff0c;它通过实现了自动配置&#xff08;大多数用户平时习惯设置的配置作为默认配置&#xff09;的功能来为用户快速构建出…

解决vue登录信息不及时更新问题

大家好&#xff0c;我是雄雄&#xff0c;欢迎关注微信公众号&#xff1a;雄雄的小课堂 前言 现在是&#xff1a;2022年5月20日09:59:34 前面写过一篇文章&#xff0c;基于bladex框架实现的模拟登录&#xff0c;后来在测试的过程中发现了个问题&#xff0c;即A系统在跳转到本系…

学习ASP.NET Core,怎能不了解请求处理管道[2]: 服务器在管道中的“龙头”地位

ASP.NET Core管道由注册的服务器和一系列中间件构成。我们在上一篇中深入剖析了中间件&#xff0c;现在我们来了解一下服务器。服务器是ASP .NET Core管道的第一个节点&#xff0c;它负责完整请求的监听和接收&#xff0c;最终对请求的响应同样也由它完成。[本文已经同步到《AS…

for循环(二)

利用for循环按规律打出星星 #include<stdio.h>main(){int i,j;for(i0;i<10;i){for(j0;j<i;j){printf(" *"); }printf("\n");} }

接口方法上的注解无法被@Aspect声明的切面拦截的原因分析

转载自 接口方法上的注解无法被Aspect声明的切面拦截的原因分析 前言 在Spring中使用MyBatis的Mapper接口自动生成时&#xff0c;用一个自定义的注解标记在Mapper接口的方法中&#xff0c;再利用Aspect定义一个切面&#xff0c;拦截这个注解以记录日志或者执行时长。但是惊奇…

springboot实现用户统一认证、管理(单点登录)

大家好&#xff0c;我是雄雄&#xff0c;欢迎关注微信公众号&#xff1a;雄雄的小课堂 前言 现在是&#xff1a;2022年5月25日13:44:16 最近和模拟登录杠上了&#xff0c;这不&#xff0c;又来了个需求&#xff0c;还是以这个技术点入手的。 需求大概是这样的&#xff1a;为了…

学习ASP.NET Core,怎能不了解请求处理管道[1]: 中间件究竟是个什么东西?

ASP.NET Core管道虽然在结构组成上显得非常简单&#xff0c;但是在具体实现上却涉及到太多的对象&#xff0c;所以我们在 “通过重建Hosting系统理解HTTP请求在ASP.NET Core管道中的处理流程”&#xff08;上篇、中篇、下篇&#xff09; 中围绕着一个经过极度简化的模拟管道讲述…

springboot实现用户统一认证、管理

“大家好&#xff0c;我是雄雄&#xff0c;欢迎关注微信公众号&#xff1a;雄雄的小课堂”前言现在是&#xff1a;2022年5月25日13:44:16最近和模拟登录杠上了&#xff0c;这不&#xff0c;又来了个需求&#xff0c;还是以这个技术点入手的。需求大概是这样的&#xff1a;为了统…

Mybatis 使用的 9 种设计模式,真是太有用了

转载自 Mybatis 使用的 9 种设计模式&#xff0c;真是太有用了 虽然我们都知道有26个设计模式&#xff0c;但是大多停留在概念层面&#xff0c;真实开发中很少遇到&#xff0c;Mybatis源码中使用了大量的设计模式&#xff0c;阅读源码并观察设计模式在其中的应用&#xff0c;…