java如何实现BIO远程调用设置实例源码介绍



java如何实现BIO远程调用设置实例源码介绍?本文是使用BIO的方式实现远程调用,也就是是Server端基于ServerSocket和InpuStream,OutputStream;客户端是基于Socket和InputStream,OutputStream。

首先看看远程调用的接口和实现,因为是基于JDK动态代理机制,所以必须要有接口,个人建议使用接口的编程模式,如果是因为客观原因没有接口,那也可以使用CGLIB,不过缺点是final无法处理。
先上传代码,有空再详细说明实现的细节。
接口

1
2
3
4
5
6
@ImplClass(className = "org.tigerl.bio.HelloWorldImpl")
public interface HelloWorld {
public String getHelloWorld(String helloWorld);
}

实现类

1
2
3
4
5
6
7
8
9
10
11
public class HelloWorldImpl implements HelloWorld {
    private static int INDEX = 0;
    @Override
    public String getHelloWorld(String helloWorld) {
        String str = helloWorld + (INDEX++);
        return str;
    }
}

注解类

1
2
3
4
5
6
7
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface ImplClass {
    String className() default "";
}

客户端

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
public class SimpleClient {
    private Socket socket;
    private final BlockingQueue<byte[]> inputBlockingQueue = new ArrayBlockingQueue<>(100);
    private final BlockingQueue<byte[]> outputBlockingQueue = new ArrayBlockingQueue<>(100);
    public SimpleClient(String host, int port) throws UnknownHostException, IOException {
        socket = new Socket(host, port);
    }
    public static SimpleClient connectServer() throws UnknownHostException, IOException {
        final SimpleClient client = new SimpleClient("localhost", 7788);
        new Thread(new Runnable() {
            public void run() {
                try {
                    client.start();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }).start();
        return client;
    }
    public void start() throws InterruptedException, IOException {
        while(true) {
            byte[] bytes = inputBlockingQueue.take();
            DataOutputStream output = new DataOutputStream(socket.getOutputStream());
            output.writeInt(bytes.length);
            output.write(bytes);
            DataInputStream in = new DataInputStream(socket.getInputStream());
            byte[] inBytes = new byte[in.readInt()];
            in.read(inBytes);
            outputBlockingQueue.put(inBytes);
        }
    }
    public void stop() throws IOException {
        socket.close();
    }
    public void putMessage(String message) throws InterruptedException, UnsupportedEncodingException {
        byte[] bytes = message.getBytes("UTF-8");
        putBytes(bytes);
    }
    public void putBytes(byte[] bytes) throws InterruptedException {
        inputBlockingQueue.put(bytes);
    }
    public byte[] takeBytes() throws InterruptedException {
        return outputBlockingQueue.take();
    }
}


客户端动态代理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
public class ClientInvoking implements InvocationHandler {
    private String className;
    @SuppressWarnings("unchecked")
    public <T> T bing(Class<T> class_) {
        className = class_.getName();
        Class<?>[] interfaces = new Class<?>[] {class_};
        return (T) Proxy.newProxyInstance(class_.getClassLoader(), interfaces, this);
    }
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        SimpleClient client = SimpleClient.connectServer();
        ClassInfo classInfo = new ClassInfo();
        classInfo.setClassName(className);
        classInfo.setMethodName(method.getName());
        classInfo.setParameters(args);
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        ObjectOutputStream out = new ObjectOutputStream(bos);
        out.writeObject(classInfo);
        byte[] bytes = bos.toByteArray();
        client.putBytes(bytes);
        byte[] inBytes = client.takeBytes();
        ObjectInputStream objIn = new ObjectInputStream(new ByteArrayInputStream(inBytes));
        Object returnObj = objIn.readObject();
        client.stop();
        return returnObj;
    }
}

调用信息

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
public class ClassInfo implements Serializable {
    /**
     *
     */
    private static final long serialVersionUID = 8971418367592789207L;
    private String className;
    private String methodName;
    private Object[] parameters;
    public String getClassName() {
        return className;
    }
    public void setClassName(String className) {
        this.className = className;
    }
    public String getMethodName() {
        return methodName;
    }
    public void setMethodName(String methodName) {
        this.methodName = methodName;
    }
    public Object[] getParameters() {
        return parameters;
    }
    public void setParameters(Object[] parameters) {
        this.parameters = parameters;
    }
}

服务端代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
public class SimpleServer {
    private ServerSocket serverScoket;
    private ExecutorService executorService;
    public SimpleServer(int port) throws IOException {
        serverScoket = new ServerSocket(port);
        executorService = Executors.newFixedThreadPool(10);
    }
    public void start() throws IOException {
        while(true) {
            Socket socket = serverScoket.accept();
            executorService.execute(new WorkThread(socket));
        }
    }
    private static class WorkThread implements Runnable {
        private Socket socket;
        private WorkThread(Socket socket) {
            this.socket = socket;
        }
        public void run() {
            try {
                DataInputStream in = new DataInputStream(socket.getInputStream());
                int length = in.readInt();
                byte[] bytes = new byte[length];
                in.read(bytes);
                ObjectInputStream objIn = new ObjectInputStream(new ByteArrayInputStream(bytes));
                ClassInfo classInfo = (ClassInfo)objIn.readObject();
                Class<?> interfaceClass = Class.forName(classInfo.getClassName());
                Class<?> implClass = Class.forName(interfaceClass.getAnnotation(ImplClass.class).className());
                Object obtj = implClass.newInstance();
                Object[] objs = classInfo.getParameters();
                Class<?>[] classes = new Class<?>[objs.length];
                for (int i = 0; i < objs.length; i++) {
                    classes[i] = objs[i].getClass();
                }
                Object returnObj = implClass.getDeclaredMethod(classInfo.getMethodName(), classes).invoke(obtj, objs);
                ByteArrayOutputStream byteOut = new ByteArrayOutputStream();
                ObjectOutputStream objOut = new ObjectOutputStream(byteOut);
                objOut.writeObject(returnObj);
                byte[] outBytes = byteOut.toByteArray();
                DataOutputStream out = new DataOutputStream(socket.getOutputStream());
                out.writeInt(outBytes.length);
                out.write(outBytes);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}

测试用例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class BIOTest {
    @Test
    public void testSimpleServer() throws IOException {
        SimpleServer server = new SimpleServer(7788);
        server.start();
    }
    @Test
    public void testInvoking() throws UnknownHostException, IOException, InterruptedException {
        ClientInvoking clientInvoking = new ClientInvoking();
        HelloWorld helloWorld = clientInvoking.bing(HelloWorld.class);
        System.out.println(helloWorld.getHelloWorld("test"));
    }
}

本文固定链接: