修改体检接口,新增字段,及修复部分bug
This commit is contained in:
@@ -15,7 +15,7 @@ import tk.mybatis.spring.annotation.MapperScan;
|
|||||||
@EnableAspectJAutoProxy(proxyTargetClass = true)
|
@EnableAspectJAutoProxy(proxyTargetClass = true)
|
||||||
@SpringBootApplication(scanBasePackages = "com")
|
@SpringBootApplication(scanBasePackages = "com")
|
||||||
@MapperScan(basePackages = {"com.guahao.*.mapper"})
|
@MapperScan(basePackages = {"com.guahao.*.mapper"})
|
||||||
@ServletComponentScan(basePackages = {"com.guahao.common.filter"})
|
@ServletComponentScan(basePackages = {"com.guahao.common.filter", "com.guahao.common.listener"})
|
||||||
@ComponentScan(basePackages = {"com.guahao"})
|
@ComponentScan(basePackages = {"com.guahao"})
|
||||||
@EnableScheduling
|
@EnableScheduling
|
||||||
public class GuahaoApplication extends SpringBootServletInitializer {
|
public class GuahaoApplication extends SpringBootServletInitializer {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
package com.guahao.api.task.mapper;
|
package com.guahao.api.task.mapper;
|
||||||
|
|
||||||
import com.guahao.api.task.model.UserMzjf;
|
|
||||||
import com.guahao.api.task.model.UserReserve8;
|
import com.guahao.api.task.model.UserReserve8;
|
||||||
import com.guahao.common.base.BaseMapper;
|
import com.guahao.common.base.BaseMapper;
|
||||||
import org.apache.ibatis.annotations.Mapper;
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
|
|||||||
@@ -0,0 +1,101 @@
|
|||||||
|
package com.guahao.common.listener;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.context.ApplicationListener;
|
||||||
|
import org.springframework.context.event.ContextClosedEvent;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import javax.servlet.ServletContextEvent;
|
||||||
|
import javax.servlet.ServletContextListener;
|
||||||
|
import javax.servlet.annotation.WebListener;
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
import java.sql.DriverManager;
|
||||||
|
import java.sql.SQLException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* MySQL连接清理监听器,用于在应用关闭时正确清理MySQL连接
|
||||||
|
*/
|
||||||
|
@Component
|
||||||
|
@WebListener
|
||||||
|
public class MysqlCleanupListener implements ServletContextListener, ApplicationListener<ContextClosedEvent> {
|
||||||
|
|
||||||
|
private static final Logger logger = LoggerFactory.getLogger(MysqlCleanupListener.class);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void contextInitialized(ServletContextEvent sce) {
|
||||||
|
// 应用启动时无需特殊处理
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void contextDestroyed(ServletContextEvent sce) {
|
||||||
|
cleanup();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onApplicationEvent(ContextClosedEvent event) {
|
||||||
|
cleanup();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 清理MySQL连接和相关资源
|
||||||
|
*/
|
||||||
|
private void cleanup() {
|
||||||
|
try {
|
||||||
|
// 注销驱动程序,防止内存泄漏
|
||||||
|
deregisterJdbcDrivers();
|
||||||
|
|
||||||
|
// 尝试停止MySQL的AbandonedConnectionCleanupThread
|
||||||
|
stopMySqlAbandonedConnectionCleanupThread();
|
||||||
|
|
||||||
|
logger.info("MySQL连接及相关资源清理完成");
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.error("清理MySQL连接资源时发生错误", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 注销JDBC驱动程序
|
||||||
|
*/
|
||||||
|
private void deregisterJdbcDrivers() {
|
||||||
|
try {
|
||||||
|
DriverManager.getDrivers();
|
||||||
|
java.sql.Driver driver;
|
||||||
|
while (DriverManager.getDrivers().hasMoreElements()) {
|
||||||
|
driver = DriverManager.getDrivers().nextElement();
|
||||||
|
if (driver.getClass().getName().startsWith("com.mysql")) {
|
||||||
|
DriverManager.deregisterDriver(driver);
|
||||||
|
logger.info("已注销MySQL驱动: {}", driver.getClass().getName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (SQLException e) {
|
||||||
|
logger.error("注销JDBC驱动时发生错误", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 停止MySQL的AbandonedConnectionCleanupThread线程
|
||||||
|
*/
|
||||||
|
private void stopMySqlAbandonedConnectionCleanupThread() {
|
||||||
|
try {
|
||||||
|
Class<?> clazz;
|
||||||
|
try {
|
||||||
|
clazz = Class.forName("com.mysql.jdbc.AbandonedConnectionCleanupThread");
|
||||||
|
} catch (ClassNotFoundException e) {
|
||||||
|
// 对于MySQL 8.0+版本,类名可能不同
|
||||||
|
try {
|
||||||
|
clazz = Class.forName("com.mysql.cj.jdbc.AbandonedConnectionCleanupThread");
|
||||||
|
} catch (ClassNotFoundException ex) {
|
||||||
|
logger.debug("未找到MySQL连接清理线程类,可能使用的是不同版本的驱动");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Method shutdownMethod = clazz.getMethod("shutdown");
|
||||||
|
shutdownMethod.invoke(null);
|
||||||
|
logger.info("已停止MySQL AbandonedConnectionCleanupThread线程");
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.warn("停止MySQL连接清理线程时发生错误", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -702,17 +702,20 @@ public class XmlUtil {
|
|||||||
str.append(vo.getPaynature());
|
str.append(vo.getPaynature());
|
||||||
str.append("</PayNature>");
|
str.append("</PayNature>");
|
||||||
// 当vo.getYbzhamount和ybtcamount都是0的时候,且zfamount>=0则此处用微信,其他情况用医保
|
// 当vo.getYbzhamount和ybtcamount都是0的时候,且zfamount>=0则此处用微信,其他情况用医保
|
||||||
if ((vo.getYbzhamount() == null || vo.getYbzhamount().compareTo(BigDecimal.valueOf(0.00)) == 0) &&
|
// if ((vo.getYbzhamount() == null || vo.getYbzhamount().compareTo(BigDecimal.valueOf(0.00)) == 0) &&
|
||||||
(vo.getYbtcamount() == null || vo.getYbtcamount().compareTo(BigDecimal.valueOf(0.00)) == 0) &&
|
// (vo.getYbtcamount() == null || vo.getYbtcamount().compareTo(BigDecimal.valueOf(0.00)) == 0) &&
|
||||||
vo.getZfamount().compareTo(BigDecimal.valueOf(0.00)) >= 0) {
|
// vo.getZfamount().compareTo(BigDecimal.valueOf(0.00)) >= 0) {
|
||||||
str.append("<PayType>");
|
// str.append("<PayType>");
|
||||||
str.append("微信");
|
// str.append("微信");
|
||||||
str.append("</PayType>");
|
// str.append("</PayType>");
|
||||||
} else {
|
// } else {
|
||||||
str.append("<PayType>");
|
// str.append("<PayType>");
|
||||||
str.append("医保");
|
// str.append("医保");
|
||||||
str.append("</PayType>");
|
// str.append("</PayType>");
|
||||||
}
|
// }
|
||||||
|
str.append("<PayType>");
|
||||||
|
str.append("微信");
|
||||||
|
str.append("</PayType>");
|
||||||
str.append("<PowerTranID>");
|
str.append("<PowerTranID>");
|
||||||
str.append(vo.getPowertranid());
|
str.append(vo.getPowertranid());
|
||||||
str.append("</PowerTranID>");
|
str.append("</PowerTranID>");
|
||||||
|
|||||||
@@ -290,11 +290,11 @@ public class HsjcController {
|
|||||||
*/
|
*/
|
||||||
@RequestMapping("/opTiQuery")
|
@RequestMapping("/opTiQuery")
|
||||||
@WebLog(description = "opTiQuery",logResponse = false)
|
@WebLog(description = "opTiQuery",logResponse = false)
|
||||||
public Object opTiQuery(Integer userId, String token,String HospitalZone ,String startDate, String endDate) {
|
public Object opTiQuery(Integer userId, String token,String HospitalZone ,String startDate, String endDate,String Type) {
|
||||||
try {
|
try {
|
||||||
int retToken = getUserToken(userId, token);
|
int retToken = getUserToken(userId, token);
|
||||||
if (retToken != 0) {
|
if (retToken != 0) {
|
||||||
Map<String, Object> stringObjectMap = hsjcService.opTiQuery(HospitalZone, startDate, endDate);
|
Map<String, Object> stringObjectMap = hsjcService.opTiQuery(HospitalZone, startDate, endDate,Type);
|
||||||
// log.info("后端返回数据为:"+stringObjectMap);
|
// log.info("后端返回数据为:"+stringObjectMap);
|
||||||
return ResponseResult.success(stringObjectMap);
|
return ResponseResult.success(stringObjectMap);
|
||||||
} else {
|
} else {
|
||||||
@@ -309,11 +309,11 @@ public class HsjcController {
|
|||||||
*/
|
*/
|
||||||
@RequestMapping("/getDetail")
|
@RequestMapping("/getDetail")
|
||||||
@WebLog(description = "getDetail")
|
@WebLog(description = "getDetail")
|
||||||
public Object getDetail(Integer userId, String token, String programId,String bookindDate) {
|
public Object getDetail(Integer userId, String token, String programId,String bookindDate,String Type) {
|
||||||
try {
|
try {
|
||||||
int retToken = getUserToken(userId, token);
|
int retToken = getUserToken(userId, token);
|
||||||
if (retToken != 0) {
|
if (retToken != 0) {
|
||||||
Map<String, Object> stringObjectMap = hsjcService.getDetail(programId,bookindDate);
|
Map<String, Object> stringObjectMap = hsjcService.getDetail(programId,bookindDate,Type);
|
||||||
// log.info("后端返回数据为:"+stringObjectMap);
|
// log.info("后端返回数据为:"+stringObjectMap);
|
||||||
return ResponseResult.success(stringObjectMap);
|
return ResponseResult.success(stringObjectMap);
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -151,7 +151,7 @@ public class HsjcService {
|
|||||||
return resSuc;
|
return resSuc;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Map<String, Object> opTiQuery(String hospitalZone, String startDate, String endDate) {
|
public Map<String, Object> opTiQuery(String hospitalZone, String startDate, String endDate,String type) {
|
||||||
Map<String, Object> result = new HashMap<>();
|
Map<String, Object> result = new HashMap<>();
|
||||||
List<Map<String, Object>> dataList = new ArrayList<>();
|
List<Map<String, Object>> dataList = new ArrayList<>();
|
||||||
|
|
||||||
@@ -166,6 +166,9 @@ public class HsjcService {
|
|||||||
str.append("<EndDate>");
|
str.append("<EndDate>");
|
||||||
str.append(endDate);
|
str.append(endDate);
|
||||||
str.append("</EndDate>");
|
str.append("</EndDate>");
|
||||||
|
str.append("<class>");
|
||||||
|
str.append(type);
|
||||||
|
str.append("</class>");
|
||||||
|
|
||||||
String respXml = SoapUtil.soapMethod4(str.toString(),"mop_canreservationphysicalprogram");
|
String respXml = SoapUtil.soapMethod4(str.toString(),"mop_canreservationphysicalprogram");
|
||||||
// log.debug("【原始SOAP响应】:\n{}", respXml);
|
// log.debug("【原始SOAP响应】:\n{}", respXml);
|
||||||
@@ -240,7 +243,7 @@ public class HsjcService {
|
|||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
public Map<String, Object> getDetail(String programId, String bookindDate) {
|
public Map<String, Object> getDetail(String programId, String bookindDate,String Type) {
|
||||||
try {
|
try {
|
||||||
StringBuffer str = new StringBuffer();
|
StringBuffer str = new StringBuffer();
|
||||||
str.append("<program_id>");
|
str.append("<program_id>");
|
||||||
@@ -249,6 +252,9 @@ public class HsjcService {
|
|||||||
str.append("<booking_date>");
|
str.append("<booking_date>");
|
||||||
str.append(bookindDate);
|
str.append(bookindDate);
|
||||||
str.append("</booking_date>");
|
str.append("</booking_date>");
|
||||||
|
str.append("<class>");
|
||||||
|
str.append(Type);
|
||||||
|
str.append("</class>");
|
||||||
|
|
||||||
String respXml = SoapUtil.soapMethod4(str.toString(),"mop_queryphysicalprogramdetail");
|
String respXml = SoapUtil.soapMethod4(str.toString(),"mop_queryphysicalprogramdetail");
|
||||||
|
|
||||||
@@ -297,6 +303,7 @@ public class HsjcService {
|
|||||||
str.append("<program_id>").append(programId).append("</program_id>");
|
str.append("<program_id>").append(programId).append("</program_id>");
|
||||||
str.append("<time_period>").append(detail.getTimePeriod()).append("</time_period>");
|
str.append("<time_period>").append(detail.getTimePeriod()).append("</time_period>");
|
||||||
str.append("<time>").append(detail.getTime()).append("</time>");
|
str.append("<time>").append(detail.getTime()).append("</time>");
|
||||||
|
str.append("<class>").append(detail.getType()).append("</class>");
|
||||||
str.append("</program>");
|
str.append("</program>");
|
||||||
|
|
||||||
// 拼接到本地存储的字符串:101,102,103
|
// 拼接到本地存储的字符串:101,102,103
|
||||||
|
|||||||
@@ -5,9 +5,19 @@ public class ProgramDetailVO {
|
|||||||
private String programId; // 项目ID(字符串或 Long,根据实际类型)
|
private String programId; // 项目ID(字符串或 Long,根据实际类型)
|
||||||
private String time; // 具体时间段,如 "8:00-12:00"
|
private String time; // 具体时间段,如 "8:00-12:00"
|
||||||
private String timePeriod; // 时段:AM / PM
|
private String timePeriod; // 时段:AM / PM
|
||||||
|
private String type; // 项目类型:1 套餐/ 2 单项
|
||||||
|
|
||||||
// ======= Getters and Setters =======
|
// ======= Getters and Setters =======
|
||||||
|
|
||||||
|
|
||||||
|
public String getType() {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setType(String type) {
|
||||||
|
this.type = type;
|
||||||
|
}
|
||||||
|
|
||||||
public String getProgramId() {
|
public String getProgramId() {
|
||||||
return programId;
|
return programId;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -131,8 +131,11 @@ public class YbServiceImpl implements YbService {
|
|||||||
return t;
|
return t;
|
||||||
});
|
});
|
||||||
|
|
||||||
// 用于跟踪正在执行延时任务的订单,防止重复执行
|
// 用于跟踪正在执行findStatus延时任务的订单,防止重复执行
|
||||||
private static final Set<String> pendingDelayedTasks = ConcurrentHashMap.newKeySet();
|
private static final Set<String> pendingFindStatusTasks = ConcurrentHashMap.newKeySet();
|
||||||
|
|
||||||
|
// 用于跟踪正在执行关闭未支付订单延时任务的订单,防止重复执行
|
||||||
|
private static final Set<String> pendingCloseOrderTasks = ConcurrentHashMap.newKeySet();
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private WxPayConfig wxPayConfig;
|
private WxPayConfig wxPayConfig;
|
||||||
@@ -1024,7 +1027,7 @@ public class YbServiceImpl implements YbService {
|
|||||||
// 启动15分钟后检查订单状态的延时任务
|
// 启动15分钟后检查订单状态的延时任务
|
||||||
String finalHospOutTradeNo = req.getHosp_out_trade_no();
|
String finalHospOutTradeNo = req.getHosp_out_trade_no();
|
||||||
// 使用防重复机制提交延时任务
|
// 使用防重复机制提交延时任务
|
||||||
if (pendingDelayedTasks.add(finalHospOutTradeNo)) {
|
if (pendingCloseOrderTasks.add(finalHospOutTradeNo)) {
|
||||||
scheduledExecutor.schedule(() -> {
|
scheduledExecutor.schedule(() -> {
|
||||||
try {
|
try {
|
||||||
// 检查订单状态是否仍为2(未支付)
|
// 检查订单状态是否仍为2(未支付)
|
||||||
@@ -1040,12 +1043,12 @@ public class YbServiceImpl implements YbService {
|
|||||||
log.error("检查订单状态异常", e);
|
log.error("检查订单状态异常", e);
|
||||||
} finally {
|
} finally {
|
||||||
// 确保无论成功或失败都从待处理集合中移除
|
// 确保无论成功或失败都从待处理集合中移除
|
||||||
pendingDelayedTasks.remove(finalHospOutTradeNo);
|
pendingCloseOrderTasks.remove(finalHospOutTradeNo);
|
||||||
}
|
}
|
||||||
}, 15, TimeUnit.MINUTES); // 15分钟后执行
|
}, 15, TimeUnit.MINUTES); // 15分钟后执行
|
||||||
log.info("已为订单 {} 安排15分钟后检查状态", req.getHosp_out_trade_no());
|
log.info("已为订单 {} 安排15分钟后检查状态", req.getHosp_out_trade_no());
|
||||||
} else {
|
} else {
|
||||||
log.info("订单 {} 已存在待执行的延时任务,跳过重复提交", req.getHosp_out_trade_no());
|
log.info("订单 {} 已存在待执行的关闭订单延时任务,跳过重复提交", req.getHosp_out_trade_no());
|
||||||
}
|
}
|
||||||
|
|
||||||
resMap.put("appid", xml.get("appid"));
|
resMap.put("appid", xml.get("appid"));
|
||||||
@@ -1708,7 +1711,7 @@ public class YbServiceImpl implements YbService {
|
|||||||
// 使用独立调度线程池异步延时执行findStatus方法,等待系统状态同步
|
// 使用独立调度线程池异步延时执行findStatus方法,等待系统状态同步
|
||||||
String hospOutTradeNo = wxResult.getHosp_out_trade_no();
|
String hospOutTradeNo = wxResult.getHosp_out_trade_no();
|
||||||
// 使用防重复机制提交延时任务
|
// 使用防重复机制提交延时任务
|
||||||
if (pendingDelayedTasks.add(hospOutTradeNo)) {
|
if (pendingFindStatusTasks.add(hospOutTradeNo)) {
|
||||||
scheduledExecutor.schedule(() -> {
|
scheduledExecutor.schedule(() -> {
|
||||||
try {
|
try {
|
||||||
log.info("用户退出流程,启用延时执行findStatus方法,写入His");
|
log.info("用户退出流程,启用延时执行findStatus方法,写入His");
|
||||||
@@ -1717,11 +1720,11 @@ public class YbServiceImpl implements YbService {
|
|||||||
log.error("延时执行findStatus异常", e);
|
log.error("延时执行findStatus异常", e);
|
||||||
} finally {
|
} finally {
|
||||||
// 确保无论成功或失败都从待处理集合中移除
|
// 确保无论成功或失败都从待处理集合中移除
|
||||||
pendingDelayedTasks.remove(hospOutTradeNo);
|
pendingFindStatusTasks.remove(hospOutTradeNo);
|
||||||
}
|
}
|
||||||
}, 10, TimeUnit.SECONDS);
|
}, 10, TimeUnit.SECONDS);
|
||||||
} else {
|
} else {
|
||||||
log.info("订单 {} 已存在待执行的延时任务,跳过重复提交", hospOutTradeNo);
|
log.info("订单 {} 已存在待执行的findStatus延时任务,跳过重复提交", hospOutTradeNo);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -37,6 +37,10 @@ druid.testOnReturn=false
|
|||||||
druid.poolPreparedStatements=true
|
druid.poolPreparedStatements=true
|
||||||
druid.maxPoolPreparedStatementPerConnectionSize=20
|
druid.maxPoolPreparedStatementPerConnectionSize=20
|
||||||
druid.filters=stat
|
druid.filters=stat
|
||||||
|
# 连接泄露检测配置
|
||||||
|
druid.removeAbandoned=true
|
||||||
|
druid.removeAbandonedTimeout=1800
|
||||||
|
druid.logAbandoned=true
|
||||||
#数据库连接信息
|
#数据库连接信息
|
||||||
#spring.datasource.dynamic.datasource.master.driver-class-name=com.mysql.jdbc.Driver
|
#spring.datasource.dynamic.datasource.master.driver-class-name=com.mysql.jdbc.Driver
|
||||||
#spring.datasource.dynamic.datasource.master.url=jdbc:mysql://localhost:3306/guahao?zeroDateTimeBehavior=convertToNull&serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai
|
#spring.datasource.dynamic.datasource.master.url=jdbc:mysql://localhost:3306/guahao?zeroDateTimeBehavior=convertToNull&serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai
|
||||||
|
|||||||
Reference in New Issue
Block a user