﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>语源科技BlogJava-Thinker IN JAVA</title><link>http://www.blogjava.net/Supershen/</link><description>Java  JavaEE  Jsp  Struts1.x Struts2.x  Hibernate Spring2.0 EJB3.0   ASP   .NET   Php   Flex</description><language>zh-cn</language><lastBuildDate>Thu, 30 Apr 2026 06:25:04 GMT</lastBuildDate><pubDate>Thu, 30 Apr 2026 06:25:04 GMT</pubDate><ttl>60</ttl><item><title>springside mini-web学习总结。</title><link>http://www.blogjava.net/Supershen/archive/2009/01/08/250512.html</link><dc:creator>Super·shen BLOG </dc:creator><author>Super·shen BLOG </author><pubDate>Thu, 08 Jan 2009 09:01:00 GMT</pubDate><guid>http://www.blogjava.net/Supershen/archive/2009/01/08/250512.html</guid><wfw:comment>http://www.blogjava.net/Supershen/comments/250512.html</wfw:comment><comments>http://www.blogjava.net/Supershen/archive/2009/01/08/250512.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.blogjava.net/Supershen/comments/commentRss/250512.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/Supershen/services/trackbacks/250512.html</trackback:ping><description><![CDATA[springside3背景struts2.1.2 spring2.5.6 Hibernate3.4GA<br />
<br />
<br />
<span style="font-family: 黑体"><strong>1.struts2 <br style="font-family: " />
</strong></span><br />
使用ZeroConfig + CodeBehind插件,实现约定大于配置的零配置文件风格.<br />
<br />
根本不用配置struts.xml文件 <br />
<br />
<br />
<br />
<img alt="" src="http://www.blogjava.net/images/blogjava_net/supershen/s1.jpg" border="0" /><br />
<br />
这里就是action实现annotation&nbsp;&nbsp;CodeBehind。<br />
如方法<br />
<img alt="" src="http://www.blogjava.net/images/blogjava_net/supershen/2s.jpg" border="0" /><br />
<br />
通过 /user/user!input.action访问， 并转到 /user/user-xxx.jsp页面<br />
即namespace + action name + "-" + "xxx.jsp"<br />
<br />
<br />
&nbsp;另外其中 action中需要注入的 service 使用annotation ，在set方法前 加入@request 或 @ autowired 或 @resource<br />
注释（具体是用那个暂时无法搞清楚，总之我用request 就不行，另外两个都可以）<br />
<br />
<img alt="" src="http://www.blogjava.net/images/blogjava_net/supershen/222.jpg" border="0" /><br />
<br />
有了这个代码之后 就能注入spring 环境中的 id = userManager 的bean （我个人理解）<br />
<br />
而spring中&nbsp;&nbsp;id = userManager 的bean&nbsp; 也是通过自动注入完成的<br />
<br />
主要代码是 applicationContext.xml文件中的<br />
代码：<br />
<br />
<img alt="" src="http://www.blogjava.net/images/blogjava_net/supershen/2222.jpg" border="0" /><br />
<br />
<br />
<span style="font-family: 黑体"><strong>2.spring<br />
</strong></span><br />
spring2.5.6的annotation特性用的比较泛滥。 新手刚开始看的一头雾水很正常。<br />
<br />
xml文件中配置自动注册bean，通过扫描包中的带注解的类。即这个代码：<br />
<br />
<img alt="" src="http://www.blogjava.net/images/blogjava_net/supershen/2222.jpg" border="0" /><br />
<br />
<br />
扫描到下面的类，就自动注册成 id=userManager<br />
<br />
<img alt="" src="http://www.blogjava.net/images/blogjava_net/supershen/223.jpg" border="0" /><br />
<br />
<br />
<br />
<span style="font-family: 黑体"><strong>3.hibernate <br />
</strong></span>使用hiberante3 注解，不要XML配置，实体类注解不用多说。<br />
<br />
需要注意的是entity类的扫描配置<br />
<br />
<br />
<img alt="" src="http://www.blogjava.net/images/blogjava_net/supershen/33.jpg" border="0" /><br />
<br />
看清楚是扫描包，不是扫描类！ 所以实体类com.mylu.User是无法扫描到，要放在 com.mylu.xxx.User才能扫描到！<br />
<br />
<br />
<br />
<br />
下边按照ss3风格做的例子，去掉spring security 框架的， 结构更清晰。<br />
<br />
<a title="按照springside3风格做的例子 无安全框架的" href="/Files/Supershen/s2s2.rar">下载：实例代码</a><br />
<br />
<br />
附：<br />
类库<br />
<img alt="" src="http://www.blogjava.net/images/blogjava_net/supershen/211.jpg" border="0" /> 
<img src ="http://www.blogjava.net/Supershen/aggbug/250512.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/Supershen/" target="_blank">Super·shen BLOG </a> 2009-01-08 17:01 <a href="http://www.blogjava.net/Supershen/archive/2009/01/08/250512.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>java jsp servlet 获得绝对路径的方法</title><link>http://www.blogjava.net/Supershen/archive/2008/09/17/229425.html</link><dc:creator>Super·shen BLOG </dc:creator><author>Super·shen BLOG </author><pubDate>Wed, 17 Sep 2008 06:55:00 GMT</pubDate><guid>http://www.blogjava.net/Supershen/archive/2008/09/17/229425.html</guid><wfw:comment>http://www.blogjava.net/Supershen/comments/229425.html</wfw:comment><comments>http://www.blogjava.net/Supershen/archive/2008/09/17/229425.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/Supershen/comments/commentRss/229425.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/Supershen/services/trackbacks/229425.html</trackback:ping><description><![CDATA[<p>在jsp中，其实jsp就是servlet，jsp和servlet也都是一个class：</p>
<p>1 .request.getRealPath()，这个方法已经不推荐使用，在servlet后继版本中将被取缔。</p>
<p>2.getServletContext().getRealPath("/")这个方法比较好用，可以直接在servlet和jsp中使用。</p>
<p>3.request.getSession().getServletContext().getRealPath()也可以在jsp和servlet使用。</p>
<p>4.this.getClass().getClassLoader().getResource("").getPath()，这个方法可以在任意jsp，servlet，java文件中使用，因为不管是jsp，servlet其实都是java程序，都是一个class。所以它应该是一个通用的方法。</p>
<img src ="http://www.blogjava.net/Supershen/aggbug/229425.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/Supershen/" target="_blank">Super·shen BLOG </a> 2008-09-17 14:55 <a href="http://www.blogjava.net/Supershen/archive/2008/09/17/229425.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>简单权限系统设计需求</title><link>http://www.blogjava.net/Supershen/archive/2008/08/18/222806.html</link><dc:creator>Super·shen BLOG </dc:creator><author>Super·shen BLOG </author><pubDate>Mon, 18 Aug 2008 08:17:00 GMT</pubDate><guid>http://www.blogjava.net/Supershen/archive/2008/08/18/222806.html</guid><wfw:comment>http://www.blogjava.net/Supershen/comments/222806.html</wfw:comment><comments>http://www.blogjava.net/Supershen/archive/2008/08/18/222806.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/Supershen/comments/commentRss/222806.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/Supershen/services/trackbacks/222806.html</trackback:ping><description><![CDATA[<p>普遍的，简单的权限系统要求：<br />
<br />
1.系统所有资源定义 [资源表]&nbsp;&nbsp; ( 还可以分为更小的权限表，操作表，这里通叫资源表)<br />
2.定义角色 [角色表]<br />
3.给角色指定资源（一个角色可以管理多个资源） [角色-资源表]<br />
4.定义用户组 [用户表]<br />
5.给用户组指定角色（一个用户组可以拥有多种角色） [用户组-角色表]<br />
6.给用户指定角色（一个用户可以拥有多种角色，可以直接指定角色，也可以继承用户组的角色）[用户-角色表]</p>
<p>&nbsp;</p>
<p><br />
查找权限时：</p>
<p>根据用户ID[用户-角色表]或用户组ID[用户组-角色表]，查到所有角色ID，再[角色-资源表]找到所有角色下的所有资源。 </p>
<p>此就是用户拥有的资源。（资源一般为模块，当然也可以分更细的定义为页面，操作方法等）</p>
<br />
此权限设计适合于模块化访问系统，如OA<br />
<br />
<br />
当然很多系统因地而已，不可能完全满足，按照自己系统需求设计是最合适的设计。<br />
<br />
<br />
<br />
<img src ="http://www.blogjava.net/Supershen/aggbug/222806.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/Supershen/" target="_blank">Super·shen BLOG </a> 2008-08-18 16:17 <a href="http://www.blogjava.net/Supershen/archive/2008/08/18/222806.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>第一个 CGIC sqlite3 代码</title><link>http://www.blogjava.net/Supershen/archive/2008/03/01/183156.html</link><dc:creator>Super·shen BLOG </dc:creator><author>Super·shen BLOG </author><pubDate>Sat, 01 Mar 2008 09:11:00 GMT</pubDate><guid>http://www.blogjava.net/Supershen/archive/2008/03/01/183156.html</guid><wfw:comment>http://www.blogjava.net/Supershen/comments/183156.html</wfw:comment><comments>http://www.blogjava.net/Supershen/archive/2008/03/01/183156.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/Supershen/comments/commentRss/183156.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/Supershen/services/trackbacks/183156.html</trackback:ping><description><![CDATA[提交页面

