Ver Fonte

模型数据集关联

ZhuDeKang há 4 meses atrás
pai
commit
05cfc1cfd4

+ 2 - 0
ruoyi-api-patform/src/main/java/com/ruoyi/interfaces/controller/MdDataSetController.java

@@ -49,6 +49,8 @@ public class MdDataSetController extends BaseController {
         return getDataTable(list);
     }
 
+
+
     /**
      * 导出数据集列表
      */

+ 9 - 18
ruoyi-api-patform/src/main/java/com/ruoyi/interfaces/controller/MdModelInfoController.java

@@ -14,6 +14,7 @@ import com.ruoyi.common.utils.StringUtils;
 import com.ruoyi.common.utils.poi.ExcelUtil;
 import com.ruoyi.interfaces.domain.MdAudit;
 import com.ruoyi.interfaces.domain.MdModelInfo;
+import com.ruoyi.interfaces.domain.vo.MdModelSetRelaVo;
 import com.ruoyi.interfaces.service.IMdAuditService;
 import com.ruoyi.interfaces.service.IMdModelInfoService;
 import io.swagger.annotations.ApiOperation;
@@ -113,24 +114,14 @@ public class MdModelInfoController extends BaseController {
         return toAjax(mdModelInfoService.deleteMdModelInfoByMdids(mdids));
     }
 
-
-    @Autowired
-    private IMdAuditService mdAuditService;
-
-    @GetMapping("/audit")
-    public AjaxResult audit(MdModelInfo mdModelInfo) {
-        Date nowDate = DateUtils.getNowDate();
-        MdAudit srv = new MdAudit(null, mdModelInfo.getMdid(), "MD", mdModelInfo.getAudit(), getUsername(), nowDate, mdModelInfo.getAuditRemark());
-        int i = mdAuditService.insertMdAudit(srv);
-        mdModelInfo.setAuditBy(getUsername());
-        mdModelInfo.setAuditTime(nowDate);
-        return success(mdModelInfoService.audit(mdModelInfo));
+    /**
+     * 模型关联数据集
+     *
+     */
+    @PostMapping("/modelSetRela")
+    public  AjaxResult modelSetRela(@RequestBody MdModelSetRelaVo modelSet) {
+        modelSet.setCreateBy(getUsername());
+        return toAjax(mdModelInfoService.modelSetRela(modelSet));
     }
 
-    @GetMapping("/publish")
-    public AjaxResult publish(MdModelInfo mdModelInfo) {
-        mdModelInfo.setPublishBy(getUsername());
-        mdModelInfo.setPublishTime(DateUtils.getNowDate());
-        return success(mdModelInfoService.publish(mdModelInfo));
-    }
 }

+ 44 - 0
ruoyi-api-patform/src/main/java/com/ruoyi/interfaces/domain/vo/MdModelSetRelaVo.java

@@ -0,0 +1,44 @@
+package com.ruoyi.interfaces.domain.vo;
+
+import com.ruoyi.common.core.domain.BaseEntity;
+
+public class MdModelSetRelaVo extends BaseEntity {
+    /**
+     *
+     */
+    private String mdId;
+    private String[] dcCodes;
+    private String dcCode;
+
+    public String getDcCode() {
+        return dcCode;
+    }
+
+    public void setDcCode(String dcCode) {
+        this.dcCode = dcCode;
+    }
+
+    public MdModelSetRelaVo(String mdId, String[] dcCodes) {
+        this.mdId = mdId;
+        this.dcCodes = dcCodes;
+    }
+
+    public MdModelSetRelaVo() {
+    }
+
+    public String getMdId() {
+        return mdId;
+    }
+
+    public void setMdId(String mdId) {
+        this.mdId = mdId;
+    }
+
+    public String[] getDcCodes() {
+        return dcCodes;
+    }
+
+    public void setDcCodes(String[] dcCodes) {
+        this.dcCodes = dcCodes;
+    }
+}

+ 5 - 0
ruoyi-api-patform/src/main/java/com/ruoyi/interfaces/mapper/MdModelInfoMapper.java

@@ -5,6 +5,7 @@ import java.util.List;
 import com.ruoyi.common.annotation.DataSource;
 import com.ruoyi.common.enums.DataSourceType;
 import com.ruoyi.interfaces.domain.MdModelInfo;
