2006年5月24日
1.index.html
<iframe id="mainIframe" scrolling="no" frameborder="0" width="100%" src="a.html"></iframe>
<a href="#" onclick="page('a.html')">a頁面</a><a href="#" onclick="page('b.html')">b頁面</a>
2 a.html //內(nèi)嵌頁面
<script language="javascript">
changeHight();
</script>
3. b.html //內(nèi)嵌頁面
<script language="javascript">
changeHight();
</script>
4. page.js
function changeHight(){
var iFrm = parent.document.getElementById("mainIframe");
var subWeb = iFrm.contentDocument;
if(subWeb){
if (subWeb.body.scrollHeight>480)
iFrm.height = subWeb.body.scrollHeight+20;
else
iFrm.height=500;
}
if(top.document.frames["mainIframe"].document && window.document.body.scrollHeight!="0"){
parent.document.getElementById("mainIframe").style.height=window.document.body.scrollHeight;
}
if(top.document.frames["mainIframe"].document && window.document.body.scrollHeight=="0"){
parent.document.getElementById("mainIframe").style.height=500;
}
}
function page(page){
document.getElementById("mainIframe").src=page;
}
造成IE,FireFox,Opera中Iframe顯示差異原因在于
1.iframe在FireFox中取法為parent.document.getElementById("mainIframe").contentDocument,而在ie,opera中為parent.document.getElementById("mainIframe").document
2.當(dāng)頁面無滾動(dòng)時(shí),window.document.body.scrollHeight在IE中能取到,fireFox和Opera中取不到。
摘要: 1.myapp/index.html
<html>
<head>
文件操作
<iframe id="iframefile" scrolling="no" frameborder="0" width="100%" src="/myapp/fileUpload.jsp"></iframe>
&l...
閱讀全文
一些頻繁使用的javascript頁面控制,做個(gè)總結(jié)。
下面是部分代碼。
<html>
<head>
<script language="javascript">
function a(){
window.document.getElementsByName("dx")[0].checked=true;
}
function b(){
window.document.getElementsByName("dx")[0].checked=false;
}
function c(){
window.document.getElementsByName("fx")[0].checked=true;
}
function d(){
window.document.getElementsByName("fx")[0].checked=false;
}
function e(){
for(i=0;i<window.document.getElementsByName("fx").length;i++){
if(!window.document.getElementsByName("fx")[i].checked){
window.document.getElementsByName("fx")[i].checked=true;
}
}
}
function f(){
for(i=0;i<window.document.getElementsByName("fx").length;i++){
if(window.document.getElementsByName("fx")[i].checked){
window.document.getElementsByName("fx")[i].checked=false;
}
}
}
function g(){
window.document.getElementById("lbka")[1].selected=true;
}
function h(){
alert("選擇號(hào)為:"+window.document.getElementById("lbka").selectedIndex + " 值為:" +window.document.getElementById("lbka")[window.document.getElementById("lbka").selectedIndex].value+" 文本值為:" + window.document.getElementById("lbka")[window.document.getElementById("lbka").selectedIndex].text);
}
function m(){
sel = false;
var val="";
for(i=0;i<window.document.getElementsByName("dx").length;i++){
if(window.document.getElementsByName("dx")[i].checked){
val = window.document.getElementsByName("dx")[i].value;
sel=true;
break;
}
}
if(sel){
alert("單選值為:"+val);
}else{
alert("請(qǐng)選擇文件");
return false;
}
}
function j(){
var sel = false;
var val="";
for(i=0;i<window.document.getElementsByName("fx").length;i++){
if(window.document.getElementsByName("fx")[i].checked){
if(val==""){
val=window.document.getElementsByName("fx")[i].value;
}else{
val = val + "," +window.document.getElementsByName("fx")[i].value;
}
}
}
if(val==""){
alert("請(qǐng)選擇文件");
return false;
}else{
alert("復(fù)選值為:"+val);
}
}
</script>
</head>
<body>
<table id="table1" width="100%" border="1" align="center" cellpadding="0" cellspacing="0">
<tr>
<td>文件</td>
<td>列表框</td>
<td>單選</td>
<td>復(fù)選</td>
</tr>
<tr>
<td>文件A</td>
<td><select name="lbka"><option value="lbka1">文件A1</option><option value="lbka2">文件A2</option></select></td>
<td><input type="radio" name="dx" value="dxa"></td>
<td><input type="checkbox" name="fx" value="fxa"></td>
</tr>
<tr>
<td>文件B</td>
<td><select name="lbkb"><option value="lbkb1">文件B1</option><option value="lbkb2">文件B2</option></select></td>
<td><input type="radio" name="dx" value="dxb"></td>
<td><input type="checkbox" name="fx" value="fxb"></td>
</tr>
<tr>
<td colspan="4">
<a href="#" onclick="a();">單選A選中</a>
<a href="#" onclick="b();">單選A不選中</a>
<a href="#" onclick="c();">復(fù)選A選中</a>
<a href="#" onclick="d();">復(fù)選A不選中</a>
<a href="#" onclick="e();">復(fù)選全選</a>
<a href="#" onclick="f();">復(fù)選全不選</a>
<a href="#" onclick="g();">選中列表框文件A2</a>
<a href="#" onclick="h();">取得選中列表框A的值,文本</a>
<a href="#" onclick="m();">判斷單選選擇</a>
<a href="#" onclick="j();">判斷復(fù)選選擇</a>
</td>
</tr>
</table>
</body>
</html>
主要通過javascript實(shí)現(xiàn),理解IE的DOM結(jié)構(gòu),并調(diào)用元素的固定方法,可以實(shí)現(xiàn)表單元素的動(dòng)態(tài)增刪。
下面是部分代碼。
<html>
<head>
<script language="javascript">
function add(){
//取得表格
var table = document.getElementById("table1");
//取得行數(shù);
var num = table.rows.length;
//增加一行
var newrow1 = table.insertRow(num-1);
var cell1 = newrow1.insertCell();
var cell2 = newrow1.insertCell();
var cell3 = newrow1.insertCell();
var cell4 = newrow1.insertCell();
//增加行元素
var inputcell2 = document.createElement("<input size='32' name=''>");
cell2.appendChild(inputcell2);
var inputcell4_1 = document.createElement("<input size='32' name=''>");
var inputcell4_2 = document.createElement("<input type='button' value='刪除元素'onClick='del(this);'/>");
cell4.appendChild(inputcell4_1);
cell4.appendChild(inputcell4_2);
//刷新標(biāo)簽顯示
frash();
}
function del(obj){
//取得按鈕所在行
var i = obj.parentNode.parentNode.rowIndex;
var tab = document.getElementById("table1");
//刪除按鈕所在行
tab.deleteRow(i-1);
frash();
}
function frash(){
var table = document.getElementById("table1");
var num = table.rows.length;
//計(jì)算動(dòng)態(tài)元素個(gè)數(shù)
var n = num-2;
for(i=1;i<=n;i++){
//設(shè)置標(biāo)簽值
table.rows[i].cells[0].innerText="元素"+i+"屬性A";
//設(shè)置屬性值
table.rows[i].cells[1].childNodes[0].setAttribute("name","ysa"+i);
table.rows[i].cells[2].innerText="元素"+i+"屬性B";
table.rows[i].cells[3].childNodes[0].setAttribute("name","ysb"+i);
}
}
</script>
</head>
<body>
<table id="table1" width="100%" border="1" align="center" cellpadding="0" cellspacing="0">
<tr>
<td>標(biāo)簽1</td>
<td><input name="a"></td>
<td>標(biāo)簽2</td>
<td><input name="b"></td>
</tr>
<tr>
<td colspan="4" align="center"><a href="#" onclick="add();">增加元素</a></td>
</tr>
</table>
</body>
</html>
頁面打印通常直接調(diào)用IE中打印命令,并通過class控制打印范圍。當(dāng)頁面文件內(nèi)容過多,無法完整打印時(shí),可以通過javascript控制縮放實(shí)現(xiàn)完整打印。
下面是部分代碼。
<
html>
<head>
<title>***上海市眼病防治中心病人結(jié)帳費(fèi)用報(bào)表***</title>
<meta http-equiv="Content-Type" content="text/
html; charset=gb2312">
<!--media=print 這個(gè)屬性可以在打印時(shí)有效-->
<style media=print>
.Noprint{display:none;}
.PageNext{page-break-after: always;}
</style>
<style>
body,td,th
{
font-size: 12px;
}
.tdp
{
border-bottom: 1 solid #000000;
border-left: 1 solid #000000;
border-right: 0 solid #ffffff;
border-top: 0 solid #ffffff;
}
.tabp
{
border-color: #000000;
border-collapse:collapse;
}
.NOPRINT {
font-family: "宋體";
font-size: 12px;
}
</style>
<script language="javascript">
var i=0;
function zoomL(){
i++;
document.getElementById("f").style.zoom=1+i/3;
}
function zoomS(){
i--;
document.getElementById("f").style.zoom=1+i/3;
}
</script>
</head>
<body >
<OBJECT id=WebBrowser classid=CLSID:8856F961-340A-11D0-A96B-00C04FD705A2 height=0 width=0 V
IEWASTEXT> </OBJECT>
<input type=button value=打印 onclick="document.all.WebBrowser.ExecWB(6,1)" class="NOPRINT">
<input type=button value=直接打印 onclick="document.all.WebBrowser.ExecWB(6,6)" class="NOPRINT">
<input type=button value=頁面設(shè)置 onclick="document.all.WebBrowser.ExecWB(8,1)" class="NOPRINT">
<input type=button value=打印預(yù)覽 onclick="document.all.WebBrowser.ExecWB(7,1)" class="NOPRINT">
<input type=button value=放大 onclick="zoomL();" class="NOPRINT">
<input type=button value=縮小 onclick="zoomS();" class="NOPRINT">
<br/>
<table width="90%" border="0" align="center" cellpadding="0" cellspacing="0">
<tr align="center">
<td colspan="5"><font size="3">上海市眼病防治中心病人結(jié)帳費(fèi)用報(bào)表(A) </font></td>
</tr>
<tr>
<td>匯總?cè)舜?5</td>
<td>費(fèi)用合計(jì) 15853.12</td>
<td>統(tǒng)計(jì)日期 </td>
<td>制表人 023</td>
<td>制表日期:2004-05-13</td>
</tr>
</table>
<table width="90%" border="1" align="center" cellpadding="2" cellspacing="0" bordercolor="#000000" class="tabp" id="f">
<tr>
<td >姓名</td>
<td >住院號(hào)</td>
<td >科室</td>
<td >結(jié)帳日期</td>
<td >出院日期</td>
<td >費(fèi)用合計(jì)</td>
<td >醫(yī)保交易費(fèi)用</td>
<td >分類給付費(fèi)用</td>
<td >非醫(yī)保交易費(fèi)</td>
</tr>
<tr>
<td > </td>
<td > </td>
<td > </td>
<td > </td>
<td > </td>
<td > </td>
<td > </td>
<td > </td>
<td > </td>
</tr>
</table>
<hr align="center" width="90%" size="1" n
oshade class="NOPRINT" >
<!--分頁-->
<div class="PageNext"></div>
<table width="90%" border="1" align="center" cellpadding="2" cellspacing="0" bordercolor="#000000" class="tabp">
<tr>
<td >第2頁</td>
</tr>
<tr>
<td >看到分頁了吧</td>
</tr>
<tr>
<td > </td>
</tr>
<tr>
<td > </td>
</tr>
<tr>
<td ><table width="100%" border="0" cellspacing="0" cellpadding="0">
<tr>
<td width="50%" >這樣的報(bào)表
對(duì)一般的要求就夠了。</td>
<td> </td>
</tr>
</table></td>
</tr>
</table>
<table width="780%" border="1" class="Noprint">
<tr>
<td>能不能打印</td>
</tr>
</table>
</body>
</
html>
思路是把表單類型設(shè)置為enctype="multipart/form-data",其他表單中文本數(shù)據(jù)通過javascript處理,附加在action后面,后臺(tái)通過request.getParameter()取得。上傳文件調(diào)用commons-fileupload.jar中方法。
下面是部分代碼。
<form name="ajform" action="/da.do" method="post" enctype="multipart/form-data">
<tr><td><input name="a" value=""></td></tr>
<tr><td><input name="b" type="file"></td></tr>
<tr><td><a href="#" onclick="checksubmit();">提交</a></td></tr>
</form>
<script language="javascript">
function checksubmit(){
var value = "/da.do?formAction=save";
value = value+"&a="+ window.document.getElementById("a").value;
window.document.ajform.action=value;
window.document.ajform.submit();
}
</script>
String a = request.getParameter("a");
try {
//文件上傳目錄“/file/wj”
String filepath= request.getSession().getServletContext().getRealPath("/")+"file"+File.separator+"wj";
//文件上傳臨時(shí)目錄“/file/temp”
String tempPath = request.getSession().getServletContext().getRealPath("/")+"file"+File.separator+"temp";
File dir = new File(filepath);
//建立目錄
if(!dir.exists()){
dir.mkdirs();
}
File dir1 = new File(tempPath);
if(!dir1.exists()){
dir1.mkdirs();
}
DiskFileUpload fu = new DiskFileUpload();
//設(shè)置最大文件尺寸,這里是10MB
fu.setSizeMax(10485760);
//設(shè)置緩沖區(qū)大小,這里是4kb
fu.setSizeThreshold(4096);
//設(shè)置臨時(shí)目錄:
fu.setRepositoryPath(tempPath);
List fileItems = fu.parseRequest(request);
Iterator iter = fileItems.iterator();
while (iter.hasNext()) {
FileItem item = (FileItem) iter.next();
String fileName = item.getName();
//判斷是否為文件
if(fileName!=null){
//取文件名
String name = fileName.substring(fileName.lastIndexOf(File.separator)+1);
if(fileName!=null&& !fileName.equals("")) {
File file = new File(filepath+File.separator+name);
//上傳文件
item.write(file);
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
<html>
<head>
</head>
<body>
<embed height=240 name=aa style="BORDER-BOTTOM:#2a8a21 3px solid;BORDER-LEFT:#2a8a21 3px ?solid;BORDER-RIGHT:#2a8a21 3px solid;BORDER-TOP:#2a8a21 3px solid"
?type=audio/x-pn-realaudio-plugin width=320 loop="no" console="clip1" reset="false"
?controls="ImageWindow" src="a1.rmvb">
</embed><br>
<embed height=30 type=audio/x-pn-realaudio-plugin width=320? console="clip1"? reset="false" autostart="false" controls="controlpanel">
</embed><br>
<embed height=30 type=audio/x-pn-realaudio-plugin width=320? console="clip1"? reset="false" autostart="false" controls="statusbar">
</embed><br>
<Script Language=JavaScript>
function OpenFile(txt){
?document.aa.src=txt.value;
}
</Script>
</body>
</html>
1。EJB打包
<?xml version="1.0"?>
<project name="jartest" default="jar" basedir=".">
<property name="build.dir" value="${basedir}/build" />
<property name="build.classes.dir" value="${build.dir}/classes" />
<target name="jar" description="打包成Jar">
<jar jarfile="${basedir}/ejbfile.jar">
<fileset dir="${build.classes.dir}">
<include name="**/*.class" />
</fileset>
<metainf dir="${basedir}/META-INF ">
<include name="**" />
</metainf>
</jar>
</target>
</project>
2。web應(yīng)用打包
<?xml version="1.0"?>
<project name="wartest" default="war" basedir=".">
<target name="war" description="創(chuàng)建WEB發(fā)布包">
<war warfile="${basedir}/EJBTest.war" webxml="${basedir}/WEB-INF/web.xml">
<fileset dir="${basedir}">
<include name="**"/>
<exclude name="build.xml" />
<exclude name="/WEB-INF/web.xml" />
</fileset>
</war>
</target>
</project>
1.web.xml中配置Spring的servlet和servlet-mapping
???<servlet>
??????? <servlet-name>example</servlet-name>
??????? <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
????????<init-param>?
????????????<param-name>contextConfigLocation</param-name>?
????????????<param-value>/WEB-INF/application-servlet.xml</param-value>?
????????</init-param>?
????????<load-on-startup>1</load-on-startup>
??? </servlet>
??? <servlet-mapping>
??????? <servlet-name>example</servlet-name>
??????? <url-pattern>*.do</url-pattern>
??? </servlet-mapping>
2.配置spring配置文件application-servlet.xml
???<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
?????<property name="prefix">
?????????<value>/page/</value>
?????</property>
?????<property name="suffix">
?????????<value>.jsp</value>
?????</property>
???</bean>
???<bean id="urlMapping"?class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
????????<property name="mappings">
????????????<props>
????????????????<prop key="/login.do">loginAction</prop>
????????????</props>
????????</property>
???</bean>
???<bean id="loginAction" class="loginAction">
????????<property name="commandClass">
????????????<value>?LoginActionVo??</value>
????????</property>
????????<property name="formView">
????????????<value>login</value>
????????</property>
????????<property name="sessionForm">
????????????<value>true</value>
????????</property>
????????<property name="serviceLocator">
????????????<ref bean="servicelocator" />
????????</property>
?</bean>
3.新建類繼承SimpleFormController﹐並複寫protected Object formBackingObject(HttpServletRequest request)?和?protected ModelAndView onSubmit(HttpServletRequest request,?HttpServletResponse response,
?Object cmd, BindException ex)。常用結(jié)構(gòu)為
???protected Object formBackingObject(HttpServletRequest request){
??????LoginActionVo??loginActionVo?? = new LoginActionVo?();
??????request.setAttribute("?loginActionVo",?loginActionVo);
??????return loginActionVo;
???}
???protected ModelAndView onSubmit(HttpServletRequest request,?HttpServletResponse response,
???????Object cmd, BindException ex){
??????LoginActionVo??loginActionVo =(LoginActionVo)cmd;
??????Map map = new HashMap();
?????map.put("?loginActionVo",?loginActionVo);
?????request.getSession().setAttribute(this.getFormSessionAttributeName(),?loginActionVo);
?????return new ModelAndView("login",map);
? }
4.將jsp頁面參數(shù)和VO進(jìn)行綁定。綁定的方法為頁面元素name和VO對(duì)象對(duì)應(yīng)﹐當(dāng)進(jìn)行深層次的綁定時(shí)﹐要注意﹐在變量的get方法中進(jìn)行初始化。在servlet2.4容器中可以不用c:out標(biāo)籤
輸入框綁定﹕<input name="user.name"? value = "<c:out value="${loginActionVo.user.name}"/>" type="text" disabled="disabled"? size="14" maxlength="14" /></td>
VO為﹕
?public class loginActionVo{
????private User user;
????public?User getUser(User user){
??????if( user == null){
?????????user = new User();
??????}
??????return user;
???}
?}
???
以SimpleFormController為例
1。spring 接收一個(gè)請(qǐng)求後首先會(huì)判斷"get"還是"post"方法
2。1 "get"方法時(shí)
?????????2。1。1 首先創(chuàng)建一個(gè)command對(duì)象﹐通過調(diào)用AbstractFormController的formBackingObject方法得到﹐通常是一個(gè)pojo﹐根據(jù)name用來和提交的數(shù)據(jù)綁定。
????????? 2。1。2 然後會(huì)創(chuàng)建一個(gè)BindException對(duì)象﹐裡面包括command對(duì)象﹐和其他一些屬性。
???????????2。1。3 判斷sessionForm 屬性﹐默認(rèn)為false。如果為true﹐就會(huì)把command對(duì)象對(duì)象保存在session裡???? 面。session中key為類名+".FORM." + command對(duì)象名。可以通過request.getSession().getAttribute(this.getFormSessionAttributeName(request));得到command對(duì)象。
??????
???2。1。4 調(diào)用AbstractFormController的referenceData方法。這個(gè)方法默認(rèn)為空﹐可以復(fù)寫來初始化頁面參數(shù)。
2。1。5 返回ModelAndView對(duì)象﹐返回formview頁面。
2 。2 “post”方法時(shí)
???2。2。1 首先得到command對(duì)象,如果SessionForm = false﹐調(diào)用formBackingObjectde創(chuàng)建
?????????????????????如果SessionForm = true,從request.getSession中得到原command對(duì)象﹐然後將command對(duì)象從
?????????????????????Session中刪除。
? 2。2。2? 然後會(huì)創(chuàng)建一個(gè)ServletRequestDataBinder對(duì)象﹐裡面包括command對(duì)象﹐和其他一些屬性。
???????????????????這個(gè)過程將調(diào)用initBinder()﹔可以複寫這個(gè)方法初始化數(shù)據(jù)。
?2。2。3 調(diào)用processFormSubmission(HttpServletRequest request, HttpServletResponse response, Object command,? BindException errors)。有錯(cuò)誤時(shí)返回formview頁面﹐否則進(jìn)入successview頁面。這個(gè)過程將調(diào)用onSubmit(Object command)﹐必須複寫這個(gè)方法放入業(yè)務(wù)邏輯。
?
???
1./WEB-INF/web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.4"
?xmlns="?xmlns:xsi="?xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
?<!--
<!DOCTYPE web-app
??? PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
??? "<web-app>
-->
?
?<!--
?<context-param>
??? ?<param-name>contextConfigLocation</param-name>
??? ?<param-value>/WEB-INF/application-servlet.xml</param-value>
? ?</context-param>
?<listener>
???? <listener-class>
?????? org.springframework.web.context.ContextLoaderListener
???? </listener-class>
? ?</listener>
? ?-->
?<servlet>
??????? <servlet-name>hello</servlet-name>
??????? <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>??
??<init-param>
????????? <param-name>contextConfigLocation</param-name>
????????? <param-value>/WEB-INF/application-servlet.xml</param-value>
???? ?</init-param>
??<load-on-startup>1</load-on-startup>
??? </servlet>
?
??? <servlet-mapping>
??????? <servlet-name>hello</servlet-name>
??????? <url-pattern>*.do</url-pattern>
??? </servlet-mapping>
?
<!--
?<taglib>
???? ?<taglib-uri>/spring</taglib-uri>
???? ?<taglib-location>/WEB-INF/spring.tld</taglib-location>
?</taglib>
-->?
</web-app>
2./WEB-INF/application-servlet.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING/DTD BEAN/EN" "<beans>
??? <bean id="urlMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
??????? <property name="mappings">
??????????? <props>
??????????????? <prop key="/login.do">loginAction</prop>
??????????? </props>
??????? </property>
??? </bean>
???
??? <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
??????? <property name="viewClass">
??????????? <value>org.springframework.web.servlet.view.JstlView</value>
??????? </property>
??????? <property name="prefix">
??????????? <value>/</value>
??????? </property>
??????? <property name="suffix">
??????????? <value>.jsp</value>
??????? </property>
??? </bean>
???
??? <bean id="loginAction" class="onlyfun.caterpillar.LoginAction">
??????? <property name="commandName">
??????? ?<value>command</value>
??</property>
??<property name="commandClass">
??????????? <value>onlyfun.caterpillar.LoginForm</value>
??????? </property>
??????? <property name="successView">
??????????? <value>success</value>
??????? </property>
??????? <property name="formView">
??????????? <value>form</value>
??????? </property>
???????<property name="user">??????????
????????????<ref local="user" />
??????? </property>
??? </bean>?
???
???<bean id="user" class="onlyfun.caterpillar.User">
?????<property name="username">
??????? ?<value>111</value>
?????</property>
?????<property name="password">
??????? ?<value>111</value>
?????</property>
????</bean>
</beans>
3./form.jsp
<%@taglib prefix="spring" uri=">
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<html>
<head><title>Login</title></head>
<body>
?<spring:bind path="command.*">
??????? <font color="red"><b>${status.errorMessage}</b></font><br>
??? </spring:bind>
?? ? ??請(qǐng)輸入使用者名稱與密碼:<p>?? ?
??? <form name="loginform" action="login.do" method="post">
???? <spring:bind path="command.username">??
???????? ?名稱 <input type="text" name="${status.expression}" value="${status.value}"/>
???????? ?<font color="red">${status.errorMessage}</font><br>
???? </spring:bind>
???? <spring:bind path="command.password">?
???????? ?密碼 <input type="password" name="${status.expression}" value="${status.value}"/>
???????? ?<font color="red">${status.errorMessage}</font><br>
???? </spring:bind>
??????? <input type="submit" value="確定"/>
??? </form>
? ??? 注意:輸入錯(cuò)誤會(huì)再回到這個(gè)頁面中。 ?
</body>
</html>
4./index.jsp
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
? <head>
? </head>
? <body>??
??? begin......
??? <%
???? response.sendRedirect("login.do");
??? %>
? </body>
</html>
5./success.jsp
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@taglib prefix="c" uri=">
<html>
<head><title>Login Success</title></head>
<body>
??? <H1><c:out value="用戶名﹕${user}"/></H1>
</body>
</html>
6./WEB-INF/classes/onlyfun/caterpillar/LoginAction.class
package onlyfun.caterpillar;
import org.springframework.validation.BindException;
import org.springframework.web.servlet.mvc.SimpleFormController;
import org.springframework.web.servlet.*;
public class LoginAction extends SimpleFormController {?
????private User user;
??? protected ModelAndView onSubmit(Object command,BindException errors) throws Exception {
?????? LoginForm form = (LoginForm) command;?
???????String username = user.getUsername();
?????? String password = user.getPassword();
?????? if(username.equals(form.getUsername()) &&
??? ???? password.equals(form.getPassword())) {
????????? return new ModelAndView(this.getSuccessView(),"user", form.getUsername());
?????? }
?????? else {
??? ??? errors.reject("loginfail", "使用者名稱或密碼錯(cuò)誤");
??? ??? if(!(username.equals(form.getUsername()))){
??? ???? errors.rejectValue("username", "error", null, "使用者名稱錯(cuò)誤");
??? ??? }
??? ???if(!(password.equals(form.getPassword()))){
??? ???? errors.rejectValue("password", "error", null, "密碼錯(cuò)誤");
??? ??? }?? ???
?????????? return new ModelAndView(this.getFormView(),errors.getModel());
?????? }
??? }
????public User getUser() {
?????return user;
????}
????public void setUser(User user) {
?????this.user = user;
????}
}
7./WEB-INF/classes/onlyfun/caterpillar/LoginForm.class
package onlyfun.caterpillar;
public class LoginForm {
??? private String username;
??? private String password;
???
??? public void setUsername(String username) {
?????? this.username = username;
??? }
???
??? public void setPassword(String password) {
?????? this.password = password;
??? }
???
??? public String getUsername() {
?????? return username;
??? }
???
??? public String getPassword() {
?????? return password;
??? }
}
8./WEB-INF/tags/spring.tld
9./WEB-INF/tags/c.tld
10./WEB-INF/classes/onlyfun/caterpillar/User.class
package onlyfun.caterpillar;
public class User {
?private String username;
?private String password;
?public String getPassword() {
??return password;
?}
?public void setPassword(String password) {
??this.password = password;
?}
?public String getUsername() {
??return username;
?}
?public void setUsername(String username) {
??this.username = username;
?}
}
?HttpServletRequest,HttpServletResponse:這兩個(gè)屬性的作用范圍最小。
????時(shí)間上:只是本身請(qǐng)求和應(yīng)答完成就失效,當(dāng)然轉(zhuǎn)發(fā)是把當(dāng)前的request對(duì)象取出來傳給另一
??????????個(gè)資源,其實(shí)本身的request對(duì)象還是只生存到本次請(qǐng)求結(jié)束,response也同樣。
????空間上:只能發(fā)送請(qǐng)求的客戶端有效。
????HttpSession:一次連結(jié)到客戶端關(guān)閉,時(shí)間作用范圍比上面兩個(gè)大,空間任用范圍相同。
????ServletConfig:從一個(gè)servlet被實(shí)例化后,對(duì)任何客戶端在任何時(shí)候訪問有效,但僅對(duì)本servlet
????有效,一個(gè)servlet的ServletConfig對(duì)象不能被另一個(gè)servlet訪問。
????ServletContext:對(duì)任何servlet,任何人在任何時(shí)間都有效,這才是真正全局的對(duì)象。
????那么,ServletConfig參數(shù)和ServletContext參數(shù)到底應(yīng)該如何使用,如何取得?
????一般來說,對(duì)整個(gè)應(yīng)用的配置,為了不使用“硬編碼”,應(yīng)該配置為ServletContext參數(shù),比如字
????符集設(shè)定。
????<web-app>
????????.................
????????<init-param>
????????????<param-name>charset</param-name>?
????????????<param-value>GB2312</param-value>?
????????</init-param>
????????.................
????</web-app>
????注意以上格式只是2。0以后的標(biāo)準(zhǔn)格式,舊容器(引擎)采用服務(wù)商自己的格式配置。注意它的
????父元素應(yīng)該是<web-app>也就是說它是對(duì)一個(gè)應(yīng)用作用的。
????而如果只有一個(gè)特定的servlet要設(shè)定的參數(shù),其它servlet不能共享,應(yīng)該配置為ServletConfig
????參數(shù),如一個(gè)讀取附件的servlet要用到絕對(duì)目錄,而別的servlet不會(huì)用到:
????<servlet>
????????????<servlet-name>GetAtt</servlet-name>
????????<servlet-class>mail.GetAttServlet</servlet-class>
????????<init-param>
????????????<param-name>absPath</param-name>?
????????????<param-value>/usr/mail/ax/axman/Maildir/</param-value>?
????????</init-param>
????</servlet>
????不用說,因?yàn)樵?lt;servlet>標(biāo)簽中已經(jīng)指定了name和class,也就是說只有mail.GetAttServlet這個(gè)
????servlet中才能取到path,而別的Servlet是不能取到的。
????那么如何訪問這兩個(gè)對(duì)象的參數(shù)呢?
????訪問ServletConfig參數(shù):
????????首先要取得ServletConfig對(duì)象,然后調(diào)用它的getInitParameter();方法。要訪問
????ServletConfig對(duì)象,jsp中直接使用config內(nèi)置對(duì)象,但因?yàn)槟愕腏SP編譯后的servlet一般不會(huì)被
????加到web.xml中的,所以一般不會(huì)通過jsp來取對(duì)本JSP編譯后的servlet的配置參數(shù),那么在servlet
????中要得到ServletConfig對(duì)象有兩種方法:
????在inii()方法中取到:通過init的重載方法傳遞
????.....
????public?class?Test?extends?HttpServlet?
????{
????????ServletConfig?config;
????????public?void?init(ServletConfig?config)?throws?ServletException?{
????????????this.config?=?config;
????????}
????????..................
????}
????然后在下面的方法中就可以訪問config對(duì)象。但要注意,為了確保能從構(gòu)造方法中到到當(dāng)前servlet的
????config對(duì)象,應(yīng)該調(diào)用父類的構(gòu)造方法:
????.....
????public?class?Test?extends?HttpServlet?
????{
????????ServletConfig?config;
????????public?void?init(ServletConfig?config)?throws?ServletException?{
????????????super.init(config);
????????????this.config?=?config;
????????}
????????..................
????}
????通過getServletConfig()方法直接到時(shí),這樣做的好處是不必調(diào)手工傳遞屬性,想在任何時(shí)候都可
????以得到。
????還有第三種方法,要自己實(shí)現(xiàn)一些接口,這里作為一般討論就不介紹了。
????要訪問ServletContext對(duì)象,只要從現(xiàn)有的ServletConfig對(duì)象getServletContext()就可以了,然后
????調(diào)用它的getInitParameter()方法就可以獲取它的參數(shù)。
????按說:ServletContext對(duì)象的作用域比ServletConfig作用域大,為什么要從ServletConfig中到得
????ServletContext對(duì)象呢?我個(gè)人認(rèn)為:容器保存了很多個(gè)ServletContext對(duì)象,請(qǐng)求時(shí)容器到底取哪一個(gè)
????給你呢?那就取其中包含ServletConfig信息的那個(gè)給你,就是說取ServletConfig對(duì)象的父級(jí)對(duì)象。就好
????象HttpSession要從requset中取得一樣,就是取那個(gè)包含當(dāng)前requese對(duì)象的session對(duì)象給你,這只是我
????的個(gè)人想法,還沒有來得及看具體實(shí)現(xiàn)。反正就這么用吧。
JSF和Spring集成的資料比較少,原理是獲得彼此的上下文引用,以此進(jìn)一步獲得各自管理的bean,這是可能的,因?yàn)閮烧呤莣eb應(yīng)用框架都遵循servlet規(guī)范,為二者整合提供了可能和基礎(chǔ).
?
在Spring中ApplicationContext是相當(dāng)重要的類,對(duì)于web應(yīng)用,它還包裝了javax.servlet.ServletContext,為web應(yīng)用提供了所有可以利用的數(shù)據(jù),包括可管理bean,Faces中通過FacesContext類可以獲得所有可以利用的資源,同樣包括JSF的可管理支持bean,它們都圍繞著ServletContext提供了自己的門面,通過各自的門面在Servlet容器的世界里彼此相通.
本文介紹兩種方式,實(shí)現(xiàn)二者集成:
1.???????? 通過寫自己的類來完成二者的連通,實(shí)際上只是獲得彼此世界里存活的bean,對(duì)于JSF中事件處理可能需要更進(jìn)一步的構(gòu)思和編碼,為了這點(diǎn),第二個(gè)方法介紹了一種框架.
2.???????? 使用框架完成二者集成.
?
一 ?自己動(dòng)手,下面的代碼以示例為主,其它涉及的類和接口略去.
這個(gè)工具類提供在JSF世界里查找Spring管理的bean.也實(shí)現(xiàn)在Spring中查找JSF組件的方法.
package com.skysoft.rbac.dao;
?
import org.springframework.context.ApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;
import javax.faces.context.FacesContext;
import javax.servlet.ServletContext;
import javax.faces.el.ValueBinding;
import javax.faces.FactoryFinder;
import javax.faces.application.Application;
import javax.faces.application.ApplicationFactory;
?
public final class SpringFacesUtil {
? public SpringFacesUtil() {
? }
? /**
?? * 從Spring中查找bean.
?? * @param beanname String
?? * @return Object
?? */
? public static Object findBean(String beanname) {
??? ServletContext context = (ServletContext) FacesContext.getCurrentInstance().
??????? getExternalContext().getContext();
??? ApplicationContext appctx = WebApplicationContextUtils.
??????? getRequiredWebApplicationContext(context);
??? return appctx.getBean(beanname);
? }
? /**
?? * 從JSF中查找bean.
?? * @param beanname String
?? * @return Object
?? */
? public static Object lookupBean(String beanname) {
??? Object obj = getValueBinding(getJsfEl(beanname)).getValue(FacesContext.
??????? getCurrentInstance());
??? return obj;
? }
?
? private static ValueBinding getValueBinding(String el) {
??? return getApplication().createValueBinding(el);
? }
?
? private static Application getApplication() {
??? ApplicationFactory appFactory = (ApplicationFactory) FactoryFinder.
??????? getFactory(FactoryFinder.APPLICATION_FACTORY);
??? //FactoryFinder.FACES_CONTEXT_FACTORY
??? //FactoryFinder.RENDER_KIT_FACTORY
??? return appFactory.getApplication();
? }
?
? private static String getJsfEl(String value) {
??? return "#{" + value + "}";
? }
}
下面定義一個(gè)由JSF管理的bean:
package com.skysoft.rbac.dao;
?
import javax.servlet.ServletContext;
?
import org.springframework.context.ApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;
import org.skysoft.struts.jsf.util.FacesUtils;
?
public class ServiceLocatorBean
??? implements ServiceLocator {
? private static final String DAO_SERVICE_BEAN_NAME = "userDAO";
? //這個(gè)dao就是由Spring提供的管理bean,這個(gè)dao可以使用Hibernate實(shí)現(xiàn).
? private UserDAO dao;
?
? public ServiceLocatorBean() {
??? this.dao = (UserDAO)SpringFacesUtil.findBean(DAO_SERVICE_BEAN_NAME);
? }
?
? public UserDAO getDao() {
??? return dao;
? }
}
下面是一個(gè)使用ServiceLocatorBean的類.
public class UserDAOImp
??? extends HibernateDaoSupport implements UserDAO {
? private UserDAO dao;
? private List list;
?
? public UserDAOImp() {}
?
? public List getList() {
??? if (list == null) {
????? list = dao.getList();
??? }
??? return list;
? }
?
? public UserDAO getDao() {
??? return dao;
? }
?
? public void setDao(UserDAO dao) {
??? this.dao = dao;
? }
}
?
在faces-config.xml中的配置:
?????? <managed-bean>
????????????? <managed-bean-name>serviceLocatorBean</managed-bean-name>
????????????? <managed-bean-class>com.skysoft.rbac.dao.ServiceLocatorBean</managed-bean-class>
????????????? <managed-bean-scope>session</managed-bean-scope>
?????? </managed-bean>
?????? <managed-bean>
????????????? <managed-bean-name>User</managed-bean-name>
????????????? <managed-bean-class>com.skysoft.rbac.User</managed-bean-class>
????????????? <managed-bean-scope>request</managed-bean-scope>
????????????? <managed-property>
???????????????????? <property-name>serviceLocator</property-name>
???????????????????? <property-class>com.skysoft.rbac.dao.ServiceLocatorBean</property-class>
???????????????????? <value>#{serviceLocatorBean}</value>
????????????? </managed-property>
?????? </managed-bean>
在applicationContext.xml中的配置:
?????? <bean id="userDAO" class="com.skysoft.rbac.dao.UserDAOImp">
????????????? <property name="sessionFactory">
???????????????????? <ref local="sessionFactory" />
????????????? </property>
?????? </bean>
二 使用框架
1 介紹
這個(gè)框架是Spring相關(guān)項(xiàng)目,提供一個(gè)包de.mindmatters.faces.spring,這個(gè)包包含JSF和Spring框架綜合集成的粘合代碼,這些代碼以獨(dú)立于一個(gè)實(shí)現(xiàn)的方式完成,這樣它能和任何JSF實(shí)現(xiàn)一起使用.
本包的提供的代碼主要目的是盡可能透明的集成兩個(gè)框架,主要特征:
l???????? JSF/JSP開發(fā)者應(yīng)該能訪問Spring管理的Beans,就好象它們是由JSF管理的.
l???????? JSF可管理beans應(yīng)能集成入Spring.
l???????? RequestHandledEvent事件也應(yīng)該能被發(fā)布到Spring.
2? JSF配置集成
本包構(gòu)造了一個(gè)基于faces配置文件(e.g. /WEB-INF/faces-config.xml)的WebApplicationContext類, 讓它成為遵循"spring-beans" DTD配置文件(e.g. defined in /WEB-INF/applicationContext.xml)來配置的ApplicationContext的孩子,這樣依從"faces-config" DTD的WebApplicationContext就是全特征的,即自動(dòng)擁有如下功能:
l???????? JSF可管理beans實(shí)現(xiàn)了Spring的*Aware interfaces:
ApplicationContextAware
BeanFactoryAware
BeanNameAware
ResourceLoaderAware
ServletContextAware
l???????? JSF可管理beans實(shí)現(xiàn)Spring的lifecycle interfaces:
InitializingBean
DisposableBean
l???????? 實(shí)現(xiàn)Spring的FactoryBean interface
l???????? 實(shí)現(xiàn)Spring的ApplicationListener interface
l???????? 發(fā)布ApplicationEvent事件.
l???????? 從資源中讀取消息.
等等,更多可看Spring.
3 訪問方式
1) 從JSF中程序化的訪問Spring管理的beans.
因?yàn)樵贔acesWebApplicationContext和ApplicationContext之間有層次關(guān)系,所以你的JSF可管理支持beans能容易的實(shí)現(xiàn)ApplicationContextAware接口,并能通過getBean方法訪問它而不管它是否定義在FacesWebApplicationContext中還是定義在父ApplicationContext類對(duì)象中.
2) 通過JSF EL從JSF中訪問Spring管理的beans.
能夠使用JSF EL訪問beans無論你引用的bean由JSF管理還是由Spring管理.兩個(gè)bean上下文在存取時(shí)間合并.
a) 直接訪問:
如果一個(gè)帶有請(qǐng)求名字的bean只存在于Spring上下文內(nèi)的話,這個(gè)bean被使用,bean的singleton屬性設(shè)置被完全保持.
b) 區(qū)域化訪問(scoped access):
如果你要從JSF定義bean的作用域的能力上得益還想讓那個(gè)bean由Spring管理,那么就要在兩個(gè)上下文中定義,只是對(duì)于JSF上下文中的定義的類類型要使用de.mindmatters.faces.spring.SpringBeanFactory類,你還應(yīng)該設(shè)置那個(gè)bean的singleton屬性到false,因這能覆蓋你的作用域設(shè)置.在你使用JSF EL訪問bean時(shí),你總能獲得一個(gè)遵從你在JSF上下文中定義的作用域設(shè)置的由Spring管理的bean的實(shí)例.
?
三 用法
通常,就象設(shè)置任何其它JSF web應(yīng)用一樣設(shè)置你的web應(yīng)用,下面的樣例配置展示怎樣使能上面提到的特征。
在web.xml
配置中必須加入下列配置條目,
同時(shí)注意把該庫的jsf-spring.jar
放在適當(dāng)?shù)奈恢?
<web-app>
??? .........
??? <!--
??????? 過濾器用于向Spring發(fā)布RequestHandledEvent,它應(yīng)該影射到和FacesServlet url相同的模式.
??? -->???
??? <filter>
??????? <filter-name>RequestHandled</filter-name>
??????? <filter-class>de.mindmatters.faces.spring.support.RequestHandledFilter</filter-class>
??? </filter>
??????
??? <filter-mapping>
??????? <filter-name>RequestHandled</filter-name>
??????? <url-pattern>*.faces</url-pattern>
??? </filter-mapping>
?
??? <!--
??? 這個(gè)偵聽器用于裝入Spring beans的父應(yīng)用上下文.
??? -->
??? <listener>
??????? <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
??? </listener>
??? .........
</web-app>
下面的一些說明,都可以通過下載這個(gè)Spring相關(guān)項(xiàng)目得到,列在這里只為演示上面的說明的功能.
WEB-INF/faces-config.xml
<!-- 一個(gè)純JSF管理的bean -->
<managed-bean>
??? <managed-bean-name>jsfBean</managed-bean-name>
??? <managed-bean-class>example.NameBean</managed-bean-class>
??? <managed-bean-scope>session</managed-bean-scope>
??? <managed-property>
??????? <property-name>name</property-name>
??? </managed-property>
</managed-bean>
<!--一個(gè)SpringBeanScope用來定義Spring可管理bean的作用域.-->
?????? <managed-bean>
????????????? <managed-bean-name>scopedAccessSpringBean</managed-bean-name>
?????? <managed-bean-class>de.mindmatters.faces.spring.SpringBeanScope</managed-bean-class>
????????????? <managed-bean-scope>session</managed-bean-scope>
?????? </managed-bean>
<!-- 這是一個(gè)純JSF可管理bean,它持有一個(gè)到Spring可管理bean的一個(gè)引用. -->
<managed-bean>
??? <managed-bean-name>referencingBean</managed-bean-name>
??? <managed-bean-class>example.ReferencingBean</managed-bean-class>
??? <managed-bean-scope>session</managed-bean-scope>
??? <managed-property>
??????? <property-name>referencedBean</property-name>
??????? <value>#{managedPropertyAccessSpringBean}</value>
??? </managed-property>
</managed-bean>
WEB-INF/applicationContext.xml (partial)
<!-- 一個(gè)純Spring的可管理bean -->
<bean id="directAccessSpringBean" class="example.NameBean"/>
<!-- 一個(gè)向JSF作用域提供的可管理bean.? -->
<bean id="scopedAccessSpringBean" class="example.NameBean" singleton="false"/>
<!-- 一個(gè)純Spring的可管理bean,它由一個(gè)JSF可管理bean引用.(當(dāng)然了,它也能被直接訪問啦.) -->
<bean id="managedPropertyAccessSpringBean" class="example.NameBean" singleton="false"/>
參考:
1./home.xsl
<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="
??? <xsl:output method="html" omit-xml-declaration="yes" />
??? <xsl:template match="/">
??????? <html>
??????????? <head><title>Hello!</title></head>
??????????? <body>
??????????????? <h1>My First Words</h1>
??????????????? <xsl:for-each select="wordList/word">
??????????????????? <xsl:value-of select="."/><br />
??????????????? </xsl:for-each>
??????????? </body>
??????? </html>
??? </xsl:template>
</xsl:stylesheet>
2./index.html
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
? <head>???
? </head>
? <body>
? ?<center><input type="button" value="xslt" onclick="location.href='home.htm'"></center>
? </body>
</html>
3./WEB-INF/web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.4"
?xmlns="
?xmlns:xsi="
?xsi:schemaLocation="
http://java.sun.com/xml/ns/j2ee?
?<servlet>
??????? <servlet-name>hello</servlet-name>
??????? <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
??<init-param>
???????? <param-name>contextConfigLocation</param-name>
???????? <param-value>/WEB-INF/application-servlet.xml</param-value>
??? ?</init-param>?
??? </servlet> ?
??? <servlet-mapping>
??????? <servlet-name>hello</servlet-name>
??????? <url-pattern>*.htm</url-pattern>
??? </servlet-mapping> ??
</web-app>
4./WEB-INF/application-servlet.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING/DTD BEAN/EN" "
<beans>
??? <bean id="urlMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
??????? <property name="mappings">
??????????? <props>
??????????????? <prop key="/home.htm">homeAction</prop>
??????????? </props>
??????? </property>
??? </bean>??
??? <bean id="bundleViewResolver" class="org.springframework.web.servlet.view.ResourceBundleViewResolver">
??????? <property name="basename">
??????????? <value>views</value>
??????? </property>
??? </bean>??
??? <bean id="homeAction" class="xslt.HomePageController"/>
</beans>
5./WEB-INF/classes/views_zh_TW.properties
home.class=xslt.HomePage
home.stylesheetLocation=/home.xsl
home.root=wordList
6./WEB-INF/classes/xslt/HomePage.class
package xslt;
import java.util.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.jdom.Element;
import org.jdom.output.DOMOutputter;
import org.springframework.web.servlet.view.xslt.AbstractXsltView;
import org.w3c.dom.Node;
public class HomePage extends AbstractXsltView {
? protected Node createDomNode(
????????? Map model, String rootName, HttpServletRequest req, HttpServletResponse res
????? ) throws Exception {? ??
????????? org.jdom.Document doc = new org.jdom.Document();
????????? Element root = new Element(rootName);
????????? doc.setRootElement(root);
????????? List words = (List) model.get("wordList");
????????? for (Iterator it = words.iterator(); it.hasNext();) {
????????????? String nextWord = (String) it.next();
????????????? Element e = new Element("word");
????????????? e.setText(nextWord);
????????????? root.addContent(e);
????????? }
????????? // convert JDOM doc to a W3C Node and return
????????? return new DOMOutputter().output( doc );
????? }
}
7./WEB-INF/classes/xslt/HomePageController.class
package xslt;
import java.util.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.AbstractController;
public class HomePageController extends AbstractController{
?protected ModelAndView handleRequestInternal(HttpServletRequest req, HttpServletResponse resp) throws Exception {
??Map map = new HashMap();
???? List wordList = new ArrayList();????????
???? wordList.add("hello");
???? wordList.add("world");???????
???? map.put("wordList", wordList);??????
???? return new ModelAndView("home", map);
?}
}
1.????????
Abstract
在
Java
的世界裡,要操控
XML
,最簡(jiǎn)單的方法莫過於使用
JDOM
。在這裡我簡(jiǎn)單的介紹如何用
JDOM
從無到有的建立一分
XML
、當(dāng)有一份
XML file
時(shí),如何將這個(gè)
XML file
讀進(jìn)程式裡及如何利用
JDOM
將
XML
透過
XSLT
轉(zhuǎn)成
HTML
。
JDOM
是由
Brett Mclaughlin
和
Jason Hunter
編寫,在
http://www.jdom.org
可免費(fèi)下載。
?
2.????????
建立、新增、刪除、輸出
範(fàn)例
1
展示如何建立、新增、刪除及輸出一份
XML
,每份
XML
在
JDOM
裡是由一個(gè)
Document
類別代表,所以一開始我們要先
new
一個(gè)
Document
,在建構(gòu)
Document
時(shí)應(yīng)指明根節(jié)點(diǎn),如果沒有指明,在建構(gòu)應(yīng)由
setRootElement
設(shè)定。基本上
XML
都可以化成一個(gè)樹狀結(jié)構(gòu),所以,在產(chǎn)生根節(jié)點(diǎn)之後,就由根節(jié)點(diǎn)開始增加子節(jié)點(diǎn),新增的方式是呼叫
Element.addContent
將新的節(jié)點(diǎn)加入。刪除如果知道是某節(jié)點(diǎn)以下的子節(jié)點(diǎn),則可呼叫
Element.getChildren
取得所有子節(jié)點(diǎn),再找出要?jiǎng)h除的點(diǎn)節(jié)予以刪除。
當(dāng)建立好
XML
之後,通常我們會(huì)希望將它輸出到檔案,
JDOM
提供了
XMLOutputter
類別供我們輸出之用,輸出前要先設(shè)定編碼方式,不然,會(huì)以
UTF-8
為預(yù)設(shè)值,
setNewlines
則是指明輸出時(shí)是否要幫我們斷行,方便閱讀,如果沒有加這行指令,預(yù)設(shè)是不會(huì)斷行,那麼所有資料將在同一行上。
=====
範(fàn)例
1 =====
import org.jdom.*;
import org.jdom.output.*;
import java.io.*;
import java.util.List;
?
public class myCreate {
? public myCreate() {
??? String[] strChapter = { "XML
簡(jiǎn)論
", "
編寫
XML", "
剖析
XML", "
約制
XML", "
驗(yàn)正
XML", "
轉(zhuǎn)換
XML" };
?
??? Element elmtRoot = new Element("Article");
??? Document docJDOM = new Document(elmtRoot);
??? //
新增
??? for(int i=0; i<6; i++) {
????? Element elmtChapter = new Element("Chapter");
????? elmtChapter.addContent(strChapter[i]);
????? elmtChapter.setAttribute("sort", new Integer(i).toString());
????
?elmtRoot.addContent(elmtChapter);
??? }
??? //
刪除
??? List lstChapter = elmtRoot.getChildren("Chapter");
??? lstChapter.remove(4);
??? //
輸出
??? OutputXML(docJDOM, "e:/myJDOM.xml");
? }
?
? private void OutputXML(Document docXML, String strFilename) {
??? XMLOutputter fmt = new XMLOutputter();
??? try {
????? fmt.setEncoding("big5");
????? fmt.setNewlines(true);
????? FileWriter fwXML = new FileWriter(strFilename);
????? fmt.output(docXML, fwXML);
????? fwXML.close();
??? }
??? catch (IOException e) {
????
?e.printStackTrace();
??? }
? }
?
? public static void main(String[] args) {
??? myCreate myCreate1 = new myCreate();
? }
}
?
3.????????
讀進(jìn)一份
XML file
目前
XML
最常被拿來應(yīng)用的領(lǐng)域之一大概就是當(dāng)作設(shè)定檔,因此,如何從檔案中讀入一份已存在的
XML
更為重要。
JDOM
是利用
SAX
或
DOM
來剖析
XML
,用
SAX
會(huì)比
DOM
,所以一般都是用
SAX
,如果對(duì)
SAX
不熟悉,在
http://www.saxproject.org/
相關(guān)文件資料。
範(fàn)例
2
就是用
SAX
建立
Document
,在建立
SAXBuilder
時(shí)傳入的參數(shù)指出是否用
DTD
驗(yàn)正
XML
的合法性,
true
表示要,
false
表示不要。當(dāng)呼叫
build
之後
JDOM
就已經(jīng)幫我們用
SAX
建立好一棵
XML Tree
,如此我們就可以很方便由
Tree
中找到我們要的節(jié)點(diǎn)。
?
=====
範(fàn)例
2 =====
import org.jdom.*;
import org.jdom.input.*;
import org.jdom.output.*;
import java.io.*;
import java.util.List;
?
public class myRead {
? public myRead() {
??? Document docJDOM;
?
??? //
利用
SAX
建立
Document
??? SAXBuilder bSAX = new SAXBuilder(false);
??? try {
????? docJDOM = bSAX.build(new File("e:/myJDOM.xml"));
??? }
??? catch (JDOMException e) {
????? e.printStackTrace();
????? return;
??? }
??? //
在根節(jié)點(diǎn)中加入一個(gè)新的子節(jié)點(diǎn)
??? Element elmtRoot = docJDOM.getRootElement();
??? Element elmtChapter = new Element("Chapter");
??? elmtChapter.setText("
驗(yàn)正
XML");
??? elmtChapter.setAttribute("sort", "4");
??? elmtRoot.addContent(elmtChapter);
??? //
印出所有根節(jié)點(diǎn)的子節(jié)點(diǎn)
??? List lstChildren = elmtRoot.getChildren("Chapter");
??? for(int i=0; i<lstChildren.size(); i++) {
????? Element elmtChild = (Element) lstChildren.get(i);
????? System.out.println("Child " + i);
????? System.out.println("? Text:" + elmtChild.getText());
????? System.out.println("? Attribute:" + elmtChild.getAttributeValue("sort"));
??? }
??? //
輸出到檔案
??? OutputXML(docJDOM, "e:/myJDOM2.xml");
? }
?
? private void OutputXML(Document docXML, String strFilename) {
??? XMLOutputter fmt = new XMLOutputter();
??? try {
????? fmt.setEncoding("big5");
????? fmt.setNewlines(true);
????? FileWriter fwXML = new FileWriter(strFilename);
????? fmt.output(docXML, fwXML);
????? fwXML.close();
??? }
??? catch (IOException e) {
????? e.printStackTrace();
??? }
? }
?
? public static void main(String[] args) {
??? myRead myRead1 = new myRead();
? }
}
?
4.????????
轉(zhuǎn)換
XML
到
HTML
要將
XML
轉(zhuǎn)成
HTML
當(dāng)然要先寫好
XSL
,但是即使寫好
XSL
,
JDOM
也並不提供
XML
轉(zhuǎn)換,幸好在
JDOM
安裝好之後,就會(huì)有
Apache
的
Xalan
,它可以幫我們做這樣的轉(zhuǎn)換。
要使用
Apache
的
Xalan
,首先確定
xalan.jar
在
classpath
裡。
Xalan
的第一個(gè)用法是在命令列執(zhí)行,指令如下…
C:\> java org.apache.xalan.xslt.Process –IN XML
文件
–XSL XSL
樣版
–OUT
輸出檔名
命令列的用法在一般的運(yùn)用裡是很方便,但是我們有興趣的是在程式裡怎麼用。範(fàn)例
4
提供了一個(gè)簡(jiǎn)單的
sample
。
=====
範(fàn)例
4 =====
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.stream.*;
?
public class myGenHTML {
?
? public myGenHTML(String strXML, String strXSL, String strHTML) {
??? try {
????? GenHTML(strXML, strXSL, strHTML);
??? }
??? catch (TransformerConfigurationException e) {
????? e.printStackTrace();
??? }
??? catch (TransformerException e) {
????? e.printStackTrace();
??? }
? }
?
? private void GenHTML(String strXMLFile, String strXSLFile, String strHTMLFile) throws TransformerConfigurationException, TransformerException
? {
??? TransformerFactory myFactory = TransformerFactory.newInstance();
??? Transformer myTransformer = myFactory.newTransformer(new StreamSource(strXSLFile));
??? myTransformer.transform(new StreamSource(strXMLFile), new StreamResult(strHTMLFile));
? }
?
? public static void main(String[] args) {
??? myGenHTML myGenHTML1 = new myGenHTML(args[0], args[1], args[2]);
? }
}
1./WEB-INF/web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.4"
?xmlns="?xmlns:xsi="?xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
??
?<servlet>
??????? <servlet-name>hello</servlet-name>
??????? <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
??<init-param>
???????? <param-name>contextConfigLocation</param-name>
???????? <param-value>/WEB-INF/application-servlet.xml</param-value>
??? ?</init-param>?
??? </servlet>
?
??? <servlet-mapping>
??????? <servlet-name>hello</servlet-name>
??????? <url-pattern>*.do</url-pattern>
??? </servlet-mapping>
?
?<welcome-file-list>
??? ?<welcome-file>form.jsp</welcome-file>
? ?</welcome-file-list>
</web-app>
2./WEB-INF/application-servlet.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING/DTD BEAN/EN" "<beans>
??? <bean id="urlMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
??????? <property name="mappings">
??????????? <props>
??????????????? <prop key="/login.do">loginAction</prop>
??????????? </props>
??????? </property>
??? </bean>
???
??? <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
??????? <property name="viewClass">
??????????? <value>org.springframework.web.servlet.view.InternalResourceView</value>
??????? </property>
??????? <property name="prefix">
??????????? <value>/</value>
??????? </property>
??????? <property name="suffix">
??????????? <value>.jsp</value>
??????? </property>
??? </bean>
???
??? <bean id="loginAction" class="onlyfun.caterpillar.LoginAction">
??????? <property name="commandClass">
??????????? <value>onlyfun.caterpillar.LoginForm</value>
??????? </property>
??????? <property name="successView">
??????????? <value>success</value>
??????? </property>
??????? <property name="formView">
??????????? <value>form</value>
??????? </property>
??? </bean>
</beans>
3./WEB-INF/classes/onlyfun/caterpillar/LoginAction.class
package onlyfun.caterpillar;
import org.springframework.web.servlet.mvc.SimpleFormController;
import org.springframework.web.servlet.*;
public class LoginAction extends SimpleFormController {
??? protected ModelAndView onSubmit(Object command) throws Exception {
?????? LoginForm form = (LoginForm) command;
???????
?????? if("111".equals(form.getUsername()) &&
???????????? "111".equals(form.getPassword())) {
????????? return new ModelAndView(this.getSuccessView(),"user", form.getUsername());
?????? }
?????? else {
?????????? return new ModelAndView(this.getFormView());
?????? }
??? }
}
4./WEB-INF/classes/onlyfun/caterpillar/LoginForm.class
package onlyfun.caterpillar;
public class LoginForm {
??? private String username;
??? private String password;
???
??? public void setUsername(String username) {
?????? this.username = username;
??? }
???
??? public void setPassword(String password) {
?????? this.password = password;
??? }
???
??? public String getUsername() {
?????? return username;
??? }
???
??? public String getPassword() {
?????? return password;
??? }
}
5./form.jsp
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<html>
<head><title>Login</title></head>
<body>
??? 請(qǐng)輸入使用者名稱與密碼:<p>
??? <form name="loginform" action="login.do" method="post">
??????? 名稱 <input type="text" name="username"/><br>
??????? 密碼 <input type="password" name="password"/><br>
??????? <input type="submit" value="確定"/>
??? </form>
??? 注意:輸入錯(cuò)誤會(huì)再回到這個(gè)頁面中。
</body>
</html>
6./success.jsp
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<html>
<head><title>Login Success</title></head>
<body>
??? <H1> Hello, ${user}!!</H1>
??? This is your secret gift.
</body>
</html>
1. /hellouser.jsp
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<html>
<head><title>HelloPage</title></head>
<body>
???? <H1> ${helloWord}</H2>
</body>
</html>
2./index.jsp
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
? <head>
? </head>
? <body>
??? <%
??? ?response.sendRedirect("hellouser.do");
??? %>
? </body>
</html>
3./WEB-INF/web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.4"
?xmlns="?xmlns:xsi="?xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
??
?<servlet>
??????? <servlet-name>hello</servlet-name>
??????? <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
??<init-param>
???????? <param-name>contextConfigLocation</param-name>
???????? <param-value>/WEB-INF/application-servlet.xml</param-value>
??? ?</init-param>?
??? </servlet>
?
??? <servlet-mapping>
??????? <servlet-name>hello</servlet-name>
??????? <url-pattern>*.do</url-pattern>
??? </servlet-mapping>
??
</web-app>
4./WEB-INF/application-servlet.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING/DTD BEAN/EN" "<beans>
??? <bean id="urlMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
??????? <property name="mappings">
??????????? <props>
??????????????? <prop key="/hellouser.do">helloUserAction</prop>
??????????? </props>
??????? </property>
??? </bean>
???
??? <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
??????? <property name="viewClass">
??????????? <value>org.springframework.web.servlet.view.InternalResourceView</value>
??????? </property>
??? </bean>
???
??? <bean id="helloUserAction" class="onlyfun.caterpillar.HelloUserAction">
??????? <property name="helloWord">
??????????? <value>Hello!</value>
??????? </property>
??????? <property name="viewPage">
??????????? <value>/hellouser.jsp</value>
??????? </property>
??? </bean>
</beans>
5./WEB-INF/classes/onlyfun/caterpillar/HelloUserAction.class
package onlyfun.caterpillar;
import java.io.IOException;
import java.util.*;
import javax.servlet.*;
import javax.servlet.http.*;
import org.springframework.web.servlet.mvc.Controller;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.bind.RequestUtils;
public class HelloUserAction implements Controller {
?? private String helloWord;
??? private String viewPage;
???
?? public ModelAndView handleRequest(HttpServletRequest req, HttpServletResponse res)
??????? throws ServletException, IOException {
???? //String user = RequestUtils.getRequiredStringParameter(req, "user");
????? Map model = new HashMap();
????? model.put("helloWord", getHelloWord());
???? // model.put("user", user);
???
?????? return new ModelAndView(getViewPage(), model);
??? }
???
??? public void setViewPage(String viewPage) {
?????? this.viewPage = viewPage;
??? }
???
??? public String getViewPage() {
?????? return viewPage;
??? }
??? public void setHelloWord(String helloWord) {
?????? this.helloWord = helloWord;
??? }
???
??? public String getHelloWord() {
?????? return helloWord;
??? }
}
1.EventRouter.js
/**
?* @author user
?*/
var jsEvent = new Array();
jsEvent.EventRouter = function(el,eventType){
?this.lsnrs = new Array();
?this.el = el;
?el.eventRouter = this;
?el[eventType] = jsEvent.EventRouter.callback;
};
jsEvent.EventRouter.prototype.addListener = function(lsnr){
?this.lsnrs.append(lsnr,true);?
} ;
jsEvent.EventRouter.prototype.notify = function(e){
?var lsnrs = this.lsnrs;
?for(var i=0;i<lsnrs.length;i++){
??var lsnr = lsnrs[i];
??lsnr.call(this,e);
?}
};
jsEvent.EventRouter.callback=function(event){
?var e = event || window.event;
?var router = this.eventRouter;
?router.notify(e);
};
Array.prototype.append = function(obj,nodup){
?if(nodup){?
??this[this.length]=obj;
?}
};
2.mousemat.css
.mousemat{
?background-color:#ffe0d0;
?border:solid maroon 0px;
?position:absolute;
?margin:0px;
?width:500px;
?height:500px;
?top:50px;
?left:50px;?
}
.thumbnail{
?background-color:#ffe0d0;
?border:solid maroon 0px;
?position:absolute;
?margin:0px;
?width:100px;
?height:100px;
?top:50px;
?left:600px;?
}
.cursor{
?background-color:blue;
?position:relative;
?height:5px;
?width:5px;
}
3.mousemat.htm
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "<html>
?<head>
??<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
??<title>Untitled Document</title>
??<link rel='stylesheet' type = 'text/css' href = 'mousemat.css'>
??<script type ='text/javascript' src = 'EventRouter.js'></script>
??<script type='text/javascript'>
???var cursor = null;
???window.onload = function(){
????var mat = document.getElementById('mousemat');
????cursor = document.getElementById('cursor');
????var mouseRouter = new jsEvent.EventRouter(mat,"onmousemove");
????//var mouseRouter = new jsEvent.EventRouter(mat,"onclick");
????mouseRouter.addListener(writeStatus);
????mouseRouter.addListener(drawThumbnail);
???};
???function writeStatus(e){
????window.status = e.clientX + "," + e.clientY;
???}
???function drawThumbnail(e){
????cursor.style.left = ((e.clientX/5)-2) + "px";
????cursor.style.top = ((e.clientY/5)-2) + "px";
???}
??</script>
?</head>
?<body>
??<div class='mousemat' id='mousemat'></div>
??<div class='thumbnail' id='thumbnail'>
???<div class = 'cursor' id = 'cursor'></div>
??</div>
?</body>
</html>
1.mousemat.htm
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "
<html>
?<head>
??<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
??<title>Untitled Document</title>
??<link rel='stylesheet' type = 'text/css' href = 'mousemat.css'>
??<script type='text/javascript'>
???var cursor = null;
???window.onload = function(){
????var mat = document.getElementById('mousemat');
????mat.onmousemove = mouseObserver;
????cursor = document.getElementById('cursor');
???}
???function mouseObserver(event){
????var e = event || window.event;
????writeStatus(e);
????drawThumbnail(e);
???}
???function writeStatus(e){
????window.status = e.clientX + "," + e.clientY;
???}
???function drawThumbnail(e){
????cursor.style.left = ((e.clientX/5)-2) + "px";
????cursor.style.top = ((e.clientY/5)-2) + "px";
???}
??</script>
?</head>
?<body>
??<div class='mousemat' id='mousemat'></div>
??<div class='thumbnail' id='thumbnail'>
???<div class = 'cursor' id = 'cursor'></div>
??</div>
?</body>
</html>
2.mousemat.css
mousemat{
?background-color:#ffe0d0;
?border:solid maroon 0px;
?position:absolute;
?margin:0px;
?width:500px;
?height:500px;
?top:50px;
?left:50px;?
}
.thumbnail{
?background-color:#ffe0d0;
?border:solid maroon 0px;
?position:absolute;
?margin:0px;
?width:100px;
?height:100px;
?top:50px;
?left:600px;?
}
.cursor{
?background-color:blue;
?position:relative;
?height:5px;
?width:5px;
}
1.MyHtml.html
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
? <head>
?<script type='text/javascript'>
??var req = null;
??var console = null;
??var READY_STATE_UNINITIALIZED = 0;
??var READY_STATE_LOADING = 1;
??var READY_STATE_LOADED = 2;
??var READY_STATE_INTERACTIVE = 3;
??var READY_STATE_COMPLETE = 4;
??
??function sendRequest(url,params,HttpMethod){
???if(!HttpMethod){
????HttpMethod = "GET";
???}
???req = initXMLHTTPRequest();
???if(req){
????req.onreadystatechange = onReadyState;
????req.open(HttpMethod,url,true);
????req.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
????req.send(params);
????
???}
??}
??
??function initXMLHTTPRequest(){
???var xRequest = null;
???if(window.XMLHttpRequest){
????xRequest = new XMLHttpRequest();
???}else if(window.ActiveXObject){
????xRequest = new ActiveXObject("Microsoft.XMLHTTP");
???}
???return xRequest;
??}
??
??function onReadyState(){
???var ready = req.readyState;
???var data = null;
???if(ready==READY_STATE_COMPLETE){
????data = req.responseText;
???}else{
????data = "loading...[" + ready +"]";
???}
???toConsole(data);
??}
??
??function toConsole(data){
???if(console!=null){
????var newline = document.createElement("div");
????console.appendChild(newline);
????var txt = document.createTextNode(data);
????console.appendChild(txt);
???}
??}
??
??window.onload = function(){
???console = document.getElementById('console');
???sendRequest("data.txt");
??}
?</script>
? </head>
? ?
? <body>
? ?<DIV id ='console'></DIV>
? </body>
</html>
2.data.txt
?i'm ok!!!!!!!!
1.new_file.htm
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "<html>
?<head>
??<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
??<title>Untitled Document</title>
??<SCRIPT type='text/javascript' src='new_file.js'></SCRIPT>
??<SCRIPT type='text/javascript'>
???window.onload = load;
??</SCRIPT>
?</head>
?<body>
??<CENTER><INPUT type='button' id='b1'></INPUT></CENTER>?
?</body>
</html>
2.new_file.js
var value = '500';
function load(){
?var domEl = document.getElementById('b1');?
?JsButton(value,domEl);
}
function JsButton(value,domEl){
?this.domEl = domEl;
?this.value = value;
?this.domEl.buttonObj = this;
?//this.domEl.onclick = function(){
??//alert(this.value);
?//}
?this.domEl.onclick = JsButton.prototype.clickHandler;
}?
JsButton.prototype.clickHandler = function(){
?//alert(this.value); 在回調(diào)函數(shù)中調(diào)用this屬性時(shí)﹐
?//得到的是對(duì)應(yīng)的DOM元素裡面的數(shù)值﹐此處為空。
?var buttonObj = this.buttonObj;
?var value =(buttonObj && buttonObj.value)? buttonObj.value:"unknown value";
?alert(value);
}
1.musical_dyn_keys.css
.musicalKeys{
?background-color:#ffe0d0;
?border:solid maroon 2px;
?position:absolute;
?overflow:auto;
?margin:4px;
}
.toplong{
?width:536px;
?height:68px;
?top:24px;
?left:24px;
}
.sidebar{
?width:100px;
?height:400px;
?top:24px;
?left:570px;
}
.musicalButton{
?border:solid navy 1px;
?width:60px;
?height:60px;
?position:relative;
?margin:2px;
?float:left;
}
.do{background-color:red;}
.re{background-color:orange;}
.mi{background-color:yellow;}
.fa{background-color:green;}
.so{background-color:blue;}
.la{background-color:indigo;}
.ti{background-color:violet;}
div.console{
?font-family:arial,helvetica;
?font-size:16px;
?color:navy;
?background-color:white;
?border:solid navy 2px;
?width:536px;
?height:320px;
?top:106px;
?left:24px;
?margin:4px;
?position:absolute;
?overflow:auto;
}
2.musical_dyn_keys.html
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "<html>
?<head>
??<title>Two Keyboards</title>
??<LINK rel='stylesheet' type='text/css' href='musical_dyn_keys.css'/>
??<SCRIPT type='text/javascript' src='musical_dyn_keys.js'></SCRIPT>
??<SCRIPT type='text/javascript'>
???window.onload=assignKeys
??</SCRIPT>
?</head>
?<body>
??<DIV id='keyboard-top' class='toplong musicalKeys'></DIV>
??<DIV id='keyboard-side' class='sidebar musicalKeys'></DIV>
??<DIV id='console' class='console'></DIV>
?</body>
</html>
3.musical_dyn_keys.js
var notes = new Array("do","re","mi","fa","so","la","ti","do");
function assignKeys(){
?var candidates = document.getElementsByTagName("DIV");
?if(candidates){
??for(var i=0;i<candidates.length;i++){
???var candidate = candidates[i];
???if(candidate.className.indexOf('musicalKeys')>=0){
????makeKeyboard(candidate);
???}
??}
?}
}
function makeKeyboard(el){
?for(var i=0;i<notes.length;i++){
??var key=document.createElement("DIV");
??key.className = notes[i] + " musicalButton";
??alert(key.className);
??key.note = notes[i];
??key.onclick = playNote;
??el.appendChild(key);
?}?
}
function playNote(event){
?var note = this.note;
?var console = document.getElementById('console');
?if(note && console){
??console.innerHTML +=note + ".";
?}
}
1.murical.html
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
? <head>??
??? <link rel='stylesheet' type='text/css' href='musical.css'>
??? <script type='text/javascript' src="musical.js"></script>
??? <script type='text/javascript'>
?? window.onload = assignKeys
??? </script>??
? </head>
?
? <body>
? ?<DIV>
? ??<DIV id='keyboard' class='musicalKeys'>
???<DIV class='do musicalButton'></DIV>
???<DIV class='re musicalButton'></DIV>
???<DIV class='mi musicalButton'></DIV>
???<DIV class='fa musicalButton'></DIV>
???<DIV class='so musicalButton'></DIV>
???<DIV class='la musicalButton'></DIV>
???<DIV class='ti musicalButton'></DIV>
???<DIV class='do musicalButton'></DIV>
??</DIV>
??<DIV id='console' class='console'></DIV>
? ?</DIV>
? </body>
</html>
2.musical.css
.body{
?background-color:white;?
}
.musicalKeys{
?background-color:#ffe0d0;
?boarder:solid maroon 2px;
?width:536px;
?height:68px;
?top:24px;
?left:24px;
?margin:4px;
?position:absolute;
?overflow:auto;
}
.musicalButton{
?border:solid navy 1px;
?width:60px;
?height:60px;
?position:relative;
?margin:2px;
?float:left;
}
.do{background-color:red;}
.re{background-color:orange;}
.mi{background-color:yellow;}
.fa{background-color:green;}
.so{background-color:blue;}
.la{background-color:indigo;}
.ti{background-color:violet;}
div.console{
?font-family:arial,helvetica;
?font-size:16px;
?color:navy;
?background-color:white;
?border:solid navy 2px;
?width:536px;
?height:320px;
?top:106px;
?left:24px;
?margin:4px;
?position:absolute;
?overflow:auto;
}
3.musical.js
function assignKeys(){
?var keyboard=document.getElementById("keyboard");
?var keys = keyboard.getElementsByTagName("DIV");
?if(keys){
??for(var i=0;i<keys.length;i++){
???var key=keys[i];
???var classes=(key.className).split(" ");
???if(classes && classes.length>=2 && classes[1]=="musicalButton"){
????var note=classes[0];
????key.note=note;
????//key.onmouseover=playNote;
????key.onclick = playNote;
???}
??}
?}
}
function playNote(event){
?var note = this.note;
?var console = document.getElementById("console");
?if(note && console){
??console.innerHTML += note + ".";
?}
}
MyHtml.html
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
? <head>
? <script type="text/javascript" src="prototype.js"></script>
? <script type="text/javascript" src="rico.js"></script>
? <script type='text/javascript'>
???? function accordion(){
?? var outer = $('myAccordion');
?? outer.style.width = '320px';??
??new Rico.Accordion(
???outer,
???{panelHeight:400,
??? expandedBg:'#909090',
??? collapsedBg:'#404040'
???}
??);
? }
??? window.onload = accordion?
? </script>
? </head>
? <body>
?? <div id='myAccordion'>
?? ?<div>
?? ??<div>first title</div>
?? ??<div>first!!!!!</div>
?? ?</div>
?? ?<div>
?? ??<div>second title</div>
?? ??<div>second!!!!!</div>
?? ?</div>
?? </div>??
? </body>
</html>
?String sql = "INSERT INTO AB(A,B,C,D,E) VALUES(?,?,?,?,?)";
?sql = sql.toUpperCase();
?String str="
\\s*INSERT\\s+INTO\\s+([^\\(]+)\\(([^\\)]+)\\)\\s*VALUES\\s*\\(([^\\)]+)\\)\\s*";
?Pattern p = Pattern.compile(str);
?Matcher m = p.matcher(sql);
?m.find();
?String table = m.group(1);
?String cols = m.group(2);
?String values = m.group(3);
?System.out.println("table ==== " + table); //AB
?System.out.println("cols ==== " + cols); //A﹐B﹐C﹐D﹐E
?System.out.println("values ==== " + values); //﹖﹐﹖﹐﹖﹐﹖﹐﹖
註﹕.表示任何字符
??????[abc]表示abc之一字符
??????[^abc]表示非abc的一字符
??????\s表示空格﹐tab,換行﹐換頁﹐回車
???? \S表示非空格﹐tab,換行﹐換頁﹐回車
??? \d表示數(shù)字[0-9]
??? \D表示非數(shù)字[^0-9]
???\w表示詞字符[a-zA-Z0-9]
?? \W表示非詞字符[^a-zA-Z0-9]
?
匹配量詞?? X? 表示1或0個(gè)X
??????????????????X* 表示0或n個(gè)X
??????????????????X+表示1或n個(gè)X
一、概要
在JAVA應(yīng)用程式特別是基於WEB的程式中,經(jīng)常遇到字符的編碼問題。為了防止出現(xiàn)亂碼,首先需要了解JAVA是如何處理字符的,這樣就可以有目的地在輸入/輸出環(huán)節(jié)中增加必要的轉(zhuǎn)碼。其次,由於各種伺服器有不同的處理方式,還需要多做試驗(yàn),確保使用中不出現(xiàn)亂碼。
二、基本概念2.1 JAVA中字符的表達(dá)
JAVA中有char、byte、String這幾個(gè)概念。char 指的是一個(gè)UNICODE字符,為16位的整數(shù)。byte 是字節(jié),字符串在網(wǎng)路傳輸或存儲(chǔ)前需要轉(zhuǎn)換為byte數(shù)組。在從網(wǎng)路接收或從存儲(chǔ)設(shè)備讀取後需要將byte數(shù)組轉(zhuǎn)換成String。String是字符串,可以看成是由char組成的數(shù)組。String 和 char 為內(nèi)存形式,byte是網(wǎng)路傳輸或存儲(chǔ)的序列化形式。
舉例:
英
String ying = “英”;
char ying = ying.charAt(0);
String yingHex = Integer.toHexString(ying);
82 F1
byte yingGBBytes = ying.getBytes(“GBK”);
GB編碼的字節(jié)數(shù)值
D3 A2
?
2.2 編碼方式的簡(jiǎn)介
String序列化成byte數(shù)組或反序列化時(shí)需要選擇正確的編碼方式。如果編碼方式不正確,就會(huì)得到一些0x3F的值。常用的字符編碼方式有ISO8859_1、GB2312、GBK、UTF-8/UTF-16/UTF-32。
ISO8859_1用來編碼拉丁文,它由單字節(jié)(0-255)組成。
GB2312、GBK用來編碼簡(jiǎn)體中文,它有單字節(jié)和雙字節(jié)混合組成。最高位為1的字節(jié)和下一個(gè)字節(jié)構(gòu)成一個(gè)漢字,最高位為0的字節(jié)是ASCII碼。
UTF-8/UTF-16/UTF-32是國際標(biāo)準(zhǔn)UNICODE的編碼方式。 用得最多的是UTF-8,主要是因?yàn)樗趯?duì)拉丁文編碼時(shí)節(jié)約空間。
UNICODE值 UTF-8編碼
U-00000000 - U-0000007F: 0xxxxxxx
U-00000080 - U-000007FF: 110xxxxx 10xxxxxx
U-00000800 - U-0000FFFF: 1110xxxx 10xxxxxx 10xxxxxx
U-00010000 - U-001FFFFF: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
U-00200000 - U-03FFFFFF: 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
U-04000000 - U-7FFFFFFF: 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
三、J2SE中相關(guān)的函數(shù)
String str =”英”;
//取得GB2312編碼的字節(jié)
byte[] bytesGB2312 = str.getBytes(“GB2312”);
//取得平臺(tái)缺省編碼的字節(jié)(solaris為ISO8859_1,windows為GB2312)
byte[] bytesDefault = str.getBytes();
//用指定的編碼將字節(jié)轉(zhuǎn)換成字符串
String newStrGB = new String(bytesGB2312, “GB2312”);
//用平臺(tái)缺省的編碼將字節(jié)轉(zhuǎn)換成字符串(solaris為ISO8859_1,windows為GB2312)
String newStrDefault = new String(bytesDefault);
//用指定的編碼從字節(jié)流裏面讀取字符
InputStream in = xxx;
InputStreamReader reader = InputStreamReader( in, “GB2312”);
char aChar = reader.read();
四、JSP、數(shù)據(jù)庫的編碼
4.1 JSP中的編碼
(1) 靜態(tài)聲明:
CHARSET有兩個(gè)作用:
JSP文件的編碼方式:在讀取JSP文件、生成JAVA類時(shí),源JSP文件中漢字的編碼
JSP輸出流的編碼方式:在執(zhí)行JSP時(shí),往response流裏面寫入數(shù)據(jù)的編碼方式
(2) 動(dòng)態(tài)改變:在往response流裏面寫數(shù)據(jù)前可以調(diào)用response.setContentType(),設(shè)定正確的編碼類型。
(3) 在TOMCAT中,由Request.getParameter() 得到的參數(shù),編碼方式都是ISO8859_1。所以如果在瀏覽器輸入框內(nèi)輸入一個(gè)漢字“英”,在伺服器端就得到一個(gè)ISO8859_1編碼的(0x00,0xD3,0x00,0xA2)。所以通常在接收參數(shù)時(shí)轉(zhuǎn)碼:
String wrongStr = response.getParameter(“name”);
String correctStr = new String(wrongStr.getBytes(“ISO8859_1”),”GB2312”);
在最新的SERVLET規(guī)範(fàn)裏面,也可以在獲取參數(shù)之前執(zhí)行如下代碼:
request.setCharacterEncoding(“GB2312”);
4.2 數(shù)據(jù)庫的編碼
(1) 數(shù)據(jù)庫使用UTF-16
如果String中是UNICODE字符,寫入讀出時(shí)不需要轉(zhuǎn)碼
(2) 數(shù)據(jù)庫使用ISO8859_1
如果String中是UNICODE字符,寫入讀出時(shí)需要轉(zhuǎn)碼
寫入:String newStr = new String(oldStr.getByte(“GB2312”), “ISO8859_1”);
讀出:String newStr = new String(oldStr.getByte(“ISO8859_1”),”GB2312”);
五、源文件的編碼
5.1 資源文件
資源文件的編碼方式和編輯平臺(tái)相關(guān)。在WINDOWS平臺(tái)下編寫的資源文件,以GB2312方式編碼。在編譯時(shí)需要轉(zhuǎn)碼,以確保在各個(gè)平臺(tái)上的正確性:
native2ascii –encoding GB2312 source.properties
這樣從資源文件中讀出的就是正確的UNICODE字符串。
5.2 源文件
源文件的編碼方式和編輯平臺(tái)相關(guān)。在WINDOWS平臺(tái)下開發(fā)的源文件,以GB2312方式編碼。在編譯的時(shí)候,需要指定源文件的編碼方式:
javac –encoding GB2312
JAVA編譯後生成的字節(jié)文件的編碼為UTF-8。
點(diǎn)最新版TOMCAT4.1.18支援request.setCharacterEncoding(String enc)
點(diǎn)資源文件轉(zhuǎn)碼成company.name=\u82f1\u65af\u514b
點(diǎn)如果數(shù)據(jù)庫使用utf-16則不需要這部分轉(zhuǎn)碼
點(diǎn)頁面上應(yīng)有
轉(zhuǎn)碼ⅰ:
String s = new String
(request.getParameter(“name”).getBytes(“ISO8859_1”),”GB2312”);
轉(zhuǎn)碼ⅱ:
String s = new String(name.getBytes(“GB2312”),”ISO8859_1”);
轉(zhuǎn)碼ⅲ:
String s = new String(name.getBytes(“ISO8859_1”),” GB2312”);
1.單個(gè).class文件編譯
??首先從控制臺(tái)進(jìn)入jad.exe目錄
?? 運(yùn)行?jad example1.class
??(此時(shí)example1.class和jad.exe位於同一個(gè)目錄)
? 成功運(yùn)行後﹐當(dāng)前目錄下產(chǎn)生一個(gè)新文件example1.jad﹐裡面為反編譯後的java代碼
2.多個(gè).class文件編譯
與1大致相同
輸入jad -o -dtest -sjava *.class
其中"test"表示反編譯文件的存放目錄﹐"java"表示反編譯後產(chǎn)生文件的後綴名
3.某文件夾下所有文件編譯
與1大致相同
輸入jad -o -dtest -sjava? tree/**/*.class
其中"test"表示反編譯文件的存放目錄﹐"java"表示反編譯後產(chǎn)生文件的後綴名
tree表示源文件夾名
詳細(xì)說明參看“Readme.txt”
jad下載聯(lián)接
http://www.infoxa.com/asp/soft_file/xxnr_soft_242.htm
Java操作Excel的一種方法?
?bromon原創(chuàng)?版權(quán)所有
MS的電子表格(Excel)是Office的重要成員,是保存統(tǒng)計(jì)數(shù)據(jù)的一種常用格式。作為辦公文檔,勢(shì)必要涉及到的電子文檔的交換,Excel是一種在企業(yè)中非常通用的文件格式,打印和管理也比較方便。在一個(gè)Java應(yīng)用中,將一部分?jǐn)?shù)據(jù)生成Excel格式,是與其他系統(tǒng)無縫連接的重要手段。
在開源世界中,有兩套比較有影響的API可供使用,一個(gè)是POI,一個(gè)是jExcelAPI。其中jExcelAPI是一個(gè)韓國程序員的作品,雖然沒有POI那樣血統(tǒng)高貴,但是在筆者的使用過程中,感覺簡(jiǎn)單方便,對(duì)中文支持非常好,功能也比較強(qiáng)大。可以在sourceforge.net下載。作者的網(wǎng)站上對(duì)它的特征有如下描述:
?●?支持Excel?95-2000的所有版本
?●?生成Excel?2000標(biāo)準(zhǔn)格式
?●?支持字體、數(shù)字、日期操作
?●?能夠修飾單元格屬性
?●?支持圖像和圖表
應(yīng)該說以上功能已經(jīng)能夠大致滿足我們的需要。最關(guān)鍵的是這套API是純Java的,并不依賴Windows系統(tǒng),即使運(yùn)行在Linux下,它同樣能夠正確的處理Excel文件。另外需要說明的是,這套API對(duì)圖形和圖表的支持很有限,而且僅僅識(shí)別PNG格式。
搭建環(huán)境
將下載后的文件解包,得到j(luò)xl.jar,放入classpath,安裝就完成了。
?基本操作
?一、創(chuàng)建文件
?擬生成一個(gè)名為“測(cè)試數(shù)據(jù).xls”的Excel文件,其中第一個(gè)工作表被命名為“第一頁”,大致效果如下:
?
?代碼(CreateXLS.java):
??
?
- //生成Excel的類
- ?import?java.io.*;
- ?import?jxl.*;
- ?import?jxl.write.*;
- ?public?class?CreateXLS
- ?{
- ? public?static?void?main(String?args[])
- ? {
- ? try
- ? {
- //打開文件
- WritableWorkbook?book=Workbook.createWorkbook(new?File(“測(cè)試.xls”));
- ?????
- //生成名為“第一頁”的工作表,參數(shù)0表示這是第一頁
- WritableSheet?sheet=book.createSheet(“第一頁”,0);
- ???
- //在Label對(duì)象的構(gòu)造子中指名單元格位置是第一列第一行(0,0)
- //以及單元格內(nèi)容為test
- Label?label=new?Label(0,0,”test”);
- //將定義好的單元格添加到工作表中
- sheet.addCell(label);
- /**生成一個(gè)保存數(shù)字的單元格
- *必須使用Number的完整包路徑,否則有語法歧義
- *單元格位置是第二列,第一行,值為789.123
- */
- jxl.write.Number?number?=?new?jxl.write.Number(1,0,789.123);
- sheet.addCell(number);
- //寫入數(shù)據(jù)并關(guān)閉文件
- book.write();
- book.close();
- }catch(Exception?e)
- {
- System.out.println(e);
- }
- }
- ?}?
?編譯執(zhí)行后,會(huì)在當(dāng)前位置產(chǎn)生一個(gè)Excel文件。
?三、讀取文件
?以剛才我們創(chuàng)建的Excel文件為例,做一個(gè)簡(jiǎn)單的讀取操作,程序代碼如下:
??
?
- //讀取Excel的類
- ?import?java.io.*;
- ?import?jxl.*;
- ?public?class?ReadXLS
- ?{
- ?public?static?void?main(String?args[])
- ?{
- ??try
- ??{
- ???Workbook?book=
- ?Workbook.getWorkbook(new?File(“測(cè)試.xls”));
- ???
- ???//獲得第一個(gè)工作表對(duì)象
- ?Sheet?sheet=book.getSheet(0);
- ?//得到第一列第一行的單元格
- ?Cell?cell1=sheet.getCell(0,0);
- ?String?result=cell1.getContents();
- ?System.out.println(result);
- ?book.close();
- ??}catch(Exception?e)
- ??{
- ???System.out.println(e);
- ??}
- ?}
- ?}?
?程序執(zhí)行結(jié)果:test
?四、修改文件
?利用jExcelAPI可以修改已有的Excel文件,修改Excel文件的時(shí)候,除了打開文件的方式不同之外,其他操作和創(chuàng)建Excel是一樣的。下面的例子是在我們已經(jīng)生成的Excel文件中添加一個(gè)工作表:
?
- //修改Excel的類,添加一個(gè)工作表
- ?import?java.io.*;
- ?import?jxl.*;
- ?import?jxl.write.*;
- ?public?class?UpdateXLS
- ?{
- ?public?static?void?main(String?args[])
- ?{
- ??try
- ??{
- ???//Excel獲得文件
- ???Workbook?wb=Workbook.getWorkbook(new?File(“測(cè)試.xls”));
- ???
- ???//打開一個(gè)文件的副本,并且指定數(shù)據(jù)寫回到原文件
- ?WritableWorkbook?book=
- ?Workbook.createWorkbook(new?File(“測(cè)試.xls”),wb);
- ???
- ???//添加一個(gè)工作表
- ???WritableSheet?sheet=book.createSheet(“第二頁”,1);
- ???sheet.addCell(new?Label(0,0,”第二頁的測(cè)試數(shù)據(jù)”));
- ???
- ???book.write();
- ???book.close();
- ??}catch(Exception?e)
- ??{
- ???System.out.println(e);
- ??}
- ?}
- ?}?
?執(zhí)行結(jié)果如圖:
?
?高級(jí)操作
?一、?數(shù)據(jù)格式化
?在Excel中不涉及復(fù)雜的數(shù)據(jù)類型,能夠比較好的處理字串、數(shù)字和日期已經(jīng)能夠滿足一般的應(yīng)用。
?1、?字串格式化
?字符串的格式化涉及到的是字體、粗細(xì)、字號(hào)等元素,這些功能主要由WritableFont和WritableCellFormat類來負(fù)責(zé)。假設(shè)我們?cè)谏梢粋€(gè)含有字串的單元格時(shí),使用如下語句,為方便敘述,我們?yōu)槊恳恍忻罴恿司幪?hào):
?
- WritableFont?font1=
- ?new?WritableFont(WritableFont.TIMES,16,WritableFont.BOLD);?①
- ?WritableCellFormat?format1=new?WritableCellFormat(font1);?②
- ?Label?label=new?Label(0,0,”data?4?test”,format1)?③
?其中①指定了字串格式:字體為TIMES,字號(hào)16,加粗顯示。WritableFont有非常豐富的構(gòu)造子,供不同情況下使用,jExcelAPI的java-doc中有詳細(xì)列表,這里不再列出。
?②處代碼使用了WritableCellFormat類,這個(gè)類非常重要,通過它可以指定單元格的各種屬性,后面的單元格格式化中會(huì)有更多描述。
?③處使用了Label類的構(gòu)造子,指定了字串被賦予那種格式。
?在WritableCellFormat類中,還有一個(gè)很重要的方法是指定數(shù)據(jù)的對(duì)齊方式,比如針對(duì)我們上面的實(shí)例,可以指定:
?
- //把水平對(duì)齊方式指定為居中
- ?format1.setAlignment(jxl.format.Alignment.CENTRE);
?
- //把垂直對(duì)齊方式指定為居中
- ?format1.setVerticalAlignment(jxl.format.VerticalAlignment.CENTRE);
?二、單元格操作
?Excel中很重要的一部分是對(duì)單元格的操作,比如行高、列寬、單元格合并等,所幸jExcelAPI提供了這些支持。這些操作相對(duì)比較簡(jiǎn)單,下面只介紹一下相關(guān)的API。
?1、?合并單元格
?
- WritableSheet.mergeCells(int?m,int?n,int?p,int?q);?
?作用是從(m,n)到(p,q)的單元格全部合并,比如:
?
- WritableSheet?sheet=book.createSheet(“第一頁”,0);
?//合并第一列第一行到第六列第一行的所有單元格
?
- sheet.mergeCells(0,0,5,0);
?合并既可以是橫向的,也可以是縱向的。合并后的單元格不能再次進(jìn)行合并,否則會(huì)觸發(fā)異常。
?2、?行高和列寬
?
- WritableSheet.setRowView(int?i,int?height);
?作用是指定第i+1行的高度,比如:
?//將第一行的高度設(shè)為200
?
- sheet.setRowView(0,200);
- ?WritableSheet.setColumnView(int?i,int?width);
?作用是指定第i+1列的寬度,比如:
?//將第一列的寬度設(shè)為30
?
- sheet.setColumnView(0,30);
?jExcelAPI還有其他的一些功能,比如插入圖片等,這里就不再一一介紹,讀者可以自己探索。
可以用Java讀取Microsoft Excel文件。微軟提供了一個(gè)Excel的ODBC驅(qū)動(dòng)程序,因此我們就可以使用JDBC和Sun的JDBC-ODBC驅(qū)動(dòng)來讀取Excel文件了。
??如果你有個(gè)Excel文件,名為Book1.xls(譯者注:由于原文的例子我沒有下載下來,所以我用了自己的例子),并且,該文件中有一個(gè)工作表(sheet)名為Sheet1
??
微軟的ODBC驅(qū)動(dòng)程序把工作表中的第一行作為列名(譯者注:即字段名),工作表名作為數(shù)據(jù)庫表名。
??要通過JDBC訪問工作表,我們還必須創(chuàng)建一個(gè)新的ODBC數(shù)據(jù)源,在Windows 2000系統(tǒng)上創(chuàng)建數(shù)據(jù)源的過程如下:
進(jìn)入“控制面板” --> “管理工具” --> “數(shù)據(jù)源(ODBC)”,(譯者注:打開后選擇系統(tǒng)DSN),點(diǎn)擊添加,在彈出窗口中選擇“Driver do Microsoft Excel(*.xls)”
然后在數(shù)據(jù)源名處輸入你一個(gè)名字Book1(譯者注:相當(dāng)于數(shù)據(jù)庫名),然后點(diǎn)擊“選擇工作簿”,然后找到并選取你的Excel文件
點(diǎn)擊確定后,系統(tǒng)數(shù)據(jù)源列表中會(huì)出現(xiàn)你設(shè)置的數(shù)據(jù)源名稱,
??
??現(xiàn)在數(shù)據(jù)表已經(jīng)在數(shù)據(jù)源列表里了(譯者注:點(diǎn)擊確定完成配置)。
??(譯者注:我的例子中)現(xiàn)在如果我們想挑出test1列中的所有“測(cè)試”值,那就需要用以下的SQL查詢:
??SELECT test1 FROM [Sheet1$] WHERE test1='測(cè)試'
??要注意的是工作表名后面跟了一個(gè)“$”符號(hào),這個(gè)符號(hào)是不可缺少的。為什么?因?yàn)樗那昂笥蟹嚼ㄌ?hào),因?yàn)椤?”是SQL語句中的保留字。Life is never easy(譯者注:作者發(fā)感慨了)。
下面是例子程序:
import java.sql.Connection;
import java.sql.Statement;
import java.sql.ResultSet;
import java.sql.DriverManager;
public class ExcelReader {
????public static void main( String[] args ) {
????????Connection c = null;
????????Statement stmnt = null;
????????try {
????????????Class.forName( "sun.jdbc.odbc.JdbcOdbcDriver" );
????????????c = DriverManager.getConnection( "jdbc:odbc:Book1", "", "" );
????????????stmnt = c.createStatement();
????????????String query = "SELECT test1 FROM [Sheet1$] WHERE test1='測(cè)試'";
????????????ResultSet rs = stmnt.executeQuery( query );
????????????
????????????System.out.println( "查得匹配'測(cè)試'的test1的記錄為:" );
????????????while( rs.next() ) {
????????????????System.out.println( rs.getString( "test1" ) );
????????????}
????????}
????????catch( Exception e ) {
????????????System.err.println( e );
????????}
????????finally {
????????????try {
????????????????stmnt.close();
????????????????c.close();
????????????}
????????????catch( Exception e ) {
????????????????System.err.println( e );
????????????}
????????}
????}
}
在此程序中,主函數(shù)main() 建立了一個(gè)數(shù)據(jù)表的連接,并取出符合條件的記錄。
(譯者注:另外,我這里還有一段程序,是讀取所有記錄的程序,僅作參考):
import java.sql.Connection;
import java.sql.Statement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.DriverManager;
public class ExcelReader {
????public static void main(String[] args){
????????Connection connection = null;
????????try{
????????????Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
????????????Connection con = DriverManager.getConnection( "jdbc:odbc:Book1","","" );
????????????Statement st = con.createStatement();
????????????ResultSet rs = st.executeQuery( "SELECT * FROM [Sheet1$]" );
????????????ResultSetMetaData rsmd = rs.getMetaData();
????????????int numberOfColumns = rsmd.getColumnCount();
????????????while (rs.next()) {
????????????????for (int i = 1; i <= numberOfColumns; i++) {
????????????????????if(i>1)??//用逗號(hào)分隔各列
??????System.out.print(", ");
????????????????????String columnValue = rs.getString(i);
????????????????????System.out.print(columnValue);
????????????????}
????????????????System.out.println("");
????????????}
????????????st.close();
????????????con.close();
????????} catch(Exception ex) {
????????????System.err.print("Exception: ");
????????????System.err.println(ex.getMessage());
????????}
????}
}
?
SQL中的單記錄函數(shù)
1.ASCII
返回與指定的字符對(duì)應(yīng)的十進(jìn)制數(shù);
SQL> select ascii('A') A,ascii('a') a,ascii('0') zero,ascii(' ') space from dual;
??????? A???????? A????? ZERO???? SPACE
--------- --------- --------- ---------
?????? 65??????? 97??????? 48??????? 32
2.CHR
給出整數(shù),返回對(duì)應(yīng)的字符;
SQL> select chr(54740) zhao,chr(65) chr65 from dual;
ZH C
-- -
趙 A
3.CONCAT
連接兩個(gè)字符串;
SQL> select concat('010-','88888888')||'轉(zhuǎn)23'? 高乾競(jìng)電話 from dual;
高乾競(jìng)電話
----------------
010-88888888轉(zhuǎn)23
4.INITCAP
返回字符串并將字符串的第一個(gè)字母變?yōu)榇髮?
SQL> select initcap('smith') upp from dual;
UPP
-----
Smith
5.INSTR(C1,C2,I,J)
在一個(gè)字符串中搜索指定的字符,返回發(fā)現(xiàn)指定的字符的位置;
C1??? 被搜索的字符串
C2??? 希望搜索的字符串
I???? 搜索的開始位置,默認(rèn)為1
J???? 出現(xiàn)的位置,默認(rèn)為1
SQL> select instr('oracle traning','ra',1,2) instring from dual;
?INSTRING
---------
??????? 9
6.LENGTH
返回字符串的長度;
SQL> select name,length(name),addr,length(addr),sal,length(to_char(sal)) from gao.nchar_tst;
NAME?? LENGTH(NAME) ADDR???????????? LENGTH(ADDR)?????? SAL LENGTH(TO_CHAR(SAL))
------ ------------ ---------------- ------------ --------- --------------------
高乾競(jìng)??????????? 3 北京市海錠區(qū)??????????????? 6?? 9999.99??????????????????? 7
?
7.LOWER
返回字符串,并將所有的字符小寫
SQL> select lower('AaBbCcDd')AaBbCcDd from dual;
AABBCCDD
--------
aabbccdd
8.UPPER
返回字符串,并將所有的字符大寫
SQL> select upper('AaBbCcDd') upper from dual;
UPPER
--------
AABBCCDD
?
9.RPAD和LPAD(粘貼字符)
RPAD? 在列的右邊粘貼字符
LPAD? 在列的左邊粘貼字符
SQL> select lpad(rpad('gao',10,'*'),17,'*')from dual;
LPAD(RPAD('GAO',1
-----------------
*******gao*******
不夠字符則用*來填滿
10.LTRIM和RTRIM
LTRIM? 刪除左邊出現(xiàn)的字符串
RTRIM? 刪除右邊出現(xiàn)的字符串
SQL> select ltrim(rtrim('?? gao qian jing?? ',' '),' ') from dual;
LTRIM(RTRIM('
-------------
gao qian jing
11.SUBSTR(string,start,count)
取子字符串,從start開始,取count個(gè)
SQL> select substr('13088888888',3,8) from dual;
SUBSTR('
--------
08888888
12.REPLACE('string','s1','s2')
string?? 希望被替換的字符或變量
s1?????? 被替換的字符串
s2?????? 要替換的字符串
SQL> select replace('he love you','he','i') from dual;
REPLACE('H
----------
i love you
13.SOUNDEX
返回一個(gè)與給定的字符串讀音相同的字符串
SQL> create table table1(xm varchar(8));
SQL> insert into table1 values('weather');
SQL> insert into table1 values('wether');
SQL> insert into table1 values('gao');
SQL> select xm from table1 where soundex(xm)=soundex('weather');
XM
--------
weather
wether
14.TRIM('s' from 'string')
LEADING?? 剪掉前面的字符
TRAILING? 剪掉后面的字符
如果不指定,默認(rèn)為空格符
15.ABS
返回指定值的絕對(duì)值
SQL> select abs(100),abs(-100) from dual;
?ABS(100) ABS(-100)
--------- ---------
????? 100?????? 100
16.ACOS
給出反余弦的值
SQL> select acos(-1) from dual;
?ACOS(-1)
---------
3.1415927
17.ASIN
給出反正弦的值
SQL> select asin(0.5) from dual;
ASIN(0.5)
---------
.52359878
18.ATAN
返回一個(gè)數(shù)字的反正切值
SQL> select atan(1) from dual;
? ATAN(1)
---------
.78539816
19.CEIL
返回大于或等于給出數(shù)字的最小整數(shù)
SQL> select ceil(3.1415927) from dual;
CEIL(3.1415927)
---------------
????????????? 4
20.COS
返回一個(gè)給定數(shù)字的余弦
SQL> select cos(-3.1415927) from dual;
COS(-3.1415927)
---------------
???????????? -1
21.COSH
返回一個(gè)數(shù)字反余弦值
SQL> select cosh(20) from dual;
?COSH(20)
---------
242582598
22.EXP
返回一個(gè)數(shù)字e的n次方根
SQL> select exp(2),exp(1) from dual;
?? EXP(2)??? EXP(1)
--------- ---------
7.3890561 2.7182818
23.FLOOR
對(duì)給定的數(shù)字取整數(shù)
SQL> select floor(2345.67) from dual;
FLOOR(2345.67)
--------------
????????? 2345
24.LN
返回一個(gè)數(shù)字的對(duì)數(shù)值
SQL> select ln(1),ln(2),ln(2.7182818) from dual;
??? LN(1)???? LN(2) LN(2.7182818)
--------- --------- -------------
??????? 0 .69314718???? .99999999
25.LOG(n1,n2)
返回一個(gè)以n1為底n2的對(duì)數(shù)
SQL> select log(2,1),log(2,4) from dual;
?LOG(2,1)? LOG(2,4)
--------- ---------
??????? 0???????? 2
26.MOD(n1,n2)
返回一個(gè)n1除以n2的余數(shù)
SQL> select mod(10,3),mod(3,3),mod(2,3) from dual;
MOD(10,3)? MOD(3,3)? MOD(2,3)
--------- --------- ---------
??????? 1???????? 0???????? 2
27.POWER
返回n1的n2次方根
SQL> select power(2,10),power(3,3) from dual;
POWER(2,10) POWER(3,3)
----------- ----------
?????? 1024???????? 27
28.ROUND和TRUNC
按照指定的精度進(jìn)行舍入
SQL> select round(55.5),round(-55.4),trunc(55.5),trunc(-55.5) from dual;
ROUND(55.5) ROUND(-55.4) TRUNC(55.5) TRUNC(-55.5)
----------- ------------ ----------- ------------
???????? 56????????? -55????????? 55????????? -55
29.SIGN
取數(shù)字n的符號(hào),大于0返回1,小于0返回-1,等于0返回0
SQL> select sign(123),sign(-100),sign(0) from dual;
SIGN(123) SIGN(-100)?? SIGN(0)
--------- ---------- ---------
??????? 1???????? -1???????? 0
30.SIN
返回一個(gè)數(shù)字的正弦值
SQL> select sin(1.57079) from dual;
SIN(1.57079)
------------
?????????? 1
31.SIGH
返回雙曲正弦的值
SQL> select sin(20),sinh(20) from dual;
? SIN(20)? SINH(20)
--------- ---------
.91294525 242582598
32.SQRT
返回?cái)?shù)字n的根
SQL> select sqrt(64),sqrt(10) from dual;
?SQRT(64)? SQRT(10)
--------- ---------
??????? 8 3.1622777
33.TAN
返回?cái)?shù)字的正切值
SQL> select tan(20),tan(10) from dual;
? TAN(20)?? TAN(10)
--------- ---------
2.2371609 .64836083
34.TANH
返回?cái)?shù)字n的雙曲正切值
SQL> select tanh(20),tan(20) from dual;
?TANH(20)?? TAN(20)
--------- ---------
??????? 1 2.2371609
?
35.TRUNC
按照指定的精度截取一個(gè)數(shù)
SQL> select trunc(124.1666,-2) trunc1,trunc(124.16666,2) from dual;
?? TRUNC1 TRUNC(124.16666,2)
--------- ------------------
????? 100???????????? 124.16
?
36.ADD_MONTHS
增加或減去月份
SQL> select to_char(add_months(to_date('199912','yyyymm'),2),'yyyymm') from dual;
TO_CHA
------
200002
SQL> select to_char(add_months(to_date('199912','yyyymm'),-2),'yyyymm') from dual;
TO_CHA
------
199910
37.LAST_DAY
返回日期的最后一天
SQL> select to_char(sysdate,'yyyy.mm.dd'),to_char((sysdate)+1,'yyyy.mm.dd') from dual;
TO_CHAR(SY TO_CHAR((S
---------- ----------
2004.05.09 2004.05.10
SQL> select last_day(sysdate) from dual;
LAST_DAY(S
----------
31-5月 -04
38.MONTHS_BETWEEN(date2,date1)
給出date2-date1的月份
SQL> select months_between('19-12月-1999','19-3月-1999') mon_between from dual;
MON_BETWEEN
-----------
????????? 9
SQL>selectmonths_between(to_date('2000.05.20','yyyy.mm.dd'),to_date('2005.05.20','yyyy.mm.dd')) mon_betw from dual;
?MON_BETW
---------
????? -60
39.NEW_TIME(date,'this','that')
給出在this時(shí)區(qū)=other時(shí)區(qū)的日期和時(shí)間
SQL> select to_char(sysdate,'yyyy.mm.dd hh24:mi:ss') bj_time,to_char(new_time
? 2? (sysdate,'PDT','GMT'),'yyyy.mm.dd hh24:mi:ss') los_angles from dual;
BJ_TIME???????????? LOS_ANGLES
------------------- -------------------
2004.05.09 11:05:32 2004.05.09 18:05:32
40.NEXT_DAY(date,'day')
給出日期date和星期x之后計(jì)算下一個(gè)星期的日期
SQL> select next_day('18-5月-2001','星期五') next_day from dual;
NEXT_DAY
----------
25-5月 -01
?
41.SYSDATE
用來得到系統(tǒng)的當(dāng)前日期
SQL> select to_char(sysdate,'dd-mm-yyyy day') from dual;
TO_CHAR(SYSDATE,'
-----------------
09-05-2004 星期日
trunc(date,fmt)按照給出的要求將日期截?cái)?如果fmt='mi'表示保留分,截?cái)嗝?br />SQL> select to_char(trunc(sysdate,'hh'),'yyyy.mm.dd hh24:mi:ss') hh,
? 2? to_char(trunc(sysdate,'mi'),'yyyy.mm.dd hh24:mi:ss') hhmm from dual;
HH????????????????? HHMM
------------------- -------------------
2004.05.09 11:00:00 2004.05.09 11:17:00
?
42.CHARTOROWID
將字符數(shù)據(jù)類型轉(zhuǎn)換為ROWID類型
SQL> select rowid,rowidtochar(rowid),ename from scott.emp;
ROWID????????????? ROWIDTOCHAR(ROWID) ENAME
------------------ ------------------ ----------
AAAAfKAACAAAAEqAAA AAAAfKAACAAAAEqAAA SMITH
AAAAfKAACAAAAEqAAB AAAAfKAACAAAAEqAAB ALLEN
AAAAfKAACAAAAEqAAC AAAAfKAACAAAAEqAAC WARD
AAAAfKAACAAAAEqAAD AAAAfKAACAAAAEqAAD JONES
43.CONVERT(c,dset,sset)
將源字符串 sset從一個(gè)語言字符集轉(zhuǎn)換到另一個(gè)目的dset字符集
SQL> select convert('strutz','we8hp','f7dec') "conversion" from dual;
conver
------
strutz
44.HEXTORAW
將一個(gè)十六進(jìn)制構(gòu)成的字符串轉(zhuǎn)換為二進(jìn)制
45.RAWTOHEXT
將一個(gè)二進(jìn)制構(gòu)成的字符串轉(zhuǎn)換為十六進(jìn)制
?
46.ROWIDTOCHAR
將ROWID數(shù)據(jù)類型轉(zhuǎn)換為字符類型
?
47.TO_CHAR(date,'format')
SQL> select to_char(sysdate,'yyyy/mm/dd hh24:mi:ss') from dual;
TO_CHAR(SYSDATE,'YY
-------------------
2004/05/09 21:14:41
?
48.TO_DATE(string,'format')
將字符串轉(zhuǎn)化為ORACLE中的一個(gè)日期
49.TO_MULTI_BYTE
將字符串中的單字節(jié)字符轉(zhuǎn)化為多字節(jié)字符
SQL>? select to_multi_byte('高') from dual;
TO
--
高
50.TO_NUMBER
將給出的字符轉(zhuǎn)換為數(shù)字
SQL> select to_number('1999') year from dual;
???? YEAR
---------
???? 1999
51.BFILENAME(dir,file)
指定一個(gè)外部二進(jìn)制文件
SQL>insert into file_tb1 values(bfilename('lob_dir1','image1.gif'));
52.CONVERT('x','desc','source')
將x字段或變量的源source轉(zhuǎn)換為desc
SQL> select sid,serial#,username,decode(command,
? 2? 0,'none',
? 3? 2,'insert',
? 4? 3,
? 5? 'select',
? 6? 6,'update',
? 7? 7,'delete',
? 8? 8,'drop',
? 9? 'other') cmd? from v$session where type!='background';
????? SID?? SERIAL# USERNAME?????????????????????? CMD
--------- --------- ------------------------------ ------
??????? 1???????? 1??????????????????????????????? none
??????? 2???????? 1??????????????????????????????? none
??????? 3???????? 1??????????????????????????????? none
??????? 4???????? 1??????????????????????????????? none
??????? 5???????? 1??????????????????????????????? none
??????? 6???????? 1??????????????????????????????? none
??????? 7????? 1275??????????????????????????????? none
??????? 8????? 1275??????????????????????????????? none
??????? 9??????? 20 GAO??????????????????????????? select
?????? 10??????? 40 GAO??????????????????????????? none
53.DUMP(s,fmt,start,length)
DUMP函數(shù)以fmt指定的內(nèi)部數(shù)字格式返回一個(gè)VARCHAR2類型的值
SQL> col global_name for a30
SQL> col dump_string for a50
SQL> set lin 200
SQL> select global_name,dump(global_name,1017,8,5) dump_string from global_name;
GLOBAL_NAME??????????????????? DUMP_STRING
------------------------------ --------------------------------------------------
ORACLE.WORLD?????????????????? Typ=1 Len=12 CharacterSet=ZHS16GBK: W,O,R,L,D
54.EMPTY_BLOB()和EMPTY_CLOB()
這兩個(gè)函數(shù)都是用來對(duì)大數(shù)據(jù)類型字段進(jìn)行初始化操作的函數(shù)
55.GREATEST
返回一組表達(dá)式中的最大值,即比較字符的編碼大小.
SQL> select greatest('AA','AB','AC') from dual;
GR
--
AC
SQL> select greatest('啊','安','天') from dual;
GR
--
天
56.LEAST
返回一組表達(dá)式中的最小值
SQL> select least('啊','安','天') from dual;
LE
--
啊
57.UID
返回標(biāo)識(shí)當(dāng)前用戶的唯一整數(shù)
SQL> show user
USER 為"GAO"
SQL> select username,user_id from dba_users where user_id=uid;
USERNAME???????????????????????? USER_ID
------------------------------ ---------
GAO?????????????????????????????????? 25
?
58.USER
返回當(dāng)前用戶的名字
SQL> select user from? dual;
USER
------------------------------
GAO
59.USEREVN
返回當(dāng)前用戶環(huán)境的信息,opt可以是:
ENTRYID,SESSIONID,TERMINAL,ISDBA,LABLE,LANGUAGE,CLIENT_INFO,LANG,VSIZE
ISDBA? 查看當(dāng)前用戶是否是DBA如果是則返回true
SQL> select userenv('isdba') from dual;
USEREN
------
FALSE
SQL> select userenv('isdba') from dual;
USEREN
------
TRUE
SESSION
返回會(huì)話標(biāo)志
SQL> select userenv('sessionid') from dual;
USERENV('SESSIONID')
--------------------
???????????????? 152
ENTRYID
返回會(huì)話人口標(biāo)志
SQL> select userenv('entryid') from dual;
USERENV('ENTRYID')
------------------
???????????????? 0
INSTANCE
返回當(dāng)前INSTANCE的標(biāo)志
SQL> select userenv('instance') from dual;
USERENV('INSTANCE')
-------------------
????????????????? 1
LANGUAGE
返回當(dāng)前環(huán)境變量
SQL> select userenv('language') from dual;
USERENV('LANGUAGE')
----------------------------------------------------
SIMPLIFIED CHINESE_CHINA.ZHS16GBK
LANG
返回當(dāng)前環(huán)境的語言的縮寫
SQL> select userenv('lang') from dual;
USERENV('LANG')
----------------------------------------------------
ZHS
TERMINAL
返回用戶的終端或機(jī)器的標(biāo)志
SQL> select userenv('terminal') from dual;
USERENV('TERMINA
----------------
GAO
VSIZE(X)
返回X的大小(字節(jié))數(shù)
SQL> select vsize(user),user from dual;
VSIZE(USER) USER
----------- ------------------------------
????????? 6 SYSTEM
?
60.AVG(DISTINCT|ALL)
all表示對(duì)所有的值求平均值,distinct只對(duì)不同的值求平均值
SQLWKS> create table table3(xm varchar(8),sal number(7,2));
語句已處理。
SQLWKS>? insert into table3 values('gao',1111.11);
SQLWKS>? insert into table3 values('gao',1111.11);
SQLWKS>? insert into table3 values('zhu',5555.55);
SQLWKS> commit;
SQL> select avg(distinct sal) from gao.table3;
AVG(DISTINCTSAL)
----------------
???????? 3333.33
SQL> select avg(all sal) from gao.table3;
AVG(ALLSAL)
-----------
??? 2592.59
61.MAX(DISTINCT|ALL)
求最大值,ALL表示對(duì)所有的值求最大值,DISTINCT表示對(duì)不同的值求最大值,相同的只取一次
SQL> select max(distinct sal) from scott.emp;
MAX(DISTINCTSAL)
----------------
??????????? 5000
62.MIN(DISTINCT|ALL)
求最小值,ALL表示對(duì)所有的值求最小值,DISTINCT表示對(duì)不同的值求最小值,相同的只取一次
SQL> select min(all sal) from gao.table3;
MIN(ALLSAL)
-----------
??? 1111.11
63.STDDEV(distinct|all)
求標(biāo)準(zhǔn)差,ALL表示對(duì)所有的值求標(biāo)準(zhǔn)差,DISTINCT表示只對(duì)不同的值求標(biāo)準(zhǔn)差
SQL> select stddev(sal) from scott.emp;
STDDEV(SAL)
-----------
? 1182.5032
SQL> select stddev(distinct sal) from scott.emp;
STDDEV(DISTINCTSAL)
-------------------
?????????? 1229.951
?
64.VARIANCE(DISTINCT|ALL)
求協(xié)方差
SQL> select variance(sal) from scott.emp;
VARIANCE(SAL)
-------------
??? 1398313.9
65.GROUP BY
主要用來對(duì)一組數(shù)進(jìn)行統(tǒng)計(jì)
SQL> select deptno,count(*),sum(sal) from scott.emp group by deptno;
?? DEPTNO? COUNT(*)? SUM(SAL)
--------- --------- ---------
?????? 10???????? 3????? 8750
?????? 20???????? 5???? 10875
?????? 30???????? 6????? 9400
?
66.HAVING
對(duì)分組統(tǒng)計(jì)再加限制條件
SQL> select deptno,count(*),sum(sal) from scott.emp group by deptno having count(*)>=5;
?? DEPTNO? COUNT(*)? SUM(SAL)
--------- --------- ---------
?????? 20???????? 5???? 10875
?????? 30???????? 6????? 9400
SQL> select deptno,count(*),sum(sal) from scott.emp having count(*)>=5 group by deptno ;
?? DEPTNO? COUNT(*)? SUM(SAL)
--------- --------- ---------
?????? 20???????? 5???? 10875
?????? 30???????? 6????? 9400
67.ORDER BY
用于對(duì)查詢到的結(jié)果進(jìn)行排序輸出
SQL> select deptno,ename,sal from scott.emp order by deptno,sal desc;
?? DEPTNO ENAME??????????? SAL
--------- ---------- ---------
?????? 10 KING??????????? 5000
?????? 10 CLARK?????????? 2450
?????? 10 MILLER????????? 1300
?????? 20 SCOTT?????????? 3000
?????? 20 FORD??????????? 3000
?????? 20 JONES?????????? 2975
?????? 20 ADAMS?????????? 1100
?????? 20 SMITH??????????? 800
?????? 30 BLAKE?????????? 2850
?????? 30 ALLEN?????????? 1600
?????? 30 TURNER????????? 1500
?????? 30 WARD??????????? 1250
?????? 30 MARTIN????????? 1250
?????? 30 JAMES??????????? 950
如何從一位菜鳥蛻變成為高手,靈活使用的SQL語句是必不可少的。本文收集了部分比較經(jīng)典,常用的SQL語句供大家參考,希望對(duì)大家有所幫助。
說明:復(fù)制表(只復(fù)制結(jié)構(gòu),源表名:a 新表名:b)
SQL: select * into b from a where 1<>1
說明:拷貝表(拷貝數(shù)據(jù),源表名:a 目標(biāo)表名:b)
SQL: insert into b(a, b, c) select d,e,f from b;
說明:顯示文章、提交人和最后回復(fù)時(shí)間
SQL: select a.title,a.username,b.adddate from table a,(select max(adddate) adddate from table where table.title=a.title) b
說明:外連接查詢(表名1:a 表名2:b)
SQL: select a.a, a.b, a.c, b.c, b.d, b.f from a LEFT OUT JOIN b ON a.a = b.c
說明:日程安排提前五分鐘提醒
SQL: select * from 日程安排 where datediff('minute',f開始時(shí)間,getdate())>5
說明:兩張關(guān)聯(lián)表,刪除主表中已經(jīng)在副表中沒有的信息
SQL:
delete from info where not exists ( select * from infobz where info.infid=infobz.infid
說明:--
SQL:
SELECT A.NUM, A.NAME, B.UPD_DATE, B.PREV_UPD_DATE
FROM TABLE1,
(SELECT X.NUM, X.UPD_DATE, Y.UPD_DATE PREV_UPD_DATE
FROM (SELECT NUM, UPD_DATE, INBOUND_QTY, STOCK_ONHAND
FROM TABLE2
WHERE TO_CHAR(UPD_DATE,'YYYY/MM') = TO_CHAR(SYSDATE, 'YYYY/MM')) X,
(SELECT NUM, UPD_DATE, STOCK_ONHAND
FROM TABLE2
WHERE TO_CHAR(UPD_DATE,'YYYY/MM') =
TO_CHAR(TO_DATE(TO_CHAR(SYSDATE, 'YYYY/MM') ¦¦ '/01','YYYY/MM/DD') - 1, 'YYYY/MM') Y,
WHERE X.NUM = Y.NUM (+)
AND X.INBOUND_QTY + NVL(Y.STOCK_ONHAND,0) <> X.STOCK_ONHAND B
WHERE A.NUM = B.NUM
說明:--
SQL:
select * from studentinfo where not exists(select * from student where studentinfo.id=student.id) and 系名稱='"&strdepartmentname&"' and 專業(yè)名稱='"&strprofessionname&"' order by 性別,生源地,高考總成績(jī)
說明:
從數(shù)據(jù)庫中去一年的各單位電話費(fèi)統(tǒng)計(jì)(電話費(fèi)定額賀電化肥清單兩個(gè)表來源)
SQL:
SELECT a.userper, a.tel, a.standfee, TO_CHAR(a.telfeedate, 'yyyy') AS telyear,
SUM(decode(TO_CHAR(a.telfeedate, 'mm'), '01', a.factration)) AS JAN,
SUM(decode(TO_CHAR(a.telfeedate, 'mm'), '02', a.factration)) AS FRI,
SUM(decode(TO_CHAR(a.telfeedate, 'mm'), '03', a.factration)) AS MAR,
SUM(decode(TO_CHAR(a.telfeedate, 'mm'), '04', a.factration)) AS APR,
SUM(decode(TO_CHAR(a.telfeedate, 'mm'), '05', a.factration)) AS MAY,
SUM(decode(TO_CHAR(a.telfeedate, 'mm'), '06', a.factration)) AS JUE,
SUM(decode(TO_CHAR(a.telfeedate, 'mm'), '07', a.factration)) AS JUL,
SUM(decode(TO_CHAR(a.telfeedate, 'mm'), '08', a.factration)) AS AGU,
SUM(decode(TO_CHAR(a.telfeedate, 'mm'), '09', a.factration)) AS SEP,
SUM(decode(TO_CHAR(a.telfeedate, 'mm'), '10', a.factration)) AS OCT,
SUM(decode(TO_CHAR(a.telfeedate, 'mm'), '11', a.factration)) AS NOV,
SUM(decode(TO_CHAR(a.telfeedate, 'mm'), '12', a.factration)) AS DEC
FROM (SELECT a.userper, a.tel, a.standfee, b.telfeedate, b.factration
FROM TELFEESTAND a, TELFEE b
WHERE a.tel = b.telfax) a
GROUP BY a.userper, a.tel, a.standfee, TO_CHAR(a.telfeedate, 'yyyy')
說明:四表聯(lián)查問題:
SQL: select * from a left inner join b on a.a=b.b right inner join c on a.a=c.c inner join d on a.a=d.d where .....
說明:得到表中最小的未使用的ID號(hào)
SQL:
SELECT (CASE WHEN EXISTS(SELECT * FROM Handle b WHERE b.HandleID = 1) THEN MIN(HandleID) + 1 ELSE 1 END) as HandleID
FROM Handle
WHERE NOT HandleID IN (SELECT a.HandleID - 1 FROM Handle a)
OC4J里配置數(shù)據(jù)源:
1.application.xml的<data-sources>元素必須指出data-sources.xml文件的文件名和路徑,即:
<data-sources
path = "data-sources.xml"
/>
一般application.xml文件和data-sources.xml 文件都在j2ee/home/config/下。所以<data-sources>元素的path屬性只包括data-sources.xml的文件名;
2.data-sources.xml文件中定義數(shù)據(jù)源:
<data-source
?class="com.evermind.sql.DriverManagerDataSource"
?name="OracleDS"
?location="jdbc/OracleCoreDS"
?xa-location="jdbc/xa/OracleXADS"
?ejb-location="jdbc/OracleDS"
?connection-driver="oracle.jdbc.driver.OracleDriver"
?username="hr"
?password="hr"
?url="jdbc:oracle:thin:@myhost:1521:ORCL"
?inactivity-timeout="30"
/>
class屬性定義需要定義的數(shù)據(jù)源類型;
location、xa-location和ejb-location定義JNDI名字;
connection-driver指出連接驅(qū)動(dòng)。
例如:
?<data-source
??class="com.evermind.sql.DriverManagerDataSource"
??name="MyConnection"
??location="jdbc/MyConnection"
??connection-driver="oracle.jdbc.driver.OracleDriver"
??username="portal"
??password="pportalgis"
??url="jdbc:oracle:thin:@172.18.2.6:1521:apps"
??inactivity-timeout="30"
??max-connections="50"
??max-connect-attempts="2"
??min-connections="4"
?/>
2.程序調(diào)用:
Context env= new InitialContext();
DataSource pool= (DataSource)env.lookup("jdbc/MyConnection");
Connection conn=pool.getConnection();
oracle.jdbc.OracleConnection 分為:
?getConnection(); //數(shù)據(jù)源中已定義用戶名和密碼
?getConnection(String username, String password); //數(shù)據(jù)源中未定義用戶名和密碼
可以如下:
oracle.jdbc.OracleConnection conn =(oracle.jdbc.OracleConnection) pool.getConnection();
作為J2EE開發(fā)人員,我們似乎經(jīng)常關(guān)注“后端機(jī)制(backend mechanics)”。我們通常會(huì)忘記,J2EE的主要成功之處在Web應(yīng)用程序方面;許多原因使得人們喜歡利用Web開發(fā)應(yīng)用程序,但主要還是因?yàn)槠湟子诓渴鸬奶攸c(diǎn)允許站點(diǎn)以盡可能低的成本擁有上百萬的用戶。遺憾的是,在過去幾年中,我們?cè)诤蠖送度肓颂嗟臅r(shí)間,而在使我們的Web用戶界面對(duì)用戶自然和響應(yīng)靈敏方面卻投入不足。
本文介紹一種方法,Ajax,使用它可以構(gòu)建更為動(dòng)態(tài)和響應(yīng)更靈敏的Web應(yīng)用程序。該方法的關(guān)鍵在于對(duì)瀏覽器端的JavaScript、DHTML和與服務(wù)器異步通信的組合。本文也演示了啟用這種方法是多么簡(jiǎn)單:利用一個(gè)Ajax框架(指DWR)構(gòu)造一個(gè)應(yīng)用程序,它直接從瀏覽器與后端服務(wù)進(jìn)行通信。如果使用得當(dāng),這種強(qiáng)大的力量可以使應(yīng)用程序更加自然和響應(yīng)靈敏,從而提升用戶的瀏覽體驗(yàn)。
該應(yīng)用程序中所使用的示例代碼已打包為單獨(dú)的WAR文件,可供下載。
簡(jiǎn)介
術(shù)語Ajax用來描述一組技術(shù),它使瀏覽器可以為用戶提供更為自然的瀏覽體驗(yàn)。在Ajax之前,Web站點(diǎn)強(qiáng)制用戶進(jìn)入提交/等待/重新顯示范例,用戶的動(dòng)作總是與服務(wù)器的“思考時(shí)間”同步。Ajax提供與服務(wù)器異步通信的能力,從而使用戶從請(qǐng)求/響應(yīng)的循環(huán)中解脫出來。借助于Ajax,可以在用戶單擊按鈕時(shí),使用JavaScript和DHTML立即更新UI,并向服務(wù)器發(fā)出異步請(qǐng)求,以執(zhí)行更新或查詢數(shù)據(jù)庫。當(dāng)請(qǐng)求返回時(shí),就可以使用JavaScript和CSS來相應(yīng)地更新UI,而不是刷新整個(gè)頁面。最重要的是,用戶甚至不知道瀏覽器正在與服務(wù)器通信:Web站點(diǎn)看起來是即時(shí)響應(yīng)的。
雖然Ajax所需的基礎(chǔ)架構(gòu)已經(jīng)出現(xiàn)了一段時(shí)間,但直到最近異步請(qǐng)求的真正威力才得到利用。能夠擁有一個(gè)響應(yīng)極其靈敏的Web站點(diǎn)確實(shí)激動(dòng)人心,因?yàn)樗罱K允許開發(fā)人員和設(shè)計(jì)人員使用標(biāo)準(zhǔn)的HTML/CSS/JavaScript堆棧創(chuàng)建“桌面風(fēng)格的(desktop-like)”可用性。
通常,在J2EE中,開發(fā)人員過于關(guān)注服務(wù)和持久性層的開發(fā),以至于用戶界面的可用性已經(jīng)落后。在一個(gè)典型的J2EE開發(fā)周期中,常常會(huì)聽到這樣的話,“我們沒有可投入U(xiǎn)I的時(shí)間”或“不能用HTML實(shí)現(xiàn)”。但是,以下Web站點(diǎn)證明,這些理由再也站不住腳了:
所有這些Web站點(diǎn)都告訴我們,Web應(yīng)用程序不必完全依賴于從服務(wù)器重新載入頁面來向用戶呈現(xiàn)更改。一切似乎就在瞬間發(fā)生。簡(jiǎn)而言之,在涉及到用戶界面的響應(yīng)靈敏度時(shí),基準(zhǔn)設(shè)得更高了。
定義Ajax
Adaptive Path公司的Jesse James Garrett這樣定義Ajax:
Ajax不是一種技術(shù)。實(shí)際上,它由幾種蓬勃發(fā)展的技術(shù)以新的強(qiáng)大方式組合而成。Ajax包含:
這非常好,但為什么要以Ajax命名呢?其實(shí)術(shù)語Ajax是由Jesse James Garrett創(chuàng)造的,他說它是“Asynchronous JavaScript + XML的簡(jiǎn)寫”。
Ajax的工作原理
Ajax的核心是JavaScript對(duì)象XmlHttpRequest。該對(duì)象在Internet Explorer 5中首次引入,它是一種支持異步請(qǐng)求的技術(shù)。簡(jiǎn)而言之,XmlHttpRequest使您可以使用JavaScript向服務(wù)器提出請(qǐng)求并處理響應(yīng),而不阻塞用戶。
在創(chuàng)建Web站點(diǎn)時(shí),在客戶端執(zhí)行屏幕更新為用戶提供了很大的靈活性。下面是使用Ajax可以完成的功能:
- 動(dòng)態(tài)更新購物車的物品總數(shù),無需用戶單擊Update并等待服務(wù)器重新發(fā)送整個(gè)頁面。
- 提升站點(diǎn)的性能,這是通過減少從服務(wù)器下載的數(shù)據(jù)量而實(shí)現(xiàn)的。例如,在Amazon的購物車頁面,當(dāng)更新籃子中的一項(xiàng)物品的數(shù)量時(shí),會(huì)重新載入整個(gè)頁面,這必須下載32K的數(shù)據(jù)。如果使用Ajax計(jì)算新的總量,服務(wù)器只會(huì)返回新的總量值,因此所需的帶寬僅為原來的百分之一。
- 消除了每次用戶輸入時(shí)的頁面刷新。例如,在Ajax中,如果用戶在分頁列表上單擊Next,則服務(wù)器數(shù)據(jù)只刷新列表而不是整個(gè)頁面。
- 直接編輯表格數(shù)據(jù),而不是要求用戶導(dǎo)航到新的頁面來編輯數(shù)據(jù)。對(duì)于Ajax,當(dāng)用戶單擊Edit時(shí),可以將靜態(tài)表格刷新為內(nèi)容可編輯的表格。用戶單擊Done之后,就可以發(fā)出一個(gè)Ajax請(qǐng)求來更新服務(wù)器,并刷新表格,使其包含靜態(tài)、只讀的數(shù)據(jù)。
一切皆有可能!但愿它能夠激發(fā)您開始開發(fā)自己的基于Ajax的站點(diǎn)。然而,在開始之前,讓我們介紹一個(gè)現(xiàn)有的Web站點(diǎn),它遵循傳統(tǒng)的提交/等待/重新顯示的范例,我們還將討論Ajax如何提升用戶體驗(yàn)。
Ajax可用于那些場(chǎng)景?——一個(gè)例子:MSN Money頁面
前幾天,在瀏覽MSN Money頁面的時(shí)候,有一篇關(guān)于房地產(chǎn)投資的文章引起了我的好奇心。我決定使用站點(diǎn)的“Rate this article”(評(píng)價(jià)本文)功能,鼓勵(lì)其他的用戶花一點(diǎn)時(shí)間來閱讀這篇文章。在我單擊vote按鈕并等待了一會(huì)兒之后,整個(gè)頁面被刷新,在原來投票問題所在的地方出現(xiàn)了一個(gè)漂亮的感謝畫面。

而Ajax能夠使用戶的體驗(yàn)更加愉快,它可以提供響應(yīng)更加靈敏的UI,并消除頁面刷新所帶來的閃爍。目前,由于要刷新整個(gè)頁面,需要傳送大量的數(shù)據(jù),因?yàn)楸仨氈匦掳l(fā)送整個(gè)頁面。如果使用Ajax,服務(wù)器可以返回一個(gè)包含了感謝信息的500字節(jié)的消息,而不是發(fā)送26,813字節(jié)的消息來刷新整個(gè)頁面。即使使用的是高速Internet,傳送26K和1/2K的差別也非常大。同樣重要的是,只需要刷新與投票相關(guān)的一小節(jié),而不是刷新整個(gè)屏幕。
讓我們利用Ajax實(shí)現(xiàn)自己的基本投票系統(tǒng)。
原始的Ajax:直接使用XmlHttpRequest
如上所述,Ajax的核心是JavaScript對(duì)象XmlHttpRequest。下面的示例文章評(píng)價(jià)系統(tǒng)將帶您熟悉Ajax的底層基本知識(shí):http://tearesolutions.com/ajax-demo/raw-ajax.html。注:如果您已經(jīng)在本地WebLogic容器中安裝了ajax-demo.war,可以導(dǎo)航到http://localhost:7001/ajax-demo/raw-ajax.html,
瀏覽應(yīng)用程序,參與投票,并親眼看它如何運(yùn)轉(zhuǎn)。熟悉了該應(yīng)用程序之后,繼續(xù)閱讀,進(jìn)一步了解其工作原理細(xì)節(jié)。
首先,您擁有一些簡(jiǎn)單的定位點(diǎn)標(biāo)記,它連接到一個(gè)JavaScriptcastVote(rank)函數(shù)。
function castVote(rank) {
var url = "/ajax-demo/static-article-ranking.html";
var callback = processAjaxResponse;
executeXhr(callback, url);
}
該函數(shù)為您想要與之通信的服務(wù)器資源創(chuàng)建一個(gè)URL并調(diào)用內(nèi)部函數(shù)executeXhr,提供一個(gè)回調(diào)JavaScript函數(shù),一旦服務(wù)器響應(yīng)可用,該函數(shù)就被執(zhí)行。由于我希望它運(yùn)行在一個(gè)簡(jiǎn)單的Apache環(huán)境中,“cast vote URL”只是一個(gè)簡(jiǎn)單的HTML頁面。在實(shí)際情況中,被調(diào)用的URL將記錄票數(shù)并動(dòng)態(tài)地呈現(xiàn)包含投票總數(shù)的響應(yīng)。
下一步是發(fā)出一個(gè)XmlHttpRequest請(qǐng)求:
function executeXhr(callback, url) {
// branch for native XMLHttpRequest object
if (window.XMLHttpRequest) {
req = new XMLHttpRequest();
req.onreadystatechange = callback;
req.open("GET", url, true);
req.send(null);
} // branch for IE/Windows ActiveX version
else if (window.ActiveXObject) {
req = new ActiveXObject("Microsoft.XMLHTTP");
if (req) {
req.onreadystatechange = callback;
req.open("GET", url, true);
req.send();
}
}
}
如您所見,執(zhí)行一個(gè)XmlHttpRequest并不簡(jiǎn)單,但非常直觀。和平常一樣,在JavaScript領(lǐng)域,大部分的工作量都花在確保瀏覽器兼容方面。在這種情況下,首先要確定XmlHttpRequest是否可用。如果不能用,很可能要使用Internet Explorer,這樣就要使用所提供的ActiveX實(shí)現(xiàn)。
executeXhr()方法中最關(guān)鍵的部分是這兩行:
req.onreadystatechange = callback;
req.open("GET", url, true);
第一行定義了JavaScript回調(diào)函數(shù),您希望一旦響應(yīng)就緒它就自動(dòng)執(zhí)行,而req.open()方法中所指定的“true”標(biāo)志說明您想要異步執(zhí)行該請(qǐng)求。
一旦服務(wù)器處理完XmlHttpRequest并返回給瀏覽器,使用req.onreadystatechange指派所設(shè)置的回調(diào)方法將被自動(dòng)調(diào)用。
function processAjaxResponse() {
// only if req shows "loaded"
if (req.readyState == 4) {
// only if "OK"
if (req.status == 200) {
502 502'votes').innerHTML = req.responseText;
} else {
alert("There was a problem retrieving the XML data:
" +
req.statusText);
}
}
}
該代碼相當(dāng)簡(jiǎn)潔,并且使用了幾個(gè)幻數(shù),這使得難以一下子看出發(fā)生了什么。為了弄清楚這一點(diǎn),下面的表格(引用自http://developer.apple.com/internet/webcontent/xmlhttpreq.html)列舉了常用的XmlHttpRequest對(duì)象屬性。
屬性 | 描述 |
onreadystatechange | 每次狀態(tài)改變所觸發(fā)事件的事件處理程序 |
readyState | 對(duì)象狀態(tài)值:
- 0 = 未初始化(uninitialized)
- 1 = 正在加載(loading)
- 2 = 加載完畢(loaded)
- 3 = 交互(interactive)
- 4 = 完成(complete)
|
responseText | 從服務(wù)器進(jìn)程返回的數(shù)據(jù)的字符串形式 |
responseXML | 從服務(wù)器進(jìn)程返回的DOM兼容的文檔數(shù)據(jù)對(duì)象 |
status | 從服務(wù)器返回的數(shù)字代碼,比如404(未找到)或200(就緒) |
statusText | 伴隨狀態(tài)碼的字符串信息 |
現(xiàn)在processVoteResponse()函數(shù)開始顯示出其意義了。它首先檢查XmlHttpRequest的整體狀態(tài)以保證它已經(jīng)完成(readyStatus == 4),然后根據(jù)服務(wù)器的設(shè)定詢問請(qǐng)求狀態(tài)。如果一切正常(status == 200),就使用innerHTML屬性重寫DOM的“votes”節(jié)點(diǎn)的內(nèi)容。
既然您親眼看到了XmlHttpRequest對(duì)象是如何工作的,就讓我們利用一個(gè)旨在簡(jiǎn)化JavaScript與Java應(yīng)用程序之間的異步通信的框架來對(duì)具體的細(xì)節(jié)進(jìn)行抽象。
Ajax: DWR方式
按照與文章評(píng)價(jià)系統(tǒng)相同的流程,我們將使用Direct Web Remoting(DWR)框架實(shí)現(xiàn)同樣的功能。
假定文章和投票結(jié)果存儲(chǔ)在一個(gè)數(shù)據(jù)庫中,使用某種對(duì)象/關(guān)系映射技術(shù)來完成抽取工作。為了部署起來盡可能地簡(jiǎn)單,我們不會(huì)使用數(shù)據(jù)庫進(jìn)行持久性存儲(chǔ)。此外,為使應(yīng)用程序盡可能通用,也不使用Web框架。相反,應(yīng)用程序?qū)囊粋€(gè)靜態(tài)HTML文件開始,可以認(rèn)為它由服務(wù)器動(dòng)態(tài)地呈現(xiàn)。除了這些簡(jiǎn)化措施,應(yīng)用程序還應(yīng)該使用Spring Framework關(guān)聯(lián)一切,以便輕松看出如何在一個(gè)“真實(shí)的”應(yīng)用程序中使用DWR。
現(xiàn)在應(yīng)該下載示例應(yīng)用程序并熟悉它。該應(yīng)用程序被壓縮為標(biāo)準(zhǔn)的WAR文件,因此您可以把它放置到任何一個(gè)Web容器中——無需進(jìn)行配置。部署完畢之后,就可以導(dǎo)航到http://localhost:7001/ajax_demo/dwr-ajax.html來運(yùn)行程序。
可以查看HTML 源代碼,了解它如何工作。給人印象最深的是,代碼如此簡(jiǎn)單——所有與服務(wù)器的交互都隱藏在JavaScript對(duì)象ajaxSampleSvc的后面。更加令人驚訝的是,ajaxSampleSvc服務(wù)不是由手工編寫而是完全自動(dòng)生成的!讓我們繼續(xù),看看這是如何做到的。
引入DWR
如同在“原始的Ajax”一節(jié)所演示的那樣,直接使用XmlHttpRequest創(chuàng)建異步請(qǐng)求非常麻煩。不僅JavaScript代碼冗長,而且必須考慮服務(wù)器端為定位Ajax請(qǐng)求到適當(dāng)?shù)姆?wù)所需做的工作,并將結(jié)果封送到瀏覽器。
設(shè)計(jì)DWR的目的是要處理將Web頁面安裝到后端服務(wù)上所需的所有信息管道。它是一個(gè)Java框架,可以很輕松地將它插入到Web應(yīng)用程序中,以便JavaScript代碼可以調(diào)用服務(wù)器上的服務(wù)。它甚至直接與Spring Framework集成,從而允許用戶直接向Web客戶機(jī)公開bean。
DWR真正的巧妙之處是,在用戶配置了要向客戶機(jī)公開的服務(wù)之后,它使用反射來生成JavaScript對(duì)象,以便Web頁面能夠使用這些對(duì)象來訪問該服務(wù)。然后Web頁面只需接合到生成的JavaScript對(duì)象,就像它們是直接使用服務(wù)一樣;DWR無縫地處理所有有關(guān)Ajax和請(qǐng)求定位的瑣碎細(xì)節(jié)。
讓我們仔細(xì)分析一下示例代碼,弄清它是如何工作的。
應(yīng)用程序細(xì)節(jié):DWR分析
關(guān)于應(yīng)用程序,首先要注意的是,它是一個(gè)標(biāo)準(zhǔn)的Java應(yīng)用程序,使用分層架構(gòu)(Layered Architecture)設(shè)計(jì)模式。使用DWR通過JavaScript公開一些服務(wù)并不影響您的設(shè)計(jì)。

