增加功能

This commit is contained in:
jiangs 2025-08-06 17:10:01 +08:00
parent 571ffad210
commit f41139ea76
11 changed files with 712 additions and 0 deletions

View File

@ -0,0 +1,177 @@
package com.czlisinterface.system.socket;
import lombok.extern.slf4j.Slf4j;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.Socket;
import java.net.SocketException;
import java.nio.charset.StandardCharsets;
import java.util.LinkedList;
import java.util.List;
import java.util.StringTokenizer;
@Slf4j
public class ConnectionHandler implements Runnable {
private static final int MESSAGE_CONTROL_ID_LOCATION = 9;
private static final String FIELD_DELIMITER = "|";
private Socket connection;
private static List pool = new LinkedList();
static final char END_OF_BLOCK = '\u001c'; //结束符
static final char START_OF_BLOCK = '\u000b'; //开始符
static final char CARRIAGE_RETURN = 13; //换行符
private static final int END_OF_TRANSMISSION = -1;
public ConnectionHandler() {
}
public void handleConnection() {
try {
System.out.println("Handling client at "
+ connection.getInetAddress().getHostAddress()
+ " on port " + connection.getPort());
// InputStream in = connection.getInputStream();
InputStreamReader in = new InputStreamReader(connection.getInputStream(), StandardCharsets.UTF_8);
OutputStream out = connection.getOutputStream();
// PrintWriter out = new PrintWriter(new OutputStreamWriter(connection.getOutputStream(), "UTF-8"), true);
String parsedHL7Message = getMessage(in); //接受消息
log.info("接受到的平台消息:"+parsedHL7Message.replaceAll("\\r","\n"));
// XtrmyyUtils xtrmyyUtils = SpringUtil.getBean(XtrmyyUtils.class);
// xtrmyyUtils.busProcess(parsedHL7Message);
String buildAcknowledgmentMessage = getSimpleAcknowledgementMessage(parsedHL7Message); //回复应答ACK消息
out.write(buildAcknowledgmentMessage.getBytes(), 0, buildAcknowledgmentMessage.length());
} catch (IOException e) {
String errorMessage = "Error whiling reading and writing to connection " + e.getMessage();
System.out.println(errorMessage);
throw new RuntimeException(errorMessage);
}
finally {
try {
connection.close();
}
catch (IOException e) {
String errorMessage = "Error whiling attempting to close to connection " + e.getMessage();
System.out.println(errorMessage);
throw new RuntimeException(errorMessage);
}
}
}
public static void processRequest(Socket requestToHandle) {
synchronized (pool) {
pool.add(pool.size(), requestToHandle);
pool.notifyAll();
}
}
public void run() {
while (true) {
synchronized (pool) {
while (pool.isEmpty()) {
try {
pool.wait();
} catch (InterruptedException e) {
return;
}
}
connection = (Socket) pool.remove(0);
}
handleConnection();
}
}
public String getMessage(InputStreamReader anInputStream) throws IOException {
boolean end_of_message = false;
StringBuffer parsedMessage = new StringBuffer();
int characterReceived = 0;
try {
characterReceived = anInputStream.read();
} catch (SocketException e) {
System.out
.println("Unable to read from socket stream. "
+ "Connection may have been closed: " + e.getMessage());
return null;
}
if (characterReceived == END_OF_TRANSMISSION) {
return null;
}
if (characterReceived != START_OF_BLOCK) {
throw new RuntimeException(
"Start of block character has not been received");
}
while (!end_of_message) {
characterReceived = anInputStream.read();
if (characterReceived == END_OF_TRANSMISSION) {
throw new RuntimeException(
"Message terminated without end of message character");
}
if (characterReceived == END_OF_BLOCK) {
characterReceived = anInputStream.read();
if (characterReceived != CARRIAGE_RETURN) {
throw new RuntimeException(
"End of message character must be followed by a carriage return character");
}
end_of_message = true;
} else {
parsedMessage.append((char) characterReceived);
}
}
System.out.println("接受到的消息:\n"+parsedMessage.toString().replaceAll("\\r","\n"));
return parsedMessage.toString();
}
private String getSimpleAcknowledgementMessage(String aParsedHL7Message) {
if (aParsedHL7Message == null)
throw new RuntimeException("Invalid HL7 message for parsing operation" +
". Please check your inputs");
String messageControlID = getMessageControlID(aParsedHL7Message);
StringBuffer ackMessage = new StringBuffer();
ackMessage = ackMessage.append(START_OF_BLOCK)
.append("MSH|^~\\&|HIS|RIH|EKG|EKG|199904140038||ACK^A01|12345678|P|2.2")
.append(CARRIAGE_RETURN)
.append("MSA|AA|")
.append(messageControlID)
.append(CARRIAGE_RETURN)
.append(END_OF_BLOCK)
.append(CARRIAGE_RETURN);
return ackMessage.toString();
}
private String getMessageControlID(String aParsedHL7Message) {
int fieldCount = 0;
StringTokenizer tokenizer = new StringTokenizer(aParsedHL7Message, FIELD_DELIMITER);
while (tokenizer.hasMoreElements())
{
String token = tokenizer.nextToken();
fieldCount++;
if (fieldCount == MESSAGE_CONTROL_ID_LOCATION){
return token;
}
}
return "";
}
}

View File

@ -0,0 +1,65 @@
package com.czlisinterface.system.socket;
import lombok.extern.slf4j.Slf4j;
import java.io.IOException;
import java.net.BindException;
import java.net.ServerSocket;
import java.net.Socket;
@Slf4j
public class MLLPBasedHL7ThreadedServer {
private int maxConnections;
private int listenPort;
public MLLPBasedHL7ThreadedServer(int aListenPort, int maxConnections) {
listenPort = aListenPort;
this.maxConnections = maxConnections;
}
public void acceptConnections() {
try {
ServerSocket server = new ServerSocket(listenPort, 5000);
Socket clientSocket = null;
while (true) {
clientSocket = server.accept();
//server.setSoTimeout(100000); 设置超时时间
handleConnection(clientSocket);
System.out.println("SocketServer start at port:"+listenPort);
}
} catch (BindException e) {
System.out.println("Unable to bind to port " + listenPort);
} catch (IOException e) {
System.out.println("Unable to instantiate a ServerSocket on port: " + listenPort);
}
}
protected void handleConnection(Socket connectionToHandle) {
ConnectionHandler.processRequest(connectionToHandle);
}
// public static void main(String[] args) {
// MLLPBasedHL7ThreadedServer server = new MLLPBasedHL7ThreadedServer(9568, 3);
// server.setUpConnectionHandlers(); //启动线程
// server.acceptConnections(); //创建socket服务
// }
public void setUpConnectionHandlers() {
for (int i = 0; i < maxConnections; i++) {
ConnectionHandler currentHandler =
new ConnectionHandler();
Thread handlerThread = new Thread(currentHandler, "Handler " + i);
handlerThread.setDaemon(true);
handlerThread.start();
}
}
}

View File