+import com.ruoyi.interfaces.domain.vo.MdModelSetRelaVo;
 import org.apache.ibatis.annotations.Param;
 
 /**
@@ -67,4 +68,8 @@ public interface MdModelInfoMapper
     int updateMdModelInfoAudit(MdModelInfo mdModelInfo);
 
     int updateMdModelInfoPublish(MdModelInfo mdModelInfo);
+
+    int insertModelSetRela(MdModelSetRelaVo modelSet);
+
+    List<MdModelSetRelaVo> selectModelSetRela(MdModelSetRelaVo modelSet);
 }

+ 3 - 0
ruoyi-api-patform/src/main/java/com/ruoyi/interfaces/service/IMdModelInfoService.java

@@ -1,6 +1,7 @@
 package com.ruoyi.interfaces.service;
 
 import com.ruoyi.interfaces.domain.MdModelInfo;
+import com.ruoyi.interfaces.domain.vo.MdModelSetRelaVo;
 
 import java.util.List;
 
@@ -63,4 +64,6 @@ public interface IMdModelInfoService
     int audit(MdModelInfo mdModelInfo);
 
     int publish(MdModelInfo mdModelInfo);
+
+    int modelSetRela(MdModelSetRelaVo modelSet);
 }

+ 18 - 0
ruoyi-api-patform/src/main/java/com/ruoyi/interfaces/service/impl/MdAppFlowServiceImpl.java

@@ -5,6 +5,10 @@ import java.util.List;
 import java.util.Map;
 
 import com.agentsflex.core.chain.Chain;
+import com.agentsflex.core.chain.ChainEvent;
+import com.agentsflex.core.chain.ChainNode;
+import com.agentsflex.core.chain.event.NodeEndEvent;
+import com.agentsflex.core.chain.listener.ChainEventListener;
 import com.ruoyi.common.utils.DateUtils;
 import com.ruoyi.interfaces.tinyflow.TinyflowUtil;
 import com.ruoyi.interfaces.tinyflow.parser.PrintNodeParser;
@@ -107,6 +111,20 @@ public class MdAppFlowServiceImpl implements IMdAppFlowService
         Tinyflow tinyflow = TinyflowUtil.getTinyflow(flowGraph);
         //tinyflow.getChainParser().addNodeParser("printNode",new PrintNodeParser());
         Chain chain = tinyflow.toChain();
+        chain.addEventListener(new ChainEventListener() {
+            @Override
+            public void onEvent(ChainEvent event, Chain chain) {
+                if (event instanceof NodeEndEvent) {
+                    NodeEndEvent nodeEndEvent = (NodeEndEvent) event;
+                    ChainNode completedNode = nodeEndEvent.getNode();
+                    Map<String, Object> executeResult = nodeEndEvent.getResult();
+                    // 节点执行完毕的回调逻辑
+                    System.out.println("节点执行完毕: " + completedNode.getName());
+                    System.out.println("节点ID: " + completedNode.getId());
+                    System.out.println("执行结果: " + executeResult);
+                }
+            }
+        });
 
 
         return chain.executeForResult(appFlow.getParams());

+ 30 - 21
ruoyi-api-patform/src/main/java/com/ruoyi/interfaces/service/impl/MdModelInfoServiceImpl.java

@@ -3,9 +3,11 @@ package com.ruoyi.interfaces.service.impl;
 import java.util.List;
 
 import com.ruoyi.common.utils.DateUtils;
+import com.ruoyi.common.utils.StringUtils;
 import com.ruoyi.common.utils.uuid.IdUtils;
 import com.ruoyi.interfaces.domain.MdModelFile;
 import com.ruoyi.interfaces.domain.MdModelInfo;
+import com.ruoyi.interfaces.domain.vo.MdModelSetRelaVo;
 import com.ruoyi.interfaces.mapper.MdModelInfoMapper;
 import com.ruoyi.interfaces.service.IMdModelFileService;
 import com.ruoyi.interfaces.service.IMdModelInfoService;
@@ -15,13 +17,12 @@ import org.springframework.web.multipart.MultipartFile;
 
 /**
  * 模型信息Service业务层处理
- * 
+ *
  * @author ruoyi
  * @date 2025-07-15
  */
 @Service
