Posted on 2011-03-03 09:44
penngo 阅读(3537)
评论(3) 编辑 收藏 所属分类:
Java
昨天网友问了下DWR的问题,DWR是一个用于改善web页面与Java类交互的远程服务器端Ajax开源框架,不过自己并未在项目中用过,只是之前在网上看过它的一些介绍,大概的了解它的调用原理。
如果要在客户端调用服务器端的java方法,一种是基于TCP协议,如RMI;另一种是基于HTTP协议,如web service、ajax。DWR就是基于ajax方式调用WEB服务器上的JAVA方法的一种。
如果是基于HTTP协议来调用,按个人理解,只需把3步做好就行了,
1、定义好访问规则,如怎样把需要调用的类名、方法名、参数提交到服务器端。
2、服务器端怎样按收客户端传类名、方法名、参数;接收到数据后,怎样实例化该类和执行指定的方法。
3、服务器把处理结果以什么形式返回给客户端。
和网友说着来了兴趣,回家顺便写了个实现尝试下。
下面开始按上面的原理步骤写一个简单的实现例子
1、类名、方法名、参数通过ajax方式pose到服务器端RemoteServlet,本文直接使用jquery的ajax
ScriptEngine.js,
function getRootPath(){
var strFullPath=window.document.location.href;
var strPath=window.document.location.pathname;
var pos=strFullPath.indexOf(strPath);
var prePath=strFullPath.substring(0,pos);
var postPath=strPath.substring(0,strPath.substr(1).indexOf('/')+1);
return(prePath+postPath);
}
function ScriptEngine(){
this.name = "";
this.method = "";
this.setClass = function(n){
name = "class=" + n;
}
this.setMethod = function(m){
method = "method=" + m;
}
this.invoke = function(){
var result;
var parames = "";
if(arguments.length > 0){
for(i = 0; i < arguments.length; i++){
parames=arguments[i];
}
}
$.ajax( {
type : "POST",
url : getRootPath() + "/RemoteServlet",
cache : false,
async : false,
data : name + "&" + method + "&args=" + parames,
success : function(data) {
result = data;
},
error :function(data){
result= data;
}
});
return result;
}
}
2、服务器端RemoteServlet接收客户端传来类名、方法名、参数,并通过反射的方式,实例化该类和执行相应的方法。
RemoteServlet.java
import java.io.IOException;
import java.lang.reflect.Method;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class RemoteServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
public RemoteServlet() {
super();
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
remote(request, response);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
remote(request, response);
}
protected void remote(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String name = request.getParameter("class");
String method = request.getParameter("method");
String args = request.getParameter("args");
if(name != null && method != null){
try{
Class cls = Class.forName(name);
Object[] parames = !args.equals("") ? args.split(";") : null;
Object obj = cls.newInstance();
Method[] methods = cls.getMethods();
for(Method m:methods){
System.out.println(m.getName());
if(m.getName().equals(method)){
Object result = parames != null ? m.invoke(obj,parames) : m.invoke(obj);
response.setCharacterEncoding("UTF-8");
response.getWriter().println(result.toString());
break;
}
}
}
catch(Exception e){
e.printStackTrace();
}
}
}
}
在web.xml中配置该servlet
<servlet>
<description></description>
<display-name>RemoteServlet</display-name>
<servlet-name>RemoteServlet</servlet-name>
<servlet-class>com.pengo.init.RemoteServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>RemoteServlet</servlet-name>
<url-pattern>/RemoteServlet</url-pattern>
</servlet-mapping>
3、RemoteServlet处理完,把数据以文本形式返回给客户端。
这样一个简单的客户端调用服务器端方法的框架就完成了。
下面开始试用该框架
先写需要被客户端调用的方法类。
HelloWorld.java
public class HelloWorld {
public String say(){
return "hello,pengo!";
}
public String tell(String name){
return "hello," + name;
}
}
DateUtil.java
import java.text.SimpleDateFormat;
import java.util.Date;
public class DateUtil {
public String today(){
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String str = sdf.format(new Date());
return str;
}
}
客户端调用这两个类
test.html
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
<script type="text/javascript" src="js/jquery-1.4.2.min.js" ></script>
<script type="text/javascript" charset=UTF-8" src="js/ScriptEngine.js" ></script>
</head>
<script type="text/javascript">
function hello(){
var se = new ScriptEngine();
se.setClass("com.pengo.remote.HelloWorld");
se.setMethod("say");
var re = se.invoke();
alert(re);
}
function tell(){
var se = new ScriptEngine();
se.setClass("com.pengo.remote.HelloWorld");
se.setMethod("tell");
var re = se.invoke("测试");
alert(re);
}
function today(){
var se = new ScriptEngine();
se.setClass("com.pengo.remote.DateUtil");
se.setMethod("today");
var re = se.invoke();
alert(re);
}
</script>
<body>
<input type="button" onClick="hello();" value="无参数调用"/>
<input type="button" onClick="tell();" value="有参数调用"/>
<input type="button" onClick="today();" value="取服务器端日期"/>
</body>
</html>
运行效果:
本文还需要改进的地方:
1、se.setClass("com.pengo.remote.HelloWorld");不应该通过完整的包名来调用,可以考虑注解实现,
2、返回的数据可以考虑定义为json或xml格式。
3、......
源码:
下载