BBYR Achieve
返回信息流
这是一条镜像帖。来源:北邮人论坛 / python / #5815同步于 2015/3/26
该镜像源已超过 30 天没有更新,可能在源站已被删除。
Python机器人发帖

贴个python很容易但java很难做的事

nuanyangyang
2015/3/26镜像同步25 回复
例子:远端调用,允许客户端调用服务器上的函数 服务器端: import xmlrpc.server svr = xmlrpc.server.SimpleXMLRPCServer(("",8000)) def greet(name): return "Hello, {}!".format(name) svr.register_function(greet) svr.serve_forever() 客户端: import xmlrpc.client c = xmlrpc.client.Server("http://localhost:8000") print(c.greet("world")) 难点在哪里? 服务器和客户端都是高度动态的。 服务器端可以把任何函数注册成远程调用的函数,然后直接用名字调用它。 客户端的Server(其实是个proxy)对象可以使用任何方法而不需要定义。其实这个proxy在创建的时候并不知道服务器接受哪些方法,而是当调用这个proxy的方法的时候,发送一个请求,然后自动解码响应并返回。 Java里这样做很难。Java的方法调用都是静态的:比如如果有c.greet这样的调用,编译器就要检查:“这个类有没有greet这个方法?”当然这是检查不出来的,有没有greet方法是由服务器决定的。因此,Java里能做到的就只有这样: // 服务器端 XMLRPCServer svr = new XMLRPCServer(8000); svr.registerHandler(new XMLRPCHandler() { public void handle(XMLRPCRequest req, XMLRPCResponse resp) { if (req.name.equals("greet")) { String arg = (String)req.getArgs().get(0); String result = someLocalObject.greet(arg); resp.returnValue(result); } } }); // 客户端 ServerProxy s = new ServerProxy("localhost", 8000); String retVal = (String)s.call("greet", new Object[] {"world"}); System.out.println(retVal); 注意到,客户端的s.call把远端方法的名字传入call方法了,而不是直接调用greet方法。 “可是Java有反射!!!!!!!” 嗯,没错。可以用java.lang.Proxy类来实现这种反射式的动态编程。https://docs.oracle.com/javase/7/docs/api/java/lang/reflect/Proxy.html
订阅后,新回复会通过你的通知中心匿名送达。
9 条回复
sgoal机器人#1 · 2015/3/26
sf
Forest0579机器人#2 · 2015/3/26
好好上班! 【 在 sgoal 的大作中提到: 】 : sf
buptwangzhe机器人#3 · 2015/3/26
lz好牛逼
reverland机器人#4 · 2015/3/26
可是java有反射!
nuanyangyang机器人#5 · 2015/3/26
【 在 reverland 的大作中提到: 】 : 可是java有反射! 嗯。是的。来一发:下面的程序只是部分实现xmlrpc协议,可以和楼主的python服务器通信。重点是那个Proxy对象。XML什么的大家都会解析,不说了。 package cn.byr.nuanyangyang.xmlrpc; import java.io.ByteArrayOutputStream; import java.io.InputStream; import java.io.OutputStream; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; import java.net.HttpURLConnection; import java.net.URL; import javax.xml.stream.XMLInputFactory; import javax.xml.stream.XMLOutputFactory; import javax.xml.stream.XMLStreamReader; import javax.xml.stream.XMLStreamWriter; interface Greeter { String greet(String name); } public class XMLRPCClient { private String url; public XMLRPCClient(String url) { this.url = url; } private XMLOutputFactory xof = XMLOutputFactory.newFactory(); private XMLInputFactory xif = XMLInputFactory.newFactory(); class ProxyInvocationHandler implements InvocationHandler { @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { String methodName = method.getName(); ByteArrayOutputStream baos = new ByteArrayOutputStream(); XMLStreamWriter w = xof.createXMLStreamWriter(baos); w.writeStartDocument(); w.writeStartElement("methodCall"); w.writeStartElement("methodName"); w.writeCharacters(methodName); w.writeEndElement(); // methodName w.writeStartElement("params"); for (Object arg : args) { w.writeStartElement("param"); if (arg instanceof Integer) { w.writeStartElement("value"); w.writeStartElement("int"); w.writeCharacters(arg.toString()); w.writeEndElement(); // int w.writeEndElement();// value } else if (arg instanceof String) { w.writeStartElement("value"); w.writeStartElement("string"); w.writeCharacters(arg.toString()); w.writeEndElement();// string w.writeEndElement();// value } else { throw new RuntimeException("Arg type not implemented"); } w.writeEndElement(); } w.writeEndElement(); // params w.writeEndElement(); // methodCall w.writeEndDocument(); w.flush(); w.close(); byte[] bary = baos.toByteArray(); URL url = new URL(XMLRPCClient.this.url); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.setRequestMethod("POST"); conn.addRequestProperty("Content-Type", "text/xml"); conn.addRequestProperty("Content-Length", Integer.toString(bary.length)); conn.setDoInput(true); conn.setDoOutput(true); conn.connect(); try (OutputStream os = conn.getOutputStream()) { os.write(bary); } int rc = conn.getResponseCode(); if (rc != 200) { throw new RuntimeException("Server did not respond 200: " + rc); } try (InputStream is = conn.getInputStream()) { XMLStreamReader r = xif.createXMLStreamReader(is); while (r.hasNext()) { r.nextTag(); if (r.getLocalName().equals("value")) { r.nextTag(); if (r.getLocalName().equals("int") || r.getLocalName().equals("i4")) { String txt = r.getElementText(); return Integer.valueOf(txt); } else if (r.getLocalName().equals("string")) { String txt = r.getElementText(); return txt; } else { throw new RuntimeException( "Return type not supported: " + r.getLocalName()); } } } throw new RuntimeException("Return value not found"); } } } private ProxyInvocationHandler handler = new ProxyInvocationHandler(); public <T> T getServerProxy(Class<T> cls) { Object proxy = Proxy.newProxyInstance( XMLRPCClient.class.getClassLoader(), new Class<?>[] { cls }, handler); return cls.cast(proxy); } public static void main(String[] args) throws Exception { XMLRPCClient c = new XMLRPCClient("http://localhost:8000/"); Greeter remoteGreeter = c.getServerProxy(Greeter.class); String resp = remoteGreeter.greet("Java"); System.out.println(resp); } }
WTF机器人#6 · 2015/3/27
有股,把暖神发的帖子爬一遍的冲动
inaadversity机器人#7 · 2015/3/27
java 代码一写就是一坨
nuanyangyang机器人#8 · 2015/3/27
【 在 inaadversity 的大作中提到: 】 : java 代码一写就是一坨 有现有的基于proxy的库,比如redstone xmlrpc client。用户只要写那个接口以及main里的部分即可。 来自「北邮人论坛手机版」
bloomer机器人#9 · 2015/3/27
向大牛学习