2008年3月2日
#
JavaScript中对正则表达式的支持
正则表达式在JS的最大用处就是验证表单字段,如验证数字,验证邮件和验证汉字等。
JavaScript中对正则表达式的支持是通过RegExp类实现的。你可以以如下方式建立一个正则表达式:
var regex=new RegExp("^[1-9]+\\d*$");
而验证的方法是regex.test(str),它返回str是否符合regex的结果。
JS中正则表达式和Java中的异同。
JavaScript
1.建立:
var regex=new RegExp("^[1-9]+\\d*$");
2.验证
return regex.test(str);
3.写法上,要验证字符串,JS中必须把起始符号^和结束符号$写全,否则就是包含验证而不是全匹配验证.除此外其它部分都是一致的.
Java
1.建立:
String regex="\\d*";
2.验证:
return Pattern.matches(regex,text);
3.写法上,JAVA中进行全匹配验证不需写全起始符号^和结束符号$.
一个完整的验证过程
表单元素:
<input type="text" name="positiveinteger"
value="1" />
表单提交之前的验证函数:
var positiveinteger=$("positiveinteger").value;
if(isPositiveInteger(positiveinteger)==false){
$("positiveinteger").focus();
$("checkMsg").innerHTML="正整数验证不通过";
return false;
}
else{
$("checkMsg").innerHTML="正整数验证通过";
}
验证函数:
function isPositiveInteger(str){
var regex=new RegExp("^[1-9]+\\d*$");
return regex.test(str);
}
常用验证函数
/**
* 正整数验证*/
function isPositiveInteger(str){
var regex=new RegExp("^[1-9]+\\d*$");
return regex.test(str);
}
/**
* 负整数验证
*/
function isNegativeInteger(str){
var regex=new RegExp("^-{1}\\d+$");
return regex.test(str);
}
/**
* 非负整数验证
*/
function isNonnegativeInteger(str){
var regex=new RegExp("^\\d+$");
return regex.test(str);
}
/**
* 整数验证
*/
function isInteger(str){
var regex=new RegExp("^-?\\d+$");
return regex.test(str);
}
/**
* 有理数验证
*/
function isRationalNumber(str){
var regex=new RegExp("^-?\\d+(\\.*)(\\d*)$");
return regex.test(str);
}
/**
* 英语字母验证
*/
function isLetter(str){
var regex=new RegExp("^[a-zA-Z]+$");
return regex.test(str);
}
/**
* 英数字验证
*/
function isLetterOrInteger(str){
var regex=new RegExp("^[a-zA-Z0-9]+$");
return regex.test(str);
}
/**
* 邮件验证
*/
function isEmail(str){
var regex=new RegExp("^\\w+([-+.]\\w+)*@\\w+([-.]\\w+)*\\.\\w+([-.]\\w+)*$");
return regex.test(str);
}
/**
* 汉字验证
*/
function isCharacter(str){
var regex=new RegExp("^[\u4E00-\u9FA5]+$");
return regex.test(str);
}
/**
* 货币验证
*/
function isCurrency(str){
return str.search("^\\d+(\\.\\d{0,2})*$")==0;
}
获取表单的引用
在开始对表单进行编程前,必须先获取表单<form>的引用.有以下方法可以来完成这一操作。
1)采用典型的DOM树中的定位元素的方法getElementById(),只要传入表单的id即可获得表单的引用:
var vform=document.getElementById(“form1”);
2)还可以用document的forms集合,并通过表单在form集合中的位置或者表单的name特性来进行引用:
var oform=document.forms[0];
var oform=document.forms[“formZ”];
访问表单字段
每个表单字段,不论它是按钮,文本框还是其它内容,均包含在表单的elements集合中.可以用它们的name特性或者它们在集合中的位置来访问不同的字段:
Var oFirstField=oForm.elements[0];
Var oTextBox1=oForm.elements[“textBox1”];
此外还可以通过名字来直接访问字段,如:
Var oTextBox1=oForm.textbox1;
如果名字中有标记,则可以使用方括号标记:
Var oTextBox1=oForm[“text box 1”];
最常见的访问表单字段的方法
最简单常用的访问表单元素的方法自然是document.getElementById(),举例如下:
<input type="text" name="count"
value="" />
在JS中取得此元素内容的代码为:
var name=document.getElementById("name").value
这种方法无论表单元素处于那个表单中甚至是不在表单中都能凑效,一般情况下是我们用JS访问表单元素的首选.
鉴于document.getElementById比较长,你可以用如下函数代替它:
function $(id){
return document.getElementById(id);
}
把这个函数放在共有JS库中,在jsp页面通过如下方法引用它:
<head>
<title>"記賬系统"添加资源页面</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<script src="web/js/check.js" type="text/javascript"></script>
<link rel="stylesheet" rev="stylesheet" href="web/css/style.css"
type="text/css" />
</head>
此后你就可以直接使用$访问表单元素中的内容:
var name=$("name").value;
表单字段的共性
以下是所有表单字段(除了隐藏字段)
Disabled可以用来获取或设置表单控件是否被禁用.
Form特性用来指向字段所在的表单.
Blur()方法使表单字段失去焦点.
Focus()方法使表单字段获得焦点.
当字段失去焦点是,发生blur事件,执行onblur事件处理程序.
当字段获取焦点时,发生focus事件,执行onfocus事件处理函数.
当页面载入时将焦点放在第一个字段
在body代码中如此书写:
<body onload=“focusOnFirstElm()”>
JS函数如下书写:
Fucntion focusOnFirstElm(){
document.forms[0].elements[0].focus();
}
如果第一个字段不是隐藏字段此方法就是凑效的,如果是的话把elements的下标改成非隐藏字段的下标即可.
控制表单只被提交一次
由于Web的响应问题,用户有可能会点击多次提交按钮从而创建重复数据或是导致错误,我们可以使用JS对提交按钮进行设置以让表单只被提交一次。
<input type=“submit” value=“提交” onclick=“this.disabled=true;this.form.submit()”/>
这里在点击提交按钮时执行了两句JS代码,一次是this.disabled=true;这是让提交按钮被禁用;一次是this.form.submit()这是提交这个按钮所在的表单。
检查用户在表单元素中的按键
为控件添加 onkeydown事件处理,然后在函数查看keyCode,就能知道用户的按键,代码如下:
<input type="text" name="test"
value="" onkeydown="testkey(this,event)"/>
JS代码如下:
function testkey(obj,event){
alert(event.keyCode);
}
这种技巧在改善用户体验如按回车键提交表单时很常用。
Servlet与JSP综合讲述
Servlet和JSP的概念
Servlet是Sun推出的用于实现CGI(通用网关接口)的java语言版本,它不但具有跨平台的特性,而且还以多线程的方式为用户提供服务而不必为每个请求都启动一个线程,因此其效率要比传统的CGI程序要高很多.
JSP和MS的ASP类似,它把JSP标签嵌入到HTML格式的网页中,这样对程序员和网页编辑人员都很方便,JSP天生就是为表现层设计的.
实际上,Servlet只是继承了HttpRequest的Java类,而JSP最终也会被Servlet引擎翻译成Servlet并编译执行,JSP的存在主要是为了方便表现层.
Servlet与JSP之间的区别,决定了Servlet与JSP在MVC构架模式中的不同角色.Servlet一般作为MVC中的控制器,JSP一般作为MVC中的视图.
Servlet的生命周期
Servlet有三个生命周期:初始化,执行和结束,它们分别对应Servlet接口中的init,service和destroy三个函数.
初始化时期:当servlet被servlet容器(如tomcat)载入后,servlet的init函数就会被调用,在这个函数可以做一些初始化工作.init函数只会在servlet容器载入servlet执行一次,以后无论有多少客户端访问这个Servlet,init函数都不会被执行.
执行期:servlet采用多线程方式向客户提供服务,当有客户请求来到时, service会被用来处理它.每个客户都有自己的service方法,这些方法接受客户端请求,并且发挥相应的响应.程序员在实现具体的Servlet时,一般不重载service方法,服务器容器会调用service方法以决定doGet,doPost,doPut,doDelete中的一种或几种,因此应该重载这些方法来处理客户端请求.]
结束期:该时期服务器会卸载servlet,它将调用destroy函数释放占用的资源,注意Web服务器是有可能崩溃的,destroy方法不一定会被执行.
如何开发和部署一个Servlet
1)从java.servlet.http.HttpServlet继承自己的servlet类.
2)重载doGet或doPost方法来处理客户请求(一般是doPost,其安全性较好),如果要在加载Servlet时被加载时进行初始化操作,可以重载init方法.
3)在web.xml中配置这个servlet.其中servlet-class用来制定这个servlet的类全名,servlet-name用来标识这个servlet,它可以是任意的字符串,不一定要和类文件名一致.url-pattern用来表示servlet被映射到的url模式.
<!– Servlet在Web.xml中的配置示例 -->
<servlet>
<servlet-name>ShowPageServlet</servlet-name>
<servlet-class>
com.sitinspring.action.ShowPageServlet
</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>ShowPageServlet</servlet-name>
<url-pattern>/ShowPage</url-pattern>
</servlet-mapping>
开发一个启动时就被执行的Servlet
一般的Servlet都是在有来自客户端请求时才会执行,要让它在启动时就执行需要在配置中进行一些特殊设置,如右.
右边的代码中, load-on-startup说明了服务器一启动就加载并初始化它,0代表了加载它的优先级,注意它必须是一个正数,而且值小的要比值大的先加载.debug制定输出调试信息的级别,0为最低.
这样的servlet在用于读取WebApp的一些初始化参数很有用处,如取得配置文件的地址,设置log4j和得到WebApp的物理路径等.右边配置的servlet就是用来初始化log4j的.
<!-- InitServlet -->
<servlet>
<servlet-name>log4j-init</servlet-name>
<servlet-class>
com.sitinspring.action.Log4jInit
</servlet-class>
<init-param>
<param-name>log4j</param-name>
<param-value>WEB-INF/classes/log4j.properties</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
Serlet中出现的线程不安全的问题
Servlet是运行在多线程的服务器上的,它对每个用户的请求创建的是线程而不是进程,因此在高效的同时也带来了数据同步和一致性的问题.
服务器值实例化一个Servlet/JSP实例,然后在多个处理线程中调用该实例的相关方法来处理请求,因此servlet的成员变量可能会被多个线程调用该实例的相关方法改变,将有可能带来问题.这也是大家在众多的Servlet中很少看到成员变量的原因.

