修改体检接口,新增字段,及修复部分bug
This commit is contained in:
@@ -15,7 +15,7 @@ import tk.mybatis.spring.annotation.MapperScan;
|
||||
@EnableAspectJAutoProxy(proxyTargetClass = true)
|
||||
@SpringBootApplication(scanBasePackages = "com")
|
||||
@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"})
|
||||
@EnableScheduling
|
||||
public class GuahaoApplication extends SpringBootServletInitializer {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package com.guahao.api.task.mapper;
|
||||
|
||||
import com.guahao.api.task.model.UserMzjf;
|
||||
|
||||
import com.guahao.api.task.model.UserReserve8;
|
||||
import com.guahao.common.base.BaseMapper;
|
||||
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("</PayNature>");
|
||||
// 当vo.getYbzhamount和ybtcamount都是0的时候,且zfamount>=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.getZfamount().compareTo(BigDecimal.valueOf(0.00)) >= 0) {
|
||||
str.append("<PayType>");
|
||||
str.append("微信");
|
||||
str.append("</PayType>");
|
||||
} else {
|
||||
str.append("<PayType>");
|
||||
str.append("医保");
|
||||
str.append("</PayType>");
|
||||
}
|
||||
// if ((vo.getYbzhamount() == null || vo.getYbzhamount().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) {
|
||||
// str.append("<PayType>");
|
||||
// str.append("微信");
|
||||
// str.append("</PayType>");
|
||||
// } else {
|
||||
// str.append("<PayType>");
|
||||
// str.append("医保");
|
||||
// str.append("</PayType>");
|
||||
// }
|
||||
str.append("<PayType>");
|
||||
str.append("微信");
|
||||
str.append("</PayType>");
|
||||
str.append("<PowerTranID>");
|
||||
str.append(vo.getPowertranid());
|
||||
str.append("</PowerTranID>");
|
||||
|
||||
@@ -290,11 +290,11 @@ public class HsjcController {
|
||||
*/
|
||||
@RequestMapping("/opTiQuery")
|
||||
@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 {
|
||||
int retToken = getUserToken(userId, token);
|
||||
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);
|
||||
return ResponseResult.success(stringObjectMap);
|
||||
} else {
|
||||
@@ -309,11 +309,11 @@ public class HsjcController {
|
||||
*/
|
||||
@RequestMapping("/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 {
|
||||
int retToken = getUserToken(userId, token);
|
||||
if (retToken != 0) {
|
||||
Map<String, Object> stringObjectMap = hsjcService.getDetail(programId,bookindDate);
|
||||
Map<String, Object> stringObjectMap = hsjcService.getDetail(programId,bookindDate,Type);
|
||||
// log.info("后端返回数据为:"+stringObjectMap);
|
||||
return ResponseResult.success(stringObjectMap);
|
||||
} else {
|
||||
|
||||
@@ -151,7 +151,7 @@ public class HsjcService {
|
||||
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<>();
|
||||
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("<class>");
|
||||
str.append(type);
|
||||
str.append("</class>");
|
||||
|
||||
String respXml = SoapUtil.soapMethod4(str.toString(),"mop_canreservationphysicalprogram");
|
||||
// log.debug("【原始SOAP响应】:\n{}", respXml);
|
||||
@@ -240,7 +243,7 @@ public class HsjcService {
|
||||
return "";
|
||||
}
|
||||
|
||||
public Map<String, Object> getDetail(String programId, String bookindDate) {
|
||||
public Map<String, Object> getDetail(String programId, String bookindDate,String Type) {
|
||||
try {
|
||||
StringBuffer str = new StringBuffer();
|
||||
str.append("<program_id>");
|
||||
@@ -249,6 +252,9 @@ public class HsjcService {
|
||||
str.append("<booking_date>");
|
||||
str.append(bookindDate);
|
||||
str.append("</booking_date>");
|
||||
str.append("<class>");
|
||||
str.append(Type);
|
||||
str.append("</class>");
|
||||
|
||||
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("<time_period>").append(detail.getTimePeriod()).append("</time_period>");
|
||||
str.append("<time>").append(detail.getTime()).append("</time>");
|
||||
str.append("<class>").append(detail.getType()).append("</class>");
|
||||
str.append("</program>");
|
||||
|
||||
// 拼接到本地存储的字符串:101,102,103
|
||||
|
||||
@@ -5,9 +5,19 @@ public class ProgramDetailVO {
|
||||
private String programId; // 项目ID(字符串或 Long,根据实际类型)
|
||||
private String time; // 具体时间段,如 "8:00-12:00"
|
||||
private String timePeriod; // 时段:AM / PM
|
||||
private String type; // 项目类型:1 套餐/ 2 单项
|
||||
|
||||
// ======= Getters and Setters =======
|
||||
|
||||
|
||||
public String getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public void setType(String type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public String getProgramId() {
|
||||
return programId;
|
||||
}
|
||||
|
||||
@@ -131,8 +131,11 @@ public class YbServiceImpl implements YbService {
|
||||
return t;
|
||||
});
|
||||
|
||||
// 用于跟踪正在执行延时任务的订单,防止重复执行
|
||||
private static final Set<String> pendingDelayedTasks = ConcurrentHashMap.newKeySet();
|
||||
// 用于跟踪正在执行findStatus延时任务的订单,防止重复执行
|
||||
private static final Set<String> pendingFindStatusTasks = ConcurrentHashMap.newKeySet();
|
||||
|
||||
// 用于跟踪正在执行关闭未支付订单延时任务的订单,防止重复执行
|
||||
private static final Set<String> pendingCloseOrderTasks = ConcurrentHashMap.newKeySet();
|
||||
|
||||
@Autowired
|
||||
private WxPayConfig wxPayConfig;
|
||||
@@ -1024,7 +1027,7 @@ public class YbServiceImpl implements YbService {
|
||||
// 启动15分钟后检查订单状态的延时任务
|
||||
String finalHospOutTradeNo = req.getHosp_out_trade_no();
|
||||
// 使用防重复机制提交延时任务
|
||||
if (pendingDelayedTasks.add(finalHospOutTradeNo)) {
|
||||
if (pendingCloseOrderTasks.add(finalHospOutTradeNo)) {
|
||||
scheduledExecutor.schedule(() -> {
|
||||
try {
|
||||
// 检查订单状态是否仍为2(未支付)
|
||||
@@ -1040,12 +1043,12 @@ public class YbServiceImpl implements YbService {
|
||||
log.error("检查订单状态异常", e);
|
||||
} finally {
|
||||
// 确保无论成功或失败都从待处理集合中移除
|
||||
pendingDelayedTasks.remove(finalHospOutTradeNo);
|
||||
pendingCloseOrderTasks.remove(finalHospOutTradeNo);
|
||||
}
|
||||
}, 15, TimeUnit.MINUTES); // 15分钟后执行
|
||||
log.info("已为订单 {} 安排15分钟后检查状态", req.getHosp_out_trade_no());
|
||||
} else {
|
||||
log.info("订单 {} 已存在待执行的延时任务,跳过重复提交", req.getHosp_out_trade_no());
|
||||
log.info("订单 {} 已存在待执行的关闭订单延时任务,跳过重复提交", req.getHosp_out_trade_no());
|
||||
}
|
||||
|
||||
resMap.put("appid", xml.get("appid"));
|
||||
@@ -1708,7 +1711,7 @@ public class YbServiceImpl implements YbService {
|
||||
// 使用独立调度线程池异步延时执行findStatus方法,等待系统状态同步
|
||||
String hospOutTradeNo = wxResult.getHosp_out_trade_no();
|
||||
// 使用防重复机制提交延时任务
|
||||
if (pendingDelayedTasks.add(hospOutTradeNo)) {
|
||||
if (pendingFindStatusTasks.add(hospOutTradeNo)) {
|
||||
scheduledExecutor.schedule(() -> {
|
||||
try {
|
||||
log.info("用户退出流程,启用延时执行findStatus方法,写入His");
|
||||
@@ -1717,11 +1720,11 @@ public class YbServiceImpl implements YbService {
|
||||
log.error("延时执行findStatus异常", e);
|
||||
} finally {
|
||||
// 确保无论成功或失败都从待处理集合中移除
|
||||
pendingDelayedTasks.remove(hospOutTradeNo);
|
||||
pendingFindStatusTasks.remove(hospOutTradeNo);
|
||||
}
|
||||
}, 10, TimeUnit.SECONDS);
|
||||
} else {
|
||||
log.info("订单 {} 已存在待执行的延时任务,跳过重复提交", hospOutTradeNo);
|
||||
log.info("订单 {} 已存在待执行的findStatus延时任务,跳过重复提交", hospOutTradeNo);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
||||
@@ -37,6 +37,10 @@ druid.testOnReturn=false
|
||||
druid.poolPreparedStatements=true
|
||||
druid.maxPoolPreparedStatementPerConnectionSize=20
|
||||
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.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