@ -0,0 +1,120 @@
package com.czlisinterface.system.socket;
import lombok.extern.slf4j.Slf4j;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.net.SocketException;
import java.nio.charset.StandardCharsets;
@Slf4j
public class SimpleTCPEchoClient {
private static final char END_OF_BLOCK = '\u001c'; //结束符
private static final char START_OF_BLOCK = '\u000b'; //开始符
private static final char CARRIAGE_RETURN = 13; //换行符
private static final int END_OF_TRANSMISSION = -1;
public static String socketClientHost;
public static String socketClientPort;
public static String simpleClient(String str) throws IOException {
int i = str.indexOf("\n", str.length() - 1);
if(i > 0){
str = str.substring(0,i);
}
str = str.replaceAll("\\n","\r");
System.out.println("str:"+str);
StringBuffer stringBuffer = new StringBuffer();
// String testMessage = "MSH|^~\\&|HIS|RIH|EKG|EKG|199904140038||ADT^A01|12345678|P|2.2\r"
// + "PID|0001|00009874|00001122|A00977|SMITH^JOHN^M|MOM|19581119|F|NOTREAL^LINDA^M|C|564 SPRING ST^^NEEDHAM^MA^02494^US|0002|(818)565-1551|(425)828-3344|E|S|C|0000444444|252-00-4414||||SA|||SA||||NONE|V1|0001|I|D.ER^50A^M110^01|ER|P00055|11B^M011^02|070615^BATMAN^GEORGE^L|555888^NOTREAL^BOB^K^DR^MD|777889^NOTREAL^SAM^T^DR^MD^PHD|ER|D.WT^1A^M010^01|||ER|AMB|02|070615^NOTREAL^BILL^L|ER|000001916994|D||||||||||||||||GDD|WA|NORM|02|O|02|E.IN^02D^M090^01|E.IN^01D^M080^01|199904072124|199904101200|199904101200||||5555112333|||666097^NOTREAL^MANNY^P\r"
// + "NK1|0222555|NOTREAL^JAMES^R|FA|STREET^OTHER STREET^CITY^ST^55566|(222)111-3333|(888)999-0000|||||||ORGANIZATION\r"
// + "PV1|0001|I|D.ER^1F^M950^01|ER|P000998|11B^M011^02|070615^BATMAN^GEORGE^L|555888^OKNEL^BOB^K^DR^MD|777889^NOTREAL^SAM^T^DR^MD^PHD|ER|D.WT^1A^M010^01|||ER|AMB|02|070615^VOICE^BILL^L|ER|000001916994|D||||||||||||||||GDD|WA|NORM|02|O|02|E.IN^02D^M090^01|E.IN^01D^M080^01|199904072124|199904101200|||||5555112333|||666097^DNOTREAL^MANNY^P\r"
// + "PV2|||0112^TESTING|55555^PATIENT IS NORMAL|NONE|||19990225|19990226|1|1|TESTING|555888^NOTREAL^BOB^K^DR^MD||||||||||PROD^003^099|02|ER||NONE|19990225|19990223|19990316|NONE\r"
// + "AL1||SEV|001^POLLEN\r"
// + "GT1||0222PL|NOTREAL^BOB^B||STREET^OTHER STREET^CITY^ST^77787|(444)999-3333|(222)777-5555||||MO|111-33-5555||||NOTREAL GILL N|STREET^OTHER STREET^CITY^ST^99999|(111)222-3333\r"
// + "IN1||022254P|4558PD|BLUE CROSS|STREET^OTHER STREET^CITY^ST^00990||(333)333-6666||221K|LENIX|||19980515|19990515|||PATIENT01 TEST D||||||||||||||||||02LL|022LP554";
stringBuffer.append(START_OF_BLOCK)
.append(str)
.append(END_OF_BLOCK)
.append(CARRIAGE_RETURN);
byte[] byteBuffer = stringBuffer.toString().getBytes(StandardCharsets.UTF_8);
// Create socket that is connected to a server running on the same machine on port 1080
socketClientHost = SocketUtils.getYmlValues("socketClientHost");
socketClientPort = SocketUtils.getYmlValues("socketClientPort");
Socket socket = new Socket(socketClientHost, Integer.parseInt(socketClientPort));
System.out.println("Connected to Server");
InputStream in = socket.getInputStream();
OutputStream out = socket.getOutputStream();
// Send the message to the server
out.write(byteBuffer);
//in.read(byteBuffer);
String message = String.valueOf(getMessage(in));
log.info("调用平台接口:入参:"+str.replaceAll("\\r","\n")+"\n"+"出参:"+message.replaceAll("\\r","\n"));
System.out.println("Message received from Server: " + message.replaceAll("\\r","\n"));
// Close the socket and its streams
socket.close();
return message;
}
public static String getMessage(InputStream anInputStream) throws IOException {
boolean end_of_message = false;
StringBuffer parsedMessage = new StringBuffer();
int characterReceived = 0;
try {
characterReceived = anInputStream.read();
} catch (SocketException e) {
System.out
.println("Unable to read from socket stream. "
+ "Connection may have been closed: " + e.getMessage());
return null;
}
if (characterReceived == END_OF_TRANSMISSION) {
return null;
}
if (characterReceived != START_OF_BLOCK) {
throw new RuntimeException(
"Start of block character has not been received");
}
while (!end_of_message) {
characterReceived = anInputStream.read();
if (characterReceived == END_OF_TRANSMISSION) {
throw new RuntimeException(
"Message terminated without end of message character");
}
if (characterReceived == END_OF_BLOCK) {
characterReceived = anInputStream.read();
if (characterReceived != CARRIAGE_RETURN) {
throw new RuntimeException(
"End of message character must be followed by a carriage return character");
}
end_of_message = true;
} else {
parsedMessage.append((char) characterReceived);
}
}
//System.out.println("接受到的消息:\n"+parsedMessage.toString().replaceAll("\\r","\n"));
return parsedMessage.toString();
}
}