<html>
<body onbeforeunload="RunOnBeforeUnload()">
<h1>插入</h1>
<form action="cgi-bin/add2.cgi" method="get">
用户:<input type="text" name="username"><br>
密码:<input type="text" name="password"><br>
<input type=submit value=插入> 
</form>
</body>
</html>



处理页面add2.cgi 代码

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "sqlite3.h"
#include "cgic.h"

int cgiMain() {
printf("Content-type:text/html\n\n");
printf("<head><meta http-equiv=\"Expires\" CONTENT=\"0\"><meta http-equiv=\"Cache-Control\" CONTENT=\"no-cache\"><meta http-equiv=\"Pragma\" CONTENT=\"no-cache\"></head>");

sqlite3 *db=NULL;
char *zErrMsg = 0;
int rc;
rc = sqlite3_open("test.db", &db);
if(rc){
printf("Can't open database\n"); //这里改了。要是按原先的，会提示stderr未定义，我不知道为什么。哪位朋友知道一定要告诉我哦。
sqlite3_close(db);
exit(1);
}
else printf("open test.db successfully!\n");


char username[241];
cgiFormString("username", username, 241);
fprintf(cgiOut, "username: <PRE>\n");
cgiHtmlEscape(username);
fprintf(cgiOut, "</pre>\n");

char password[241];
cgiFormString("password", password, 241);
fprintf(cgiOut, "password: <PRE>\n");
cgiHtmlEscape(password);
fprintf(cgiOut, "</pre>\n");



char sql[300]={'\0'};  //不能用指针!

//插入数据 

sprintf(sql, "INSERT INTO \"user\" VALUES('%s', '%s');", username,password);
//sql = "INSERT INTO \"user\" VALUES('username', 'password');" ;
sqlite3_exec( db , sql , 0 , 0 , &zErrMsg );

printf(sql);
printf("插入数据成功!\n"); 


int nrow = 0, ncolumn = 0;
char **azResult; //二维数组存放结果

//查询数据
/*
int sqlite3_get_table(sqlite3*, const char *sql,char***result , int *nrow , int *ncolumn ,char **errmsg );
result中是以数组的形式存放你所查询的数据，首先是表名，再是数据。
nrow ,ncolumn分别为查询语句返回的结果集的行数，列数，没有查到结果时返回0
*/
char *sql2 = "SELECT * FROM user";
sqlite3_get_table( db , sql2 , &azResult , &nrow , &ncolumn , &zErrMsg );

int i = 0 ;
printf( "row:%d column=%d <br>" , nrow , ncolumn );
printf( "\nThe result of querying is : \n" );

for( i=0 ; i<( nrow + 1 ) * ncolumn ; i++ )
printf( "azResult[%d] = %s <br>", i , azResult[i] );

//释放掉 azResult 的内存空间
sqlite3_free_table( azResult );


sqlite3_close(db); //关闭数据库
return 0;
}