-public class MdModelInfoServiceImpl implements IMdModelInfoService
-{
+public class MdModelInfoServiceImpl implements IMdModelInfoService {
     @Autowired
     private MdModelInfoMapper mdModelInfoMapper;
 
@@ -31,37 +32,34 @@ public class MdModelInfoServiceImpl implements IMdModelInfoService
 
     /**
      * 查询模型信息
-     * 
+     *
      * @param mdid 模型信息主键
      * @return 模型信息
      */
     @Override
-    public MdModelInfo selectMdModelInfoByMdid(String mdid)
-    {
+    public MdModelInfo selectMdModelInfoByMdid(String mdid) {
         return mdModelInfoMapper.selectMdModelInfoByMdid(mdid);
     }
 
     /**
      * 查询模型信息列表
-     * 
+     *
      * @param mdModelInfo 模型信息
      * @return 模型信息
      */
     @Override
-    public List<MdModelInfo> selectMdModelInfoList(MdModelInfo mdModelInfo)
-    {
+    public List<MdModelInfo> selectMdModelInfoList(MdModelInfo mdModelInfo) {
         return mdModelInfoMapper.selectMdModelInfoList(mdModelInfo);
     }
 
     /**
      * 新增模型信息
-     * 
+     *
      * @param mdModelInfo 模型信息
      * @return 结果
      */
     @Override
-    public String insertMdModelInfo(MdModelInfo mdModelInfo)
-    {
+    public String insertMdModelInfo(MdModelInfo mdModelInfo) {
         mdModelInfo.setMdid(IdUtils.fastUUID());
         mdModelInfo.setCreateby(DateUtils.getNowDate());
         mdModelInfoMapper.insertMdModelInfo(mdModelInfo);
@@ -70,38 +68,35 @@ public class MdModelInfoServiceImpl implements IMdModelInfoService
 
     /**
      * 修改模型信息
-     * 
+     *
      * @param mdModelInfo 模型信息
      * @return 结果
      */
     @Override
-    public int updateMdModelInfo(MdModelInfo mdModelInfo)
-    {
+    public int updateMdModelInfo(MdModelInfo mdModelInfo) {
         mdModelInfo.setModifyby(DateUtils.getNowDate());
         return mdModelInfoMapper.updateMdModelInfo(mdModelInfo);
     }
 
     /**
      * 批量删除模型信息
-     * 
+     *
      * @param mdids 需要删除的模型信息主键
      * @return 结果
      */
     @Override
-    public int deleteMdModelInfoByMdids(String[] mdids)
-    {
+    public int deleteMdModelInfoByMdids(String[] mdids) {
         return mdModelInfoMapper.deleteMdModelInfoByMdids(mdids);
     }
 
     /**
      * 删除模型信息信息
-     * 
+     *
      * @param mdid 模型信息主键
      * @return 结果
      */
     @Override
-    public int deleteMdModelInfoByMdid(String mdid)
-    {
+    public int deleteMdModelInfoByMdid(String mdid) {
         return mdModelInfoMapper.deleteMdModelInfoByMdid(mdid);
     }
 
@@ -115,4 +110,18 @@ public class MdModelInfoServiceImpl implements IMdModelInfoService
     public int publish(MdModelInfo mdModelInfo) {
         return mdModelInfoMapper.updateMdModelInfoPublish(mdModelInfo);
     }
+
+    @Override
+    public int modelSetRela(MdModelSetRelaVo modelSet) {
+        String mdId = modelSet.getMdId();
+        modelSet.setCreateTime(DateUtils.getNowDate());
+        int i = 0;
+        for (String dcCode : modelSet.getDcCodes()) {
+            modelSet.setDcCode(dcCode);
+            if (StringUtils.isEmpty(mdModelInfoMapper.selectModelSetRela(modelSet))) {
+                i += mdModelInfoMapper.insertModelSetRela(modelSet);
+            }
+        }
+        return i;
+    }
 }

+ 16 - 7
ruoyi-api-patform/src/main/resources/mapper/interfaces/MdDataSetMapper.xml

@@ -21,13 +21,22 @@
     <select id="selectMdDataSetList" parameterType="com.ruoyi.interfaces.domain.MdDataSet" resultMap="MdDataSetResult">
         <include refid="selectMdDataSetVo"/>
         <where>
-            <if test="dcCode != null  and dcCode != ''"> and DC_CODE = #{dcCode} </if>
-            <if test="cateId != null  and cateId != ''"> and CATE_ID = #{cateId} </if>
-            <if test="dcName != null  and dcName != ''"> and DC_NAME like concat('%', #{dcName}, '%')</if>
-            <if test="dcType != null  and dcType != ''"> and DC_TYPE = #{dcType}</if>
-            <if test="dcSort != null "> and DC_SORT = #{dcSort}</if>
-            <if test="dcIcon != null  and dcIcon != ''"> and DC_ICON = #{dcIcon}</if>
-            <if test="dcNote != null  and dcNote != ''"> and DC_NOTE = #{dcNote}</if>
+            <if test="dcCode != null  and dcCode != ''">and DC_CODE = #{dcCode}</if>
+            <if test="cateId != null  and cateId != ''">and CATE_ID = #{cateId}</if>
+            <if test="dcName != null  and dcName != ''">and DC_NAME like concat('%', #{dcName}, '%')</if>
+            <if test="dcType != null  and dcType != ''">and DC_TYPE = #{dcType}</if>
+            <if test="dcSort != null ">and DC_SORT = #{dcSort}</if>
+            <if test="dcIcon != null  and dcIcon != ''">and DC_ICON = #{dcIcon}</if>
+            <if test="dcNote != null  and dcNote != ''">and DC_NOTE = #{dcNote}</if>
+            <if test="params.notInMdid != null ">and DC_CODE NOT in (
+                select DC_CODE FROM md_model_set_rela WHERE MD_ID = #{params.notInMdid}
+                )
+            </if>
+            <if test="params.inMdid != null ">and DC_CODE  in (
+                select DC_CODE FROM md_model_set_rela WHERE MD_ID = #{params.notInMdid}
+                )
+            </if>
+
         </where>
         order by DC_SORT
     </select>

+ 18 - 0
ruoyi-api-patform/src/main/resources/mapper/interfaces/MdModelInfoMapper.xml

@@ -225,6 +225,17 @@
         <include refid="selectMdModelInfoVo"/>
         where MDID = #{mdid}
     </select>
+    <select id="selectModelSetRela" resultType="com.ruoyi.interfaces.domain.vo.MdModelSetRelaVo">
+        select MD_ID, DC_CODE, CREATE_BY, CREATE_TIME from md_model_set_rela
+        <where>
+            <if test="mdId != null and mdId != ''">
+                and MD_ID = #{mdId}
+            </if>
+            <if test="dcCode != null and dcCode != ''">
+                and DC_CODE = #{dcCode}
+            </if>
+        </where>
+    </select>
 
     <insert id="insertMdModelInfo" parameterType="com.ruoyi.interfaces.domain.MdModelInfo">
         insert into md_model_info
@@ -355,6 +366,13 @@
             <if test="audit != null">#{audit}</if>
         </trim>
     </insert>
+    <insert id="insertModelSetRela">
+        insert into md_model_set_rela(MD_ID, DC_CODE, CREATE_BY, CREATE_TIME)
+        values (#{mdId},
+                #{dcCode},
+                #{createBy},
+                #{createTime})
+    </insert>
 
     <update id="updateMdModelInfo" parameterType="com.ruoyi.interfaces.domain.MdModelInfo">
         update md_model_info

+ 6 - 0
ruoyi-framework/pom.xml

@@ -35,6 +35,12 @@
             <artifactId>druid-spring-boot-starter</artifactId>
         </dependency>
 
+        <!-- SpringBoot Websocket -->
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-websocket</artifactId>
+        </dependency>
+
         <!-- 验证码 -->
         <dependency>
             <groupId>pro.fessional</groupId>

+ 2 - 0
ruoyi-framework/src/main/java/com/ruoyi/framework/config/SecurityConfig.java

@@ -111,6 +111,8 @@ public class SecurityConfig {
                             .antMatchers(HttpMethod.GET, "/", "/*.html", "/**/*.html", "/**/*.css", "/**/*.js", "/profile/**").permitAll()
                             .antMatchers("/swagger-ui.html", "/swagger-resources/**", "/webjars/**", "/*/api-docs", "/druid/**").permitAll()
                             .antMatchers("/workflows/**").permitAll()
+                            .antMatchers("/websocket/**").permitAll()
+
                             // 除上面外的所有请求全部需要鉴权认证
                             .anyRequest().authenticated();
                 })

+ 58 - 0
ruoyi-framework/src/main/java/com/ruoyi/framework/websocket/SemaphoreUtils.java

@@ -0,0 +1,58 @@
+package com.ruoyi.framework.websocket;
+
+import java.util.concurrent.Semaphore;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * 信号量相关处理
+ * 
+ * @author ruoyi
+ */
+public class SemaphoreUtils
+{
+    /**
+     * SemaphoreUtils 日志控制器
+     */
+    private static final Logger LOGGER = LoggerFactory.getLogger(SemaphoreUtils.class);
+
+    /**
+     * 获取信号量
+     * 
+     * @param semaphore
+     * @return
+     */
+    public static boolean tryAcquire(Semaphore semaphore)
+    {
+        boolean flag = false;
+
+        try
+        {
+            flag = semaphore.tryAcquire();
+        }
+        catch (Exception e)
+        {
+            LOGGER.error("获取信号量异常", e);
+        }
+
+        return flag;
+    }
+
+    /**
+     * 释放信号量
+     * 
+     * @param semaphore
+     */
+    public static void release(Semaphore semaphore)
+    {
+
+        try
+        {
+            semaphore.release();
+        }
+        catch (Exception e)
+        {
+            LOGGER.error("释放信号量异常", e);
+        }
+    }
+}

+ 20 - 0
ruoyi-framework/src/main/java/com/ruoyi/framework/websocket/WebSocketConfig.java

@@ -0,0 +1,20 @@
+package com.ruoyi.framework.websocket;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.socket.server.standard.ServerEndpointExporter;
+
+/**
+ * websocket 配置
+ * 
+ * @author ruoyi
+ */
+@Configuration
+public class WebSocketConfig
+{
+    @Bean
+    public ServerEndpointExporter serverEndpointExporter()
+    {
+        return new ServerEndpointExporter();
+    }
+}

+ 107 - 0
ruoyi-framework/src/main/java/com/ruoyi/framework/websocket/WebSocketServer.java

@@ -0,0 +1,107 @@
+package com.ruoyi.framework.websocket;
+
+import java.util.concurrent.Semaphore;
+import javax.websocket.OnClose;
+import javax.websocket.OnError;
+import javax.websocket.OnMessage;
+import javax.websocket.OnOpen;
+import javax.websocket.Session;
+import javax.websocket.server.ServerEndpoint;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Component;
+
+/**
+ * websocket 消息处理
+ * 
+ * @author ruoyi
+ */
+@Component
+@ServerEndpoint("/websocket/message")
+public class WebSocketServer
+{
+    /**
+     * WebSocketServer 日志控制器
+     */
+    private static final Logger LOGGER = LoggerFactory.getLogger(WebSocketServer.class);
+
+    /**
+     * 默认最多允许同时在线人数100
+     */
+    public static int socketMaxOnlineCount = 100;
+
+    private static Semaphore socketSemaphore = new Semaphore(socketMaxOnlineCount);
+
+    /**
+     * 连接建立成功调用的方法
+     */
+    @OnOpen
+    public void onOpen(Session session) throws Exception
+    {
+        boolean semaphoreFlag = false;
+        // 尝试获取信号量
+        semaphoreFlag = SemaphoreUtils.tryAcquire(socketSemaphore);
+        if (!semaphoreFlag)
+        {
+            // 未获取到信号量
+            LOGGER.error("\n 当前在线人数超过限制数- {}", socketMaxOnlineCount);
+            WebSocketUsers.sendMessageToUserByText(session, "当前在线人数超过限制数:" + socketMaxOnlineCount);
+            session.close();
+        }
+        else
+        {
+            // 添加用户
+            WebSocketUsers.put(session.getId(), session);
+            LOGGER.info("\n 建立连接 - {}", session);
+            LOGGER.info("\n 当前人数 - {}", WebSocketUsers.getUsers().size());
+            WebSocketUsers.sendMessageToUserByText(session, "连接成功");
+        }
+    }
+
+    /**
+     * 连接关闭时处理
+     */
+    @OnClose
+    public void onClose(Session session)
+    {
+        LOGGER.info("\n 关闭连接 - {}", session);
+        // 移除用户
+        boolean removeFlag = WebSocketUsers.remove(session.getId());
+        if (!removeFlag)
+        {
+            // 获取到信号量则需释放
+            SemaphoreUtils.release(socketSemaphore);
+        }
+    }
+
+    /**
+     * 抛出异常时处理
+     */
+    @OnError
+    public void onError(Session session, Throwable exception) throws Exception
+    {
+        if (session.isOpen())
+        {
+            // 关闭连接
+            session.close();
+        }
+        String sessionId = session.getId();
+        LOGGER.info("\n 连接异常 - {}", sessionId);
+        LOGGER.info("\n 异常信息 - {}", exception);
+        // 移出用户
+        WebSocketUsers.remove(sessionId);
+        // 获取到信号量则需释放
+        SemaphoreUtils.release(socketSemaphore);
+    }
+
+    /**
+     * 服务器接收到客户端消息时调用的方法
+     */
+    @OnMessage
+    public void onMessage(String message, Session session)
+    {
+        String msg = message.replace("你", "我").replace("吗", "");
+        System.out.println("接收信息:"+message);
+        WebSocketUsers.sendMessageToUserByText(session, msg);
+    }
+}

+ 140 - 0
ruoyi-framework/src/main/java/com/ruoyi/framework/websocket/WebSocketUsers.java

@@ -0,0 +1,140 @@
+package com.ruoyi.framework.websocket;
+
+import java.io.IOException;
+import java.util.Collection;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import javax.websocket.Session;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * websocket 客户端用户集
+ * 
+ * @author ruoyi
+ */
+public class WebSocketUsers
+{
+    /**
+     * WebSocketUsers 日志控制器
+     */
+    private static final Logger LOGGER = LoggerFactory.getLogger(WebSocketUsers.class);
+
+    /**
+     * 用户集
+     */
+    private static Map<String, Session> USERS = new ConcurrentHashMap<String, Session>();
+
+    /**
+     * 存储用户
+     *
+     * @param key 唯一键
+     * @param session 用户信息
+     */
+    public static void put(String key, Session session)
+    {
+        USERS.put(key, session);
+    }
+
+    /**
+     * 移除用户
+     *
+     * @param session 用户信息
+     *
+     * @return 移除结果
+     */
+    public static boolean remove(Session session)
+    {
+        String key = null;
+        boolean flag = USERS.containsValue(session);
+        if (flag)
+        {
+            Set<Map.Entry<String, Session>> entries = USERS.entrySet();
+            for (Map.Entry<String, Session> entry : entries)
+            {
+                Session value = entry.getValue();
+                if (value.equals(session))
+                {
+                    key = entry.getKey();
+                    break;
+                }
+            }
+        }
+        else
+        {
+            return true;
+        }
+        return remove(key);
+    }
+
+    /**
+     * 移出用户
+     *
+     * @param key 键
+     */
+    public static boolean remove(String key)
+    {
+        LOGGER.info("\n 正在移出用户 - {}", key);
+        Session remove = USERS.remove(key);
+        if (remove != null)
+        {
+            boolean containsValue = USERS.containsValue(remove);
+            LOGGER.info("\n 移出结果 - {}", containsValue ? "失败" : "成功");
+            return containsValue;
+        }
+        else
+        {
+            return true;
+        }
+    }
+
+    /**
+     * 获取在线用户列表
+     *
+     * @return 返回用户集合
+     */
+    public static Map<String, Session> getUsers()
+    {
+        return USERS;
+    }
+
+    /**
+     * 群发消息文本消息
+     *
+     * @param message 消息内容
+     */
+    public static void sendMessageToUsersByText(String message)
+    {
+        Collection<Session> values = USERS.values();
+        for (Session value : values)
+        {
+            sendMessageToUserByText(value, message);
+        }
+    }
+
+    /**
+     * 发送文本消息
+     *
+     * @param userName 自己的用户名
+     * @param message 消息内容
+     */
+    public static void sendMessageToUserByText(Session session, String message)
+    {
+        if (session != null)
+        {
+            try
+            {
+                session.getBasicRemote().sendText(message);
+            }
+            catch (IOException e)
+            {
+                LOGGER.error("\n[发送消息异常]", e);
+            }
+        }
+        else
+        {
+            LOGGER.info("\n[你已离线]");
+        }
+    }
+}