View File

@ -0,0 +1,68 @@
package com.czlisinterface.system.socket;
import lombok.extern.slf4j.Slf4j;
import org.yaml.snakeyaml.Yaml;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.Map;
@Slf4j
public class SocketUtils {
public static String socketServerPort;
/**
* 启动socket
*/
public static void socketStart(){
socketServerPort = getYmlValues("socketServerPort");
MLLPBasedHL7ThreadedServer server = new MLLPBasedHL7ThreadedServer(Integer.parseInt(socketServerPort), 3000);
server.setUpConnectionHandlers(); //启动线程
server.acceptConnections(); //创建socket服务
}
/**
* 获取配置文件的值
* @param key
* @return
*/
public static String getYmlValues(String key) {
String value = "";
Yaml yaml = new Yaml();
InputStream inputStream = null;
String basePath= Thread.currentThread().getContextClassLoader().getResource("application.yml").getPath();
try {
inputStream = new FileInputStream(basePath);
Map map = (Map) yaml.load(inputStream);
value = String.valueOf(map.get(key));
} catch (FileNotFoundException e) {
e.printStackTrace();
}
return value;
}
/**
* 创建一个socket客户端并发送消息
*/
public static String sendMessage(String str){
try {
String s = SimpleTCPEchoClient.simpleClient(str);
return s;
} catch (IOException e) {
e.printStackTrace();
}
return "";
}
}

View File

@ -0,0 +1,34 @@
package com.czlisinterface.system.socket;
import ca.uhn.hl7v2.DefaultHapiContext;
import ca.uhn.hl7v2.HapiContext;
import ca.uhn.hl7v2.llp.MinLowerLayerProtocol;
import ca.uhn.hl7v2.llp.MllpConstants;
/**
* @Author : sxd
* @Date : 2022/7/28 8:53
* @Description : WebContext
*/
public enum WebContext {
INSTANCE;
WebContext() {
HapiContext ctx = new DefaultHapiContext();
MinLowerLayerProtocol minLowerLayerProtocol = new MinLowerLayerProtocol();
minLowerLayerProtocol.setCharset("UTF-8");
System.setProperty(MllpConstants.CHARSET_KEY, "UTF-8");
ctx.setLowerLayerProtocol(minLowerLayerProtocol);
this.hapiContext = ctx;
}
private HapiContext hapiContext;
public HapiContext getHapiContext() {
return this.hapiContext;
}
}

View File

