本次分享的是一个简单的Web项目里使用的Socket通信案例
1、建立监听类:
package com.trust.fricem.TCPC.service;import org.springframework.web.context.WebApplicationContext;import org.springframework.web.context.support.WebApplicationContextUtils;import javax.servlet.ServletContextEvent;import javax.servlet.ServletContextListener;/** * @Author:Singularity * @Date:2019/6/1 14:23 * @Description: Socket 服务监听 */public class SocketServiceLoader implements ServletContextListener { //socket server 线程 private SocketThread socketThread; /** * 当Servlet 容器启动Web 应用时调用该方法。在调用完该方法之后,容器再对Filter 初始化, * 并且对那些在Web 应用启动时就需要被初始化的Servlet 进行初始化。 */ @Override public void contextInitialized(final ServletContextEvent sce) { System.out.println("容器启动-------"); if (null == socketThread) { //新建线程类 WebApplicationContext wac = WebApplicationContextUtils.getWebApplicationContext(sce.getServletContext()); socketThread = new SocketThread(null, wac); //启动线程 socketThread.start(); } } /** * 当Servlet 容器终止Web 应用时调用该方法。在调用该方法之前,容器会先销毁所有的Servlet 和Filter 过滤器。 */ @Override public void contextDestroyed(ServletContextEvent sce) { System.out.println("容器终止-------"); if (null != socketThread && !socketThread.isInterrupted()) { socketThread.closeSocketServer(); socketThread.interrupt(); } }}
2、创建线程类,同时创建 ServerSocket 服务端并监听客户端的连接
package com.trust.fricem.TCPC.service;import com.trust.fricem.TCPC.controller.SocketDataDealController;import org.springframework.web.context.WebApplicationContext;import java.io.*;import java.net.InetAddress;import java.net.ServerSocket;import java.net.Socket;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;/** * @Author:Singularity * @Date:2019/6/1 14:32 * @Description: Socket 服务端 */public class SocketThread extends Thread { private ExecutorService threadPool = Executors.newFixedThreadPool(100); private ServerSocket serverSocket = null; private WebApplicationContext webApplicationContext = null; Socket socket; BufferedReader reader; BufferedWriter writer; public SocketThread(ServerSocket serverScoket, WebApplicationContext wac) { try { if (null == serverSocket) { this.serverSocket = new ServerSocket(8088); webApplicationContext = wac; System.out.println("socket start"); System.out.println("Spring 容器 webApplicationContext 获取"); } } catch (Exception e) { System.out.println("SocketThread创建socket服务出错"); e.printStackTrace(); } } public void run() { while (!this.isInterrupted()) { try { //1、创建一个服务器端Socket,即ServerSocket,指定绑定的端口,并监听此端口 1024-65535的某个端口 while (true) { // 巧用死循环 //2、调用accept()方法开始监听,等待客户端的连接 socket = serverSocket.accept(); InetAddress address = socket.getInetAddress();//获取远程客户端的IP信息 System.out.println("InetAddress:" + address); System.out.println("IP地址:" + address.getHostAddress()); System.out.println("主机名:" + address.getHostName()); reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));//读取客户端消息 writer = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));//向客户端写消息 try { //3、获取输入流,并读取客户端信息 String info = null; SocketDataDealController sdd = new SocketDataDealController(webApplicationContext); while (!(info = reader.readLine()).equals("bye")) { System.out.println("收到来自客户端的发送的消息是:" + new String(info.getBytes(), "UTF-8")); String returnInfo = sdd.dealSocketData(info); System.out.println("给客户端的发送的消息是:" + returnInfo); writer.write(new String(returnInfo.getBytes(), "UTF-8") + "\n"); writer.flush(); } } catch (IOException e) { e.printStackTrace(); } finally { try { if (reader != null) { reader.close(); } if (writer != null) { writer.close(); } if (socket != null) { System.out.println("Socket通道关闭"); socket.close(); } } catch (Exception e2) { e2.printStackTrace(); } } } } catch (Exception e) { e.printStackTrace(); } } } public void closeSocketServer() { try { if (null != serverSocket && !serverSocket.isClosed()) { System.out.println("ServerSocket 终止"); serverSocket.close(); } } catch (IOException e) { e.printStackTrace(); } }}
3、处理客户端数据类,其中包含调用 Service 层方法的用法
package com.trust.fricem.QRCode.controller;import com.trust.fricem.QRCode.entity.ProdQRCodeEntity;import com.trust.fricem.QRCode.entity.ReturnMessage;import com.trust.fricem.QRCode.entity.UniversalcodeEntity;import com.trust.fricem.QRCode.service.ProdQRCodeService;import com.trust.fricem.QRCode.service.UniversaleCodeService;import com.trust.fricem.common.Constant;import com.trust.fricem.common.util.ASCIIUtils;import com.trust.fricem.common.util.CRC8;import com.trust.fricem.equipment.entity.EquipmenttypeEntity;import com.trust.fricem.equipment.service.EquipmenttypeDisService;import com.trust.fricem.product.entity.ProducttypeEntity;import com.trust.fricem.product.service.ProductTypeService;import org.springframework.web.context.WebApplicationContext;/** * GPRS 通信接口 * @author Singularity * @Time 2019.2.25 */public class SCMInterface { private WebApplicationContext context = null; private ProdQRCodeService prodQRCodeService; private EquipmenttypeDisService equipmenttypeDisService; private ProductTypeService productTypeService; private UniversaleCodeService universaleCodeService; public SCMInterface(WebApplicationContext webApplicationContext) { context = webApplicationContext; // 利用 webApplicationContext 创建 service prodQRCodeService = context.getBean(ProdQRCodeService.class); equipmenttypeDisService = context.getBean(EquipmenttypeDisService.class); productTypeService = context.getBean(ProductTypeService.class); universaleCodeService = context.getBean(UniversaleCodeService.class); } /** * 接口1 */ public String receiveMessage(String param) { ReturnMessage object = null; String returnStr = null; if (null != object) { if (null != object.getCodeStr()) { String str = object.getCodeStr(); if (null != str && "" != str) { //二维码类型标识 String codeType = str.substring(0, 2); if (Constant.PROQrCode_BS.equals(codeType)) { //----普通二维码 returnStr = prodQRCodeService.updateQrCodeInfo(object);//修改二维码加工状态 } if (Constant.PROQrCode_WS.equals(codeType)) { //----万能二维码 returnStr = universaleCodeService.saveUniversaleCode(object);//添加万能码使用记录数据 //returnStr = CRC8.returnType(Constant.PROQrCode_SUCCESS, Constant.PROQrCode_EQUIPNO); } } } } return returnStr; }}
4、再 Web.xml 中添加监听
org.springframework.web.context.ContextLoaderListener org.springframework.web.util.IntrospectorCleanupListener com.trust.fricem.TCPC.service.SocketServiceLoader
注意:由于使用的是 Servlet 的监听方法,servlet 容器是在 Spring 容器之前加载的,而本次我用的是 SSM 框架,其中的 service 层和 dao 层等使用 Spring 容器管理的,所以上方的黄色标注的地方调用的方法会报错, 其中的 webApplicationContext 就是为了解决,这个问题 (有什么不对或者不合理的地方,欢迎大家赐教!)