public class ThreadUnsafeServlet extends HttpServlet {
private String unsafeString="";
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, java.io.IOException {
request.setCharacterEncoding("UTF-8");
unsafeString=request.getParameter("str");
try{
Thread.sleep(5000);
}
catch(Exception ex){
ex.printStackTrace();
}
PrintWriter out=response.getWriter();
out.println(unsafeString);
}
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, java.io.IOException {
doPost(request, response);
}
}
关于重定向的两种方法
在servlet中,重定向一般是通过HttpResponse的sendRedirect()方法或RequestDispatcher的forward方法来实现的.
sendRedirect的参数可以是相对或绝对地址,如果以/开头容器将认为相对于当前Web引用的根.这种请求将导致客户端浏览器请求URL跳转,而且从Browser的地址栏中可以看到新的Url地址.另外使用这个方法时,前一个页面的状态不会被带到下一个页面,通过request.getAttribute(“XXXX”)方法将得到空值.
RequestDispatcher是一个Web资源的包装器,可以用来把当前请求传递到该资源,而且客户端浏览器的地址栏也不会显示为转向后的地址.另外此方法还可以将请求发送到任意一个服务器资源.
如果两种方法都能达到要求,最好使用forward方法,它比sendRedirect安全而高效.
获取当前绝对路径
Servlet/JSP有时需要对拥有的资源进行操作,这就要求得到它们所在的绝对路径.此时可以使用ServletContext接口提供的方法来得到当前应用所在的绝对路径,代码如下:
ServletContext sct = getServletContext();
String realPath=sct.getRealPath("/");
注: ServletContext 用于Servlet和Servlet容器交换信息.
XML的由来
XML是eXtensible Markup Language的缩写。扩展标记语言XML是一种简单的数据存储语言,使用一系列简单的标记描述数据,而这些标记可以用方便的方式建立,虽然XML占用的空间比二进制数据要占用更多的空间,但XML极其简单易于掌握和使用
XML是现代程序中一个必不可少的组成部分,也是世界上发展最快的技术之一。它的主要目的是以结构化的方式来表示数据,在某些方面,XML也类似于数据库,提供数据的结构化视图。
XML(可扩展标记语言)是从称为SGML(标准通用标记语言)发展而来的,SGML的主要目的是定义使用标签来表示数据的标记语言的语法。基于SGML的重要语言之一就是著名的HTML.
标签由包围在一个小于号<和一个大于号>之间的文本组成,起始标签(tag)表示一个特定区域的开始,例如<start>;结束标签定义了一个区域的结束,除了在小于号之后紧跟一个斜线外和起始标签一致,例如</end>.举例说明标签如下:
<member id=“007”>邦德</member>中,左边的<member id=“007”>是起始标签,邦德是标签中的文字,007是属性Attribute, </member >是结束标签.
XML的发展
由于SGML中存在特殊而随意的语法(如标签的非嵌套使用),使得建立一个SGML语言的解析器成了一项艰巨的任务,这些困难导致了SGML一直停步不前.
XML通过相对严格的语法规定使得建立一个XML解析器要容易得多,这些语法包括:
1)任何起始标签都必须有一个结束标签。
2)可以采用另一种简化语法,可以在一个标签中同时表示起始和结束标签。这种语法是在大于符号前紧跟一个斜线/.如<tag />等同于<tag></tag>.
3)标签必须按照合适的顺序进行嵌套,在没有关闭内部节点之前不能关闭外部节点。
4)所有的特性都必须有值,特性的值周围应该加上双引号。
XML文档示例
<?xml version="1.0" encoding="GBK"?>
<members>
<member name="Andy">
<age>25</age>
<title>JSE</title>
</member>
<member name="Bill">
<age>35</age>
<title>SSE</title>
</member>
<member name="Cindy">
<age>45</age>
<title>PM</title>
</member>
<member name="Douglas">
<age>45</age>
<title>GM</title>
</member>
</members>
<?xml version=“1.0” encoding=“GBK”?>是XML序言,这一行代码告诉解析器文件将按XML规则进行解析, GBK制定了此文件的编码方式。
<members>是文档的根节点,一个XML中有且只有一个根节点,否则会造成解析失败。
<member name=“Andy”>。。。</member>是根节点下面的子节点,name是其特性,特性的值为Andy。这个子节点下面有age和title两个子节点。
XML的用途
以文本的形式存储数据,这样的形式适于机器阅读,对于人阅读也相对方便.
作为程序的配置文件使用,如著名的web.xml,struts-config.xml
Ajax程序传递数据的载体.
WebService,SOAP的基础.
针对XML的API
将XML定义为一种语言之后,就出现了使用常见的编程语言(如Java)来同时表现和处理XML代码的需求。
首先出现的是Java上的SAX(Simple API for XML)项目。SAX提供了一个基于事件的XML解析的API。从其本质上来说,SAX解析器从文件的开头出发,从前向后解析,每当遇到起始标签或者结束标签、特性、文本或者其他的XML语法时,就会触发一个事件。然后,当事件发生时,具体要怎么做就由开发人员决定。
因为SAX解析器仅仅按照文本的方式来解析它们,所以SAX更轻量、更快速。而它们的主要缺点是在解析中无法停止、后退或者不从文件开始,直接访问XML结构中的指定部分。
DOM是针对XML的基于树的API。它关注的不仅仅是解析XML代码,而是使用一系列互相关联的对象来表示这些代码,而这些对象可以被修改且无需重新解析代码就能直接访问它们。
使用DOM,只需解析代码一次来创建一个树的模型;某些时候会使用SAX解析器来完成它。在这个初始解析过程之后,XML已经完全通过DOM模型来表现出来,同时也不再需要原始的代码。尽管DOM比SAX慢很多,而且,因为创建了相当多的对象而需要更多的开销,但由于它使用上的简便,因而成为Web浏览器和JavaScript最喜欢的方法。
最方便的XML解析利器-dom4j
Dom4j是一个易用的、开源的库,用于XML,XPath和XSLT。它应用于Java平台,采用了Java集合框架并完全支持DOM,SAX和JAXP.
sax和dom本身的api都比较复杂,不易使用,而开源包dom4j却综合了二者的优点,屏蔽了晦涩的细节,封装了一系列类和接口以方便用户使用它来读写XML.
Dom4j下载
要使用dom4j读写XML文档,需要先下载dom4j包,dom4j官方网站在 http://www.dom4j.org/ 目前最新dom4j包下载地址:http://nchc.dl.sourceforge.net/sourceforge/dom4j/dom4j-1.6.1.zip
解开后有两个包,仅操作XML文档的话把dom4j-1.6.1.jar加入工程就可以了,如果需要使用XPath的话还需要加入包jaxen-1.1-beta-7.jar.
使用dom4j读写xml的一些常用对象
1.Document:文档对象,它代表着整篇xml文档.
2.Element:节点元素,它代表着xml文档中的一个节点元素,如前面的<age>25</age>就是一个Element.其值(文本值)为25.
3.Attribute:节点属性,如前面的节点元素<member name=“Andy”>…< /member >中, name就是节点元素的一个属性,其值(文本值)为Andy.
与Document对象相关的API
1.读取XML文件,获得document对象.
SAXReader reader = new SAXReader();
Document document = reader.read(new File("input.xml"));
2.解析XML形式的文本,得到document对象.
String text = "<members></members>";
Document document = DocumentHelper.parseText(text);
3.主动创建document对象.
Document document = DocumentHelper.createDocument();
Element root = document.addElement("members");// 创建根节点
与Element有关的API
1.获取文档的根节点.
Element rootElm = document.getRootElement();
2.取得某节点的单个子节点.
Element memberElm=root.element(“member”);// “member”是节点名
3.取得节点的文字
String text=memberElm.getText();
也可以用:
String text=root.elementText("name");这个是取得根节点下的name字节点的文字.
4.取得某节点下名为"member"的所有字节点并进行遍历.
List nodes = rootElm.elements("member");
for (Iterator it = nodes.iterator(); it.hasNext();) {
Element elm = (Element) it.next();
// do something
}
5.对某节点下的所有子节点进行遍历.
for(Iterator it=root.elementIterator();it.hasNext();){
Element element = (Element) it.next();
// do something
}
6.在某节点下添加子节点.
Element ageElm = newMemberElm.addElement("age");
7.设置节点文字.
ageElm.setText("29");
8.删除某节点.
parentElm.remove(childElm);// childElm是待删除的节点,parentElm是其父节点
与Attribute相关的API
1.取得某节点下的某属性
Element root=document.getRootElement();
Attribute attribute=root.attribute("size");// 属性名name
2.取得属性的文字
String text=attribute.getText();
也可以用:
String text2=root.element("name").attributeValue("firstname");这个是取得根节点下name字节点的属性firstname的值.
3.遍历某节点的所有属性
Element root=document.getRootElement();
for(Iterator it=root.attributeIterator();it.hasNext();){
Attribute attribute = (Attribute) it.next();
String text=attribute.getText();
System.out.println(text);
}
4.设置某节点的属性和文字.
newMemberElm.addAttribute("name", "sitinspring");
5.设置属性的文字
Attribute attribute=root.attribute("name");
attribute.setText("sitinspring");
6.删除某属性
Attribute attribute=root.attribute("size");// 属性名name
root.remove(attribute);
将document的内容写入XML文件
1.文档中全为英文,不设置编码,直接写入的形式.
XMLWriter writer = new XMLWriter(new FileWriter("output.xml"));
writer.write(document);
writer.close();
2.文档中含有中文,设置编码格式写入的形式.
OutputFormat format = OutputFormat.createPrettyPrint();
format.setEncoding("GBK"); // 指定XML编码
XMLWriter writer = new XMLWriter(new FileWriter("output.xml"),format);
writer.write(document);
writer.close();
字符串与XML的转换
1.将字符串转化为XML
String text = "<members> <member>sitinspring</member> </members>";
Document document = DocumentHelper.parseText(text);
2.将文档或节点的XML转化为字符串.
SAXReader reader = new SAXReader();
Document document = reader.read(new File("input.xml"));
Element root=document.getRootElement();
String docXmlText=document.asXML();
String rootXmlText=root.asXML();
Element memberElm=root.element("member");
String memberXmlText=memberElm.asXML();
使用XPath快速找到节点.
读取的XML文档示例
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>MemberManagement</name>
<comment></comment>
<projects>
<project>PRJ1</project>
<project>PRJ2</project>
<project>PRJ3</project>
<project>PRJ4</project>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.jdt.core.javanature</nature>
</natures>
</projectDescription>
使用XPath快速找到节点project.
public static void main(String[] args){
SAXReader reader = new SAXReader();
try{
Document doc = reader.read(new File("sample.xml"));
List projects=doc.selectNodes("/projectDescription/projects/project");
Iterator it=projects.iterator();
while(it.hasNext()){
Element elm=(Element)it.next();
System.out.println(elm.getText());
}
}
catch(Exception ex){
ex.printStackTrace();
}
}