请注意数据库文件 test.db的访问权限! 这里改成777! <img src ="http://www.blogjava.net/Supershen/aggbug/183156.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/Supershen/" target="_blank">Super·shen BLOG </a> 2008-03-01 17:11 <a href="http://www.blogjava.net/Supershen/archive/2008/03/01/183156.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>CGIC简明教程</title><link>http://www.blogjava.net/Supershen/archive/2008/02/28/182683.html</link><dc:creator>Super·shen BLOG </dc:creator><author>Super·shen BLOG </author><pubDate>Thu, 28 Feb 2008 06:19:00 GMT</pubDate><guid>http://www.blogjava.net/Supershen/archive/2008/02/28/182683.html</guid><wfw:comment>http://www.blogjava.net/Supershen/comments/182683.html</wfw:comment><comments>http://www.blogjava.net/Supershen/archive/2008/02/28/182683.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/Supershen/comments/commentRss/182683.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/Supershen/services/trackbacks/182683.html</trackback:ping><description><![CDATA[<p>[转自] http://webdn.trueself.cn/archives/107</p>
<img src ="http://www.blogjava.net/Supershen/aggbug/182683.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/Supershen/" target="_blank">Super·shen BLOG </a> 2008-02-28 14:19 <a href="http://www.blogjava.net/Supershen/archive/2008/02/28/182683.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>c字符串处理函数</title><link>http://www.blogjava.net/Supershen/archive/2008/02/27/182513.html</link><dc:creator>Super·shen BLOG </dc:creator><author>Super·shen BLOG </author><pubDate>Wed, 27 Feb 2008 08:35:00 GMT</pubDate><guid>http://www.blogjava.net/Supershen/archive/2008/02/27/182513.html</guid><wfw:comment>http://www.blogjava.net/Supershen/comments/182513.html</wfw:comment><comments>http://www.blogjava.net/Supershen/archive/2008/02/27/182513.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/Supershen/comments/commentRss/182513.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/Supershen/services/trackbacks/182513.html</trackback:ping><description><![CDATA[<p>&#9670; 使用strtok函数分割。<br />
&nbsp;&nbsp;&nbsp;&nbsp; 原型：char *strtok(char *s, char delim); <br />
&nbsp;&nbsp;&nbsp; strtok在s中查找包含在delim中的字符并用NULL('\0')来替换,直到找遍整个字符串。&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp; 功能：分解字符串为一组字符串。s为要分解的字符串，delim为分隔符字符串。 <br />
&nbsp;&nbsp;&nbsp; 说明：首次调用时，s指向要分解的字符串，之后再次调用要把s设成NULL。 <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; strtok在s中查找包含在delim中的字符并用NULL('\0')来替换，直到找遍整个字符串。 <br />
&nbsp;&nbsp;&nbsp; 返回值：从s开头开始的一个个被分割的串。当没有被分割的串时则返回NULL。 <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 所有delim中包含的字符都会被滤掉，并将被滤掉的地方设为一处分割的节点。 <br />
<br />
使用例：<br />
#include &lt;stdio.h&gt;<br />
#include &lt;string.h&gt;<br />
#include &lt;stdio.h&gt;<br />
#include &lt;string.h&gt;<br />
<br />
int main(int argc,char **argv)<br />
{<br />
&nbsp;&nbsp;&nbsp; char * buf1="aaa, ,a, ,,,bbb-c,,,ee|abc";<br />
<br />
&nbsp;&nbsp;&nbsp; /* Establish string and get the first token: */<br />
&nbsp;&nbsp;&nbsp; char* token = strtok( buf1, ",-|");<br />
&nbsp;&nbsp;&nbsp; while( token != NULL )<br />
&nbsp;&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* While there are tokens in "string" */<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; printf( "%s ", token );<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* Get next token: */<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; token = strtok( NULL, ",-|");<br />
&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; return 0;<br />
}<br />
<br />
OUT 值： <br />
aaa<br />
<br />
a</p>
<p>bbb<br />
c<br />
ee<br />
abc</p>
<p>&#9670; 使用strstr函数分割。</p>
<p>&nbsp;&nbsp;&nbsp; 原型：extern char *strstr(char *haystack,char *needle);<br />
<br />
&nbsp;&nbsp;&nbsp; 用法：#include &lt;string.h&gt; <br />
&nbsp;&nbsp; 功能：从字符串haystack中寻找needle第一次出现的位置（不比较结束NULL) <br />
&nbsp;&nbsp; 说明：返回指向第一次出现needle位置的指针，如果没找到则返回NULL。 <br />
<br />
使用例：<br />
#include &lt;stdio.h&gt;<br />
#include &lt;string.h&gt;</p>
<p>int main(int argc,char **argv)<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp; char *haystack="aaa||a||bbb||c||ee||";<br />
&nbsp;&nbsp;&nbsp;&nbsp; char *needle="||";<br />
&nbsp;&nbsp;&nbsp;&nbsp; char* buf = strstr( haystack, needle);<br />
&nbsp;&nbsp;&nbsp;&nbsp; while( buf != NULL )<br />
&nbsp;&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; buf[0]='\0';<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; printf( "%s\n ", haystack);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; haystack = buf + strlen(needle);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* Get next token: */<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; buf = strstr( haystack, needle);<br />
&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp; return 0;<br />
}</p>
<p>OUT 值： <br />
aaa<br />
a<br />
bbb<br />
c<br />
ee</p>
<p>&#9670; strtok比较适合多个字符作分隔符的场合，而strstr适合用字符串作分隔符的场合。</p><img src ="http://www.blogjava.net/Supershen/aggbug/182513.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/Supershen/" target="_blank">Super·shen BLOG </a> 2008-02-27 16:35 <a href="http://www.blogjava.net/Supershen/archive/2008/02/27/182513.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>C语言CGI程序 POST表单处理 </title><link>http://www.blogjava.net/Supershen/archive/2008/02/27/182480.html</link><dc:creator>Super·shen BLOG </dc:creator><author>Super·shen BLOG </author><pubDate>Wed, 27 Feb 2008 05:52:00 GMT</pubDate><guid>http://www.blogjava.net/Supershen/archive/2008/02/27/182480.html</guid><wfw:comment>http://www.blogjava.net/Supershen/comments/182480.html</wfw:comment><comments>http://www.blogjava.net/Supershen/archive/2008/02/27/182480.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/Supershen/comments/commentRss/182480.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/Supershen/services/trackbacks/182480.html</trackback:ping><description><![CDATA[我们来看看到底如何从POST表单收集数据到CGI程序，下面給出了一個比较简单的C源代碼:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;
<p>&nbsp;</p>
<p>#include&lt;stdio.h&gt;<br />
#include&lt;stdlib.h&gt;&nbsp;&nbsp;&nbsp;&nbsp; <br />
#define MAXLEN 80&nbsp;&nbsp;&nbsp;&nbsp; <br />
#define EXTRA 5<br />
/*&nbsp;&nbsp; 4个字节留给字段的名字"data",&nbsp;&nbsp; 1个字节留给"="&nbsp;&nbsp; */<br />
#define&nbsp;&nbsp; MAXINPUT&nbsp;&nbsp; MAXLEN+EXTRA+2&nbsp; <br />
/*&nbsp;&nbsp; 1个字节留给换行符，还有一个留给后面的NULL&nbsp;&nbsp; */<br />
#define DATAFILE "../data/data.txt"<br />
/*&nbsp;&nbsp; 要被添加数据的文件&nbsp;&nbsp; */</p>
<p>void&nbsp;&nbsp; unencode(char&nbsp;&nbsp; *src,&nbsp;&nbsp; char&nbsp;&nbsp; *last,&nbsp;&nbsp; char&nbsp;&nbsp; *dest)<br />
{<br />
&nbsp;for(; src != last; src++, dest++) <br />
&nbsp;&nbsp;if(*src == "+")<br />
&nbsp;&nbsp;&nbsp;*dest = " ";<br />
&nbsp;&nbsp;else if(*src == "%") {&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;int&nbsp;&nbsp; code;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;if(sscanf(src+1,"%2x",&amp;code)!=1)code="?"; <br />
&nbsp;&nbsp;&nbsp;*dest=code;<br />
&nbsp;&nbsp;&nbsp;src&nbsp;&nbsp; +=2;}<br />
&nbsp;&nbsp;else<br />
&nbsp;&nbsp;&nbsp;*dest=*src;<br />
&nbsp;&nbsp;*dest=" ";<br />
&nbsp;&nbsp;*++dest="";&nbsp;&nbsp;&nbsp;&nbsp; <br />
}&nbsp;&nbsp;&nbsp;&nbsp; </p>
<p>int&nbsp;&nbsp; main(void)&nbsp;&nbsp;&nbsp;&nbsp; <br />
{&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;char *lenstr;<br />
&nbsp;char input[MAXINPUT], data[MAXINPUT];<br />
&nbsp;long len;<br />
&nbsp;<br />
&nbsp;printf("%s%c%c", "Content-Type:text/html;charset=gb2312",13,10);<br />
&nbsp;printf("&lt;TITLE&gt;Response&lt;/TITLE&gt;");</p>
<p>&nbsp;lenstr=getenv("CONTENT_LENGTH");<br />
&nbsp;if(lenstr==NULL || sscanf(lenstr,"%ld",&amp;len)!=1 || len&gt;MAXLEN)<br />
&nbsp;&nbsp;printf("&lt;P&gt;表单提交错误");<br />
&nbsp;else{<br />
&nbsp;&nbsp;FILE *f;<br />
&nbsp;&nbsp;fgets(input,&nbsp;&nbsp; len+1,&nbsp;&nbsp; stdin);<br />
&nbsp;&nbsp;unencode(input+EXTRA,&nbsp;&nbsp; input+len,&nbsp;&nbsp; data);</p>
<p>&nbsp;&nbsp;f =fopen(DATAFILE, "a");<br />
&nbsp;&nbsp;if(f == NULL)&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;printf("&lt;P&gt;对不起，意外错误，不能够保存你的数据");&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;else<br />
&nbsp;&nbsp;&nbsp;fputs(data,&nbsp;&nbsp; f);&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;fclose(f);<br />
&nbsp;&nbsp;printf("&lt;P&gt;非常感谢，您的数据已经被保存&lt;BR&gt;%s",data);&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;}&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;return&nbsp;&nbsp; 0;&nbsp;&nbsp;&nbsp;&nbsp; <br />
}&nbsp;&nbsp;&nbsp;&nbsp; <br />
</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp; 　　 &nbsp; 从本质上来看，程序先从CONTENT_LENGTH环境变量中得到数据的字长，然后读取相应长度的字符串。因为数据内容在传输的过程中是经过了编码的，所以必须进行相应的解码。编码的规则很简单，主要的有这几条:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
<br />
1. &nbsp; 表单中每个每个字段用字段名后跟等号，再接上上这个字段的值来表示，每个字段之间的内容用&amp;连结；&nbsp;&nbsp;&nbsp; 2. &nbsp; 所有的空格符号用加号代替，所以在编码码段中出现空格是非法的；&nbsp;&nbsp;&nbsp;&nbsp; <br />
3. &nbsp; 特殊的字符比如标点符号，和一些有特定意义的字符如&#8220;+&#8221;，用百分号后跟其对应的ACSII码值来表示。&nbsp;&nbsp;&nbsp;&nbsp; <br />
<br />
例如：如果<a class="qs_highlight1" id="hl_5" onmouseover="window.clearTimeout(_ht[5]);qs_show_frame(event,this,5);" style="font-size: 1em" onclick="_write_cookie('click46',5);" onmouseout="_on_div[5]=false;_ht[5]=window.setTimeout('qs_is_on_div(5)',500);" href="http://clk.qunsee.com/click/click.php?cpid=510&amp;ads_id=46&amp;pid=99000800&amp;cid=806&amp;url=http%3A//www.qunsee.com/sitepage.php&amp;k=%u7528%u6237&amp;s=http%3A//www.80diy.com/home/20050401/11/3900238.html&amp;rn=442524&amp;v=1&amp;ref=http%3A//www.baidu.com/s%3Fct%3D0%26ie%3Dgb2312%26bs%3DC%25B4%25A6%25C0%25ED%25B1%25ED%25B5%25A5cgi%25B3%25CC%25D0%25F2%26sr%3D%26z%3D%26cl%3D3%26f%3D8%26wd%3Dcgi%25B1%25ED%25B5%25A5%25B4%25A6%25C0%25ED+c%25D3%25EF%25D1%25D4&amp;province=%u5E7F%u4E1C&amp;city=%u5E7F%u5DDE" target="_blank">用户</a>输入的是：&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp; <br />
Hello &nbsp; there!&nbsp;&nbsp;&nbsp;&nbsp; <br />
<br />
那么数据传送到服务器的时候经过编码，就变成了data=Hello+there%21 &nbsp; 上面的unencode（）函数就是用来把编码后的数据进行解码的。在解码完成后，数据被添加到data.txt文件的尾部，并在浏览其中回显出来。&nbsp;&nbsp;&nbsp;&nbsp; <br />
<br />
把文件编译完成后，把它改名为collect.cgi后放在CGI目录中就可以被表单调用了。下面给出了其相应的表单：&nbsp;&nbsp;&nbsp;&nbsp; <br />
<br />
&lt;FORM &nbsp; ACTION="/cgi-bin/collect.cgi" &nbsp; METHOD="POST" &nbsp; &gt;<br />
&lt;P&gt;请输入您的留言（最多80个字符）：&lt;BR&gt;<br />
&lt;INPUT &nbsp; NAME="data" &nbsp; SIZE="60" &nbsp; MAXLENGTH="80" &nbsp; &gt;&lt;BR&gt;<br />
&lt;INPUT &nbsp; TYPE="SUBMIT" &nbsp; VALUE="确定"&gt;<br />
&lt;/FORM &nbsp; &gt; &nbsp; &nbsp; <br />
&nbsp; &nbsp; <br />
&nbsp; &nbsp; <br />
&nbsp; 　　 &nbsp; 事实上，这个程序只能作为例子，是不能够正式的使用的。它漏掉了很关键的一个问题：当有多个用户同时像文件写入数据是，肯定会有错误发生。而对于一个这样的程序而言，文件被同时写入的几率是很大的。因此，在比较正式的留言版程序中，都需要做一些更多的考虑，比如加入一个信号量，或者是借助于一个钥匙文件等。因为那只是编程的技巧问题，在这儿就不多说了。<br />
</p>
<img src ="http://www.blogjava.net/Supershen/aggbug/182480.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/Supershen/" target="_blank">Super·shen BLOG </a> 2008-02-27 13:52 <a href="http://www.blogjava.net/Supershen/archive/2008/02/27/182480.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>C语言编写CGI程序 </title><link>http://www.blogjava.net/Supershen/archive/2008/02/26/182230.html</link><dc:creator>Super·shen BLOG </dc:creator><author>Super·shen BLOG </author><pubDate>Tue, 26 Feb 2008 07:37:00 GMT</pubDate><guid>http://www.blogjava.net/Supershen/archive/2008/02/26/182230.html</guid><wfw:comment>http://www.blogjava.net/Supershen/comments/182230.html</wfw:comment><comments>http://www.blogjava.net/Supershen/archive/2008/02/26/182230.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/Supershen/comments/commentRss/182230.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/Supershen/services/trackbacks/182230.html</trackback:ping><description><![CDATA[啥都不说，直接看代码！<br />
<br />
简单输出代码<br />
<p>#include &lt;stdio.h&gt;<br />
#include &lt;stdlib.h&gt; <br />
#include &lt;string.h&gt;<br />
void main() <br />
{ <br />
printf("Content-type:text/html\n\n");</p>
<p>printf("hello world!");</p>
<p>fflush(stdout);</p>
<p>} <br />
<br />
<br />
<br />
处理get代码<br />
<br />
#include &lt;stdio.h&gt;<br />
#include &lt;stdlib.h&gt;<br />
int zmain(void)<br />
{char *data;<br />
long m,n;<br />
printf("%s%c%c\n","Content-Type:text/html;charset=iso-8859-1",13,10);<br />
printf("&lt;TITLE&gt;Multiplication results&lt;/TITLE&gt;\n");<br />
printf("&lt;H3&gt;Multiplication results&lt;/H3&gt;\n");<br />
data = getenv("QUERY_STRING");<br />
if(data == NULL)&nbsp; <br />
printf("&lt;P&gt;Error! Error in passing data from form to script.");<br />
else if(sscanf(data,"m=%ld&amp;n=%ld",&amp;m,&amp;n)!=2)&nbsp; <br />
printf("&lt;P&gt;Error! Invalid data. Data must be numeric.");<br />
else&nbsp; <br />
printf("&lt;P&gt;The product of %ld and %ld is %ld.",m,n,m*n);<br />
return 0;<br />
}<br />
<br />
<br />
处理post代码<br />
<br />
#include&lt;stdio.h&gt;<br />
#include&lt;stdlib.h&gt;<br />
void main()<br />
{<br />
&nbsp;int i,n;<br />
&nbsp;printf("Content-type:text/html\n\n");<br />
&nbsp;n=0;<br />
&nbsp;if(getenv("CONTENT_LENGTH"))<br />
&nbsp;&nbsp;n=atoi(getenv("CONTENT_LENGTH"));<br />
&nbsp;printf("%d",n);<br />
&nbsp;for(i=0;i&lt;n;i++)<br />
&nbsp;&nbsp;putchar(getchar());<br />
&nbsp;putchar('\n');<br />
&nbsp;fflush(stdout);<br />
}<br />
<br />
<br />
<br />
还是代码<br />
<br />
</p>
<p><br />
#include &lt;stdio.h&gt;<br />
#include &lt;stdlib.h&gt; <br />
#include &lt;string.h&gt;</p>
<p>/* 转换函数声明 */<br />
int htoi(char *); </p>
<p>/*&nbsp; 主函数 */<br />
void zmain() { <br />
&nbsp;int i,n;<br />
&nbsp;char c;<br />
&nbsp;printf ("Content-type: text/html\n\n");<br />
&nbsp;n=0; <br />
&nbsp;if (getenv("CONTENT_LENGTH")) <br />
&nbsp;&nbsp;n=atoi(getenv("CONTENT_LENGTH")); <br />
&nbsp;for (i=0; i&lt;n;i++){<br />
&nbsp;&nbsp;<br />
&nbsp;&nbsp;int is_eq=0; //判断是否有等于号。<br />
&nbsp;&nbsp;<br />
&nbsp;&nbsp;c=getchar(); <br />
&nbsp;&nbsp;switch(c){<br />
&nbsp;&nbsp;case '&amp;':<br />
&nbsp;&nbsp;&nbsp;c='\n';<br />
&nbsp;&nbsp;&nbsp;break;<br />
&nbsp;&nbsp;case '+':<br />
&nbsp;&nbsp;&nbsp;c='+';<br />
&nbsp;&nbsp;&nbsp;break;<br />
&nbsp;&nbsp;case '%':<br />
&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;char s[3]; <br />
&nbsp;&nbsp;&nbsp;&nbsp;s[0]=getchar();<br />
&nbsp;&nbsp;&nbsp;&nbsp;s[1]=getchar();<br />
&nbsp;&nbsp;&nbsp;&nbsp;s[2]=0;<br />
&nbsp;&nbsp;&nbsp;&nbsp;c=htoi(s);<br />
&nbsp;&nbsp;&nbsp;&nbsp;i+=2;<br />
&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;break; <br />
&nbsp;&nbsp;case '=': <br />
&nbsp;&nbsp;&nbsp;c='=';<br />
&nbsp;&nbsp;&nbsp;is_eq=1; <br />
&nbsp;&nbsp;&nbsp;break;<br />
&nbsp;&nbsp;}; <br />
&nbsp;&nbsp;<br />
&nbsp;&nbsp;putchar(c); <br />
&nbsp;&nbsp;//if (is_eq) putchar(' '); <br />
&nbsp;} <br />
&nbsp;putchar ('\n'); <br />
&nbsp;fflush(stdout); <br />
} </p>
<p>/* 转换为小写 */<br />
int islower (int ch )&nbsp; </p>
<p>{<br />
&nbsp;&nbsp;&nbsp; return (unsigned int) (ch - 'a') &lt; 26u;<br />
}</p>
<p><br />
/* convert hex string to int 16进制转换成10进制 */ <br />
int htoi(char *s) </p>
<p>{ <br />
&nbsp;<br />
&nbsp;char *digits="0123456789ABCDEF";<br />
&nbsp;<br />
&nbsp;if(islower(s[0])) s[0]=toupper(s[0]); <br />
&nbsp;if(islower(s[1])) s[1]=toupper(s[1]); <br />
&nbsp;<br />
&nbsp;return 16 * (strchr(digits, s[0]) -strchr(digits,'0') ) +(strchr(digits,s[1])-strchr(digits,'0')); <br />
&nbsp;<br />
} </p>
<p><br />
#include&lt;stdio.h&gt;<br />
#include&lt;stdlib.h&gt;<br />
void zzzmain()<br />
{<br />
&nbsp;int i,n;<br />
&nbsp;printf("Content-type:text/html\n\n");<br />
&nbsp;n=0;<br />
&nbsp;if(getenv("CONTENT_LENGTH"))<br />
&nbsp;&nbsp;n=atoi(getenv("CONTENT_LENGTH"));<br />
&nbsp;printf("%d",n);<br />
&nbsp;for(i=0;i&lt;n;i++)<br />
&nbsp;&nbsp;putchar(getchar());<br />
&nbsp;putchar('\n');<br />
&nbsp;fflush(stdout);<br />
}</p>
<p>&nbsp;</p>
<img src ="http://www.blogjava.net/Supershen/aggbug/182230.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/Supershen/" target="_blank">Super·shen BLOG </a> 2008-02-26 15:37 <a href="http://www.blogjava.net/Supershen/archive/2008/02/26/182230.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>dwr教程2</title><link>http://www.blogjava.net/Supershen/archive/2008/01/18/176287.html</link><dc:creator>Super·shen BLOG </dc:creator><author>Super·shen BLOG </author><pubDate>Fri, 18 Jan 2008 09:14:00 GMT</pubDate><guid>http://www.blogjava.net/Supershen/archive/2008/01/18/176287.html</guid><wfw:comment>http://www.blogjava.net/Supershen/comments/176287.html</wfw:comment><comments>http://www.blogjava.net/Supershen/archive/2008/01/18/176287.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/Supershen/comments/commentRss/176287.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/Supershen/services/trackbacks/176287.html</trackback:ping><description><![CDATA[http://samhe.javaeye.com/blog/142416
<img src ="http://www.blogjava.net/Supershen/aggbug/176287.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/Supershen/" target="_blank">Super·shen BLOG </a> 2008-01-18 17:14 <a href="http://www.blogjava.net/Supershen/archive/2008/01/18/176287.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>DWR实例教程</title><link>http://www.blogjava.net/Supershen/archive/2008/01/18/176207.html</link><dc:creator>Super·shen BLOG </dc:creator><author>Super·shen BLOG </author><pubDate>Fri, 18 Jan 2008 06:43:00 GMT</pubDate><guid>http://www.blogjava.net/Supershen/archive/2008/01/18/176207.html</guid><wfw:comment>http://www.blogjava.net/Supershen/comments/176207.html</wfw:comment><comments>http://www.blogjava.net/Supershen/archive/2008/01/18/176207.html#Feedback</comments><slash:comments>27</slash:comments><wfw:commentRss>http://www.blogjava.net/Supershen/comments/commentRss/176207.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/Supershen/services/trackbacks/176207.html</trackback:ping><description><![CDATA[DWR(Direct Web Remoting)是一个WEB远程调用框架.利用这个框架可以让AJAX开发变得很简单.利用DWR可以在客户端利用JavaScript直接调用服务端的Java方法并返回值给JavaScript就好像直接本地客户端调用一样(DWR根据Java类来动态生成JavaScrip代码).它的最新版本DWR0.6添加许多特性如:支持Dom Trees的自动配置,支持Spring(JavaScript远程调用spring bean),更好浏览器支持,还支持一个可选的commons-logging日记操作.<br />
<br />
以上摘自open-open，它通过反射，将java翻译成javascript，然后利用回调机制，轻松实现了javascript调用Java代码。<br />
<br />
其大概开发过程如下：<br />
1.编写业务代码，该代码是和dwr无关的。<br />
2.确认业务代码中哪些类、哪些方法是要由javascript直接访问的。<br />
3.编写dwr组件，对步骤2的方法进行封装。<br />
4.配置dwr组件到dwr.xml文件中，如果有必要，配置convert，进行java和javascript类型互转。<br />
5.通过反射机制，dwr将步骤4的类转换成javascript代码，提供给前台页面调用。<br />
5.编写网页，调用步骤5的javascript中的相关方法（间接调用服务器端的相关类的方法），执行业务逻辑，将执行结果利用回调函数返回。<br />
6.在回调函数中，得到执行结果后，可以继续编写业务逻辑的相关javascript代码。<br />
<br />
下面以用户注册的例子，来说明其使用。（注意，本次例子只是用于演示，说明DWR的使用，类设计并不是最优的）。<br />
<br />
1.先介绍下相关的Java类<br />
<br />
&nbsp;&nbsp;User: 用户类，<br />
&nbsp;&nbsp;public class User {<br />
//登陆ID，主键唯一<br />
private String id;<br />
//姓名<br />
private String name;<br />
//口令<br />
private String password;<br />
//电子邮件<br />
private String email;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
//以下包含getXXX和setXXX方法<br />
.......<br />
&nbsp;&nbsp;}<br />
<br />
&nbsp;&nbsp;UserDAO：实现User的数据库访问，这里作为一个演示，编写测试代码<br />
&nbsp;&nbsp;public class UserDAO { <br />
&nbsp;&nbsp;&nbsp;&nbsp;//存放保存的数据<br />
&nbsp;&nbsp;&nbsp;&nbsp;private static Map dataMap = new HashMap();<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;//持久用户<br />
&nbsp;&nbsp;&nbsp;&nbsp;public boolean save(User user) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (dataMap.containsKey(user.getId()))<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return false;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println("下面开始保存用户");<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println("id："+user.getId());<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println("password："+user.getPassword());<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println("name："+user.getName());<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println("email："+user.getEmail());<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;dataMap.put(user.getId(), user);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println("用户保存结束");<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return true;<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;//查找用户<br />
&nbsp;&nbsp;&nbsp;&nbsp;public User find(String id) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return (User)dataMap.get(id);<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
}<br />
<br />
&nbsp;&nbsp;DWRUserAccess：DWR组件，提供给javascript访问的。<br />
<br />
&nbsp;&nbsp;public class DWRUserAccess {<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;UserDAO userDAO = new UserDAO();<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;public boolean save(User user) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return userDAO.save(user);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;public User find(String id) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return userDAO.find(id);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;}<br />
&nbsp;&nbsp;<br />
<br />
&nbsp;&nbsp;下面说明下程序执行的流程<br />
<br />
&nbsp;&nbsp;1.用户在页面上输入相关注册信息，id、name、password、email，点击&#8220;提交&#8221;按钮<br />
&nbsp;&nbsp;2.javascript代码开始执行，根据用户填写相关信息，通过dwr提供的DWRUserAccess.js里save的方法，调用服务器端的DWRUserAccess类save方法，将注册信息保存。<br />
&nbsp;&nbsp;3.通过DWRUserAccess.jsp里的find方法，调用服务器端DWRUserAccess类里的find方法，执行用户信息查找。<br />
<br />
&nbsp;&nbsp;注意，在以上的执行过程中，DWRUserAccess是供DWR调用的，是DWR组件，因此需要将DWRUserAccess类配置到dwr中。<br />
<br />
&nbsp;&nbsp;接下来讲解本次dwr测试环境的配置。<br />
<br />
&nbsp;&nbsp;1.新建一个webapp，命名为testApp<br />
&nbsp;&nbsp;2.将dwr.jar拷贝到testApp的WEB-INF的lib目录下<br />
&nbsp;&nbsp;3.编译上面的User，UserDAO，DWRUserAccess类，放到classes目录下<br />
&nbsp;&nbsp;4.在web.xml中配置servlet,适配路径到dwr目录下,如下所示<br />
&nbsp;&nbsp;&nbsp;&nbsp;&lt;servlet&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&lt;servlet-name&gt;dwr-invoker&lt;/servlet-name&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&lt;display-name&gt;DWR Servlet&lt;/display-name&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&lt;description&gt;Direct Web Remoter Servlet&lt;/description&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&lt;servlet-class&gt;uk.ltd.getahead.dwr.DWRServlet&lt;/servlet-class&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&lt;init-param&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;param-name&gt;debug&lt;/param-name&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;param-value&gt;true&lt;/param-value&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&lt;/init-param&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&lt;init-param&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;param-name&gt;scriptCompressed&lt;/param-name&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;param-value&gt;false&lt;/param-value&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&lt;/init-param&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&lt;load-on-startup&gt;1&lt;/load-on-startup&gt;<br />
&nbsp;&nbsp;&lt;/servlet&gt;<br />
<br />
&nbsp;&nbsp;&lt;servlet-mapping&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&lt;servlet-name&gt;dwr-invoker&lt;/servlet-name&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&lt;url-pattern&gt;/dwr/*&lt;/url-pattern&gt;<br />
&nbsp;&nbsp;&lt;/servlet-mapping&gt;<br />
<br />
&nbsp;&nbsp;以上的配置可以拦截testApp下所有指向dwr的请求，关于这个拦截器，我们会在后面介绍。<br />
<br />
&nbsp;&nbsp;5.WEB-INF下新建一个dwr.xml文件，内容如下：<br />
&nbsp;&nbsp;&lt;&nbsp;xml version="1.0" encoding="UTF-8"&nbsp;&gt;<br />
&lt;!DOCTYPE dwr PUBLIC "-//GetAhead Limited//DTD Direct Web Remoting 1.0//EN" "http://www.getahead.ltd.uk/dwr/dwr10.dtd"&gt;<br />
<br />
&lt;dwr&gt;<br />
&nbsp;&nbsp;&lt;allow&gt;<br />
&lt;create creator="new" javascript="DWRUserAccess"&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;param name="class" value="test.DWRUserAccess"/&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&lt;/create&gt;<br />
&lt;convert converter="bean" match="test.User"/&gt;<br />
&nbsp;&nbsp;&lt;/allow&gt;<br />
&lt;/dwr&gt;<br />
<br />
&nbsp;&nbsp;这里我们把DWRUserAccess配置到了dwr中，create元素中，creater="new"表示每调用一次DWRUserAccess时，需要new一个这样的类；javascript="DWRUserAccess"，表示提供给前台页面调用的javascirpt文件是DWRUserAccess.js。<br />
<br />
&nbsp;&nbsp;convert元素用于数据类型转换，即java类和javascript之间相互转换，因为和前台交换的是User对象，因此需要对此使用bean转换，我们将在后面介绍这个类。<br />
<br />
&nbsp;&nbsp;4.编写测试的HTML页面 test.html<br />
&nbsp;&nbsp; &lt;!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"&gt;<br />
&lt;HTML&gt;<br />
&lt;HEAD&gt;<br />
&lt;TITLE&gt;DWR测试&lt;/TITLE&gt;<br />
&lt;meta http-equiv=Content-Type content="text/html; charset=gb2312"&gt;<br />
&lt;script src="/oblog312/dwr/engine.js"&gt;&lt;/script&gt;<br />
&lt;script src="/oblog312/dwr/util.js"&gt;&lt;/script&gt;<br />
&lt;script src="/oblog312/dwr/interface/DWRUserAccess.js"&gt;&lt;/script&gt;<br />
&lt;/HEAD&gt;<br />
&lt;BODY&gt;<br />
&lt;B&gt;用户注册&lt;/B&gt;&lt;br&gt;<br />
------------------------------------------------<br />
&lt;Br&gt;<br />
&lt;form name="regForm"&gt;<br />
登陆ID：&lt;input type="text" name="id"&gt;&lt;br&gt;<br />
口&nbsp;&nbsp;令：&lt;input type="password" name="password"&gt;&lt;br&gt;<br />
姓&nbsp;&nbsp;名：&lt;input type="text" name="name"&gt;&lt;br&gt;<br />
电子邮件：&lt;input type="text" name="email"&gt;&lt;br&gt;<br />
&lt;input type="button" name="submitBtn" value="提交" onclick="OnSave()"&gt;&lt;br&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&lt;/form&gt;<br />
<br />
&lt;br&gt;<br />
&lt;br&gt;&lt;B&gt;用户查询&lt;/B&gt;&lt;br&gt;<br />
------------------------------------------------<br />
&lt;Br&gt;<br />
&lt;form name="queryForm"&gt;<br />
登陆ID：&lt;input type="text" name="id"&gt;&lt;br&gt;<br />
&lt;input type="button" name="submitBtn" value="提交" onclick="OnFind()"&gt;&lt;br&gt;<br />
&lt;/form&gt;<br />
&lt;br&gt;<br />
&lt;/BODY&gt;<br />
&lt;/HTML&gt;<br />
&lt;SCRIPT LANGUAGE="JavaScript"&gt;<br />
&lt;!--<br />
function saveFun(data) {<br />
if (data) {<br />
&nbsp;&nbsp;alert("注册成功！");<br />
} else {<br />
&nbsp;&nbsp;alert("登陆ID已经存在！");<br />
}<br />
}<br />
<br />
function OnSave() {<br />
var userMap = {};<br />
userMap.id = regForm.id.value;<br />
userMap.password = regForm.password.value;<br />
userMap.name = regForm.name.value;<br />
userMap.email = regForm.email.value;<br />
DWRUserAccess.save(userMap, saveFun); <br />
}<br />
<br />
function findFun(data) {<br />
if (data == null) {<br />
&nbsp;&nbsp;alert("无法找到用户："+queryForm.id.value);<br />
&nbsp;&nbsp;return;<br />
}<br />
<br />
alert("找到用户，nid："+data.id+"，npassword："+data.password+"，nname："+data.name+"，nemail："+data.email);<br />
<br />
}<br />
<br />
function OnFind() {<br />
DWRUserAccess.find(queryForm.id.value, findFun); <br />
}<br />
//--&gt;<br />
&lt;/SCRIPT&gt;<br />
<br />
<br />
以下对页面的javascript进行解释<br />
<br />
&lt;script src="/oblog312/dwr/engine.js"&gt;&lt;/script&gt;<br />
&lt;script src="/oblog312/dwr/util.js"&gt;&lt;/script&gt;<br />
这两个是dwr提供的，用户可以不必关心，只需要导入即可<br />
<br />
&lt;script src="/oblog312/dwr/interface/DWRUserAccess.js"&gt;&lt;/script&gt;<br />
是我们编写的DWRUserAccess类，经dwr反射后，生成的javascript代码，它和DWRUserAccess.java是对应的，供用户调用，实际上我们就是通过这个js文件去调用服务器端的DWRUserAccess类的。<br />
<br />
&lt;SCRIPT LANGUAGE="JavaScript"&gt;<br />
&lt;!--<br />
function saveFun(data) {<br />
if (data) {<br />
&nbsp;&nbsp;alert("注册成功！");<br />
} else {<br />
&nbsp;&nbsp;alert("用户名已经存在！");<br />
}<br />
}<br />
<br />
function OnSave() {<br />
var userMap = {};<br />
userMap.id = regForm.id.value;<br />
userMap.password = regForm.password.value;<br />
userMap.name = regForm.name.value;<br />
userMap.email = regForm.email.value;<br />
DWRUserAccess.save(userMap, saveFun); <br />
}<br />
<br />
function findFun(data) {<br />
if (data == null) {<br />
&nbsp;&nbsp;alert("无法找到用户："+queryForm.id.value);<br />
&nbsp;&nbsp;return;<br />
}<br />
<br />
alert("找到用户，nid："+data.id+"，npassword："+data.password+"，nname："+data.name+"，nemail："+data.email);<br />
<br />
}<br />
<br />
function OnFind() {<br />
DWRUserAccess.find(queryForm.id.value, findFun); <br />
}<br />
//--&gt;<br />
&lt;/SCRIPT&gt;<br />
<br />
这段javascirpt代码，我们来看下OnSave函数，首先它构造一个map，将表单数据都设置到map中，然后调用DWRUserAccess.save(userMap, saveFun)，执行save操作。大家可以注意到，服务器端的DWRUserAccess中的save方法是这样的：boolean save(User user)，其参数是一个User对象，返回一个boolean值；而客户端的方法是这样的：save(userMap,saveFun)，第一个参数userMap是javascirpt中的map对象，在这里相当于服务器端的User对象（在服务器端执行时，会通过convert转换成User对象），前面我们提到dwr是利用回调函数来返回执行结果的，第二个参数saveFun即是一个回调函数。在函数function saveFun(data)中，data是执行结果，这里是一个bool值，非常简单的，我们通过判断data是否为真，可以知道用户名是否重复，用户是否注册成功。<br />
<br />
看一下OnFind查找函数，执行结果在回调函数findFun(data)中，因为服务器端返回的是一个User对象，通过convert，将会转换成javascript的一个map对象，<br />
于是在findFun中，通过data.id、data.name、data.password、data.email我们可以轻松的访问到这个User对象。<br />
<br />
<br />
好了配置完毕，启动服务器，在目录中打入localhost/testApp/test.html。<br />
<br />
1.在&#8220;用户注册&#8221;表单中，id框中输入admin，password中输入123456，name中输入chenbug，email中输入chenbug@zj.com，点击提交按钮，弹出对话框：&#8220;注册成功&#8221;，在服务器后台可以看到信息如下：<br />
<br />
下面开始保存用户<br />
id：admin<br />
password：123456<br />
name：chenbug<br />
email：chenbug@zj.com<br />
用户保存结束<br />
<br />
再次点击提交按钮，弹出对话框&#8220;登陆ID已经存在&#8221;。<br />
<br />
2.在&#8220;用户查询&#8221;对话框中，输入登陆ID为admin，点击提交按钮，提示找到用户，并显示相关信息，输入admin123，点击提交按钮，提示无法找到用户。<br />
<br />
至此，测试结束。<br />
<br />
<br />
后续：<br />
1。拦截器 uk.ltd.getahead.dwr.DWRServlet<br />
该类拦截所有指向dwr目录下的请求，并调用Processor的handler方法进行处理，在uk.ltd.getahead.dwr.impl.DefaultProcessor下，我们可以看到详细的处理过程。<br />
if (pathInfo.length() == 0 ||<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pathInfo.equals(HtmlConstants.PATH_ROOT) ||<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pathInfo.equals(req.getContextPath()))<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;resp.sendRedirect(req.getContextPath() + servletPath + HtmlConstants.FILE_INDEX);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;else if (pathInfo.startsWith(HtmlConstants.FILE_INDEX))<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;index.handle(req, resp);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;else if (pathInfo.startsWith(HtmlConstants.PATH_TEST))<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;test.handle(req, resp);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;else if (pathInfo.startsWith(HtmlConstants.PATH_INTERFACE))<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;iface.handle(req, resp);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;else if (pathInfo.startsWith(HtmlConstants.PATH_EXEC))<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;exec.handle(req, resp);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;else if (pathInfo.equalsIgnoreCase(HtmlConstants.FILE_ENGINE))<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;file.doFile(req, resp, HtmlConstants.FILE_ENGINE, HtmlConstants.MIME_JS);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;else if (pathInfo.equalsIgnoreCase(HtmlConstants.FILE_UTIL))<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;file.doFile(req, resp, HtmlConstants.FILE_UTIL, HtmlConstants.MIME_JS);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;else if (pathInfo.equalsIgnoreCase(HtmlConstants.FILE_DEPRECATED))<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;file.doFile(req, resp, HtmlConstants.FILE_DEPRECATED, HtmlConstants.MIME_JS);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;else<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;log.warn("Page not found (" + pathInfo + "). In debug/test mode try viewing /[WEB-APP]/dwr/"); //$NON-NLS-1$ //$NON-NLS-2$<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;resp.sendError(HttpServletResponse.SC_NOT_FOUND);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
通过判断request请求的servlet路径，进行处理，大家可以自己去参看，这里不详细讨论。<br />
<br />
<br />
2.bean转换器，&lt;convert converter="bean" match="test.User"/&gt;<br />
将dwr.jar解压缩，在路径ukltdgetaheaddwr下可以看到dwr.xml，这里配置了系统默认的一些转换器，<br />
&lt;converter id="bean" class="uk.ltd.getahead.dwr.convert.BeanConverter"/&gt;即是刚才用到User类的转换器，进入代码我们来看看它是如何在javascript和java间进行转换的。<br />
<br />
打开BeanConverter代码，定位到函数<br />
<br />
public Object convertInbound(Class paramType, InboundVariable iv, InboundContext inctx) throws ConversionException<br />
<br />
即是将javascript对象转换成java对象的，其中<br />
paramType即Class类型，在上面的例子中是test.User，<br />
InboundVariable iv，是传入的值，通过iv.getValue可以得到传入的javascript值串<br />
InboundContext inctx，是入口参数上下文，用于保存转换的后java对象。<br />
<br />
因为前台传入的是一个javascript的map类型，而map肯定是以{开始和以}结束的，于是在这个函数一开始进行了判断<br />
if (!value.startsWith(ConversionConstants.INBOUND_MAP_START))<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;throw new IllegalArgumentException(Messages.getString("BeanConverter.MissingOpener", ConversionConstants.INBOUND_MAP_START)); //$NON-NLS-1$<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (!value.endsWith(ConversionConstants.INBOUND_MAP_END))<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;throw new IllegalArgumentException(Messages.getString("BeanConverter.MissingCloser", ConversionConstants.INBOUND_MAP_START)); //$NON-NLS-1$<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
javascript中，map里各个项是用逗号连接的，如var userMap = {id:'admin',password:'123456',name:'chenbug',email:'chenbug@zj.com'};而每个项的键值对是用冒号连接的，<br />
在convertInbound函数的接下来的处理中，即是通过分析map字串，通过paramType构造java实例（即User类），然后通过反射，将这些键值对设置到java实例中，并返回。<br />
这样就完成了javascript到java的转换。<br />
<br />
<br />
另一个函数<br />
public String convertOutbound(Object data, String varname, OutboundContext outctx) throws ConversionException<br />
<br />
即是将java对象转换为javascript对象（其实是声明和赋值语句）。<br />
Object data ，是待转换的java对象<br />
String varname，是javascript中的该对象的变量名<br />
OutboundContext outctx，传出参数上下文，用于保存转换后的javascript值<br />
<br />
StringBuffer buffer = new StringBuffer();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;buffer.append("var "); //$NON-NLS-1$<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;buffer.append(varname);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;buffer.append("={};"); //$NON-NLS-1$<br />
这里声明了map类型的变量。<br />
<br />
即下来来的代码即是通过反射进行变量赋值，如下<br />
&nbsp;&nbsp;buffer.append(varname);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;buffer.append('.');<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;buffer.append(name);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;buffer.append('=');<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;buffer.append(nested.getAssignCode());<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;buffer.append(';');<br />
大家可以自己去参看更多的代码。<br />
<br />
3.dwr本身提供了一个测试环境，大家在配置完后，可以在IE中输入地址http://localhost/testApp/dwr/index.html，看到配置的各DWR组件，并进行相关测试。
<img src ="http://www.blogjava.net/Supershen/aggbug/176207.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/Supershen/" target="_blank">Super·shen BLOG </a> 2008-01-18 14:43 <a href="http://www.blogjava.net/Supershen/archive/2008/01/18/176207.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>