javaweb启动时启动socket服务端

说明:在javaweb项目启动的时候启动socket服务端,可以接受客户端发送过来的数据,客户端可以反复断开连接

1.新建SocketThread线程类

package com.wlw.modules.startImplement.web;

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;

/**
 * socket 线程类
 * @Author: zhouhe
 * @Date: 2019/4/16 14:58
 */
public class SocketThread extends Thread {
    private ServerSocket serverSocket = null;

    public SocketThread(ServerSocket serverScoket){
        try {
            if(null == serverSocket){
                this.serverSocket = new ServerSocket(8877);
                System.out.println("socket start");
            }
        } catch (Exception e) {
            System.out.println("SocketThread创建socket服务出错");
            e.printStackTrace();
        }

    }

    public void run(){
        while(!this.isInterrupted()){
            try {
                Socket socket = serverSocket.accept();

                if(null != socket && !socket.isClosed()){
                    //处理接受的数据
                    new SocketOperate(socket).start();
                }
//                socket.setSoTimeout(30000);   //设置超时

            }catch (Exception e) {

            }
        }
    }


    public void closeSocketServer(){
        try {
            if(null!=serverSocket && !serverSocket.isClosed())
            {
                serverSocket.close();
            }
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}

2.新建SocketOperate,用于接受客户端传来的数据

package com.wlw.modules.startImplement.web;

import com.wlw.modules.lhjh.socket.tstandard.MessageParsing;

import java.io.BufferedInputStream;
import java.io.DataInputStream;
import java.io.IOException;
import java.net.Socket;

/**
 * 多线程处理socket接收的数据
 * @Author: zhouhe
 * @Date: 2019/4/16 14:59
 */
public class SocketOperate extends Thread {
    private Socket socket;

    public SocketOperate(Socket socket) {
        this.socket=socket;
    }

    @Override
    public void run() {
        try {
            //封装输入流(接收客户端的流)
            BufferedInputStream bis = new BufferedInputStream(socket.getInputStream());
            DataInputStream dis = new DataInputStream(bis);
            byte[] bytes = new byte[1]; // 一次读取一个byte

            String ret = "";
            while (dis.read(bytes) != -1) {
                ret += MessageParsing.bytesToHexString(bytes) + "";
                if (dis.available() == 0) { //一个请求

                    System.out.println("转换为字符串后:"+MessageParsing.hexStringToString(ret));
                    System.out.println("转为map后的数据:"+MessageParsing.stringToMap(MessageParsing.hexStringToString(ret)));

                    ret = "";
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            System.out.println("client is over");
            if (socket != null) {
                try {
                    socket.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

3.新建InitJob,web项目启动的时候会执行里面的方法,去启动socket,可以用串口调试工具测试

package com.wlw.modules.startImplement.web;

import com.wlw.common.config.Global;

import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;

/**
 * @Author: zhouhe
 * @Date: 2019/4/16 11:00
 */
//创建的类名根据需要定义,但一定要实现ServletContextListener接口
public class InitJob implements ServletContextListener {

    //socket server 线程
    private SocketThread socketThread;

    /**
     * 项目在启动初始化的时候就会执行的方法(启动服务时执行)
     * @param arg0
     */
    @Override
    public void contextInitialized(ServletContextEvent arg0) {
        // TODO Auto-generated method stub
        //这里可以放你要执行的代码或方法
        if(null==socketThread && "yes".equals(Global.getConfig("socket"))){
//            MessageParsing.calculation();
            //新建线程类
            socketThread=new SocketThread(null);
            //启动线程
            socketThread.start();
        }
    }

    /**
     *contextDestroyed是在消亡的时候执行的方法(关闭服务时执行)
     * @param arg0
     */
    @Override
    public void contextDestroyed(ServletContextEvent arg0) {
        // TODO Auto-generated method stub
        if(null!=socketThread && !socketThread.isInterrupted()){
            socketThread.closeSocketServer();
            socketThread.interrupt();
        }
    }

}

4.这里需要一个报文解析工具类

package com.wlw.modules.lhjh.socket.tstandard;

import java.util.HashMap;
import java.util.Map;

/**
 * HJ/T212 报文解析
 * @Author: zhouhe
 * @Date: 2019/4/12 10:11
 */
public class MessageParsing {
    /**
     * 字符串转换为 map
     * @param arr
     * @return
     */
    public static Map stringToMap(String arr){
        arr=arr.replaceAll(",",";");
        Map map = new HashMap();
        if (null != arr) {
            String[] param = arr.split(";");
            for (int i = 0; i < param.length; i++) {
                //这里的 index 要 >-1 才是 map格式
                int index = param[i].indexOf('=');
                if(index>-1)
                    map.put(param[i].substring(0,index), param[i].substring((index + 1)));
            }
        }
        return map;
    }

    /**
     * byte[]数组转换为16进制的字符串
     *
     * @param bytes 要转换的字节数组
     * @return 转换后的结果
     */
    public static String bytesToHexString(byte[] bytes) {
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < bytes.length; i++) {
            String hex = Integer.toHexString(0xFF & bytes[i]);
            if (hex.length() == 1) {
                sb.append('0');
            }
            sb.append(hex);
        }
        return sb.toString();
    }

    /**
     * 16进制转换成为string类型字符串
     * 这个方法中文会乱码,字母和数字都不会乱码
     *
     * @Author zhouhe
     * @param s
     * @return
     */
    public static String hexStringToString(String s) {
        if (s == null || s.equals("")) {
            return null;
        }
        s = s.replace(" ", "");
        byte[] baKeyword = new byte[s.length() / 2];
        for (int i = 0; i < baKeyword.length; i++) {
            try {
                baKeyword[i] = (byte) (0xff & Integer.parseInt(s.substring(i * 2, i * 2 + 2), 16));
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        try {
            s = new String(baKeyword, "UTF-8");
            new String();
        } catch (Exception e1) {
            e1.printStackTrace();
        }
        return s;
    }
}

这样就大功告成了,启动web项目,就可以接受客户端过来的数据了

原文地址:https://www.cnblogs.com/zhouheblog/p/11245833.html