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")); }} |
本文固定链接: