时间: 2023.6.21-2023.7.9
实现对学校低值易耗品管理,包括功能:
时间:
任何 提交申请 -> 审批列表 -> 审批详情 -> 审批(通过/驳回) 流程的表单均可快速生成,只需下面几步:
自上而下依次为:
添加条件和删除条件节点接口使用到了栈来寻找 虚拟节点(聚合节点)
// 记录当前节点(发散节点)
AppProcessNodeConfig dummyNodeUp = dummyNode;
// 获取当前 虚拟节点(发散节点) 所对应的 虚拟节点(聚合节点)
Stack<AppProcessNodeConfig> dummyNodeStack = new Stack<>();
dummyNodeStack.push(dummyNode);
while (!dummyNodeStack.empty()) {
dummyNode = getNextNode(dummyNode); // 获取虚拟节点的下一个节点
List<String> prevIdList = JSONObject.parseArray(dummyNode.getPrevId(), String.class);
List<String> nextIdList = JSONObject.parseArray(dummyNode.getNextId(), String.class);
if (nextIdList.size() > 1) { // 子节点有多个
dummyNodeStack.push(dummyNode);
} else if (prevIdList.size() > 1) { // 父节点有多个
if (dummyNodeStack.size() == 1) {
break;
}
dummyNodeStack.pop();
}
}
// 此时 dummyNode 为 虚拟节点(发散节点) 所对应的 虚拟节点(聚合节点)
/**
* 获取传入的 两个节点之间 所有节点的id集合 [左闭右开]
*
* @param node 当前节点
* @param targetNode 目标节点
* @param nodeIdList 用来存放id的集合
*/
public void getIdList(AppProcessNodeConfig node, AppProcessNodeConfig targetNode, HashSet<String> nodeIdList) {
if (!node.getId().equals(targetNode.getId())) { // 当前节点不等于目标节点
// 把当前 节点id 存入 nodeIdList
nodeIdList.add(node.getId());
// 递归向下查找
for (AppProcessNodeConfig nextNode : getNextNodeList(node)) {
getIdList(nextNode, targetNode, nodeIdList);
}
}
}
示例:
@ApiModelProperty(value = "提交申请表数据并生成流程")
@PostMapping("/submitData")
public ResponseResult submitApplicationData(@RequestBody SubmitApplicationDataReq req, HttpServletRequest request) {
String userId = jwtTokenUtil.getUserIdByRequest(request);
return appApplicationDataService.submitApplicationData(req, userId);
}
实现:
@Override
public ResponseResult submitApplicationData(SubmitApplicationDataReq req, String userId) {
//校验参数
if (isNullOrEmpty(req.getAppId(), req.getDataReqList())) {
return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
}
//校验 数据数量 与 控件数量 是否匹配
List<String> controlOrderIdList = req.getDataReqList().stream().map(ApplicationDataReq::getControlOrderId).collect(Collectors.toList());
Integer controlNum = appControlOrderMapper.selectCount(new LambdaQueryWrapper<AppControlOrder>()
.eq(AppControlOrder::getAppId, req.getAppId())
.in(AppControlOrder::getId, controlOrderIdList));
if (controlNum != req.getDataReqList().size()) {
return CommonResult.failed(CommonCodeEnum.DATA_NUM_NOT_EQUALS_CONTROL_NUM);
}
//校验必填控件是否全部填写
for (ApplicationDataReq dataReq : req.getDataReqList()) {
if (isNullOrEmpty(dataReq.getControlOrderId())) {
return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
}
Boolean isRequired = appDynamicUtil.getIsRequired(dataReq.getControlOrderId());
if (isRequired == null) {
return CommonResult.failed(CommonCodeEnum.CONTROL_NOT_EXIST);
}
if (isRequired) {
if (isNullOrEmpty(dataReq.getData())) {
return CommonResult.failed(CommonCodeEnum.REQUIRED_CONTROL_NOT_FILL);
}
}
}
List<AppProcessNodeConfigResp> processNodeRespList = new ArrayList<>();
//获取申请人节点配置
AppProcessNodeConfig nodeConfig = appProcessNodeConfigMapper.selectList(new LambdaQueryWrapper<AppProcessNodeConfig>()
.eq(AppProcessNodeConfig::getAppId, req.getAppId())
.eq(AppProcessNodeConfig::getType, APPLICANT_NODE)).get(0);
//记录节点顺序
int sort = 0;
while (nodeConfig.getType() != END_NODE) {
//添加当前节点
AppProcessNodeConfigResp nodeConfigResp = new AppProcessNodeConfigResp();
BeanUtils.copyProperties(nodeConfig, nodeConfigResp);
//设置节点顺序
nodeConfigResp.setSort(sort++);
//设置审批人信息
if (nodeConfigResp.getApproverType() == DYNAMIC_APP_ROLE) {
SmsRole role = smsRoleMapper.selectById(nodeConfigResp.getApproverObjectId());
nodeConfigResp.setObjectName(role.getRoleName());
} else if (nodeConfigResp.getApproverType() == DYNAMIC_APP_ASSIGNER) {
SmsUser user = smsUserMapper.selectById(nodeConfigResp.getApproverObjectId());
AppSearchUserResp userResp = new AppSearchUserResp();
BeanUtils.copyProperties(user, userResp);
nodeConfigResp.setUserInfo(userResp);
} else if (nodeConfigResp.getApproverType() == DYNAMIC_APP_SUBMITTER) {
SmsUser user = smsUserMapper.selectById(userId);
AppSearchUserResp userResp = new AppSearchUserResp();
BeanUtils.copyProperties(user, userResp);
nodeConfigResp.setUserInfo(userResp);
nodeConfigResp.setApproverType(DYNAMIC_APP_ASSIGNER);
nodeConfigResp.setApproverObjectId(userId);
}
//设置权限
nodeConfigResp.setAuthority(JSONObject.parseArray(nodeConfig.getAuthority(), AuthorityResp.class));
//添加本节点
processNodeRespList.add(nodeConfigResp);
//节点向后传递
List<AppProcessNodeConfig> nextNodeList = appDynamicUtil.getNextNodeList(nodeConfig);
a:
for (AppProcessNodeConfig nextNode : nextNodeList) {
while (true) {
if (nextNode.getType() == COPY_NODE || nextNode.getType() == APPROVE_NODE || nextNode.getType() == END_NODE) {
nodeConfig = nextNode;
break a;
} else if (nextNode.getType() == DUMMY_NODE) {
List<String> nextNodeSonIdList = JSON.parseArray(nextNode.getNextId(), String.class);
//虚拟节点(发散节点)
if (nextNodeSonIdList.size() > 1) {
for (int priority = 1; priority <= nextNodeSonIdList.size(); priority++) {
//根据 前节点id 及 优先级 检索到条件组集合
List<AppConditionGroup> conditionGroupList = appConditionGroupMapper.selectList(new LambdaQueryWrapper<AppConditionGroup>()
.eq(AppConditionGroup::getPrevNodeId, nextNode.getId())
.eq(AppConditionGroup::getPriority, priority));
//校验条件组是否存在
if (conditionGroupList.isEmpty()) {
return CommonResult.failed(CommonCodeEnum.APP_CONDITION_GROUP_NOT_EXIST);
}
//若当前条件组为默认条件
if (priority == nextNodeSonIdList.size() && conditionGroupList.get(0).getIsDefault()) {
AppProcessNodeConfig node = appProcessNodeConfigMapper.selectById(conditionGroupList.get(0).getNodeId());
nodeConfig = appDynamicUtil.getNextNode(node);
break a;
}
//遍历条件组中的条件是否完成
for (AppConditionGroup conditionGroup : conditionGroupList) {
List<AppCondition> conditionList = appConditionMapper.selectList(new LambdaQueryWrapper<AppCondition>()
.eq(AppCondition::getConditionGroupId, conditionGroup.getId()));
//校验条件是否存在
if (conditionList.isEmpty()) {
return CommonResult.failed(CommonCodeEnum.APP_CONDITION_NOT_EXIST);
}
//校验条件集合是否全部符合
boolean isReachedConditionList = appDynamicUtil.getIsReachedConditionList(req.getDataReqList(), conditionList, userId);
//若 条件组中 有 条件集合全部符合
if (isReachedConditionList) {
AppProcessNodeConfig node = appProcessNodeConfigMapper.selectById(conditionGroupList.get(0).getNodeId());
nodeConfig = appDynamicUtil.getNextNode(node);
break a;
}
}
}
} else {//虚拟节点(聚合节点)
nextNode = appDynamicUtil.getNextNodeList(nextNode).get(0);
}
}
}
}
}
return CommonResult.success(processNodeRespList, processNodeRespList.size());
}
时间: 2023.8.3-2023.8.29
学校对于会议室进行预约、申请、管理等操作
时间: 2023.10.25-2023.11.19
对接第三方厂商经验得到提升
对接视频监控
添加第三方依赖
<!-- ICC鉴权 -->
<dependency>
<groupId>com.dahuatech.icc</groupId>
<artifactId>java-sdk-oauth</artifactId>
<version>${icc.sdk.version}</version>
<exclusions>
<exclusion>
<artifactId>java-sdk-core</artifactId>
<groupId>com.dahuatech.icc</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.dahuatech.icc</groupId>
<artifactId>java-sdk-core</artifactId>
<version>${icc.sdk.version}</version>
</dependency>
<!-- ICC基础资源SDK -->
<dependency>
<groupId>com.dahuatech.icc</groupId>
<artifactId>java-sdk-oauth</artifactId>
<version>${icc.sdk.version}</version>
</dependency>
<!-- ICC 事件中心sdk -->
<dependency>
<groupId>com.dahuatech.icc</groupId>
<artifactId>java-sdk-event</artifactId>
<version>${icc.sdk.version}</version>
</dependency>
根据第三方系统规则获取鉴权
带鉴权、签名等(根据第三方规则)去请求第三方接口获取到数据,对数据进行处理(存数据库/返回给前端展示)
对接气体监测
添加mqtt
依赖
<dependency>
<groupId>com.github.tocrhz</groupId>
<artifactId>mqtt-spring-boot-starter</artifactId>
<version>1.2.7</version>
</dependency>
利用第三方规则请求其接口再对回应数据进行处理
/**
* 获取token
* @return token
*/
public String getGasToken() {
String gasValue = cacheUtil.getObject(gasKey, String.class);
// redis中获取到token
if (!isNullOrEmpty(gasValue)) {
// log.info("redis中有access_token:{}", gasValue);
return gasValue;
}
// redis未获取token,请求token
String gasTokenResult = OkHttpUtils.builder().url(tokenUrl)
.addParam("appKey", gasConfigProperties.getApp_key())
.addParam("appSecret", gasConfigProperties.getApp_secret())
.post(true)
.async();
JSONObject gasTokenJsonObject = JSONObject.parseObject(gasTokenResult);
// {"code":0,"data":{"access_token":"da8c3b33-972d-4f8c-a839-e0e913ad465c"}}
// 校验code
Integer code = gasTokenJsonObject.getInteger("code");
if (code != 0) {
ExceptionCast.cast(CommonResult.failed(CommonCodeEnum.GAS_ACCESS_TOKEN_FAIL));
}
// 获取access_token
String access_token = gasTokenJsonObject.getJSONObject("data").getString("access_token");
cacheUtil.add(gasKey, access_token, 2, TimeUnit.HOURS);
// log.info("access_token:{}", access_token);
return access_token;
}
利用mqtt
监听器监听到的数据有选择性地对数据库进行操作(插入、修改、删除等)
/**
* 接受来?设备的实时浓度数据
* @param topic 主题
* @param groupId 分组id
* @param deviceId 设备id
* @param slaveEventResp 每个探测器 15分钟数据上传?次(设备上报属性)
*/
@MqttSubscribe(value = lastTopic, qos = 0)
@Transactional
public void subLast(String topic,@NamedValue("groupId") String groupId,@NamedValue("deviceId") String deviceId,@Payload String slaveEventResp) {
// log.info("开始接受每个探测器15分钟数据上传?次......");
// log.info("receive from : {}", topic);
// log.info("groupId :{}",groupId);
// log.info("deviceId : {}",deviceId);
// log.info("设备上报 : {}", slaveEventResp);
updateSlaveData(groupId,deviceId,SLAVE_REPORT_TYPE,slaveEventResp);
// log.info("接受每个探测器15分钟数据上传?次结束!!!!!!");
}
时间: 2023.11.8-2023.12.12
平台主体
接收闸机请求
与第三方平台交互
城市社区
楼栋管理
房屋管理
住户管理
设备管理
门禁信息
其他
时间: 2023.11.29-2024.1.4 [第一阶段完成]
这里我主要展示自己第一次接触的订单模块,其他模块都基本上是增删改查操作以及对文件的处理
微信支付回调模块涉及公司业务不变展示,大家有任何问题可以私聊我了解.
有不对的或者可以改进的地方都可以一起交流,有则改之无则加勉!
import org.springframework.context.annotation.Bean;
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 java.util.concurrent.Executor;
import java.util.concurrent.Executors;
@Configuration
@EnableScheduling
public class ScheduleConfig implements SchedulingConfigurer {
@Override
public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
taskRegistrar.setScheduler(taskExecutor());
}
@Bean
public Executor taskExecutor() {
return Executors.newScheduledThreadPool(10); //指定线程池大小
}
}
@Component
@Log4j2
public class OrderScheduleTask {
@Resource
private MmsOrderScheduleService mmsOrderScheduleService;
@Resource
private MmsOrderService mmsOrderService;
@Resource
private MmsOrderRefundService mmsOrderRefundService;
@Resource
private WxPayUtil wxPayUtil;
@Resource
private OrderUtil orderUtil;
@Resource
private MmsUserCouponRelationService mmsUserCouponRelationService;
@Resource
private PlatformTransactionManager transactionManager; // 事务
@Scheduled(cron = "0 */1 * * * ?") // 每隔1分钟执行一次
public void schedulingTask() {
// 获取所有 未结束且已达过期时间 的定时任务
Date nowDate = new Date(); // 当前时间
List<MmsOrderSchedule> orderScheduleList = mmsOrderScheduleService.list(new LambdaQueryWrapper<MmsOrderSchedule>()
.eq(MmsOrderSchedule::getIsClose, false) // 状态未结束
.le(MmsOrderSchedule::getExpireTime, nowDate)); // 过期时间 早于 当前时间
if (orderScheduleList.isEmpty()) { // 没有定时任务直接结束方法
return;
}
for (MmsOrderSchedule orderSchedule : orderScheduleList) {
// 开启事务
DefaultTransactionDefinition dt = new DefaultTransactionDefinition();
// 嵌套事务 PROPAGATION_REQUIRES_NEW 每次开启一个新的事务
dt.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW);
// 设置嵌套事务
TransactionStatus status = transactionManager.getTransaction(dt);
try {
// 获取定时任务订单
MmsOrder order = mmsOrderService.getById(orderSchedule.getOrderId());
if (order == null) { //订单不存在
continue;
}
// 根据 进度类型(0.支付进度 1.发货进度 2.订单结束进度) 进行不同处理
switch (orderSchedule.getType()) {
case OrderScheduleConstant.ORDER_SCHEDULE_TYPE_PAYMENT: // 支付进度
// 主动查询用户支付情况
Transaction transaction = wxPayUtil.queryOrderByOutTradeNo(order.getId());
// 用户支付成功
if (transaction != null && transaction.getTradeState() == Transaction.TradeStateEnum.SUCCESS) {
if (!orderUtil.isPaid(order.getId())) {
// 修改订单状态等信息
order.setPaymentTransactionId(transaction.getTransactionId()); // 支付订单号
order.setPaymentAmount(centsToYuan(transaction.getAmount().getTotal())); // 支付金额
order.setPaymentMethod(OrderConstant.ORDER_PAYMENT_METHOD_WECHAT); // 订单支付方式: 微信支付
order.setPaymentTime(TimeUtil.rfc3339ParseDate(transaction.getSuccessTime())); // 支付时间
order.setOrderStatus(OrderConstant.ORDER_STATUS_TO_BE_DELIVERED); // 待发货
}
} else { // 支付失败
order.setOrderStatus(OrderConstant.ORDER_STATUS_ORDER_CANCELLED); // 订单状态: 0.取消订单
order.setIsClose(OrderConstant.ORDER_IS_CLOSE_YES); // 结束订单
order.setEndTime(nowDate); // 订单结束时间
}
break;
case OrderScheduleConstant.ORDER_SCHEDULE_TYPE_DELIVERY: // 发货进度
order.setOrderStatus(OrderConstant.ORDER_STATUS_ORDER_CANCELLED); // 订单状态: 0.取消订单
order.setIsClose(OrderConstant.ORDER_IS_CLOSE_YES); // 结束订单
order.setEndTime(nowDate); // 订单结束时间
// 付款金额大于0,自动退款
if (order.getPaymentAmount().compareTo(BigDecimal.valueOf(0)) > 0) {
// 查询不到支付订单号直接回滚
if (isNullOrEmpty(order.getPaymentTransactionId())) {
rollback(status); // 手动回滚事务
continue;
}
// 待退款中的订单改为退款失败
List<MmsOrderRefund> orderRefundList = mmsOrderRefundService.list(new LambdaQueryWrapper<MmsOrderRefund>()
.eq(MmsOrderRefund::getOrderId, order.getId()) // 订单编号
.eq(MmsOrderRefund::getStatus, OrderRefundConstant.ORDER_REFUND_STATUS_TO_BE_REFUNDED)); // 待退款
if (!orderRefundList.isEmpty()) {
MmsOrderRefund orderRefund = new MmsOrderRefund();
orderRefund.setStatus(OrderRefundConstant.ORDER_REFUND_STATUS_REFUNDED_FAIL); // 退款失败
List<String> orderRefundIdList = orderRefundList.stream().map(MmsOrderRefund::getId).collect(Collectors.toList());
boolean refundUpdSuccess = mmsOrderRefundService.update(orderRefund, new LambdaQueryWrapper<MmsOrderRefund>()
.in(MmsOrderRefund::getId, orderRefundIdList));
if (!refundUpdSuccess) { //修改失败
rollback(status); // 手动回滚事务
continue;
}
}
// 记录退款行为
MmsOrderRefund orderRefund = new MmsOrderRefund();
orderRefund.setUserId(order.getUserId());
orderRefund.setOrderId(order.getId());
orderRefund.setMedicineInfo(order.getMedicineInfo());
orderRefund.setStatus(OrderRefundConstant.ORDER_REFUND_STATUS_REFUNDING); // 退货状态: 退款中
orderRefund.setProcessApproverId(ProcessApproverConstant.PROCESS_APPROVER_SYSTEM); // 审批人: 系统-定时任务
orderRefund.setNotes(OrderRefundConstant.ORDER_REFUND_REASON_DELIVERY_TIMEOUT);
boolean refundSaveSuccess = mmsOrderRefundService.save(orderRefund);
if (!refundSaveSuccess) {
rollback(status); // 手动回滚事务
continue;
}
// 发起预退款
RefundReq preRefundReq = new RefundReq();
preRefundReq.setTransaction_id(order.getPaymentTransactionId()); // 微信交易订单号
preRefundReq.setOut_trade_no(order.getId()); // 商户订单号
preRefundReq.setOut_refund_no(orderRefund.getId()); // 退款单号
preRefundReq.setReason(OrderRefundConstant.ORDER_REFUND_REASON_USER_SUBMIT); // 退款原因: 用户申请退款
// 设置订单金额 单位:分(订单金额 = 原金额(元) * 100)
long total = order.getPaymentAmount().multiply(BigDecimal.valueOf(100)).longValue();
preRefundReq.setTotal(total); // 订单金额 单位:分
preRefundReq.setRefund(total); // 退款金额 单位:分(全部退)
Refund refund = wxPayUtil.createRefund(preRefundReq);
if (refund == null) {
rollback(status); // 手动回滚事务
continue;
}
// 修改退款记录
orderRefund.setRefundId(refund.getRefundId()); // 微信退款id
orderRefund.setRefundAmount(centsToYuan(refund.getAmount().getTotal())); // 退款金额
orderRefund.setRefundTime(TimeUtil.rfc3339ParseDate(refund.getSuccessTime())); // 退款时间
orderRefund.setStatus(OrderRefundConstant.ORDER_REFUND_STATUS_REFUNDED); // 退货状态: 已退款
boolean refundUpdSuccess = mmsOrderRefundService.updateById(orderRefund);
if (!refundUpdSuccess) {
rollback(status); // 手动回滚事务
continue;
}
}
// 退还优惠券
if (!isNullOrEmpty(order.getCouponInfo())) { // 存在优惠券信息
MmsUserCouponRelationResp couponInfo = JSONObject.parseObject(order.getCouponInfo(), MmsUserCouponRelationResp.class);
if (couponInfo != null) {
MmsUserCouponRelation userCoupon = mmsUserCouponRelationService.getById(couponInfo.getId());
if (userCoupon != null) {
// 优惠券状态修改为未使用
userCoupon.setIsUse(UserCouponRelationConstant.USER_COUPON_RELATION_NOT_USE);
boolean couponUpdSuccess = mmsUserCouponRelationService.updateById(userCoupon);
if (!couponUpdSuccess) { // 修改失败
rollback(status); // 手动回滚事务
continue;
}
}
}
}
break;
case OrderScheduleConstant.ORDER_SCHEDULE_TYPE_ORDER_END: // 订单结束进度
order.setOrderStatus(OrderConstant.ORDER_STATUS_ALREADY_RECEIVED); // 订单状态: 4.已收货
order.setIsClose(OrderConstant.ORDER_IS_CLOSE_YES); // 结束订单
order.setEndTime(nowDate); // 订单结束时间
// 发起分账
// 支付订单号不存在
if (isNullOrEmpty(order.getPaymentTransactionId())) {
continue;
}
wxPayUtil.profitSharingUnfreezeOrder(order.getId(), order.getPaymentTransactionId());
// 待退款中的订单改为退款失败
List<MmsOrderRefund> orderRefundList = mmsOrderRefundService.list(new LambdaQueryWrapper<MmsOrderRefund>()
.eq(MmsOrderRefund::getOrderId, order.getId()) // 订单编号
.eq(MmsOrderRefund::getStatus, OrderRefundConstant.ORDER_REFUND_STATUS_TO_BE_REFUNDED)); // 待退款
if (!orderRefundList.isEmpty()) {
MmsOrderRefund orderRefund = new MmsOrderRefund();
orderRefund.setStatus(OrderRefundConstant.ORDER_REFUND_STATUS_REFUNDED_FAIL); // 退款失败
List<String> orderRefundIdList = orderRefundList.stream().map(MmsOrderRefund::getId).collect(Collectors.toList());
boolean refundUpdSuccess = mmsOrderRefundService.update(orderRefund, new LambdaQueryWrapper<MmsOrderRefund>()
.in(MmsOrderRefund::getId, orderRefundIdList));
if (!refundUpdSuccess) { //修改失败
rollback(status); // 手动回滚事务
continue;
}
}
break;
}
// 修改订单
boolean orderUpdSuccess = mmsOrderService.updateById(order);
if (!orderUpdSuccess) {
rollback(status); // 手动回滚事务
continue;
}
// 关闭定时任务
orderSchedule.setIsClose(true); // 结束定时任务
orderSchedule.setEndTime(nowDate); // 结束时间
orderSchedule.setUpdateUserId(ProcessApproverConstant.PROCESS_APPROVER_SYSTEM); // 修改人
boolean scheduleUpdSuccess = mmsOrderScheduleService.updateById(orderSchedule);
if (!scheduleUpdSuccess) {
rollback(status); // 手动回滚事务
continue;
}
} catch (Exception e) {
e.printStackTrace();
// 手动回滚事务
transactionManager.rollback(status);
} finally {
if (status.isNewTransaction() && !status.isCompleted()) {
transactionManager.commit(status);
}
}
}
}
/**
* 将以分为单位的金额转换为以元为单位的金额(BigDecimal)
*
* @param <T> 可以是Integer或Long类型
* @param moneyInCents 以分为单位的金额(T)
* @return 以元为单位的金额(BigDecimal)
*/
private <T extends Number> BigDecimal centsToYuan(T moneyInCents) {
// 将分转换为元, 需要除以100, 并将结果存储为BigDecimal类型
return new BigDecimal(moneyInCents.longValue()).divide(BigDecimal.valueOf(100), 2, RoundingMode.HALF_UP);
}
/**
* 手动回滚事务
*
* @param status 嵌套事务
*/
private void rollback(TransactionStatus status) {
// 手动回滚事务
transactionManager.rollback(status);
if (status.isNewTransaction() && !status.isCompleted()) {
transactionManager.commit(status);
}
}
}
定时任务
定时任务其实并没有多么复杂,有些需求难免会遇到需要定时任务去解决的地方,了解定时任务之后再去处理这样的需求便会简单很多了
微信支付
首次接触对接微信支付受益匪浅,虽然很复杂,需要很多步骤,但是实现下来成就感满满,经过对微信支付的对接,我相信对其他支付(支付宝、云闪付等)的对接会更加得心应手
今年的收货特别多,技术层面以及逻辑思维能力得到了极大的提升,也交到了特别好的同事们,绝对称得上自己工作以来的一个良好开端,希望自己可以不忘初心,继续努力下去!!!