本次分享的是一个简单的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 中添加监听
<!-- spring监听器 -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- 防止spring内存溢出监听器,比如quartz -->
<listener>
<listener-class>org.springframework.web.util.IntrospectorCleanupListener</listener-class>
</listener>
<!-- Socket 监听器 (注意,监听要放在 Spring 之后,不然创建的 ServletContextEvent 是空的)-->
<listener>
<listener-class>com.trust.fricem.TCPC.service.SocketServiceLoader</listener-class>
</listener>
注意:由于使用的是 Servlet 的监听方法,servlet 容器是在 Spring 容器之前加载的,而本次我用的是 SSM 框架,其中的 service 层和 dao 层等使用 Spring 容器管理的,所以上方的黄色标注的地方调用的方法会报错, 其中的 webApplicationContext 就是为了解决,这个问题 (有什么不对或者不合理的地方,欢迎大家赐教!)
来源:https://www.cnblogs.com/Singulariity-gs/p/11038239.html