();
+ params.put("dt", dt);
+ String msg = TemplateUtils.renderTemplate(responseType, params);
+ LogKit.info("hjta-BizMessage-responseMsg-response:{}", msg);
+ return msg;
+ }
+
+ /**
+ * 用户变更广播处理
+ *
+ * @param request
+ * @throws Exception
+ */
+ private void operationUser(String request) {
+ int start = request.indexOf(USER_BEAN_ARRAY_START) + USER_BEAN_ARRAY_START.length();
+ int end = request.indexOf(USER_BEAN_ARRAY_END);
+ String[] users = request.substring(start, end).split(USER_BEAN_END);
+ for (String user : users) {
+ if (!StringUtils.contains(user, USER_BEAN_START)) {
+ continue;
+ }
+ int beanStart = user.indexOf(USER_BEAN_START) + USER_BEAN_START.length();
+ String userBean = user.substring(beanStart);
+ write2xml("\n" + userBean + "\n\n", SsoConfig.getInstance().getUserOutput());
+ }
+ }
+
+ /**
+ * 机构变更广播
+ *
+ * @param request
+ * @throws Exception
+ */
+ private void operationInstitution(String request) {
+ int start = request.indexOf(INST_BEAN_ARRAY_START) + INST_BEAN_ARRAY_START.length();
+ int end = request.indexOf(INST_BEAN_ARRAY_END);
+ String[] insts = request.substring(start, end).split(INST_BEAN_END);
+ for (String inst : insts) {
+ if (!StringUtils.contains(inst, INST_BEAN_START)) {
+ continue;
+ }
+ int beanStart = inst.indexOf(INST_BEAN_START) + INST_BEAN_START.length();
+ String instBean = inst.substring(beanStart);
+ write2xml("\n" + instBean + "\n\n", SsoConfig.getInstance().getInstOutput());
+ }
+ }
+
+ /**
+ * 解析获得msgCd
+ *
+ * @param request
+ * @return
+ */
+ private String parseMsgCd(String request) {
+ String labelStart = "";
+ String labelEnd = "";
+ int startIndex;
+ int endIndex;
+ startIndex = request.indexOf(labelStart) + labelStart.length();
+ endIndex = request.indexOf(labelEnd);
+ return request.substring(startIndex, endIndex);
+ }
+
+ /**
+ * 报文输出到xml
+ *
+ * @param data
+ * @param path
+ */
+ private void write2xml(String data, String path) {
+ String fileContent;
+ if (WorkContext.getWorkResource().createFile(path)) {
+ fileContent = "\n" + data;
+ } else {
+ InputStream fileInputStream = WorkContext.getWorkResource().openStream(path);
+ fileContent = ResourceIOUtils.inputStream2String(fileInputStream) + data;
+ }
+ WorkContext.getWorkResource().write(path, fileContent.getBytes());
+ }
+
+// /**
+// * 报文输出到xml
+// *
+// * @param data
+// * @param path
+// */
+// private void write2xml(String data, String path) {
+// API.LOG.info("sso-BizMessage-write2xml-before-getUnderlying:{}", ResourceIOUtils.getUnderlying().toString());
+// if (ResourceIOUtils.createFile(path)) {
+// String xmlHead = "\n";
+// ResourceIOUtils.write(path, xmlHead + data);
+// } else {
+// InputStream fileInputStream = ResourceIOUtils.read(path);
+// String fileContent = ResourceIOUtils.inputStream2String(fileInputStream);
+// ResourceIOUtils.write(path, fileContent + data);
+// }
+// API.LOG.info("sso-BizMessage-write2xml-after-getUnderlying:{}", ResourceIOUtils.getUnderlying().toString());
+// }
+}
diff --git a/src/main/java/com/fr/plugin/hjta/user/xsocket/server/ServerHandler.java b/src/main/java/com/fr/plugin/hjta/user/xsocket/server/ServerHandler.java
new file mode 100644
index 0000000..f85ee2c
--- /dev/null
+++ b/src/main/java/com/fr/plugin/hjta/user/xsocket/server/ServerHandler.java
@@ -0,0 +1,236 @@
+package com.fr.plugin.hjta.user.xsocket.server;
+
+import com.fanruan.api.log.LogKit;
+import org.xsocket.MaxReadSizeExceededException;
+import org.xsocket.connection.*;
+
+import java.io.IOException;
+import java.nio.BufferUnderflowException;
+import java.nio.channels.ClosedChannelException;
+
+
+/**
+ * 服务端定义数据的处理类
+ *
+ * @author fr.open
+ */
+public class ServerHandler
+ implements IDataHandler, IConnectHandler, IIdleTimeoutHandler, IConnectionTimeoutHandler, IDisconnectHandler {
+
+ /**
+ * 即当建立完连接之后可以进行的一些相关操作处理。包括修改连接属性、准备资源、等! 连接的成功时的操作
+ */
+ @Override
+ public boolean onConnect(INonBlockingConnection nbc)
+ throws IOException, BufferUnderflowException, MaxReadSizeExceededException {
+
+ String remoteName = nbc.getRemoteAddress().getHostName();
+ System.out.println("remoteName " + remoteName + " has connected !");
+
+ return true;
+ }
+
+ /**
+ * 即如果失去连接应当如何处理? 需要实现 IDisconnectHandler 这个接口 连接断开时的操作
+ */
+ @Override
+ public boolean onDisconnect(INonBlockingConnection nbc) throws IOException {
+ System.out.println("remote close !");
+ return false;
+ }
+
+ /**
+ * 即这个方法不光是说当接收到一个新的网络包的时候会调用而且如果有新的缓存存在的时候也会被调用。而且 The onData will also be called, if the connection is
+ * closed当连接被关闭的时候也会被调用的!
+ */
+ @Override
+ public boolean onData(INonBlockingConnection nbc)
+ throws IOException, BufferUnderflowException, ClosedChannelException, MaxReadSizeExceededException {
+
+ // 无报文头获取报文
+ // return rcvData(nbc,"ok");
+ // 报文头获取文
+
+ return rcvDataByHrdLen(nbc, 8);
+// return rcvDataByHrdLenTest(nbc, 8);
+ }
+
+ // 无报文头接收
+ public boolean rcvData(INonBlockingConnection nbc, String delimiterStr)
+ throws IOException, BufferUnderflowException, ClosedChannelException, MaxReadSizeExceededException {
+ // 接收请求报文体
+ byte[] rcvMsgByte = nbc.readBytesByDelimiter(delimiterStr);
+ String rcvMsg = new String(rcvMsgByte, "UTF-8");
+
+ // 输出请求
+ LogKit.info("hjta-ServerHandler-rcvData-rcvMsgByte size:" + rcvMsgByte.length);
+ LogKit.info("hjta-ServerHandler-rcvData-rcvMsgBody:" + rcvMsg);
+
+ BizMessage bizMessage = new BizMessage();
+ String rspMsg = "";
+ try {
+ rspMsg = bizMessage.responseMsg(rcvMsg);// 获取应答报文
+
+ } catch (Exception ex) {
+ ex.printStackTrace();
+ }
+
+ String rspHdrLen = String.format("%08d", rspMsg.getBytes("UTF-8").length);
+ byte[] rspMsgByte = (rspHdrLen + rspMsg).getBytes("utf-8");
+
+ // 输出应答报文
+ nbc.write(rspMsgByte);
+ nbc.flush();
+ // 不输出应答报文
+
+ LogKit.info("hjta-ServerHandler-rcvData-rspHdrLen:" + rspHdrLen + ",rspMsgByte:" + rspMsg);
+ return true;
+ }
+
+ public boolean rcvDataByHrdLen(INonBlockingConnection nbc, int hrdLen)
+ throws IOException, BufferUnderflowException, ClosedChannelException, MaxReadSizeExceededException {
+
+ // 接收请求报文头
+ byte[] rcvHdr = nbc.readBytesByLength(hrdLen);
+ String rcvHdrLen = new String(rcvHdr, "UTF-8");
+
+ // 接收请求报文体
+ byte[] rcvMsgByte = nbc.readBytesByLength(Integer.parseInt(rcvHdrLen));
+ String rcvMsg = new String(rcvMsgByte, "UTF-8");
+
+ // 输出请求
+ LogKit.info("hjta-ServerHandler-rcvDataByHrdLen-rcvMsgHdrLen:" + rcvHdrLen);
+ // System.out.println("rcvMsgBody:" + rcvMsg);
+
+ // try {
+ // //阻塞69秒
+ // Thread.sleep(10000);
+ // }catch (Exception ex){
+ // ex.printStackTrace();
+ // }
+
+ BizMessage bizMessage = new BizMessage();
+ String rspMsg = "";
+ try {
+ rspMsg = bizMessage.responseMsg(rcvMsg);// 获取应答报文
+ } catch (Exception ex) {
+ ex.printStackTrace();
+ }
+
+ String rspHdrLen = String.format("%08d", rspMsg.getBytes("UTF-8").length);
+ byte[] rspMsgByte = (rspHdrLen + rspMsg).getBytes("utf-8");
+
+ nbc.close();
+ // 输出应答报文
+ nbc.write(rspMsgByte);
+ nbc.flush();
+
+ LogKit.info("hjta-ServerHandler-rcvDataByHrdLen-rspHdrLen:" + rspHdrLen + "\n\n");
+ return true;
+ }
+
+ public boolean rcvDataByHrdLenTest(INonBlockingConnection nbc, int hrdLen)
+ throws IOException, BufferUnderflowException, ClosedChannelException, MaxReadSizeExceededException {
+ // test user
+ String rcvMsg = "1.0BI.1000000020.01UCA20200929094246976UCA20200929094246976BRDUCAGUCA-2020092900942469769999990001UCA900000100010014259张三113073219910624085413831314787278178879@qq.com张家口市桥西区六01200005科员8000017120200929";
+ // test inist
+// String rcvMsg = "1.0BI.1000000010.01UCA20200929094722390UCA20200929094722390BRDUCAGUCA-2020092900947223909999990001UCA90000010001001BYpQl1Mg1eOKHgFKeT6MLA56055605涿州支行x3r1KEVrVO9YIAFKeT5FoA5600河北省保定市涿州市平安北街123号0312-545512311872涿州支行13060020180314000710000010河北省保定市涿州河北省保定市涿州市平安北街123号116.02473939.502208C1313134002017135213060005605|5600|0000|202009291130681";
+ BizMessage bizMessage = new BizMessage();
+ String rspMsg = "";
+ try {
+ rspMsg = bizMessage.responseMsg(rcvMsg);// 获取应答报文
+ } catch (Exception ex) {
+ ex.printStackTrace();
+ }
+
+ String rspHdrLen = String.format("%08d", rspMsg.getBytes("UTF-8").length);
+ byte[] rspMsgByte = (rspHdrLen + rspMsg).getBytes("utf-8");
+
+ nbc.close();
+ // 输出应答报文
+ nbc.write(rspMsgByte);
+ nbc.flush();
+
+ LogKit.info("hjta-ServerHandler-rcvDataByHrdLen-rspHdrLen:" + rspHdrLen + "\n\n");
+ return true;
+ }
+
+ /**
+ * 请求处理超时的处理事件 Handles idle timeout. The timeouts will be defined by the server. To modify the timeouts the proper
+ * server methods has to be called. E.g.
+ *
+ *
+ * ...
+ * IServer server = new Server(new MyHandler());
+ * server.setIdleTimeoutMillis(60 * 1000);
+ * ConnectionUtils.start(server);
+ * ...
+ *
+ *
+ * class MyHandler implements IIdleTimeoutHandler {
+ *
+ * public boolean onIdleTimeout(INonBlockingConnection connection) throws IOException {
+ * ...
+ * connection.close();
+ * return true; // true -> event has been handled (by returning false xSocket will close the connection)
+ * }
+ * }
+ *
+ *
+ * @author grro@xsocket.org
+ */
+
+ /**
+ * handles the idle timeout.
+ *
+ * @param connection the underlying connection
+ * @return true if the timeout event has been handled (in case of false the connection will be closed by the server)
+ * @throws IOException if an error occurs. Throwing this exception causes that the underlying connection will be closed.
+ */
+ @Override
+ public boolean onIdleTimeout(INonBlockingConnection connection) throws IOException {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+ /**
+ * Handles connection timeout. The timeouts will be defined by the server. To modify the timeouts the proper server
+ * methods has to be called. E.g.
+ *
+ *
+ * ...
+ * IServer server = new Server(new MyHandler());
+ * server.setConnectionTimeoutMillis(60 * 1000);
+ * ConnectionUtils.start(server);
+ * ...
+ *
+ *
+ * class MyHandler implements IConnectionTimeoutHandler {
+ *
+ * public boolean onConnectionTimeout(INonBlockingConnection connection) throws IOException {
+ * ...
+ * connection.close();
+ * return true; // true -> event has been handled (by returning false xSocket will close the connection)
+ * }
+ * }
+ *
+ *
+ * @author grro@xsocket.org
+ */
+
+ /**
+ * handles the connection timeout.
+ *
+ * @param connection the underlying connection
+ * @return true if the timeout event has been handled (in case of false the connection will be closed by the server)
+ * @throws IOException if an error occurs. Throwing this exception causes that the underlying connection will be closed.
+ */
+ /**
+ * 连接超时处理事件
+ */
+ @Override
+ public boolean onConnectionTimeout(INonBlockingConnection connection) throws IOException {
+ // TODO Auto-generated method stub
+ return false;
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/com/fr/plugin/hjta/locale/lang.properties b/src/main/resources/com/fr/plugin/hjta/locale/lang.properties
new file mode 100644
index 0000000..8885a2c
--- /dev/null
+++ b/src/main/resources/com/fr/plugin/hjta/locale/lang.properties
@@ -0,0 +1,18 @@
+Plugin-hjta=Sso Plugin
+Plugin-hjta_Group=Sso Plugin
+Plugin-hjta_Config_HomePage=Home Page
+Plugin-hjta_Config_HomePage_Description=Home Page
+Plugin-hjta_Config_UriBase=Uri Base
+Plugin-hjta_Config_UriBase_Description=Uri Base
+Plugin-hjta_Config_ServerIp=Server Ip
+Plugin-hjta_Config_ServerIp_Description=Server Ip
+Plugin-hjta_Config_ServerPort=Server Port
+Plugin-hjta_Config_ServerPort_Description=Server Port
+Plugin-hjta_Config_UserMsgCd=UserMsgCd
+Plugin-hjta_Config_UserMsgCd_Description=UserMsgCd
+Plugin-hjta_Config_InstMsgCd=InstMsgCd
+Plugin-hjta_Config_InstMsgCd_Description=InstMsgCd
+Plugin-hjta_Config_UserOutput=UserOutput
+Plugin-hjta_Config_UserOutput_Description=UserOutput
+Plugin-hjta_Config_InstOutput=Inst Output
+Plugin-hjta_Config_InstOutput_Description=Inst Output
\ No newline at end of file
diff --git a/src/main/resources/com/fr/plugin/hjta/locale/lang_zh_CN.properties b/src/main/resources/com/fr/plugin/hjta/locale/lang_zh_CN.properties
new file mode 100644
index 0000000..d2992ef
--- /dev/null
+++ b/src/main/resources/com/fr/plugin/hjta/locale/lang_zh_CN.properties
@@ -0,0 +1,18 @@
+Plugin-hjta=\u5355\u70B9\u767B\u9646\u63D2\u4EF6
+Plugin-hjta_Group=\u5355\u70B9\u767B\u9646\u63D2\u4EF6
+Plugin-hjta_Config_HomePage=\u6307\u5B9A\u9996\u9875
+Plugin-hjta_Config_HomePage_Description=\u6307\u5B9A\u9996\u9875
+Plugin-hjta_Config_UriBase=\u7EDF\u4E00\u8BA4\u8BC1\u63A5\u53E3
+Plugin-hjta_Config_UriBase_Description=\u7EDF\u4E00\u8BA4\u8BC1\u63A5\u53E3
+Plugin-hjta_Config_ServerIp=\u672C\u5730\u670D\u52A1IP
+Plugin-hjta_Config_ServerIp_Description=\u672C\u5730\u670D\u52A1IP
+Plugin-hjta_Config_ServerPort=\u672C\u5730\u670D\u52A1\u7AEF\u53E3
+Plugin-hjta_Config_ServerPort_Description=\u672C\u5730\u670D\u52A1\u7AEF\u53E3
+Plugin-hjta_Config_UserMsgCd=\u7528\u6237MsgCd
+Plugin-hjta_Config_UserMsgCd_Description=\u7528\u6237MsgCd
+Plugin-hjta_Config_InstMsgCd=\u673A\u6784MsgCd
+Plugin-hjta_Config_InstMsgCd_Description=\u673A\u6784MsgCd
+Plugin-hjta_Config_UserOutput=\u7528\u6237\u4FE1\u606Fxml\u6587\u4EF6
+Plugin-hjta_Config_UserOutput_Description=\u7528\u6237\u4FE1\u606Fxml\u6587\u4EF6
+Plugin-hjta_Config_InstOutput=\u673A\u6784\u4FE1\u606Fxml\u6587\u4EF6
+Plugin-hjta_Config_InstOutput_Description=\u673A\u6784\u4FE1\u606Fxml\u6587\u4EF6
\ No newline at end of file
diff --git a/统一认证单点登录方案.docx b/统一认证单点登录方案.docx
new file mode 100644
index 0000000..a6ee094
Binary files /dev/null and b/统一认证单点登录方案.docx differ