下面是一個(gè)簡(jiǎn)單的Java服務(wù),我們將使用DWR框架直接將其向JavaScript代碼公開:
package com.tearesolutions.service;
public interface AjaxSampleSvc {
Article castVote(int rank);
}
這是一個(gè)被簡(jiǎn)化到幾乎不可能的程度的例子,其中只有一篇文章可以投票。該服務(wù)由Spring管理,它使用的bean名是ajaxSampleSvc,它的持久性需求則依賴于ArticleDao。詳情請(qǐng)參見applicationContext.xml。
為了把該服務(wù)公開為JavaScript對(duì)象,需要配置DWR,添加dwr.xml文件到WEB-INF目錄下:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE dwr PUBLIC
"-//GetAhead Limited//DTD Direct Web Remoting 0.4//EN"
"http://www.getahead.ltd.uk/dwr/dwr.dtd">
<dwr>
<allow>
<create creator="spring" javascript="ajaxSampleSvc">
<param name="beanName" value="ajaxSampleSvc" />
</create>
<convert converter="bean" match="com.tearesolutions.model.Article"/>
<exclude method="toString"/>
<exclude method="setArticleDao"/>
</allow>
</dwr>
dwr.xml文件告訴DWR哪些服務(wù)是要直接向JavaScript代碼公開的。注意,已經(jīng)要求公開Spring bean ajaxSampleSvc。DWR將自動(dòng)找到由應(yīng)用程序設(shè)置的SpringApplicationContext。為此,必須使用標(biāo)準(zhǔn)的servlet過濾器ContextLoaderListener來初始化Spring ApplicationContext。
DWR被設(shè)置為一個(gè)servlet,所以把它的定義添加到web.xml:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD
Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd">
<web-app>
<display-name>Ajax Examples</display-name>
<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
<servlet>
<servlet-name>ajax_sample</servlet-name>
<servlet-class>com.tearesolutions.web.AjaxSampleServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet>
<servlet-name>dwr-invoker</servlet-name>
<display-name>DWR Servlet</display-name>
<description>Direct Web Remoter Servlet</description>
<servlet-class>uk.ltd.getahead.dwr.DWRServlet</servlet-class>
<init-param>
<param-name>debug</param-name>
<param-value>true</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>ajax_sample</servlet-name>
<url-pattern>/ajax_sample</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>dwr-invoker</servlet-name>
<url-pattern>/dwr/*</url-pattern>
</servlet-mapping>
</web-app>
做完這些之后,可以加載http://localhost:7001/ajax-demo/dwr,看看哪些服務(wù)可用。結(jié)果如下:

圖3. 可用的服務(wù)
單擊ajaxSampleSvc鏈接,查看有關(guān)如何在HTML頁面內(nèi)直接使用服務(wù)的示例實(shí)現(xiàn)。其中包含的兩個(gè)JavaScript文件完成了大部分的功能:
<script type='text/javascript'
src='/ajax-demo/dwr/interface/ajaxSampleSvc.js'></script>
<script type='text/javascript'
src='/ajax-demo/dwr/engine.js'></script>
ajaxSampleSvc.js是動(dòng)態(tài)生成的:
function ajaxSampleSvc() { }
ajaxSampleSvc.castVote = function(callback, p0)
{
DWREngine._execute(callback, '/ajax-demo/dwr',
'ajaxSampleSvc', 'castVote', p0);
}
現(xiàn)在可以使用JavaScript對(duì)象ajaxSampleSvc替換所有的XmlHttpRequest代碼,從而重構(gòu)raw-ajax.html文件。可以在dwr-ajax.html文件中看到改動(dòng)的結(jié)果;下面是新的JavaScript函數(shù):
function castVote(rank) {
ajaxSampleSvc.castVote(processResponse, rank);
}
function processResponse(data) {
var voteText = "Thanks for Voting!
"
+ "Current ranking: " + data.voteAverage
+ " out of 5
"
+ "Number of votes placed: "
+ data.numberOfVotes + "
";
502 502'votes').innerHTML = voteText;
}
驚人地簡(jiǎn)單,不是嗎?由ajaxSampleSvc對(duì)象返回的Article域?qū)ο笮蛄谢癁橐粋€(gè)JavaScript對(duì)象,允許在它上面調(diào)用諸如numberOfVotes()和voteAverage()之類的方法。在動(dòng)態(tài)生成并插入到DIV元素“votes”中的HTML代碼內(nèi)使用這些數(shù)據(jù)。
下一步工作
在后續(xù)文章中,我將繼續(xù)有關(guān)Ajax的話題,涉及下面這些方面:
像許多技術(shù)一樣,Ajax是一把雙刃劍。對(duì)于一些用例,其應(yīng)用程序其實(shí)沒有必要使用Ajax,使用了反而有損可用性。我將介紹一些不適合使用的模式,突出說明Ajax的一些消極方面,并展示一些有助于緩和這些消極方面的機(jī)制。例如,對(duì)Netflix電影瀏覽器來說,Ajax是合適的解決方案嗎?或者,如何提示用戶確實(shí)出了一些問題,而再次單擊按鈕也無濟(jì)于事?
在使用Ajax時(shí),最初的文檔DOM會(huì)發(fā)生一些變化,并且有大量的頁面狀態(tài)信息存儲(chǔ)在客戶端變量中。當(dāng)用戶跟蹤一個(gè)鏈接到應(yīng)用程序中的另一個(gè)頁面時(shí),狀態(tài)就丟失了。當(dāng)用戶按照慣例單擊Back按鈕時(shí),呈現(xiàn)給他們的是緩存中的初始頁面。這會(huì)使用戶感到非常迷惑!
使用JavaScript在客戶端執(zhí)行更多的工作時(shí),如果事情不按預(yù)期方式進(jìn)行,就需要一些調(diào)試工具來幫助弄清出現(xiàn)了什么問題。
結(jié)束語
本文介紹了Ajax方法,并展示了如何使用它來創(chuàng)建一個(gè)動(dòng)態(tài)且響應(yīng)靈敏的Web應(yīng)用程序。通過使用DWR框架,可以輕松地把Ajax融合到站點(diǎn)中,而無需擔(dān)心所有必須執(zhí)行的實(shí)際管道工作。
特別感謝Getahead IT咨詢公司的Joe Walker和他的團(tuán)隊(duì)開發(fā)出DWR這樣神奇的工具。感謝你們與世界共享它!
下載
本文中演示的應(yīng)用程序源代碼可供下載:ajax-demo.war(1.52 MB)。
參考資料
原文出處
An Introduction To Ajax
http://dev2dev.bea.com/pub/a/2005/08/ajax_introduction.html
國際化是使程序具有足夠的靈活性、能在世界上任何地區(qū)運(yùn)行的過程。國際化所要求的必然結(jié)果是地方化――使一個(gè)程序能夠運(yùn)行在特定地區(qū)的過程。本文嘗試用一個(gè)簡(jiǎn)單的例子來演示Java用戶界面本地化。Java語言內(nèi)核基于Unicode3.0(Java 1.4)提供了對(duì)不同國家和不同語言文字的內(nèi)部支持,由于先天的原因,Java對(duì)于國際化的支持遠(yuǎn)遠(yuǎn)要比C/C++來的優(yōu)越。
在我看來本地化必須滿足以下的三個(gè)條件:
1、程序必須能讀、寫和操作本地化的文本。
2、程序在顯示日期和時(shí)間、使數(shù)字格式化以及排序子串時(shí),必須符合地方習(xí)慣。(通過java.text包里面的類可以實(shí)現(xiàn)這些要求)
3、所有用戶可見的文本都能在運(yùn)行時(shí)獲得,而不是直接寫入程序中。(通過java.util包里的ResourceBundle類和他的子類可以實(shí)現(xiàn)這些要求。)
實(shí)現(xiàn)這三個(gè)方面可以真正實(shí)現(xiàn)程序的國際化。
首先讓我們來了解一下地區(qū)。地區(qū)代表一個(gè)地理上、政治上或文化上的區(qū)域。在Java中,地區(qū)由java.util.Locale類表示。地區(qū)常常以一種語言來定義,該語言則由其標(biāo)準(zhǔn)的小寫雙字母代碼表示。(例如:en代表英國,fr代表法國,zh代表中國),但有時(shí)候語言是不能代表一個(gè)地區(qū)的,那就要在語言后面再加上一個(gè)國家或該國家的地域(例如:en_US代表美國,zh_TW)。Locale類保存著一個(gè)靜態(tài)的默認(rèn)地區(qū),它可以用Locale.setDefault()和Locale.getDefault()來設(shè)置和查詢。一個(gè)程序可以生成和使用任意數(shù)目的非默認(rèn)Locale對(duì)象。
讓我們?cè)賮砜匆幌耈nicode字符編碼。Java使用Unicode的字符編碼,其本身就是邁向國際化的一大步。Unicode編碼其每個(gè)字符都占兩個(gè)字節(jié)。用\u****的形式表示。Unicode的字符可以等價(jià)于其他編碼的字符(例如:從\u0020到\u007E的字符等價(jià)于ASCII和ISO8859-1字符的0x20到0x7E)。
本文主要是對(duì)用戶界面地方化,由于我使用的是資源束!所以有必要對(duì)資源束作一下解釋。
為定義一束地方化的資源,你需要生成一個(gè)ResourceBundle(資源束)的子類并且提供handleGetObject()和getKeys()方法的定義。為了在程序中使用來自ResourceBundle的地方化資源,就需要先調(diào)用靜態(tài)的getBundle()方法,用getBundle()獲得一個(gè)ResourceBundle對(duì)象,然后再用getObject()方法去按照名字來查找資源。當(dāng)然也可以使用getString()簡(jiǎn)單的把getObject()的返回值分配給一個(gè)String對(duì)象。GetBundle()方法采用basename_language_country_variait----沒找到的話->basename_language_country----沒找到的話->basename_language----沒找到的話->basename(默認(rèn)資源文件)的算法尋找合適的資源。如果以上都沒找到的話,則會(huì)拋出一個(gè)MissingResourceException異常。
現(xiàn)在我們來看一個(gè)簡(jiǎn)單的例子,如何使Java程序用戶界面地方化的。
首先我們的程序需要查找特定Locale對(duì)象關(guān)聯(lián)的資源包,所以應(yīng)該定義一個(gè)Local對(duì)象,來獲取本地默認(rèn)的地區(qū)!然后可以調(diào)用ResourceBundle的getBundle方法,并將locale對(duì)象作為參數(shù)傳入。
清單一:
Locale locale = Locale.getDefault(); //獲取地區(qū):默認(rèn)
//獲取資源束。如未發(fā)現(xiàn)則會(huì)拋出MissingResourceException異常
ResourceBundle bundle = ResourceBundle.getBundle("Properties.Dorian",locale);
清單一中的”Properties.Dorian”代表Properties包下以Dorian命名的默認(rèn)資源文件。這樣就可以使用資源文件了!讓我們來看看資源文件是如何定義的。
清單二:
# Dorian.properties是默認(rèn)的"Dorian"資源束文件。
# 作為中國人,我用自己的地區(qū)作為默認(rèn)
Title=\u4e2d\u56fd;
red.label=\u7ea2\u8272;
green.label=\u7eff\u8272;
blue.label=\u84dd\u8272;
清單三:
# 文件Dorian_en_US.properties,是美國地區(qū)的資源束
# 它覆蓋了默認(rèn)資源束
Title=America;
red.label=Red;
green.label=Green;
blue.label=Blue ;
清單一和二定義了一個(gè)默認(rèn)資源文件,和美國地區(qū)的資源文件。其中等號(hào)左邊的字符串表示主鍵,它們是唯一的。為了獲得主鍵對(duì)應(yīng)的值,你可以調(diào)用ResourceBundle類的getString方法,并將主鍵作為參數(shù)。此外,文件中以“#”號(hào)開頭的行表示注釋行。需要注意的是清單二中的“\u4e2d\u56fd”,它是字符“中國”的Unicode字符碼。是使用Java自帶的native2ascii工具轉(zhuǎn)換的(native2ascii in.properties out.properties),這是為了不在程序界面中產(chǎn)生亂碼。
清單四:
cmdRed.setText(bundle.getString("red.label"));
cmdBlue.setText (bundle.getString("blue.label"));
cmdGreen.setText (bundle.getString("green.label"));
清單二中的cmdRed、cmdBlue、cmdGreen 為按鈕。bundle.getString("red.label")為得到資源文件中主鍵是red.label的值。
好了到此為止Java程序用戶界面的本地化就是這么簡(jiǎn)單。不過,要提醒你的是在為用戶界面事件編寫事件監(jiān)聽器代碼時(shí),要格外小心。請(qǐng)看下面這段代碼。
清單五:
public class MyApplet extends Japplet implements ActionListener{
public void init(){
JButton cancelButton=new JButton(“Cancel”);
CancelButton.addActionListener(this);
...
}
public void actionPerformed(ActionEvent e){
String s=e.getActionCommand();
if(arg.equals(“Cancel”);
doCancel();
else ……
}
}
如果你對(duì)清單五的代碼不進(jìn)行本地化,她就可能會(huì)運(yùn)行的很好。但當(dāng)你的按鈕被本地化為中文時(shí),“Cancel”變?yōu)榱恕叭∠薄_@時(shí)就會(huì)出現(xiàn)你不愿意看到的問題。下面有三個(gè)方法可以消除這個(gè)潛在的問題!
1> 使用內(nèi)部類而不使用獨(dú)立的actionPerformed程序。
2> 使用引號(hào)而不使用標(biāo)簽來標(biāo)識(shí)組件。
3> 使用name屬性來標(biāo)識(shí)組件
本例稍后的代碼就是采用第一種方法來消除這個(gè)問題的。
清單六:完整的代碼
//:MyNative.java
/**
Copyright (c) 2003 Dorian. All rights reserved
@(#)MyNative.java 2003-12-21
@author Dorian
@version 1.0.0
visit http://www.Dorian.com/Java/
*/
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.util.*;
/**
這是一個(gè)將Java程序界面地方化的例子本例采用讀取屬性文件來達(dá)到目的
@see java.util.Locale;
@see java.util.ResourceBundle;
@see java.util.MissingResourceException;
*/
public class MyNative{
public static void main(String[] args){
JFrame frame = new MyNativeFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setResizable(false);
frame.setVisible(true); // Pop the window up.
}
}
class MyNativeFrame extends JFrame{
public MyNativeFrame(){
Locale locale = Locale.getDefault();//獲取地區(qū):默認(rèn)
//獲取資源束。如未發(fā)現(xiàn)則會(huì)拋出MissingResourceException異常
//"Properties.Dorian"為在Properties下以Dorian為文件名的默認(rèn)屬性文件
ResourceBundle bundle = ResourceBundle.getBundle("Properties.Dorian",locale);
setTitle(bundle.getString("Title"));//通過getString()的返回值來設(shè)置Title
setSize(WIDTH,HEIGHT); // Set the window size.
panel=new MyNativePanel();
Container contentPane=getContentPane();
contentPane.add(panel);
//通過獲取資源束中*.label的值對(duì)三個(gè)按鈕設(shè)置其Label
panel.setCmdRed(bundle.getString("red.label"));
panel.setCmdBlue(bundle.getString("blue.label"));
panel.setCmdGreen(bundle.getString("green.label"));
}
private MyNativePanel panel;
private static final int WIDTH=400;
private static final int HEIGHT=100;
}
class MyNativePanel extends JPanel{
public MyNativePanel(){
layout=new BorderLayout();
setLayout(layout);
txt=new JTextField(50);
add(txt,layout.CENTER);
cmdRed=new JButton();
cmdBlue=new JButton();
cmdGreen=new JButton();
panel.add(cmdRed);
panel.add(cmdBlue);
panel.add(cmdGreen);
add(panel,layout.SOUTH);
cmdRed.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){
String s = e.getActionCommand();
txt.setBackground(Color.red);
txt.setText(s);
}
});
cmdBlue.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){
String s = e.getActionCommand();
txt.setBackground(Color.blue);
txt.setText(s);
}
});
Log4j基本使用方法
|
作者:佚名 ????來自:未知
Log4j由三個(gè)重要的組件構(gòu)成:日志信息的優(yōu)先級(jí),日志信息的輸出目的地,日志信息的輸出格式。日志信息的優(yōu)先級(jí)從高到低有ERROR、WARN、INFO、DEBUG,分別用來指定這條日志信息的重要程度;日志信息的輸出目的地指定了日志將打印到控制臺(tái)還是文件中;而輸出格式則控制了日志信息的顯示內(nèi)容。
一、定義配置文件
其實(shí)您也可以完全不使用配置文件,而是在代碼中配置Log4j環(huán)境。但是,使用配置文件將使您的應(yīng)用程序更加靈活。Log4j支持兩種配置文件格式,一種是XML格式的文件,一種是Java特性文件(鍵=值)。下面我們介紹使用Java特性文件做為配置文件的方法:
1.配置根Logger,其語法為:
log4j.rootLogger = [ level ] , appenderName, appenderName, …
其中,level 是日志記錄的優(yōu)先級(jí),分為OFF、FATAL、ERROR、WARN、INFO、DEBUG、ALL或者您定義的級(jí)別。Log4j建議只使用四個(gè)級(jí)別,優(yōu)先級(jí)從高到低分別是ERROR、WARN、INFO、DEBUG。通過在這里定義的級(jí)別,您可以控制到應(yīng)用程序中相應(yīng)級(jí)別的日志信息的開關(guān)。比如在這里定義了INFO級(jí)別,則應(yīng)用程序中所有DEBUG級(jí)別的日志信息將不被打印出來。 appenderName就是指定日志信息輸出到哪個(gè)地方。您可以同時(shí)指定多個(gè)輸出目的地。
2.配置日志信息輸出目的地Appender,其語法為:
log4j.appender.appenderName = fully.qualified.name.of.appender.class log4j.appender.appenderName.option1 = value1 … log4j.appender.appenderName.option = valueN
其中,Log4j提供的appender有以下幾種: org.apache.log4j.ConsoleAppender(控制臺(tái)), org.apache.log4j.FileAppender(文件), org.apache.log4j.DailyRollingFileAppender(每天產(chǎn)生一個(gè)日志文件), org.apache.log4j.RollingFileAppender(文件大小到達(dá)指定尺寸的時(shí)候產(chǎn)生一個(gè)新的文件), org.apache.log4j.WriterAppender(將日志信息以流格式發(fā)送到任意指定的地方)
3.配置日志信息的格式(布局),其語法為:
log4j.appender.appenderName.layout = fully.qualified.name.of.layout.class log4j.appender.appenderName.layout.option1 = value1 … log4j.appender.appenderName.layout.option = valueN
其中,Log4j提供的layout有以下幾種: org.apache.log4j.HTMLLayout(以HTML表格形式布局), org.apache.log4j.PatternLayout(可以靈活地指定布局模式), org.apache.log4j.SimpleLayout(包含日志信息的級(jí)別和信息字符串), org.apache.log4j.TTCCLayout(包含日志產(chǎn)生的時(shí)間、線程、類別等等信息)
Log4J采用類似C語言中的printf函數(shù)的打印格式格式化日志信息,打印參數(shù)如下: %m 輸出代碼中指定的消息
%p 輸出優(yōu)先級(jí),即DEBUG,INFO,WARN,ERROR,F(xiàn)ATAL %r 輸出自應(yīng)用啟動(dòng)到輸出該log信息耗費(fèi)的毫秒數(shù) %c 輸出所屬的類目,通常就是所在類的全名 %t 輸出產(chǎn)生該日志事件的線程名 %n 輸出一個(gè)回車換行符,Windows平臺(tái)為“\r\n”,Unix平臺(tái)為“\n” %d 輸出日志時(shí)間點(diǎn)的日期或時(shí)間,默認(rèn)格式為ISO8601,也可以在其后指定格式,比如:%d{yyy MMM dd HH:mm:ss,SSS},輸出類似:2002年10月18日 22:10:28,921 %l 輸出日志事件的發(fā)生位置,包括類目名、發(fā)生的線程,以及在代碼中的行數(shù)。舉例:Testlog4.main(TestLog4.java:10)
二、在代碼中使用Log4j
1.得到記錄器
使用Log4j,第一步就是獲取日志記錄器,這個(gè)記錄器將負(fù)責(zé)控制日志信息。其語法為:
public static Logger getLogger( String name)
通過指定的名字獲得記錄器,如果必要的話,則為這個(gè)名字創(chuàng)建一個(gè)新的記錄器。Name一般取本類的名字,比如:
static Logger logger = Logger.getLogger ( ServerWithLog4j.class.getName () )
2.讀取配置文件
當(dāng)獲得了日志記錄器之后,第二步將配置Log4j環(huán)境,其語法為:
BasicConfigurator.configure (): 自動(dòng)快速地使用缺省Log4j環(huán)境。 PropertyConfigurator.configure ( String configFilename) :讀取使用Java的特性文件編寫的配置文件。 DOMConfigurator.configure ( String filename ) :讀取XML形式的配置文件。
3.插入記錄信息(格式化日志信息)
當(dāng)上兩個(gè)必要步驟執(zhí)行完畢,您就可以輕松地使用不同優(yōu)先級(jí)別的日志記錄語句插入到您想記錄日志的任何地方,其語法如下:
Logger.debug ( Object message ) ; Logger.info ( Object message ) ; Logger.warn ( Object message ) ; Logger.error ( Object message ) ;
|