@ -0,0 +1,123 @@
package com.czlisinterface.system.task;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.dynamic.datasource.annotation.DSTransactional;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.czlisinterface.system.mapper.Hisinter_exec_log_Mapper;
import com.czlisinterface.system.pojo.Hisinter_exec_log;
import com.czlisinterface.system.pojo.Result;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.util.Date;
import java.util.List;
@Component
@Slf4j
public class BaskCommonTask implements BaskTask {
@Value("${lisinterface.task.cron:}")
private String taskCron;
@Value("${lisinterface.task.type:0}")
private String type;
@Resource
public Hisinter_exec_log_Mapper hisinterExecLogMapper;
@Override
public String getCron() {
if(type.equals("0")){
return null;
}else{
return taskCron;
}
}
@Override
public void execute() {
}
@Override
public void run() {
execute();
}
public Result sendReport(Date jyrq, String yq, String ybh, String status) {
return null;
}
/**
* 发送报告定时任务
*/
public void sendReportTask(){
List<Hisinter_exec_log> topData = hisinterExecLogMapper.getTopData();
for (Hisinter_exec_log topDatNum : topData) {
Integer id = topDatNum.getId();
String recordid = topDatNum.getRecordid();
String status = topDatNum.getStatus();
List<String> split = StrUtil.split(recordid, "|");
String jyrq = split.get(0);
String sjyrq = jyrq.substring(0, 4) + "-" + jyrq.substring(4, 6) + "-" + jyrq.substring(6, 8);
String yq = split.get(1);
String ybh = split.get(2);
try{
Result result = sendReport(DateUtil.parse(sjyrq, "yyyy-MM-dd"), yq, ybh, status);
saveTaskInfo(id,result);
}catch(Exception e){
e.printStackTrace();
log.error("调用定时报告任务出错,id:"+id+";错误信息:",e);
saveTaskInfo(id,new Result("-1",e.getMessage()));
}
}
}
public Result sendReportAll(Hisinter_exec_log hisinter_exec_log) {
return null;
}
/**
* 发送报告定时任务
*/
public void sendReportTaskAll(){
List<Hisinter_exec_log> topData = hisinterExecLogMapper.getTopData();
for (Hisinter_exec_log topDatNum : topData) {
Integer id = topDatNum.getId();
try{
//Result result = sendReport(DateUtil.parse(sjyrq, "yyyy-MM-dd"), yq, ybh, status);
Result result = sendReportAll(topDatNum);
saveTaskInfo(id,result);
}catch(Exception e){
e.printStackTrace();
log.error("调用定时报告任务出错,id:"+id+";错误信息:",e);
saveTaskInfo(id,new Result("-1",e.getMessage()));
}
}
}
/**
* 保存结果信息
* @param id
* @param result
*/
@DSTransactional
public void saveTaskInfo(Integer id,Result result){
UpdateWrapper<Hisinter_exec_log> updateWrapper = new UpdateWrapper<>();
updateWrapper.eq("id",id);
Hisinter_exec_log hisinterExecLog = new Hisinter_exec_log();
hisinterExecLog.setTextlog(result.getMessage());
hisinterExecLog.setTxt1(result.getResultCode());
hisinterExecLogMapper.update(hisinterExecLog, updateWrapper);
}
}

View File

@ -0,0 +1,10 @@
package com.czlisinterface.system.task;
public interface BaskTask extends Runnable {
//获取执行频率
String getCron();
//执行任务逻辑
void execute();
}

View File

@ -0,0 +1,46 @@
package com.czlisinterface.system.task;
import cn.hutool.core.util.StrUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.SchedulingConfigurer;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
import org.springframework.scheduling.config.ScheduledTaskRegistrar;
import org.springframework.scheduling.support.CronTrigger;
import java.util.Map;
@EnableScheduling
@Configuration
@Slf4j
public class ReUploadTask implements SchedulingConfigurer {
@Autowired
private ApplicationContext applicationContext;
@Override
public void configureTasks(ScheduledTaskRegistrar scheduledTaskRegistrar) {
//在注册器添加定时任务前,添加线程池
ThreadPoolTaskScheduler threadPoolTaskScheduler = new ThreadPoolTaskScheduler();
threadPoolTaskScheduler.setPoolSize(10);
threadPoolTaskScheduler.initialize();
scheduledTaskRegistrar.setTaskScheduler(threadPoolTaskScheduler);
//获取所有的定时任务
Map<String,BaskTask> map=applicationContext.getBeansOfType(BaskTask.class);
//遍历注册
for(String key:map.keySet()){
BaskTask baskTask = map.get(key);
scheduledTaskRegistrar.addTriggerTask(
baskTask,triggerContext -> {
if(StrUtil.isBlank(baskTask.getCron())){
return null;
}
return new CronTrigger(baskTask.getCron()).nextExecutionTime(triggerContext);
}
);
}
}
}

View File

@ -1,5 +1,7 @@
package com.czlisinterface.jldermyy.service.impl;
import cn.hutool.core.util.XmlUtil;
import cn.hutool.http.webservice.SoapClient;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.czlisinterface.jldermyy.mapper.HisMapper_jldermyy;
@ -9,10 +11,13 @@ import com.czlisinterface.system.pojo.LabReqmain;
import com.czlisinterface.system.pojo.Result;
import com.czlisinterface.system.service.impl.CommonImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Configuration;
import org.w3c.dom.Document;
import javax.annotation.Resource;
import javax.xml.xpath.XPathConstants;
import java.util.List;
@ -25,6 +30,9 @@ import java.util.List;
@ConditionalOnProperty(name="lisinterface.action.type",havingValue = "jldermyy_new1")
public class Lisinterface_jldermyy extends CommonImpl {
@Value("${lisinterface.postURL:}")
String postURL;
@Resource
CommonMapper commonMapper;
@Resource
@ -40,4 +48,52 @@ public class Lisinterface_jldermyy extends CommonImpl {
return new Result("0",labreqmain.toString());
}
/**
* 调用his的webservice接口
* @param action
* @param xmlStr
* @return
*/
public Result xmlInvoke(String action,String xmlStr){
String result = "";
try{
//String url = "http://172.29.91.236/sj_web_ss/StandardService.asmx?wsdl";
SoapClient client = SoapClient.create(postURL)
.header("SOAPAction","http://www.bkgtsoft.com/ESB.SoapService.Send")
// 设置要请求的方法,此接口方法前缀为web,传入对应的命名空间
.setMethod("bkg:Send", "http://www.bkgtsoft.com")
.setParam("action",action,true)//此处写true,会自动填写命名空间
.setParam("message","<![CDATA["+xmlStr+"]]>",true);
// log.info("接口地址:{}\n入参:{}",postURL,client.getMsgStr(false));
// 发送请求,参数true表示返回一个格式化后的XML内容
// 返回内容为XML字符串,可以配合XmlUtil解析这个响应
result = client.send(false);
//log.info("webservice返回内容:"+result);
// if(result.contains("<![CDATA[")){
// result = result.substring(result.indexOf("<![CDATA[")+9,result.indexOf("]]>"));
// }
while(result.contains("<![CDATA[") || result.contains("]]>")){
result = result.replace("<![CDATA[","");
result = result.replace("]]>","");
}
result = result.substring(result.indexOf("<Response>"),result.indexOf("</Response>")+11);
// log.info("result:"+result);
}catch (Exception ex){
log.error("服务标识:{}\r\n入参:{}\r\n出参:{},{}",action,xmlStr,result,ex);
throw ex;
}
log.info("服务标识:{}\r\n调用平台接口入参:{}\r\n出参:{}",action,xmlStr,result);
//解析出参
String resultCode = "";
String msg = "";
Document doc = XmlUtil.parseXml(result);
return null;
}
}

View File

@ -1,5 +1,6 @@
package com.czlisinterface.start;
import com.czlisinterface.system.socket.SocketUtils;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@ -15,5 +16,11 @@ import org.springframework.transaction.annotation.EnableTransactionManagement;
public class InterfaceApplication {
public static void main(String[] args) {
SpringApplication.run(InterfaceApplication.class,args);
//运行socket服务
String socketstart = SocketUtils.getYmlValues("socketstart");
if(socketstart.equals("1")){
SocketUtils.socketStart();
}
}
}

View File

@ -8,6 +8,12 @@ server:
# Tomcat启动初始化的线程数,默认值10
min-spare: 100
#socket是否开启:
socketstart: 0
socketServerPort: 9223
socketClientHost: localhost
socketClientPort: 9222
spring:
mvc:
pathmatch: