phprpc初步
in Web on phprpc, web html css 前端 - Hits()
官网:
java只有源代码,不过包含了个make.bat运行后就生成了三个jar包,服务端只需要phprpc.jar,客户端需要phprpc_client.jar,不需要别的依赖包,very nice,那个phprpc_spring.jar的包尚不知是做什么用的。
服务端,自定义接口:
package kzg.phprpc.hello.api; public interface Hello { String hello(String msg); Cdata getData1(); }
自定义Cdata类(要实现Serializable接口):
package kzg.phprpc.hello.api; import java.io.Serializable; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; public class Cdata implements Serializable { private static final long serialVersionUID = 1L; private String s1; private int s2; private List ss = new ArrayList(); private Map map = new HashMap(); public Cdata(String arg) { map.put("m1", "m1v"); ss.add("l1"); s1 = arg; s2 = 12; } public String getS1() { return s1; } public int getS2() { return s2; } public List getSs() { return ss; } public Map getMap() { return map; } }
发布rpc的filter(servlet都可以):
package kzg.phprpc.hello.service; import java.io.IOException; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.phprpc.PHPRPC_Server; public class RpcService implements Filter { public void destroy() { } public void doFilter(ServletRequest arequest, ServletResponse aresponse, FilterChain chain) throws IOException, ServletException { HttpServletRequest request = (HttpServletRequest) arequest; HttpServletResponse response = (HttpServletResponse) aresponse; PHPRPC_Server phprpc_server = new PHPRPC_Server(); phprpc_server.add(new HelloImpl()); phprpc_server.start(request, response); } public void init(FilterConfig filterConfig) throws ServletException { } }
注意,这里将helloimpl整个类的public方法都发布了,如果是使用javascript,则根本就不需要接口申明,但是对于Java客户端,还是写个接口便于操作。
配置web.xml:
<filter> <filter-name>rpcFilter</filter-name> <filter-class>kzg.phprpc.hello.service.RpcService</filter-class> </filter> <filter-mapping> <filter-name>rpcFilter</filter-name> <url-pattern>/phprpc/</url-pattern> </filter-mapping>
java客户端代码:
package kzg.phprpc.hello.client; import kzg.phprpc.hello.api.Cdata; import kzg.phprpc.hello.api.Hello; import org.phprpc.PHPRPC_Client; public class HelloClient { public static void main(String[] args) { PHPRPC_Client client = new PHPRPC_Client("http://localhost:10010/phprpc-test/phprpc/"); client.setKeyLength(512); client.setEncryptMode(1); Hello api = (Hello) client.useService(Hello.class); Cdata data = api.getData1(); System.out.println("call---->" + api.hello("hi.")); System.out.println("string:" + data.getS1()); System.out.println("int:" + data.getS2()); System.out.println("array:" + data.getSs()); System.out.println("map:" + data.getMap()); } }
javascript客户端代码:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <title>test.html</title> <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"> <meta http-equiv="description" content="this is my page"> <meta http-equiv="content-type" content="text/html; charset=utf-8"> <!--<link rel="stylesheet" type="text/css" href="./styles.css">--> <script type="text/javascript" src="js/phprpc_client.js"></script> <script type="text/javascript"> var client = new PHPRPC_Client('http://localhost:10010/phprpc-test/phprpc/', ['hello', 'getData1']); client.setKeyLength(256); client.setEncryptMode(2); client.hello('你好',function (result, args, output, warning) { alert(result); }); client.getData1(function (result, args, output, warning) { console.log(result); alert(result.map['m1']); }); </script> </head> <body> </body> </html>
返回的将Cdata转为了json对象。
phprpc_client.js这个脚本才18k,gzip压缩后才9k,非常小。
这里我故意使用中文测试了一下编码问题,运行得很好,由于PHPRPC默认使用UTF-8 字符集,我的html编码也是utf-8,这样就不需要什么额外处理,非常不错。
这里使用加密方法,看了一下他们的介绍,加密算法是Diffie-Hellman 密钥交换算法,很好!
这样来看,它起码是一个很好的ajax工具,非常不错!
然后尝试一下发送一个Map和自定义pojo型数据:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <title>test.html</title> <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"> <meta http-equiv="description" content="this is my page"> <meta http-equiv="content-type" content="text/html; charset=utf-8"> <!--<link rel="stylesheet" type="text/css" href="./styles.css">--> <script type="text/javascript" src="js/phprpc_client.js"></script> <script type="text/javascript"> var client = new PHPRPC_Client('http://localhost:10010/phprpc-test/phprpc/', ['hello', 'getData1','sendData','sendData1']); client.setKeyLength(256); client.setEncryptMode(2); /* client.hello('你好',function (result, args, output, warning) { alert(result); }); client.getData1(function (result, args, output, warning) { console.log(result); alert(result.map['m1']); });*/ var cdata = {s1:'client string',map:{'k1':'cstring'}}; client.sendData1(cdata,function (result, args, output, warning) { //console.log(result); // alert(result.map['m1']); }); var data = {'k1':'cstring'}; client.sendData(data,function (result, args, output, warning) { //console.log(result); // alert(result.map['m1']); }); </script> </head> <body> </body> </html>
可以看到调用了sendData方法,传入的是个json,sendData1传入的也是个与Cdata类型相配的json.
服务端添加sendData函数:
package kzg.phprpc.hello.service; import java.util.Map; import org.phprpc.util.Cast; import kzg.phprpc.hello.api.Cdata; import kzg.phprpc.hello.api.Hello; public class HelloImpl implements Hello { public String hello(String msg) { return "这是travel back from server:" + msg; } public Cdata getData1() { Cdata data = new Cdata("server data"); return data; } public void sendData1(Cdata data) { System.out.println("call---- sendData1:" + Cast.cast(data.getMap().get("k1"),String.class)); } public void sendData(Map data) { System.out.println("call---- sendData:" + Cast.cast(data.get("k1"),String.class)); } }
在Map里面直接取get(“k1”)是不行的,还要使用Cast.cast方法转换一下。
同样pojo类型中的相容型数据是转过来了,但是对于数组等容器类型,还得自己再处理一下。
我觉得这样就比较繁琐了,不过传复杂类型参数可以使用别的方法解决,使用json同样存在这样的问题,这里自动将json转为pojo,还是减省了一步。
见:
另外一些问题 :
找半天不知道怎么处理异常,出了错,什么也没有。文档还是不全!这些基本的东西,要找半天。