2005年10月25日
先来看一下默认的连接SQL Server数据库配置 <connectionStrings> <add name="LocalSqlServer" connectionString="Data Source=.\SQLExpress;Integrated Security=SSPI;AttachDBFilename=|DataDirectory|aspnetdb.mdf;User Instance=true" providerName="System.Data.SqlClient" /> </connectionStrings>
SqlConnectionStringBuilder实例化时需要使用connectionString。如:SqlConnectionStringBuild builder = new SqlConnectionStringBuild(connectionString);
一、Data Source SqlConnectionStringBuilder的DataSource属性,对应connectionString中的Data Source,“Data Source”可以由下列字符串代替:“Server”,“Address”,“Addr”和“Network Address”。 Data Source=.\SQLExpress也可以写成这样Data Source=(local)\SQLExpress。
二、Integrated Security SqlConnectionStringBuilder 的 IntegratedSecurity 属性,对应 connectionString 中的I ntegrated Security,“Integrated Security”可以写成“trusted_connection”。 为 True 时,使用当前的 Windows 帐户凭据进行身份验证,为 False 时,需要在连接中指定用户 ID 和密码。可识别的值为 True、False、Yes、No 以及与 True 等效的 SSPI。 如果没有些则必须写上 uid=sa;pwd=123 之类的设置“uid”也可使用“User ID”,“pwd”也可换为“PassWord”。
SSPI:Microsoft安全支持提供器接口(SSPI)是定义得较全面的公用API,用来获得验证、信息完整性、信息隐私等集成安全服务,以及用于所有分布式应用程序协议的安全方面的服务。 应用程序协议设计者能够利用该接口获得不同的安全性服务而不必修改协议本身。
三、AttachDBFilename SqlConnectionStringBuilder 的 AttachDBFilename 属性,对应 connectionString 中的 AttachDBFilename,“AttachDBFilename”可以写成“extended properties”,“initial file name”。 AttachDbFileName 属性指定连接打开的时候动态附加到服务器上的数据库文件的位置。 这个属性可以接受数据库的完整路径和相对路径(例如使用|DataDirectory|语法),在运行时这个路径会被应用程序的 App_Data 目录所代替。
四、User Instance SqlConnectionStringBuilder 的 UserInstance 属性,对应 connectionString 中的 User Instance ,该值指示是否将连接从默认的 SQL Server 实例重定向到在调用方帐户之下运行并且在运行时启动的实例。 UserInstance=true 时,SQLServerExpress 为了把数据库附加到新的实例,建立一个新的进程,在打开连接的用户身份下运行。 在 ASP.NET 应用程序中,这个用户是本地的 ASPNET 帐号或默认的 NetworkService,这依赖于操作系统。 为了安全地附加非系统管理员帐号(例如ASP.NET帐号)提供的数据库文件,建立一个独立的 SQLServer 用户实例是必要的。
五、Initial Catalog 等同于 Database。
六、providerName 指定值“System.Data.OracleClient”,该值指定 ASP.NET 在使用此连接字符串进行连接时应使用 ADO.NET System.Data.OracleClient 提供程序。
PS: DataDirectory是什么?
asp.net 2.0有一个特殊目录app_data,通常Sql Server 2005 express数据文件就放在这个目录,相应的数据库连接串就是: connectionString="…… data source=.\SQLEXPRESS;Integrated Security=SSPI;AttachDBFilename=|DataDirectory|data.mdf;User Instance=true" 这里有一个DataDirectory的宏,它表示什么意义呢?
DataDirectory是表示数据库路径的替换字符串。由于无需对完整路径进行硬编码,DataDirectory 简化了项目的共享和应用程序的部署。例如,无需使用以下连接字符串: "Data Source= c:\program files\MyApp\app_data\Mydb.mdf" 通过使用|DataDirectory|(包含在如下所示的竖线中),即可具有以下连接字符串: "Data Source = |DataDirectory|\Mydb.mdf" 。
不仅仅是Sql server 2005 express中使用,也可以在其它的文件数据库中使用,例如Sqllite数据库文件的连接字符串:
<add name="DefaultDB" connectionString="DriverClass=NHibernate.Driver.SQLite20Driver;Dialect=NHibernate.Dialect.SQLiteDialect;Data Source=|DataDirectory|\data.db3" />
--------------------------------------- 附加一些连接语句例子 ---------------------------------------
<--普通例子1--> <configuration> <connectionStrings> <add name="Sales" providerName="System.Data.SqlClient" connectionString="server=myserver;database=Products;uid=salesUser;pwd=sellMoreProducts" />
<add name="NorthWind" providerName="System.Data.SqlClient" connectionString="server=.;database=NorthWind;Integrated Security=SSPI" />
</connectionStrings> </configuration>
<--普通例子2--> <configuration> <connectionStrings> <add name="NorthWind" connectionString="Provider=SQLOLEDB;Integrated Security=SSPI;Initial Catalog=da;Data Source=bar" /> </configuration>
----------------------------------------------------------------------------------------------------------
<connectionStrings> <add name="LocalSqlServer" connectionString="Data Source=.\SQLExpress;Initial Catalog=NorthWind;Integrated Security=SSPI" providerName="System.Data.SqlClient" /> </connectionStrings> <--也可写为--> <connectionStrings> <add name="LocalSqlServer" connectionString="Server=.\SQLExpress;Database=NorthWind;Integrated Security=Yes" providerName="System.Data.SqlClient" /> </connectionStrings>
----------------------------------------------------------------------------------------------------------
<configuration> <connectionStrings> <add name="DB2005_2" providerName="System.Data.SqlClient" connectionString="Data Source=.;Initial Catalog=Northwind;User ID=dbtester;Password=zhi;Trusted_Connection=False;Connect Timeout=30;Min Pool Size=16;Max Pool Size=100"/>
<add name="DB2005_1" providerName="System.Data.SqlClient" connectionString="Server=.;Database=Northwind;User ID=dbtester;Password=zhi;Trusted_Connection=False;Connect Timeout=30;Min Pool Size=16;Max Pool Size=100"/>
<add name="Northword2000" providerName="System.Data.SqlClient" connectionString="Initial Catalog=Northwind;User ID=dbtester;PassWord=zhi;Persist Security Info=false;Data Source=(local);Connect Timeout=30;Min Pool Size=16;Max Pool Size=100;"/>
<add name="SQLExp" providerName="System.Data.SqlClient" connectionString="Data Source=.\SQLEXPRESS;AttachDbFilename=|DataDirectory|\northwnd1.mdf;Integrated Security=True;Connect Timeout=30;User Instance=True"/> <add name="Oracle" connectionString="Data Source=TEST;User ID=sa;Password=sa;" providerName="System.Data.OracleClient" />
<add name="oleconn" providerName="System.Data.OleDb" connectionString="Provider=Microsoft.Jet.OleDb.4.0;Data Source=|DataDirectory|northwind.mdb"/>
<add name="MySql" providerName="MySql.Data.MySqlClient" connectionString="Server=172.29.131.27;Port=3311;DataBase=comctl;Persist Security Info=False;User ID=root;Password=123456;Allow Zero Datetime=true;" /> </connectionStrings> <system.data> <DbProviderFactories> <add name="MySQL Data Provider" invariant="MySql.Data.MySqlClient" description=".Net Framework Data Provider for MySQL" type="MySql.Data.MySqlClient.MySqlClientFactory, MySql.Data, Version=5.2.5.0, Culture=neutral, PublicKeyToken=c5687fc88969c44d"/> </DbProviderFactories> </system.data> </configuration>
====================================== 可以保存为(以下转自他处).cs ======================================
using System.Data.SqlClient; using System.Configuration; public class Class1 { public Class1() { //Persist Security Info如果数据库连接成功后不再需要连接的密码,建议False //string sql2000 = "Initial Catalog=Northwind;User ID=dbtester;PassWord=zhi;Persist Security Info=false;Data Source=(local);Connect Timeout=30;Min Pool Size=16;Max Pool Size=100;"; //string sql2000 = "Initial Catalog=Northwind;User ID=sa;PassWord=5;Persist Security Info=false;Data Source=."; //string sql2000 = "Initial Catalog=Northwind;User ID=sa;PassWord=5;Persist Security Info=false;Data Source=newtime"; string source = "server=(local);integrated security=SSPI;database=Northwind"; string expressSource = @"Data Source=.\SQLEXPRESS;AttachDbFilename=|DataDirectory|\northwnd.mdf;Integrated Security=True;Connect Timeout=30;User Instance=True"; //Integrated Security采用windows的集成身份验证,integraged Security=SSPI; //Integrated Security=SSPI 这个表示以当前WINDOWS系统用户身去登录SQL SERVER服务器,如果SQL SERVER服务器不支持这种方式登录时,就会出错 //表示你的连接安全验证方式,可用trusted_connection=yes取代 //Integrated Security 为 True。用户实例仅与集成安全性一起使用,带有用户名和密码的 SQL Server 用户不起作用。 //string source3 = @"Data Source=190.190.200.100,1433;Network Library=DBMSSOCN;Initial Catalog= pubs;UserID=sa;Password=asdasd;"; //(DBMSSOCN=TCP/IP instead of Named Pipes, at the end of the Data Source is the port to use (1433 is the default)) //Standard Security: string source4 = "Data Source=Aron1;Initial Catalog= pubs;UserId=sa;Password=asdasd;"; string source5 = "Server=Aron1;Database=pubs;UserID=sa;Password=asdasd;Trusted_Connection=False"; //Trusted_Connection 'false' 当为 false 时,将在连接中指定用户 ID 和密码。当为 true 时,将使用当前的 Windows 帐户凭据进行身份验证。 //可识别的值为 true、false、yes、no 以及与 true 等效的 sspi(强烈推荐)。所以一定要设置Trusted_Connection= false,以防被别人"登录"、"注入语句"等 string source6 = "Data Source=Aron1;Initial Catalog=pubs;Integrated Security=SSPI;"; string source7 = "Server=Aron1;Database=pubs;Trusted_Connection=True;"; //(use serverName\instanceName as Data Source to use an specifik SQLServer instance, only SQLServer2000) //Integrated Security或Trusted_Connection 'false' 当为 false 时, //将在连接中指定用户 ID 和密码。当为 true 时,将使用当前的 Windows 帐户凭据进行身份验证 //VS2003:string connStr=System.Configuration.ConfigurationSettings.AppSettings["SQLCONNECTIONSTRING"];2003中用的 //VS2005:string connStr=System.Configuration.ConfigurationManager.ConnectionStrings["SQLCONNECTIONSTRING"].ToString();2005-8中用 System.Configuration.ConnectionStringSettings i = System.Configuration.ConfigurationManager.ConnectionStrings["Northword2000"]; } }
先来了解一下文件属性, 在shell环境里输入:ls -l 可以查看当前目录文件。如: drwxr-xr-x 2 nsf users 1024 12-10 17:37 下载文件备份 分别对应的是: 文件属性 连接数 文件拥有者 所属群组 文件大小 文件修改时间 文件名 这里r是可读,w可写,x 可执行,其中文件属性分为四段,---- --- --- 10个位置 例如: d rwx r-x r-x 第一个字符指定了文件类型。在通常意义上,一个目录也是一个文件。如果第一个字符是横线,表示是一个非目录的文件。如果是d,表示是一个目录。 第二段是文件拥有者的属性, 第三段是文件所属群组的属性, 第四段是对于其它用户的属性, 如上面文件夹“下载文件备份” 的访问权限,表示文件夹“下载文件备份” 是一个目录文件;文件夹“下载文件备份” 的属主有读写可执行权限;与文件夹“下载文件备份” 属主同组的用户只有读和可执行权限;其他用户也有读和可执行权限。 确定了一个文件的访问权限后,用户可以利用Linux系统提供的chmod命令来重新设定不同的访问权限。也可以利用chown命令来更改某个文件或目录的所有者。利用chgrp命令来更改某个文件或目录的用户组。 chmod 命令 功能:chmod命令是非常重要的,用于改变文件或目录的访问权限.用户用它控制文件或目录的访问权限. 语法:该命令有两种用法。一种是包含字母和操作符表达式的文字设定法;另一种是包含数字的数字设定法。 1. 文字设定法 chmod [who] [+ | - | =] [mode] 文件名? 参数: 操作对象who可是下述字母中的任一个或者它们的组合: u 表示“用户(user)”,即文件或目录的所有者。 g 表示“同组(group)用户”,即与文件属主有相同组ID的所有用户。 o 表示“其他(others)用户”。 a 表示“所有(all)用户”。它是系统默认值。 操作符号可以是: + 添加某个权限。 - 取消某个权限。 = 赋予给定权限并取消其他所有权限(如果有的话)。
设置mode所表示的权限可用下述字母的任意组合: r 可读。 w 可写。 x 可执行。 X 只有目标文件对某些用户是可执行的或该目标文件是目录时才追加x 属性。 s 在文件执行时把进程的属主或组ID置为该文件的文件属主。方式“u+s”设置文件的用 户ID位,“g+s”设置组ID位。 t 保存程序的文本到交换设备上。 u 与文件属主拥有一样的权限。 g 与和文件属主同组的用户拥有一样的权限。 o 与其他用户拥有一样的权限。 文件名:以空格分开的要改变权限的文件列表,支持通配符。 在一个命令行中可给出多个权限方式,其间用逗号隔开。例如:chmod g+r,o+r example 使同组和其他用户对文件example 有读权限。 chgrp命令 功能:改变文件或目录所属的组。 语法:chgrp [选项] group filename? 该命令改变指定指定文件所属的用户组。其中group可以是用户组ID,也可以是/etc/group文件中用户组的组名。文件名是以空格分开的要改变属组的文件列表,支持通配符。如果用户不是该文件的属主或超级用户,则不能改变该文件的组。 参数: - R 递归式地改变指定目录及其下的所有子目录和文件的属组。 例1:$ chgrp - R book /opt/local /book 改变/opt/local /book/及其子目录下的所有文件的属组为book。 chown 命令 功能:更改某个文件或目录的属主和属组。这个命令也很常用。例如root用户把自己的一个文件拷贝给用户xu,为了让用户xu能够存取这个文件,root用户应该把这个文件的属主设为xu,否则,用户xu无法存取这个文件。 语法:chown [选项] 用户或组 文件 说明:chown将指定文件的拥有者改为指定的用户或组。用户可以是用户名或用户ID。组可以是组名或组ID。文件是以空格分开的要改变权限的文件列表,支持通配符。 参数: - R 递归式地改变指定目录及其下的所有子目录和文件的拥有者。 - v 显示chown命令所做的工作。 例1:把文件shiyan.c的所有者改为wang。 $ chown wang shiyan.c 例2:把目录/his及其下的所有文件和子目录的属主改成wang,属组改成users。 $ chown - R wang.users /his
2TrLinux联盟用sqlplus链接数据库,运行以下命令 2TrLinux联盟 set pagesize 02TrLinux联盟 2TrLinux联盟 set long 900002TrLinux联盟 2TrLinux联盟 set feedback off2TrLinux联盟 2TrLinux联盟 set echo off 2TrLinux联盟 2TrLinux联盟 spool d:/get_schema.sql 2TrLinux联盟 2TrLinux联盟2TrLinux联盟 2TrLinux联盟 SELECT DBMS_METADATA.GET_DDL(TABLE,u.table_name)2TrLinux联盟 2TrLinux联盟 FROM USER_TABLES u;2TrLinux联盟 2TrLinux联盟 SELECT DBMS_METADATA.GET_DDL(INDEX,u.index_name)2TrLinux联盟 2TrLinux联盟 FROM USER_INDEXES u;2TrLinux联盟 2TrLinux联盟 spool off;
ArrayList中存放的对象,他的contains方法 是调用对象的equals方法。 比较的是对象的地址是否相等。 我们可以重写对象里面的equals方法: //重写equals方法 public boolean equals(Object test) { //参数类型一定要是Object if (Integer.parseInt(this.id) ==Integer.parseInt(((ChatRoom)test).id)) { return true; } else { return false; } } 变成之比较对象里面的id值是否相等。
GROUP BY 是分组查询, 一般是和聚合函数配合使用. group by 有一个原则,就是 select 后面的所有列中,没有使用聚合函数的列,必须出现在 group by 后面
1. 选用适合的ORACLE优化器
ORACLE的优化器共有3种:
a. RULE (基于规则) b. COST (基于成本) c. CHOOSE (选择性)
设置缺省的优化器,可以通过对init.ora文件中OPTIMIZER_MODE参数的各种声明,如RULE,COST,CHOOSE,ALL_ROWS,FIRST_ROWS . 你当然也在SQL句级或是会话(session)级对其进行覆盖.
为了使用基于成本的优化器(CBO, Cost-Based Optimizer) , 你必须经常运行analyze 命令,以增加数据库中的对象统计信息(object statistics)的准确性.
如果数据库的优化器模式设置为选择性(CHOOSE),那么实际的优化器模式将和是否运行过analyze命令有关. 如果table已经被analyze过, 优化器模式将自动成为CBO , 反之,数据库将采用RULE形式的优化器.
在缺省情况下,ORACLE采用CHOOSE优化器, 为了避免那些不必要的全表扫描(full table scan) , 你必须尽量避免使用CHOOSE优化器,而直接采用基于规则或者基于成本的优化器.
2. 访问Table的方式
ORACLE 采用两种访问表中记录的方式:
a. 全表扫描
全表扫描就是顺序地访问表中每条记录. ORACLE采用一次读入多个数据块(database block)的方式优化全表扫描.
b. 通过ROWID访问表
你可以采用基于ROWID的访问方式情况,提高访问表的效率, ,
ROWID包含了表中记录的物理位置信息..ORACLE采用索引(INDEX)实现了数据和存放数据的物理位置(ROWID)之间的联系.
通常索引提供了快速访问ROWID的方法,因此那些基于索引列的查询就可以得到性能上的提高. 3. 共享SQL语句
为了不重复解析相同的SQL语句,在第一次解析之后, ORACLE将SQL语句存放在内存中.这块位于系统全局区域SGA(system
global area)的共享池(shared buffer pool)中的内存可以被所有的数据库用户共享.
因此,当你执行一个SQL语句(有时被称为一个游标)时,如果它 和之前的执行过的语句完全相同,
ORACLE就能很快获得已经被解析的语句以及最好的执行路径. ORACLE的这个功能大大地提高了SQL的执行性能并节省了内存的使用. 可惜的是ORACLE只对简单的表提供高速缓冲(cache buffering) ,这个功能并不适用于多表连接查询.
数据库管理员必须在init.ora中为这个区域设置合适的参数,当这个内存区域越大,就可以保留更多的语句,当然被共享的可能性也就越大了.
当你向ORACLE 提交一个SQL语句,ORACLE会首先在这块内存中查找相同的语句.
这里需要注明的是,ORACLE对两者采取的是一种严格匹配,要达成共享,SQL语句必须完全相同(包括空格,换行等).
共享的语句必须满足三个条件:
A. 字符级的比较:
当前被执行的语句和共享池中的语句必须完全相同.
例如:
SELECT * FROM EMP;
和下列每一个都不同
SELECT * from EMP;
Select * From Emp;
SELECT * FROM EMP;
B. 两个语句所指的对象必须完全相同:
例如:
用户 对象名 如何访问
Jack sal_limit private synonym
Work_city public synonym
Plant_detail public synonym
Jill sal_limit private synonym
Work_city public synonym
Plant_detail table owner
考虑一下下列SQL语句能否在这两个用户之间共享.
SQL能否共享,原因
select max(sal_cap) from sal_limit;
不能。每个用户都有一个private synonym - sal_limit , 它们是不同的对象
select count(*0 from work_city where sdesc like 'NEW%';
能。两个用户访问相同的对象public synonym - work_city
select a.sdesc,b.location from work_city a , plant_detail b where a.city_id = b.city_id
不能。用户jack 通过private synonym访问plant_detail 而jill 是表的所有者,对象不同.
C. 两个SQL语句中必须使用相同的名字的绑定变量(bind variables)
例如:
第一组的两个SQL语句是相同的(可以共享),而第二组中的两个语句是不同的(即使在运行时,赋于不同的绑定变量相同的值)
a.
select pin , name from people where pin = :blk1.pin;
select pin , name from people where pin = :blk1.pin;
b.
select pin , name from people where pin = :blk1.ot_ind;
select pin , name from people where pin = :blk1.ov_ind;
4. 选择最有效率的表名顺序(只在基于规则的优化器中有效)
ORACLE的解析器按照从右到左的顺序处理FROM子句中的表名,因此FROM子句中写在最后的表(基础表 driving
table)将被最先处理. 在FROM子句中包含多个表的情况下,你必须选择记录条数最少的表作为基础表.当ORACLE处理多个表时,
会运用排序及合并的方式连接它们.首先,扫描第一个表(FROM子句中最后的那个表)并对记录进行派序,然后扫描第二个表(FROM子句中最后第二个
表),最后将所有从第二个表中检索出的记录与第一个表中合适记录进行合并. 例如:
表 TAB1 16,384 条记录
表 TAB2 1 条记录
选择TAB2作为基础表 (最好的方法)
select count(*) from tab1,tab2 执行时间0.96秒
选择TAB2作为基础表 (不佳的方法)
select count(*) from tab2,tab1 执行时间26.09秒
如果有3个以上的表连接查询, 那就需要选择交叉表(intersection table)作为基础表, 交叉表是指那个被其他表所引用的表.
例如:
EMP表描述了LOCATION表和CATEGORY表的交集.
SELECT *
FROM LOCATION L ,
CATEGORY C,
EMP E
WHERE E.EMP_NO BETWEEN 1000 AND 2000
AND E.CAT_NO = C.CAT_NO
AND E.LOCN = L.LOCN
将比下列SQL更有效率
SELECT *
FROM EMP E ,
LOCATION L ,
CATEGORY C
WHERE E.CAT_NO = C.CAT_NO
AND E.LOCN = L.LOCN
AND E.EMP_NO BETWEEN 1000 AND 2000
5. WHERE子句中的连接顺序.
ORACLE采用自下而上的顺序解析WHERE子句,根据这个原理,表之间的连接必须写在其他WHERE条件之前, 那些可以过滤掉最大数量记录的条件必须写在WHERE子句的末尾.
例如: (低效,执行时间156.3秒)
SELECT …
FROM EMP E
WHERE SAL > 50000
AND JOB = ‘MANAGER'
AND 25 < (SELECT COUNT(*) FROM EMP
WHERE MGR=E.EMPNO);
(高效,执行时间10.6秒)
SELECT …
FROM EMP E
WHERE 25 < (SELECT COUNT(*) FROM EMP
WHERE MGR=E.EMPNO)
AND SAL > 50000
AND JOB = ‘MANAGER';
6. SELECT子句中避免使用 ‘ * ‘
当你想在SELECT子句中列出所有的COLUMN时,使用动态SQL列引用 ‘*'
是一个方便的方法.不幸的是,这是一个非常低效的方法. 实际上,ORACLE在解析的过程中, 会将'*' 依次转换成所有的列名,
这个工作是通过查询数据字典完成的, 这意味着将耗费更多的时间. 7. 减少访问数据库的次数
当执行每条SQL语句时, ORACLE在内部执行了许多工作: 解析SQL语句, 估算索引的利用率, 绑定变量 , 读数据块等等. 由此可见, 减少访问数据库的次数 , 就能实际上减少ORACLE的工作量.
例如, 以下有三种方法可以检索出雇员号等于0342或0291的职员.
方法1 (最低效)
SELECT EMP_NAME , SALARY , GRADE
FROM EMP
WHERE EMP_NO = 342;
SELECT EMP_NAME , SALARY , GRADE
FROM EMP
WHERE EMP_NO = 291;
方法2 (次低效)
DECLARE
CURSOR C1 (E_NO NUMBER) IS
SELECT EMP_NAME,SALARY,GRADE
FROM EMP
WHERE EMP_NO = E_NO;
BEGIN
OPEN C1(342);
FETCH C1 INTO …,..,.. ;
…..
OPEN C1(291);
FETCH C1 INTO …,..,.. ;
CLOSE C1;
END;
方法3 (高效)
SELECT A.EMP_NAME , A.SALARY , A.GRADE,
B.EMP_NAME , B.SALARY , B.GRADE
FROM EMP A,EMP B
WHERE A.EMP_NO = 342
AND B.EMP_NO = 291;
注意:
在SQL*Plus , SQL*Forms和Pro*C中重新设置ARRAYSIZE参数, 可以增加每次数据库访问的检索数据量 ,建议值为200。
8. 使用DECODE函数来减少处理时间
使用DECODE函数可以避免重复扫描相同记录或重复连接相同的表.
例如:
SELECT COUNT(*),SUM(SAL) FROM EMP
WHERE DEPT_NO = 0020
AND ENAME LIKE ‘SMITH%';
SELECT COUNT(*),SUM(SAL)
FROM EMP
WHERE DEPT_NO = 0030
AND ENAME LIKE ‘SMITH%';
你可以用DECODE函数高效地得到相同结果
SELECT COUNT(DECODE(DEPT_NO,0020,'X',NULL)) D0020_COUNT,
COUNT(DECODE(DEPT_NO,0030,'X',NULL)) D0030_COUNT,
SUM(DECODE(DEPT_NO,0020,SAL,NULL)) D0020_SAL,
SUM(DECODE(DEPT_NO,0030,SAL,NULL)) D0030_SAL
FROM EMP WHERE ENAME LIKE ‘SMITH%';
类似的,DECODE函数也可以运用于GROUP BY 和ORDER BY子句中.
9. 整合简单,无关联的数据库访问
如果你有几个简单的数据库查询语句,你可以把它们整合到一个查询中(即使它们之间没有关系)
例如:
SELECT NAME FROM EMP
WHERE EMP_NO = 1234;
SELECT NAME FROM DPT
WHERE DPT_NO = 10 ;
SELECT NAME FROM CAT
WHERE CAT_TYPE = ‘RD';
上面的3个查询可以被合并成一个:
SELECT E.NAME , D.NAME , C.NAME FROM CAT C , DPT D , EMP E,DUAL X
WHERE NVL(‘X',X.DUMMY) = NVL(‘X',E.ROWID(+))
AND NVL(‘X',X.DUMMY) = NVL(‘X',D.ROWID(+))
AND NVL(‘X',X.DUMMY) = NVL(‘X',C.ROWID(+))
AND E.EMP_NO(+) = 1234
AND D.DEPT_NO(+) = 10
AND C.CAT_TYPE(+) = ‘RD';
(译者按: 虽然采取这种方法,效率得到提高,但是程序的可读性大大降低,所以读者 还是要权衡之间的利弊)
10. 删除重复记录
最高效的删除重复记录方法 ( 因为使用了ROWID)
DELETE FROM EMP E
WHERE E.ROWID > (SELECT MIN(X.ROWID)
FROM EMP X
WHERE X.EMP_NO = E.EMP_NO);
11. 用TRUNCATE替代DELETE
当删除表中的记录时,在通常情况下, 回滚段(rollback segments ) 用来存放可以被恢复的信息.
如果你没有COMMIT事务,ORACLE会将数据恢复到删除之前的状态(准确地说是恢复到执行删除命令之前的状况) ,而当运用TRUNCATE时,
回滚段不再存放任何可被恢复的信息.当命令运行后,数据不能被恢复.因此很少的资源被调用,执行时间也会很短。(注:
TRUNCATE只在删除全表适用,TRUNCATE是DDL不是DML) 12. 尽量多使用COMMIT
只要有可能,在程序中尽量多使用COMMIT, 这样程序的性能得到提高,需求也会因为COMMIT所释放的资源而减少:
COMMIT所释放的资源:
a. 回滚段上用于恢复数据的信息.
b. 被程序语句获得的锁
c. redo log buffer 中的空间
d. Oracle为管理上述3种资源中的内部花费
(注:在使用COMMIT时必须要注意到事务的完整性,现实中效率和事务完整性往往是鱼和熊掌不可得兼)
如果DECODE取值为NULL,SUM(NULL)的值是NULL -->如果所有的值都是NULL , SUM(NULL) = NULL 但是只要有一个值不是NULL,SUM() <> NULL 所以原SQL应该没有什么逻辑上的问题
关于第八点的个人看法:如果DECODE取值为NULL,SUM(NULL)的值是NULL,不会正常求和的。可以改成如下所示就好了:
SELECT COUNT(DECODE(DEPT_NO,0020,'X',NULL)) D0020_COUNT,
COUNT(DECODE(DEPT_NO,0030,'X',NULL)) D0030_COUNT,
SUM(DECODE(DEPT_NO,0020,SAL,0)) D0020_SAL,
SUM(DECODE(DEPT_NO,0030,SAL,0)) D0030_SAL FROM EMP WHERE ENAME LIKE
‘SMITH%';
采用华为包发送短信:
CMPPSubmitMessage中定义:
int msg_Fmt = 15;
content.getBytes("GBK");
必须定义GBK字符才不会出现乱码。
主要区别在加密方面:
加密算法:DES(); sun下jdk自带这个算法的jar包 而ibm下jdk没有这个包 需要自己加上sunjce_provider.jar这个包(weblogic下可以找到这个包)。
keytool工具也是对不同版本的jdk依赖性非常大,不能通用。
#1 定义了两个输出端
log4j.rootLogger = INFO, A1, A2,A3
#2 定义A1输出到控制器
log4j.appender.A1 = org.apache.log4j.ConsoleAppender
#3 定义A1的布局模式为PatternLayout
log4j.appender.A1.layout = org.apache.log4j.PatternLayout
#4 定义A1的输出格式
log4j.appender.A1.layout.ConversionPattern = %-4r [%t] %-5p %c - %m%n
#5 定义A2输出到文件
log4j.appender.A2 = org.apache.log4j.RollingFileAppender
#6 定义A2要输出到哪一个文件
log4j.appender.A2.File = F:\\nepalon\\classes\\example3.log
#7 定义A2的输出文件的最大长度
log4j.appender.A2.MaxFileSize = 1KB
#8 定义A2的备份文件数
log4j.appender.A2.MaxBackupIndex = 3
#9 定义A2的布局模式为PatternLayout
log4j.appender.A2.layout = org.apache.log4j.PatternLayout
#10 定义A2的输出格式
log4j.appender.A2.layout.ConversionPattern = %d{yyyy-MM-dd hh:mm:ss}:%p %t %c - %m%n
#11区 定义A3输出到数据库
log4j.appender.A3 = org.apache.log4j.jdbc.JDBCAppender
log4j.appender.A3.BufferSize = 40
log4j.appender.A3.Driver = com.microsoft.jdbc.sqlserver.SQLServerDriver
log4j.appender.A3.URL = jdbc:microsoft:sqlserver://127.0.0.1:1433;DatabaseName=nepalon
log4j.appender.A3.User = sa
log4j.appender.A3.Password =
log4j.appender.A3.layout = org.apache.log4j.PatternLayout
log4j.appender.A3.layout.ConversionPattern = INSERT INTO log4j
(createDate, thread, priority, category, message) values(getdate(),
'%t', '%-5p', '%c', '%m')
JSTL教程- -
JSP 标准标记库(JSP Standard Tag Library,JSTL)是一个实现 Web 应用程序中常见的通用功能的定制标记库集,这些功能包括迭代和条件判断、数据管理格式化、XML 操作以及数据库访问。在 developerWorks 上其新系列的第一篇文章中,软件工程师 Mark Kolb 向您展示了如何使用 JSTL 标记来避免在 JSP 页面中使用脚本编制元素。您还将了解如何通过从表示层删除源代码来简化软件维护。最后,您将了解 JSTL 经过简化的表达式语言,它允许在不必使用功能齐全的编程语言的情况下对 JSTL 操作指定动态属性值。
JavaServer Pages(JSP)是用于 J2EE 平台的标准表示层技术。JSP 技术提供了用于执行计算(这些计算用来动态地生成页面内容)的脚本编制元素和操作。脚本编制元素允许在 JSP 页面中包括程序源代码,在为响应用户请求而呈现页面时可以执行这些源代码。操作将计算操作封装到很象 HTML 或 XML 标记的标记中,JSP 页面的模板文本通常包含这些标记。JSP 规范只将几种操作定义成了标准,但从 JSP 1.1 开始,开发人员已经能够以定制标记库的方式创建其自己的操作了。
JSP 标准标记库(JSTL)是 JSP 1.2 定制标记库集,这些标记库实现大量服务器端 Java 应用程序常用的基本功能。通过为典型表示层任务(如数据格式化和迭代或条件内容)提供标准实现,JSTL 使 JSP 作者可以专注于特定于应用程序的开发需求,而不是为这些通用操作“另起炉灶”。
当然,您可以使用 JSP 脚本编制元素(scriptlet、表达式和声明)来实现此类任务。例如,可以使用三个 scriptlet 实现条件内容,清单 1 中着重显示了这三个 scriptlet。但是,因为脚本编制元素依赖于在页面中嵌入程序源代码(通常是 Java 代码),所以对于使用这些脚本编制元素的 JSP 页面,其软件维护任务的复杂度大大增加了。例如,清单 1 中的 scriptlet 示例严格地依赖于花括号的正确匹配。如果不经意间引入了一个语法错误,则条件内容中的嵌套其它 scriptlet 可能会造成严重破坏,并且在 JSP 容器编译该页面时,要使所产生的错误信息有意义可能会很困难。
清单 1. 通过 scriptlet 实现条件内容 <% if (user.getRole() == "member")) { %>
<p>Welcome, member!</p>
<% } else { %>
<p>Welcome, guest!</p>
<% } %>/PRE>
|
BR> 修正此类问题通常需要相当丰富的编程经验。尽管通常会由十分精通页面布局和图形设计的设计人员来开发和维护 JSP,但是同一页面中的脚本编制元素出现问题时,需要程序员的介入。这种状况将单个文件中代码的责任分担给多人,因而使得开发、调试和增强此类 JSP 页面成为很麻烦的任务。通过将常用功能包装到定制标记库的标准集合中,JSTL 使 JSP 作者可以减少对编制脚本元素的需求,甚至可以不需要它们,并避免了相关的维护成本。
JSTL 1.0
JSTL 1.0 发布于 2002 年 6 月,由四个定制标记库(core、format、xml 和 sql)和一对通用标记库验证器(ScriptFreeTLV 和 PermittedTaglibsTLV)组成。core 标记库提供了定制操作,通过限制了作用域的变量管理数据,以及执行页面内容的迭代和条件操作。它还提供了用来生成和操作 URL 的标记。顾名思义,format 标记库定义了用来格式化数据(尤其是数字和日期)的操作。它还支持使用本地化资源束进行 JSP 页面的国际化。xml 库包含一些标记,这些标记用来操作通过 XML 表示的数据,而 sql 库定义了用来查询关系数据库的操作。
两个 JSTL 标记库验证器允许开发人员在其 JSP 应用程序中强制使用编码标准。可以配置 ScriptFreeTLV 验证器以在 JSP 页面中禁用各种类型的 JSP 脚本元素 — scriptlet、表达式和声明。类似地,PermittedTaglibsTLV 验证器可以用来限制可能由应用程序的 JSP 页面访问的定制标记库集(包括 JSTL 标记库)。
尽管 JSTL 最终将会成为 J2EE 平台的必需组件,但目前只有少数应用程序服务器包括它。JSTL 1.0 的参考实现可作为 Apache 软件基金会(Apache Software Foundation)的 Jakarta Taglibs 项目(请参阅参考资料)的一部分而获得。可以将该参考实现中的定制标记库合并到任何支持 JSP 1.2 和 Servlet 2.3 规范的服务器,以添加对 JSTL 的支持。
表达式语言
在 JSP 1.2 中,可以使用静态字符串或表达式(如果允许的话)指定 JSP 操作的属性。例如,在清单 2 中,对 <jsp:setProperty> 操作的 name 和 property 属性指定了静态值,而用表达式指定了其 value 属性。这个操作的效果是将请求参数的当前值赋予命名的 bean 特性。以这种形式使用的表达式被称为请求时属性值(request-time attribute value),这是构建到 JSP 规范中的用于动态指定属性值的唯一机制。
清单 2. 合并请求时属性值的 JSP 操作
<jsp:setProperty name="user" property="timezonePref"
value='<%= request.getParameter("timezone") %>'/>/PRE> | BR> 因为请求时属性值是用表达式指定的,所以它们往往有和其它脚本元素一样的软件维护问题。因此,JSTL 定制标记支持另一种用于指定动态属性值的机制。可以用简化的表达式语言(EL)而不使用完整的 JSP 表达式来指定 JSTL 操作的属性值。EL 提供了一些标识符、存取器和运算符,用来检索和操作驻留在 JSP 容器中的数据。EL 在某种程度上以 EcmaScript(请参阅参考资料)和 XML 路径语言(XML Path Language,XPath)为基础,因此页面设计人员和程序员都应该熟悉它的语法。EL 擅长寻找对象及其特性,然后对它们执行简单操作;它不是编程语言,甚至不是脚本编制语言。但是,与 JSTL 标记一起使用时,它就能使用简单而又方便的符号来表示复杂的行为。EL 表达式的格式是这样的:用美元符号($)定界,内容包括在花括号({})中,如清单 3 所示。
清单 3. 说明 EL 表达式定界符的 JSTL 操作
<c:out value="${user.firstName}"/>
此外,您可以将多个表达式与静态文本组合在一起以通过字符串并置来构造动态属性值,如清单 4 所示。单独的表达式由标识符、存取器、文字和运算符组成。标识符用来引用存储在数据中心中的数据对象。EL 有 11 个保留标识符,对应于 11 个 EL 隐式对象。假定所有其它标识符都引用限制了作用域的变量。存取器用来检索对象的特性或集合的元素。文字表示固定的值 — 数字、字符、字符串、布尔型或空值。运算符允许对数据和文字进行组合以及比较。
清单 4. 组合静态文本和多个 EL 表达式以指定动态属性值
<c:out value="Hello ${user.firstName} ${user.lastName}"/>
限制了作用域的变量
JSP API 通过 <jsp:useBean> 操作允许从 JSP 容器内的四个不同作用域中存储和检索数据。JSTL 通过提供用于指定和除去这些作用域中的对象的附加操作来扩展这一能力。此外,EL 提供将这些对象作为限制了作用域的变量进行检索的内置支持。特别地,任何出现在 EL 表达式中但不对应于任何 EL 隐式对象的标识符,都被自动假定为引用存储在四个 JSP 作用域的其中某个中的对象,这四个作用域是:
·页面作用域
·请求作用域
·会话作用域
·应用程序作用域
您可能还记得,只有在为特定请求处理页面期间才能检索存储在该页面作用域中的对象。如果对象是存储在请求作用域中的,可以在处理所有参与处理某请求的页面期间检索这些对象(譬如在对某个请求的处理中遇到了一个或多个 <jsp:include> 或 <jsp:forward> 操作)。如果对象是存储在会话作用域中的,则在与 Web 应用程序的交互式会话期间,可以由用户访问的任何页面检索它(即,直到与该用户交互相关联的 HttpSession 对象无效为止)。可以由任何用户从任何页面访问存储在应用程序作用域中的对象,直到卸载 Web 应用程序本身为止(通常是由于关闭 JSP 容器所致)。
通过将字符串映射为期望作用域中的对象来将对象存储到该作用域。然后,就可以通过提供相同字符串来从该作用域检索该对象。在作用域的映射中查找字符串,并返回被映射的对象。在 Servlet API 中,将此类对象称为相应作用域的属性。但是,在 EL 的上下文中,也将与属性相关联的字符串看作变量的名称,该变量通过属性映射的方式获得特定的值。
在 EL 中,与隐式对象无关联的标识符被认为是存储在四个 JSP 作用域中的名称对象。首先对页面作用域检查是否存在这样的标识符,其次对请求作用域、然后对会话作用域、最后对应用程序作用域依次进行这样的检查,然后测试该标识符的名称是否与存储在该作用域中的某个对象的名称匹配。第一个这样的匹配作为 EL 标识符的值被返回。通过这种方法,可以将 EL 标识符看作引用限制了作用域的变量。
从更技术的方面来说,没有映射到隐式对象的标识符是用 PageContext 实例的 findAttribute() 方法求值的,该实例表示对页面的处理,在该页面上,当前正在处理用于请求的表达式。标识符的名称作为参数传递给这个方法,然后该方法依次在四个作用域中搜索具有相同名称的属性。并将所找到的第一个匹配项作为 findAttribute() 方法的值返回。如果未在这四个作用域中找到这样的属性,则返回 null。
最终,限制了作用域的变量是四个 JSP 作用域的属性,这些属性具有可以用作 EL 标识符的名称。只要对限制了作用域的变量赋予由字母数字组成的名称,就可以通过 JSP 中提供的用于设置属性的任何机制来创建它们。这包括内置的 <jsp:useBean> 操作,以及由 Servlet API 中的几个类定义的 setAttribute() 方法。此外,四个 JSTL 库中定义的许多定制标记本身就能够设置作为限制了作用域的变量使用的属性值。
隐式对象
表 1 中列出了 11 个 EL 隐式对象的标识符。不要将这些对象与 JSP 隐式对象(一共只有九个)混淆,其中只有一个对象是它们所共有的。
表 1. EL 隐式对象
类别 标识符 描述
JSP pageContext PageContext 实例对应于当前页面的处理
作用域 pageScope 与页面作用域属性的名称和值相关联的 Map 类
requestScope 与请求作用域属性的名称和值相关联的 Map 类
sessionScope 与会话作用域属性的名称和值相关联的 Map 类
applicationScope 与应用程序作用域属性的名称和值相关联的 Map 类
请求参数 param 按名称存储请求参数的主要值的 Map 类
paramValues 将请求参数的所有值作为 String 数组存储的 Map 类
请求头 header 按名称存储请求头主要值的 Map 类
headerValues 将请求头的所有值作为 String 数组存储的 Map 类
Cookie cookie 按名称存储请求附带的 cookie 的 Map 类
初始化参数 initParam 按名称存储 Web 应用程序上下文初始化参数的 Map 类
尽管 JSP 和 EL 隐式对象中只有一个公共对象(pageContext),但通过 EL 也可以访问其它 JSP 隐式对象。原因是 pageContext 拥有访问所有其它八个 JSP 隐式对象的特性。实际上,这是将它包括在 EL 隐式对象中的主要理由。
其余所有 EL 隐式对象都是映射,可以用来查找对应于名称的对象。前四个映射表示先前讨论的各种属性作用域。可以用它们来查找特定作用域中的标识符,而不用依赖于 EL 在缺省情况下使用的顺序查找过程。
接下来的四个映射用来获取请求参数和请求头的值。因为 HTTP 协议允许请求参数和请求头具有多个值,所以它们各有一对映射。每对中的第一个映射返回请求参数或头的主要值,通常是恰巧在实际请求中首先指定的那个值。每对中第二个映射允许检索参数或头的所有值。这些映射中的键是参数或头的名称,但这些值是 String 对象的数组,其中的每个元素都是单一参数值或头值。
cookie 隐式对象提供了对由请求设置的 cookie 名称的访问。这个对象将所有与请求相关联的 cookie 名称映射到表示那些 cookie 特性的 Cookie 对象。
最后一个 EL 隐式对象 initParam 是一个映射,它储存与 Web 应用程序相关联的所有上下文的初始化参数的名称和值。初始化参数是通过 web.xml 部署描述符文件指定的,该文件位于应用程序的 WEB-INF 目录中。
存取器
因为 EL 标识符是作为隐式对象或限制了作用域的变量(通过属性来实现)解析的,因此有必要将它们转换成 Java 对象。EL 可以自动包装和解包其相应的 Java 类中的基本类型(例如,可以在后台将 int 强制转换成 Integer 类,反之亦可),但大多数的标识符将成为指向完整的 Java 对象的指针。
结果是,对这些对象的特性或(在对象是数组和集合的情况下)对其元素的访问通常是令人满意的。就为了实现这种用途,EL 提供了两种不同的存取器(点运算符(.)和方括号运算符([])),也支持通过 EL 操作特性和元素。
点运算符通常用于访问对象的特性。例如,在表达式 ${user.firstName} 中,使用点运算符来访问 user 标识符所引用对象的名为 firstName 的特性。EL 使用 Java bean 约定访问对象特性,因此必须定义这个特性的 getter 方法(通常是名为 getFirstName() 的方法),以便表达式正确求值。当被访问的特性本身是对象时,可以递归地应用点运算符。例如,如果我们虚构的 user 对象有一个实现为 Java 对象的 address 特性,那么也可以用点运算符来访问这个对象的特性。例如,表达式 ${user.address.city} 将会返回这个地址对象嵌套的 city 特性。
方括号运算符用来检索数组和集合的元素。在数组和有序集合(也即,实现了 java.util.List 接口的集合)的情况下,把要检索的元素的下标放在方括号中。例如,表达式 ${urls[3]} 返回 urls 标识符所引用的数组或集合的第四个元素(和 Java 语言以及 JavaScript 中一样,EL 中的下标是从零开始的)。
对于实现 java.util.Map 接口的集合,方括号运算符使用关联的键查找存储在映射中的值。在方括号中指定键,并将相应的值作为表达式的值返回。例如,表达式 ${commands["dir"]} 返回与 commands 标识符所引用的 Map 中的 "dir" 键相关联的值。
对于上述两种情况,都可允许表达式出现在方括号中。对嵌套表达式求值的结果将被作为下标或键,用来检索集合或数组的适当元素。和点运算符一样,方括号运算符也可以递归应用。这使得 EL 能够从多维数组、嵌套集合或两者的任意组合中检索元素。此外,点运算符和方括号运算符还可以互操作。例如,如果数组的元素本身是对象,则可以使用方括号运算符来检索该数组的元素,并结合点运算符来检索该元素的一个特性(例如 ${urls[3].protocol})。
假定 EL 充当指定动态属性值的简化语言,EL 存取器有一个有趣的功能(与 Java 语言的存取器不同),那就是它们在应用于 null 时不抛出异常。如果应用 EL 存取器的对象(例如,${foo.bar} 和 ${foo["bar"]} 中的 foo 标识符)是 null,那么应用存取器的结果也是 null。事实证明,在大多数情况下,这是一个相当有用的行为,不久您就会了解这一点。
最后,点运算符和方括号运算符可能实现某种程度的互换。例如,也可以使用 ${user["firstName"]} 来检索 user 对象的 firstName 特性,正如可以用 ${commands.dir} 获取与 commands 映射中的 "dir" 键相关联的值一样。
运算符
EL 还可以通过使用标识符和存取器,遍历包含应用程序数据(通过限制了作用域的变量公开)或关于环境的信息(通过 EL 隐式对象)的对象层次结构。但是,只是访问这些数据,通常不足以实现许多 JSP 应用程序所需的表示逻辑。
最终,EL 还包括了几个用来操作和比较 EL 表达式所访问数据的运算符。表 2 中汇总了这些运算符。
表 2. EL 运算符
类别 运算符
算术运算符 +、-、*、/(或 div)和 %(或 mod)
关系运算符 ==(或 eq)、!=(或 ne)、<</code>(或 lt)、>(或 gt)、<=(或 le)和 >=(或 ge)
逻辑运算符 &&(或 and)、||(或 or)和 !(或 not)
验证运算符 empty
算术运算符支持数值的加法、减法、乘法和除法。还提供了一个求余运算符。注:除法和求余运算符都有替代的、非符号的名称(为的是与 XPath 保持一致)。清单 5 中显示了一个演示算术运算符用法的示例表达式。对几个 EL 表达式应用算术运算符的结果是将该算术运算符应用于这些表达式返回的数值所得的结果。
清单 5. 利用算术运算符的 EL 表达式
${item.price * (1 + taxRate[user.address.zipcode])}/PRE> | BR> 关系运算符允许比较数字或文本数据。比较的结果作为布尔值返回。逻辑运算符允许合并布尔值,返回新的布尔值。因此,可以将 EL 逻辑运算符应用于嵌套的关系或逻辑运算符的结果,如清单 6 所示。
清单 6. 利用关系和逻辑运算符的 EL 表达式
${(x >= min) && (x <= max)}/PRE> | BR> 最后一种 EL 运算符是 empty,它对于验证数据特别有用。empty 运算符采用单个表达式作为其变量(也即,${empty input}),并返回一个布尔值,该布尔值表示对表达式求值的结果是不是“空”值。求值结果为 null 的表达式被认为是空,即无元素的集合或数组。如果参数是对长度为零的 String 求值所得的结果,则 empty 运算符也将返回 true。
表 3 显示了 EL 运算符的优先级。正如清单 5 和 6 所示,可以用圆括号对表达式分组,高于普通的优先级规则。
表 3. EL 运算符优先级(自顶到底,从左到右)
[], .
()
unary -、not、!、empty
*、/、div、%、mod
+、binary -
() <</code>、>、<=、>=、lt、gt、le、ge
==、!=、eq、ne
&&、and
||、or/PRE> | BR> 文字
在 EL 表达式中,数字、字符串、布尔值和 null 都可以被指定为文字值。字符串可以用单引号或双引号定界。布尔值被指定为 true 和 false。
Taglib 伪指令
正如我们先前讨论的,JSTL 1.0 包括四个定制标记库。为了演示 JSTL 标记和表达式语言的交互,我们将研究几个来自 JSTL core 库的标记。和使用任何 JSP 定制标记库一样,必须在您想要使用这个库标记的任何页面中包括 taglib 伪指令。清单 7 显示了用于这个特定库的伪指令。
清单 7. 用于 JSTL core 库 EL 版本的 taglib 伪指令
<%@ taglib uri="http://java.sun.com/jstl/core" prefix="c" %>/PRE> | BR> 实际上,对应于 JSTL core 库的 taglib 伪指令有两种,因为在 JSTL 1.0 中,EL 是可选的。所有四个 JSTL 1.0 定制标记库都有使用 JSP 表达式(而不是 EL)指定动态属性值的备用版本。因为这些备用库依赖于 JSP 的更传统的请求时属性值,所以它们被称为 RT 库,而那些使用表达式语言的则被称为 EL 库。开发人员用不同的 taglib 伪指令来区分每个库的这两个版本。清单 8 显示了使用 core 库的 RT 版本的伪指令。但是,由于现在我们讨论的重点是 EL,所以首先需要这些伪指令。
清单 8. 用于 JSTL core 库 RT 版本的 taglib 伪指令
<%@ taglib uri="http://java.sun.com/jstl/core_rt" prefix="c_rt" %>/PRE> | BR> 变量标记
我们首先要考虑的 JSTL 定制标记是 <c:set> 操作。正如已经说明的,限制了作用域的变量在 JSTL 中起关键作用,<c:set> 操作提供基于标记的机制来创建和设置限制了作用域的变量。清单 9 中显示了该操作的语法,其中 var 属性指定了限制了作用域的变量的名称,scope 属性表明了该变量驻留在哪个作用域中,value 属性指定了分配给该变量的值。如果指定变量已经存在,则简单地将所指明的值赋给它。如果不存在,则创建新的限制了作用域的变量,并用该值初始化这个变量。
清单 9. <c:set> 操作的语法
<c:set var="name" scope="scope" value="expression"/>/PRE> | BR> scope 属性是可选的,其缺省值是 page。
清单 10 中显示了 <c:set> 的两个示例。在第一个示例中,将会话作用域变量设置成 String 值。在第二个示例中,用表达式来设置数值:将页面作用域内名为 square 的变量赋值为名为 x 的请求参数的值的平方。
清单 10. <c:set> 操作示例
<c:set var="timezone" scope="session" value="CST"/>
<c:set var="square" value="${param['x'] * param['x']}"/>/PRE> | BR> 您还可以将限制了作用域的变量的值指定为 <c:set> 操作的主体内容,而不是使用属性。使用这种方法,您可以重新编写清单 10 中的第一个示例,如清单 11 所示。此外,正如我们马上可以看到的,<c:set> 标记的主体内容本身也可以使用定制标记。<c:set> 主体内生成的所有内容都将作为一个 String 值赋给指定变量。
清单 11. 通过主体内容指定 <c:set> 操作的值
<c:set var="timezone" scope="session">CST</c:set>/PRE> | BR> JSTL core 库包含第二个用于管理限制了作用域的变量的标记 — <c:remove>。顾名思义,<c:remove> 操作是用来删除限制了作用域的变量的,它获取两个属性。var 属性指定待删除变量的名称,scope 属性是可选的,它表示待删除变量来自哪个作用域,缺省为 page,如清单 12 所示。
清单 12. <c:remove> 操作示例
<c:remove var="timezone" scope="session"/>/PRE> | BR> 输出
尽管 <c:set> 操作允许将表达式结果赋给限制了作用域的变量,但开发人员通常会希望只显示表达式的值,而不存储它。JSTL <c:out> 定制标记承担这一任务,其语法如清单 13 所示。该标记对由其 value 属性指定的表达式进行求值,然后打印结果。如果指定了可选属性 default,那么,在对 value 属性的表达式求值所得结果为 null 或空 String 的情况下,<c:out> 将打印其值。
清单 13. <c:out> 操作的语法
<c:out value="expression" default="expression" escapeXml="boolean"/>/PRE> | BR> escapeXml 属性也是可选的。它控制当用 <c:out> 标记输出诸如“<”、“>”和“&”之类的字符(在 HTML 和 XML 中具有特殊意义)时是否应该进行转义。如果将 escapeXml 设置为 true,则会自动将这些字符转换成相应的 XML 实体(此处提到的字符分别转换成 <、> 和 &)。
例如,假定有一个名为 user 的会话作用域变量,它是一个类的实例,该类为用户定义了两个特性:username 和 company。每当用户访问站点时,这个对象被自动分配给会话,但直到用户实际登录后,才会设置这两个特性。假定是这种方案,请考虑清单 14 中的 JSP 片段。在用户登录之后,这个片段将显示单词“Hello”,其后是他/她的用户名和一个惊叹号。但是,在用户登录之前,由这个片段生成的内容则是短语“Hello Guest!”。在这种情况下,因为 username 特性还有待初始化,所以 <c:out> 标记将转而打印出 default 属性的值(即字符串“Guest”)。
清单 14. 带缺省内容的 <c:out> 操作示例 Hello
<c:out value="${user.username}" default=="Guest"/>!/PRE> | BR> 接下来,考虑清单 15,它使用了 <c:out> 标记的 escapeXml 属性。如果在这种情况下已经将 company 特性设置成 Java String 值 "Flynn & Sons",那么,实际上该操作生成的内容将是 Flynn & Sons。如果这个操作是生成 HTML 或 XML 内容的 JSP 页面的一部分,那么,这个字符串中间的“&”符号最终可能被解释为 HTML 或 XML 控制字符,从而妨碍了对该内容的显示或解析。但是,如果将 escapeXml 属性值设置成 true,则所生成的内容将是 Flynn & Sons。浏览器或解析器不会因在解释时遇到这种内容而出问题。假定 HTML 和 XML 是 JSP 应用程序中最常见的内容类型,所以 escapeXml 属性的缺省值是 true 就不足为奇了。
清单 15. 禁用转义的 <c:out> 操作示例
<c:out value="${user.company}" escapeXml=="false"/>/PRE> | BR> 用缺省值设置变量
除了简化动态数据的显示之外,当通过 <c:set> 设置变量值时,<c:out> 指定缺省值的能力也很有用。正如清单 11 所示,用来赋给限制了作用域的变量的值可以指定为 <c:set> 标记的主体内容,也可以通过其值属性来指定。通过将 <c:out> 操作嵌套在 <c:set> 标记的主体内容中,变量赋值就可以利用其缺省值能力。
清单 16 中说明了这种方法。外部 <c:set> 标记的行为非常简单:它根据其主体内容设置会话作用域 timezone 变量的值。但是,在这种情况下,主体内容是通过 <c:out> 操作生成的。这个嵌套操作的值属性是表达式 ${cookie['tzPref'].value},它尝试通过 cookie 隐式对象返回名为 tzPref 的 cookie 值。(cookie 隐式对象将 cookie 名称映射到相应的 Cookie 实例,这意味着必须通过对象的 value 特性使用点运算符来检索储存在 cookie 中的实际数据。)
清单 16. 合并 <c:set> 和 <c:out> 以提供缺省变量值
<c:set var="timezone" scope=="session">
<c:out value="${cookie['tzPref'].value}" default=="CST"/>
</c:set>/PRE> | BR> 但是,请考虑以下情况,用户是第一次尝试使用这段代码的 Web 应用程序。结果是,请求中没有提供名为 tzPref 的 cookie。这意味着使用隐式对象的查找将返回 null,在这种情况下整个表达式将返回 null。因为对 <c:out> 标记的 value 属性求值的结果是 null,所以 <c:out> 标记会转而输出对其 default 属性求值的结果。在这里是字符串 CST。因此,实际的结果是将 timezone 限制了作用域的变量设置成用户的 tzPref cookie 中存储的时区,或者,如果没有,则使用缺省时区 CST。
EL 和 JSP 2.0
目前,表达式语言仅可用于指定 JSTL 定制标记中的动态属性值。但 JSTL 1.0 表达式语言的一个扩展已经被提出,会把它包括到 JSP 2.0 中去,眼下正在进行最后评审。这个扩展将允许开发人员通过自己的定制标记来使用 EL。页面作者将可以在目前允许使用 JSP 表达式的任何地方使用 EL 表达式,譬如将动态值插入模板文本中:<p>Your preferred time zone is ${timezone}</p>。
这个 JSP 2.0 功能(就象 JSTL 本身一样)将支持页面作者进一步减少对 JSP 编制脚本元素的依赖,从而改进 JSP 应用程序的可维护性。
结束语
EL(与四个 JSTL 定制标记库提供的操作结合起来)允许页面作者不使用脚本元素即可实现表示层逻辑。例如,对比本文开头清单 1 中的 JSP 代码和清单 17 中显示的通过 JSTL 实现的同样功能。(JSTL core 库中其余的标记,包括 <c:choose> 及其子标记,将在本系列的下一篇文章中讨论。)尽管显然执行了条件逻辑,但是 JSTL 版本中没有 Java 语言源代码,并且标记之间的关系(尤其是关于嵌套需求)对于任何精通 HTML 语法的人都应该是熟悉的。
清单 17. 合并 <c:set> 和 <c:out> 以提供缺省变量值
<c:choose><c:when test="${user.role == 'member'}">
<p>Welcome, member!</p>
</c:when><c:otherwise>
<p>Welcome, guest!</p>
</c:otherwise></c:choose>/PRE> |
BR> 通过提供大多数 Web 应用程序常用功能的标准实现,JSTL 有助于加速开发周期。与 EL 结合起来,JSTL 可以不需要对表示层程序编写代码,这极大地简化了 JSP 应用程序的维护。
转:删节 Firefox 不支持 document.all
解决也很简单 不用document.all就行了 那么用什么呢? 如下: getElementsByTagName("*") 可以得到得到所有元素的集合 getElemntById 可以按id得到某一元素 getElementsByName 可以得到按name属性得到某一元素
(转) <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> <html> <head> <title> New Document </title> </head> <body> <form action="somepage.asp"> <input type="text" value="0" name="txt1"/> <input type="button" value="开始" name="btnStart"/> <input type="button" value="重置" name="btnReset"/> </form> </body> </html> <script language="JavaScript" type="text/javascript"> <!-- //获取表单中的表单域 var txt=document.forms[0].elements["txt1"]; var btnStart=document.forms[0].elements["btnStart"]; var btnReset=document.forms[0].elements["btnReset"] //定义定时器的id var id; //每10毫秒该值增加1 var seed=0; btnStart.onclick=function(){ //根据按钮文本来判断当前操作 if(this.value=="开始"){ //使按钮文本变为停止 this.value="停止"; //使重置按钮不可用 btnReset.disabled=true; //设置定时器,每0.01s跳一次 id=window.setInterval(tip,10); }else{ //使按钮文本变为开始 this.value="开始"; //使重置按钮可用 btnReset.disabled=false; //取消定时 window.clearInterval(id); } }
//重置按钮 btnReset.onclick=function(){ seed=0; } //让秒表跳一格 function tip(){ seed++; txt.value=seed/100; } //--> </script>
摘要: 计算机只能读懂0或者1,而我们用高级语言编写的程序(原程序)是抽象的符号化了的东西,为了让计算机读懂我们写的程序,必须把我们书写的程序翻译成某台机器能够读懂的(机器)语言(目标程序),这就是翻译程序的作用。而“编译”则是翻译程序实现的一种方式。
编译程序的工作过程通常是词法分析、语法分析、语义分析、代码生成、代码优化。编译程序的这些... 阅读全文
href="javascript:void(0)" onClick="javascript:method()"
原因就在这两个javascript方法上了 2个在一个连接下同时使用会出这种错误
1.建立连接 : XMLHttpReq=window.XMLHttpRequest?new XMLHttpRequest():new ActiveXObject("Msxml2.XMLHTTP"); 2.发送请求: XMLHttpReq.open("GET",url,true); 3.返回请求: XMLHttpReq.onreadystatechange=function() { if(XMLHttpReq.readystate==4) { if(XMLHttpReq.status==200) { updateObj(); } else { alert("error:"+XMLHttpReq.status); } } } 4.页面取数据: var resCode=XMLHttpReq.responseXML.getElementByTagName("code");
元字符:"+","*","?" + ,规定前导字符必须在目标对象中出现一次或多次 * ,规定前导字符必须在目标对象中出现零次或多次 ? ,规定前导字符必须在目标对象中出现零次或一次
{n},{n,},{n,m}:最少比配N次最多匹配M次 例: o{2} "bood" o{2,} "boooooooood" o{2,3} 注意,逗号和两个数之间不能有空格
具体: var patrn=/^[0,9]{1,10}$/ if(!patrn.exec(s)) return false; return true;
javascript 中的replace方法 s=s.replace(/\./,"!") 只替换第一个 s=s.replace(/\./g,"!")替换全部 s=s.replace(/^\./g,"!") 替换开头 s=s.replace(/\.$/g,"!")替换结尾
<div style="border:10px red solid"> <input type="button" value="父元素标签" onclick="alert(event.srcElement.parentNode.tagName)"> </div>
event.srcElement有关问题- -
event.srcElement的子标签 和父标签: 第一个子标签为 event.srcElement.firstChild 最后个一个是 event.srcElement.lastChild 当然也可以用 event.srcElement.children[i] event.srcElement.ChildNode[i] 至于event.srcElement.parentElement是指在鼠标所在对象的上一个对象. \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ <script> function a() { alert("您点击的标记是:" + event.srcElement.tagName) } </script>
<body onclick="a()"> 点鼠标测试<br> <input><a href=#>test</a> <div>测试</div> <p>测试</p> <span>测试</span> <span> <a href="/" onmouseover="alert(event.srcElement.parentElement.tagName);">放在我上面</a> </span> </body> \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ <input type=button value=GO title="?page=1" onclick=f()> <script language="JavaScript"> function f() { alert('index.asp'+event.srcElement.title) location.href='index.asp'+event.srcElement.title } </script> <a title="a测试" onclick="alert(event.srcElement.title)" >a测试</a> <br> <table border=1 width="200"> <tr title="tr测试" onclick="alert(event.srcElement.parentElement.title)"><td>tr</td></tr> </table> <table border=1 width="200"> <tr><td title="td测试" onclick="alert(event.srcElement.title)">td</td></tr> </table> <select name="selectname" onchange="alert(event.srcElement.options[event.srcElement.selectedIndex].value)" > <option value="1">1</option> <option value="2">2</option> <option value="3">3</option> <option value="4">4</option> <option value="5">5</option> </select> 可以调用的方法还有: event.srcElement.id event.srcElement.tagname event.srcElement.type event.srcElement.value event.srcElement.name event.srcElement.classname event.srcElement.parentelement event.srcElement.getattribute event.srcElement.children event.srcElement.lastChild event.srcElement.ChildNode event.srcElement.selectedIndex baidu
/** * 当数据库字段为Text类型时调用 * @param rs * @param col * @return */ public static String getClobString(ResultSet rs, String col) { try { Reader reader = rs.getCharacterStream(col); if (reader == null) { return null; } StringBuffer sb = new StringBuffer(); char[] charbuf = new char[4096]; for (int i = reader.read(charbuf); i > 0; i = reader.read(charbuf)) { sb.append(charbuf, 0, i); } return sb.toString(); } catch (Exception e) { return ""; } }
刚开始使用SQL Server 2000,就给了我一个下马威。不过最终还是解决了。具体情况和解决方法: 安装SQL Server 2000的操作系统是Windows 2000 Profession Edition,安装简体中文标准版。会提示该版本的操作系统不能安装服务器组件,只能安装SQL Server 2000个人版。于是退出,选择安装个人版。却出现了新的错误: “以前的某个程序安装已在安装计算机上创建挂起的文件操作。运行安装程序之前必须重新启动计算机。” 接着按照提示重启计算机,再安装,仍然出现同样的提示。再网上查找相关资料,得知是安装程序在先前的安装过程中在系统注册表留下某些信息,导致不能安装。于是经过多次试,发现删除掉如下键值信息即可安装: 在运行窗口输入regedit,打开注册表编辑器,在HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Control\Session Manager中找到PendingFileRenameOperations,删除该键值,关闭注册表编辑器。重新安装SQL Server 2000,哈哈,久违的安装界面终于浮出水面了。 这个键值是安装程序暂挂项目,只要找到对应的应用程序清除掉就行了。
//建立分区 create tablespace tsp_jn
datafile 'E:\oracle\oradata\testtable\tsp_jn.dbf'
size 50m
autoextend on
next 5m;

create tablespace tsp_jni
datafile 'E:\oracle\oradata\testtable\tsp_jni.dbf'
size 50m
autoextend on
next 5m;

create tablespace tsp_ta
datafile 'E:\oracle\oradata\testtable\tsp_ta.dbf'
size 50m
autoextend on
next 5m;

create tablespace tsp_lw
datafile 'E:\oracle\oradata\testtable\tsp_lw.dbf'
size 50m
autoextend on
next 5m;

create tablespace tsp_ly
datafile 'E:\oracle\oradata\testtable\tsp_ly.dbf'
size 50m
autoextend on
next 5m;

create tablespace tsp_zz
datafile 'E:\oracle\oradata\testtable\tsp_zz.dbf'
size 50m
autoextend on
next 5m;

create tablespace tsp_hz
datafile 'E:\oracle\oradata\testtable\tsp_hz.dbf'
size 50m
autoextend on
next 5m;

create tablespace tsp_wh
datafile 'E:\oracle\oradata\testtable\tsp_wh.dbf'
size 50m
autoextend on
next 5m;

create tablespace tsp_rz
datafile 'E:\oracle\oradata\testtable\tsp_rz.dbf'
size 50m
autoextend on
next 5m;

create tablespace tsp_zb
datafile 'E:\oracle\oradata\testtable\tsp_zb.dbf'
size 50m
autoextend on
next 5m;

create tablespace tsp_bz
datafile 'E:\oracle\oradata\testtable\tsp_bz.dbf'
size 50m
autoextend on
next 5m;

create tablespace tsp_dy
datafile 'E:\oracle\oradata\testtable\tsp_dy.dbf'
size 50m
autoextend on
next 5m;

create tablespace tsp_lc
datafile 'E:\oracle\oradata\testtable\tsp_lc.dbf'
size 50m
autoextend on
next 5m;

create tablespace tsp_dz
datafile 'E:\oracle\oradata\testtable\tsp_dz.dbf'
size 50m
autoextend on
next 5m;

create tablespace tsp_sd
datafile 'E:\oracle\oradata\testtable\tsp_sd.dbf'
size 50m
autoextend on
next 5m;

create tablespace tsp_yt
datafile 'E:\oracle\oradata\testtable\tsp_yt.dbf'
size 50m
autoextend on
next 5m;

create tablespace tsp_wf
datafile 'E:\oracle\oradata\testtable\tsp_wf.dbf'
size 50m
autoextend on
next 5m;

 //建分区索引 CREATE INDEX fit_main_code ON fit_main(BRAND_CODE,FIT_CODE,PART_CODE,STYLE_CODE)
PARALLEL
LOCAL
(
PARTITION part_fit_main_jn TABLESPACE tsp_jn,
PARTITION part_fit_main_jni TABLESPACE tsp_jni,
PARTITION part_fit_main_ta TABLESPACE tsp_ta,
PARTITION part_fit_main_dz TABLESPACE tsp_dz,
PARTITION part_fit_main_lc TABLESPACE tsp_lc,
PARTITION part_fit_main_hz TABLESPACE tsp_hz,
PARTITION part_fit_main_ly TABLESPACE tsp_ly,
PARTITION part_fit_main_rz TABLESPACE tsp_rz,
PARTITION part_fit_main_wh TABLESPACE tsp_wh,
PARTITION part_fit_main_yt TABLESPACE tsp_yt,
PARTITION part_fit_main_wf TABLESPACE tsp_wf,
PARTITION part_fit_main_zb TABLESPACE tsp_zb,
PARTITION part_fit_main_bz TABLESPACE tsp_bz,
PARTITION part_fit_main_dy TABLESPACE tsp_dy,
PARTITION part_fit_main_lw TABLESPACE tsp_lw,
PARTITION part_fit_main_zz TABLESPACE tsp_zz,
PARTITION part_fit_main_sd TABLESPACE tsp_sd
);
mysql: 1.修改mysql.ini 字符格式 2.修改连接池url encode infomix: 在连接的url后加一段 强制字符类型:";NEWCODESET=gb18030,8859-1,819" postgresql : 建立数据库时选择utf8
按下面的步骤处理
: 1.新建一个同名的数据库
2.再停掉sqlserver服务(注意不要分离数据库) 3.用原数据库的数据文件覆盖掉这个新建的数据库
4.再重启sqlserver服务 5.此时打开企业管理器时会出现置疑,先不管,执行下面的语句(注意修改其中的数据库名)
6.完成后一般就可以访问数据库中的数据了。这时,数据库本身一般还有问题,解决办法是:利用数据库的脚本创建一个新的数据库,然后通过DTS将数据导进去就行了
use master go sp_configure 'allow updates',1 reconfigure with override go update sysdatabases set status =32768 where name='置疑的数据库名' go sp_dboption '置疑的数据库名', 'single user', 'true' go dbcc checkdb('置疑的数据库名') go update sysdatabases set status =28 where name='置疑的数据库名' go sp_configure 'allow updates', 0 reconfigure with override go sp_dboption '置疑的数据库名', 'single user', 'false' go
(此方法只是针对那种用普通方法附加时报:缺少日志文件,保日志物理文件错误的情况时适用)
修改安装目录下的pdflm12.dll文件,使用二进制编辑器打开此文件,查找:83 C4 14 8B 85 E4 FE FF FF将此字符串改为83 C4 14 33 C0 90 90 90 90
blogjava现在的编辑器特难用。打着字经常的刷页面,反应还有点迟钝。
昨天做了一个交叉表的统计: 得到的统计表有30列 4行,需要执行120个select count当时要的比较急匆忙的做了一个 总感觉有些的麻烦,想今天到网上找找有没有更好的方法。搜了一天也没找到个效率更高一点的方法 现在把我的思路先发出来: 我的工程是web project 用的是struts 用DBManager联数据库 120个select 如果要联120次数据库是恐怖的, 即使用连接池 如果被多个用户同时使用也难以承受。 我先建了一个table 120个字段 然后用update table set abc="select count ..",set bbc="select count ".. 用建好的一个类 取出数据 放到页面上。
后来用户又提出了 每一列都需要一个合计 ,我就直接在页面上用取出的值进行相加。
统计表做完后 眼睛都看花了,现在正在找一些简单的方法替代这种笨办法。
Unicode字符介绍
2007年02月16日 星期五 12:25
java使用的字符集是Unicode字符集,所以了解Unicode字符集,对学好java是必不可少的,
Unicode是一种字符编码规范 。 先从ASCII说起。ASCII是用来表示英文字符的一种编码规范,每个ASCII字符占用1个字节(1byte=8bits)
因此,ASCII编码可以表示的最大字符数是256,其实英文字符并没有那么多,一般只用前128个(最高位为0),其中包括了控制字符、数字、大小写字母和其他一些符号 。
而最高位为1的另128个字符被成为“扩展ASCII”,一般用来存放英文的制表符、部分音标字符等等的一些其他符号
这种字符编码规范显然用来处理英文没有什么问题 。(实际上也可以用来处理法文、德文等一些其他的西欧字符,但是不能和英文通用),但是面对中文、阿拉伯文之类复杂的文字,255个字符显然不够用
于是,各个国家纷纷制定了自己的文字编码规范,其中中文的文字编码规范叫做“GB2312-80”,它是和ASCII兼容的一种编码规范,其实就是利用扩展ASCII没有真正标准化这一点,把一个中文字符用两个扩展ASCII字符来表示。
但 是这个方法有问题,最大的问题就是,中文文字没有真正属于自己的编码,因为扩展ASCII码虽然没有真正的标准化,但是PC里的ASCII码还是有一个事 实标准的(存放着英文制表符),所以很多软件利用这些符号来画表格。这样的软件用到中文系统中,这些表格符就会被误认作中文字,破坏版面。而且,统计中英 文混合字符串中的字数,也是比较复杂的,我们必须判断一个ASCII码是否扩展,以及它的下一个ASCII是否扩展,然后才“猜”那可能是一个中文字 。
总之当时处理中文是很痛苦的。而更痛苦的是GB2312是国家标准,台湾当时有一个Big5编码标准,很多编码和GB是相同的,所以……,嘿嘿。
这 时候,我们就知道,要真正解决中文问题,不能从扩展ASCII的角度入手,也不能仅靠中国一家来解决。而必须有一个全新的编码系统,这个系统要可以将中 文、英文、法文、德文……等等所有的文字统一起来考虑,为每个文字都分配一个单独的编码,这样才不会有上面那种现象出现。
于是,Unicode诞生了。
Unicode有两套标准,一套叫UCS-2(Unicode-16),用2个字节为字符编码,另一套叫UCS-4(Unicode-32),用4个字节为字符编码。
以目前常用的UCS-2为例,它可以表示的字符数为2^16=65535,基本上可以容纳所有的欧美字符和绝大部分的亚洲字符 。
UTF-8的问题后面会提到 。
在Unicode里,所有的字符被一视同仁。汉字不再使用“两个扩展ASCII”,而是使用“1个Unicode”,注意,现在的汉字是“一个字符”了,于是,拆字、统计字数这些问题也就自然而然的解决了 。
但是,这个世界不是理想的,不可能在一夜之间所有的系统都使用Unicode来处理字符,所以Unicode在诞生之日,就必须考虑一个严峻的问题:和ASCII字符集之间的不兼容问题。
我们知道,ASCII字符是单个字节的,比如“A”的ASCII是65。而Unicode是双字节的,比如“A”的Unicode是0065,这就造成了一个非常大的问题:以前处理ASCII的那套机制不能被用来处理Unicode了 。
另一个更加严重的问题是,C语言使用'\0'作为字符串结尾,而Unicode里恰恰有很多字符都有一个字节为0,这样一来,C语言的字符串函数将无法正常处理Unicode,除非把世界上所有用C写的程序以及他们所用的函数库全部换掉 。
于是,比Unicode更伟大的东东诞生了,之所以说它更伟大是因为它让Unicode不再存在于纸上,而是真实的存在于我们大家的电脑中。那就是:UTF 。
UTF= UCS Transformation Format UCS转换格式
它是将Unicode编码规则和计算机的实际编码对应起来的一个规则。现在流行的UTF有2种:UTF-8和UTF-16 。
其中UTF-16和上面提到的Unicode本身的编码规范是一致的,这里不多说了。而UTF-8不同,它定义了一种“区间规则”,这种规则可以和ASCII编码保持最大程度的兼容 。
UTF-8有点类似于Haffman编码,它将Unicode编码为00000000-0000007F的字符,用单个字节来表示;
00000080-000007FF的字符用两个字节表示
00000800-0000FFFF的字符用3字节表示
因为目前为止Unicode-16规范没有指定FFFF以上的字符,所以UTF-8最多是使用3个字节来表示一个字符。但理论上来说,UTF-8最多需要用6字节表示一个字符。
在UTF-8里,英文字符仍然跟ASCII编码一样,因此原先的函数库可以继续使用。而中文的编码范围是在0080-07FF之间,因此是2个字节表示(但这两个字节和GB编码的两个字节是不同的),用专门的Unicode处理类可以对UTF编码进行处理。
下面说说中文的问题。
由于历史的原因,在Unicode之前,一共存在过3套中文编码标准。
GB2312-80,是中国大陆使用的国家标准,其中一共编码了6763个常用简体汉字。Big5,是台湾使用的编码标准,编码了台湾使用的繁体汉字,大概有8千多个。HKSCS,是中国香港使用的编码标准,字体也是繁体,但跟Big5有所不同。
这3套编码标准都采用了两个扩展ASCII的方法,因此,几套编码互不兼容,而且编码区间也各有不同
因为其不兼容性,在同一个系统中同时显示GB和Big5基本上是不可能的。当时的南极星、RichWin等等软件,在自动识别中文编码、自动显示正确编码方面都做了很多努力 。
他们用了怎样的技术我就不得而知了,我知道好像南极星曾经以同屏显示繁简中文为卖点。
后来,由于各方面的原因,国际上又制定了针对中文的统一字符集GBK和GB18030,其中GBK已经在Windows、Linux等多种操作系统中被实现。
GBK兼容GB2312,并增加了大量不常用汉字,还加入了几乎所有的Big5中的繁体汉字。但是GBK中的繁体汉字和Big5中的几乎不兼容。
GB18030相当于是GBK的超集,比GBK包含的字符更多。据我所知目前还没有操作系统直接支持GB18030。
谈谈Unicode编码,简要解释UCS、UTF、BMP、BOM等名词 这是一篇程序员写给程序员的趣味读物。所谓趣味是指可以比较轻松地了解一些原来不清楚的概念,增进知识,类似于打RPG游戏的升级。整理这篇文章的动机是两个问题:
问题一: 使用Windows记事本的“另存为”,可以在GBK、Unicode、Unicode big endian和UTF-8这几种编码方式间相互转换。同样是txt文件,Windows是怎样识别编码方式的呢?
我 很早前就发现Unicode、Unicode big endian和UTF-8编码的txt文件的开头会多出几个字节,分别是FF、FE (Unicode),FE、FF(Unicode big endian),EF、BB、BF(UTF-8)。但这些标记是基于什么标准呢?
问题二: 最 近在网上看到一个ConvertUTF.c,实现了UTF-32、UTF-16和UTF-8这三种编码方式的相互转换。对于Unicode(UCS2)、 GBK、UTF-8这些编码方式,我原来就了解。但这个程序让我有些糊涂,想不起来UTF-16和UCS2有什么关系。 查了查相关资料,总算将这些问题弄清楚了,顺带也了解了一些Unicode的细节。写成一篇文章,送给有过类似疑问的朋友。本文在写作时尽量做到通俗易懂,但要求读者知道什么是字节,什么是十六进制。
0、big endian和little endian big endian 和little endian是CPU处理多字节数的不同方式。例如“汉”字的Unicode编码是6C49。那么写到文件里时,究竟是将6C写在前面, 还是将49写在前面?如果将6C写在前面,就是big endian。还是将49写在前面,就是little endian。
“endian”这个词出自《格列佛游记》。小人国的内战就源于吃鸡蛋时是究竟从大头(Big-Endian)敲开还是从小头(Little-Endian)敲开,由此曾发生过六次叛乱,其中一个皇帝送了命,另一个丢了王位。
我们一般将endian翻译成“字节序”,将big endian和little endian称作“大尾”和“小尾”。
1、字符编码、内码,顺带介绍汉字编码 字符必须编码后才能被计算机处理。计算机使用的缺省编码方式就是计算机的内码。早期的计算机使用7位的ASCII编码,为了处理汉字,程序员设计了用于简体中文的GB2312和用于繁体中文的big5。
GB2312(1980年)一共收录了7445个字符,包括6763个汉字和682个其它符号。汉字区的内码范围高字节从B0-F7,低字节从A1-FE,占用的码位是72*94=6768。其中有5个空位是D7FA-D7FE。
GB2312 支持的汉字太少。1995年的汉字扩展规范GBK1.0收录了21886个符号,它分为汉字区和图形符号区。汉字区包括21003个字符。2000年的 GB18030是取代GBK1.0的正式国家标准。该标准收录了27484个汉字,同时还收录了藏文、蒙文、维吾尔文等主要的少数民族文字。现在的PC平 台必须支持GB18030,对嵌入式产品暂不作要求。所以手机、MP3一般只支持GB2312。
从ASCII、GB2312、GBK到 GB18030,这些编码方法是向下兼容的,即同一个字符在这些方案中总是有相同的编码,后面的标准支持更多的字符。在这些编码中,英文和中文可以统一地 处理。区分中文编码的方法是高字节的最高位不为0。按照程序员的称呼,GB2312、GBK到GB18030都属于双字节字符集 (DBCS)。
有的中文Windows的缺省内码还是GBK,可以通过GB18030升级包升级到GB18030。不过GB18030相对GBK增加的字符,普通人是很难用到的,通常我们还是用GBK指代中文Windows内码。
这里还有一些细节:
GB2312的原文还是区位码,从区位码到内码,需要在高字节和低字节上分别加上A0。
在DBCS中,GB内码的存储格式始终是big endian,即高位在前。
GB2312 的两个字节的最高位都是1。但符合这个条件的码位只有128*128=16384个。所以GBK和GB18030的低字节最高位都可能不是1。不过这不影 响DBCS字符流的解析:在读取DBCS字符流时,只要遇到高位为1的字节,就可以将下两个字节作为一个双字节编码,而不用管低字节的高位是什么。
2、Unicode、UCS和UTF 前面提到从ASCII、GB2312、GBK到GB18030的编码方法是向下兼容的。而Unicode只与ASCII兼容(更准确地说,是与ISO-8859-1兼容),与GB码不兼容。例如“汉”字的Unicode编码是6C49,而GB码是BABA。
Unicode 也是一种字符编码方法,不过它是由国际组织设计,可以容纳全世界所有语言文字的编码方案。Unicode的学名是"Universal Multiple -Octet Coded Character Set",简称为UCS。UCS可以看作是"Unicode Character Set"的缩写。
根据维基百科全书(http://zh.wikipedia.org/wiki/)的记载:历史上存在两个试图独立设计Unicode的组织,即国际标准化组织(ISO)和一个软件制造商的协会(unicode.org)。ISO开发了ISO 10646项目,Unicode协会开发了Unicode项目。
在1991年前后,双方都认识到世界不需要两个不兼容的字符集。于是它们开始合并双方的工作成果,并为创立一个单一编码表而协同工作。从Unicode2.0开始,Unicode项目采用了与ISO 10646-1相同的字库和字码。
目前两个项目仍都存在,并独立地公布各自的标准。Unicode协会现在的最新版本是2005年的Unicode 4.1.0。ISO的最新标准是10646-3:2003。
UCS规定了怎么用多个字节表示各种文字。怎样传输这些编码,是由UTF(UCS Transformation Format)规范规定的,常见的UTF规范包括UTF-8、UTF-7、UTF-16。
IETF 的RFC2781和RFC3629以RFC的一贯风格,清晰、明快又不失严谨地描述了UTF-16和UTF-8的编码方法。我总是记不得IETF是 Internet Engineering Task Force的缩写。但IETF负责维护的RFC是Internet上一切规范的基础。
3、UCS-2、UCS-4、BMP
UCS有两种格式:UCS-2和UCS-4。顾名思义,UCS-2就是用两个字节编码,UCS-4就是用4个字节(实际上只用了31位,最高位必须为0)编码。下面让我们做一些简单的数学游戏:
UCS-2有2^16=65536个码位,UCS-4有2^31=2147483648个码位。
UCS -4根据最高位为0的最高字节分成2^7=128个group。每个group再根据次高字节分为256个plane。每个plane根据第3个字节分为 256行 (rows),每行包含256个cells。当然同一行的cells只是最后一个字节不同,其余都相同。
group 0的plane 0被称作Basic Multilingual Plane, 即BMP。或者说UCS-4中,高两个字节为0的码位被称作BMP。
将UCS-4的BMP去掉前面的两个零字节就得到了UCS-2。在UCS-2的两个字节前加上两个零字节,就得到了UCS-4的BMP。而目前的UCS-4规范中还没有任何字符被分配在BMP之外。
4、UTF编码
UTF-8就是以8位为单元对UCS进行编码。从UCS-2到UTF-8的编码方式如下:
UCS-2编码(16进制) UTF-8 字节流(二进制) 0000 - 007F 0xxxxxxx 0080 - 07FF 110xxxxx 10xxxxxx 0800 - FFFF 1110xxxx 10xxxxxx 10xxxxxx
例 如“汉”字的Unicode编码是6C49。6C49在0800-FFFF之间,所以肯定要用3字节模板了: 1110xxxx 10xxxxxx 10xxxxxx。将6C49写成二进制是:0110 110001 001001, 用这个比特流依次代替模板中 的x,得到:11100110 10110001 10001001,即E6 B1 89。
读者可以用记事本测试一下我们的编码是否正确。
UTF -16以16位为单元对UCS进行编码。对于小于0x10000的UCS码,UTF-16编码就等于UCS码对应的16位无符号整数。对于不小于 0x10000的UCS码,定义了一个算法。不过由于实际使用的UCS2,或者UCS4的BMP必然小于0x10000,所以就目前而言,可以认为UTF -16和UCS-2基本相同。但UCS-2只是一个编码方案,UTF-16却要用于实际的传输,所以就不得不考虑字节序的问题。
5、UTF的字节序和BOM UTF -8以字节为编码单元,没有字节序的问题。UTF-16以两个字节为编码单元,在解释一个UTF-16文本前,首先要弄清楚每个编码单元的字节序。例如收 到一个“奎”的Unicode编码是594E,“乙”的Unicode编码是4E59。如果我们收到UTF-16字节流“594E”,那么这是“奎”还是 “乙”?
Unicode规范中推荐的标记字节顺序的方法是BOM。BOM不是“Bill Of Material”的BOM表,而是Byte Order Mark。BOM是一个有点小聪明的想法:
在UCS 编码中有一个叫做"ZERO WIDTH NO-BREAK SPACE"的字符,它的编码是FEFF。而FFFE在UCS中是不存在的字符,所以不应该 出现在实际传输中。UCS规范建议我们在传输字节流前,先传输字符"ZERO WIDTH NO-BREAK SPACE"。
这样如果接收者收到FEFF,就表明这个字节流是Big-Endian的;如果收到FFFE,就表明这个字节流是Little-Endian的。因此字符"ZERO WIDTH NO-BREAK SPACE"又被称作BOM。
UTF -8不需要BOM来表明字节顺序,但可以用BOM来表明编码方式。字符"ZERO WIDTH NO-BREAK SPACE"的UTF-8编码是 EF BB BF(读者可以用我们前面介绍的编码方法验证一下)。所以如果接收者收到以EF BB BF开头的字节流,就知道这是UTF-8编码了。
Windows就是使用BOM来标记文本文件的编码方式的。
|
STATIC: 1.可以声明变量,加载时初始化变量,并赋值; 2.声明一个方法,加载时初始化该方法的引用; 3.声明一个类,加载时初始化该类中的变量和语句,此类中只能有变量和语句,不能有方法。
在Java中你要调用一个class某一个方法时 你必须 你显示列化它 或者你把它申明为 静态的(static)
SUN公司的一道测试题:
public class X{ public static void main(String[] args){ String s=new String("Hello"); modify(s); System.out.println(s); } public static void modify(String s){ s+=" World"; }
}
what is the result? 分析一下: 1.执行main,定义了字符串s 并赋值hello 2.调用方法modify(变量S) 我们注意到 modify方法是静态的,即他在内存中地址是固定的。也就是说不管上面的方法引用modify时 传过来的变量S是多少,对于modify方法都不重要,因为他的作用是把自己的S变量改变。 而外面的 引用 不起任何的作用; 把这个题目改改就好理解了: public class X{ public static void main(String[] args){ String s=new String("Hello"); modify(s); System.out.println(s); } public static void modify(String s){ s+=" World"; System.out.println(s); }
}
result: HelloWord Hello
3.有一点需要注意的是,当传过来的变量S是个数组,前面定义了S[0],传的是S(起始地址)这种修改变的有意思了,也变得有意义了。modify才真正的有用
Oracle数据导入导出imp/exp就相当于oracle数据还原与备份。exp命令可以把数据从远程数据库服务器导出到本地的dmp文件,imp命令可以把dmp文件从本地导入到远处的数据库服务器中。 利用这个功能可以构建两个相同的数据库,一个用来测试,一个用来正式使用。 执行环境:可以在SQLPLUS.EXE或者DOS(命令行)中执行, DOS中可以执行时由于 在oracle 8i 中 安装目录ora81BIN被设置为全局路径, 该目录下有EXP.EXE与IMP.EXE文件被用来执行导入导出。 oracle用java编写,SQLPLUS.EXE、EXP.EXE、IMP.EXE这两个文件有可能是被包装后的类文件。 SQLPLUS.EXE调用EXP.EXE、IMP.EXE所包裹的类,完成导入导出功能。 下面介绍的是导入导出的实例。 数据导出: 1 将数据库TEST完全导出,用户名system 密码manager 导出到D:daochu.dmp中 exp system/manager@TEST file=d:daochu.dmp full=y 2 将数据库中system用户与sys用户的表导出 exp system/manager@TEST file=d:daochu.dmp owner=(system,sys) 3 将数据库中的表inner_notify、notify_staff_relat导出 exp aichannel/aichannel@TESTDB2 file= d:datanewsmgnt.dmp tables=(inner_notify,notify_staff_relat)
4 将数据库中的表table1中的字段filed1以"00"打头的数据导出 exp system/manager@TEST file=d:daochu.dmp tables=(table1) query=" where filed1 like '00%'" 上面是常用的导出,对于压缩,既用winzip把dmp文件可以很好的压缩。 也可以在上面命令后面 加上 compress=y 来实现。
数据的导入 1 将D:daochu.dmp 中的数据导入 TEST数据库中。 imp system/manager@TEST file=d:daochu.dmp imp aichannel/aichannel@HUST full=y file=d:datanewsmgnt.dmp ignore=y 上面可能有点问题,因为有的表已经存在,然后它就报错,对该表就不进行导入。 在后面加上 ignore=y 就可以了。 2 将d:daochu.dmp中的表table1 导入 imp system/manager@TEST file=d:daochu.dmp tables=(table1) 基本上上面的导入导出够用了。不少情况要先是将表彻底删除,然后导入。 注意: 操作者要有足够的权限,权限不够它会提示。 数据库时可以连上的。可以用tnsping TEST 来获得数据库TEST能否连上。
附录一: 给用户增加导入数据权限的操作 第一,启动sql*puls 第二,以system/manager登陆 第三,create user 用户名 IDENTIFIED BY 密码 (如果已经创建过用户,这步可以省略) 第四,GRANT CREATE USER,DROP USER,ALTER USER ,CREATE ANY VIEW , DROP ANY VIEW,EXP_FULL_DATABASE,IMP_FULL_DATABASE, DBA,CONNECT,RESOURCE,CREATE SESSION TO 用户名字 第五, 运行-cmd-进入dmp文件所在的目录, imp userid=system/manager full=y file=*.dmp 或者 imp userid=system/manager full=y file=filename.dmp
执行示例: F:WorkOracle_Databackup>imp userid=test/test full=y file=inner_notify.dmp
屏幕显示 Import: Release 8.1.7.0.0 - Production on 星期四 2月 16 16:50:05 2006 (c) Copyright 2000 Oracle Corporation. All rights reserved.
连接到: Oracle8i Enterprise Edition Release 8.1.7.0.0 - Production With the Partitioning option JServer Release 8.1.7.0.0 - Production
经由常规路径导出由EXPORT:V08.01.07创建的文件 已经完成ZHS16GBK字符集和ZHS16GBK NCHAR 字符集中的导入 导出服务器使用UTF8 NCHAR 字符集 (可能的ncharset转换) . 正在将AICHANNEL的对象导入到 AICHANNEL . . 正在导入表 "INNER_NOTIFY" 4行被导入 准备启用约束条件... 成功终止导入,但出现警告。
附录二: Oracle 不允许直接改变表的拥有者, 利用Export/Import可以达到这一目的. 先建立import9.par, 然后,使用时命令如下:imp parfile=/filepath/import9.par 例 import9.par 内容如下: FROMUSER=TGPMS TOUSER=TGPMS2 (注:把表的拥有者由FROMUSER改为TOUSER,FROMUSER和TOUSER的用户可以不同) ROWS=Y INDEXES=Y GRANTS=Y CONSTRAINTS=Y BUFFER=409600 file==/backup/ctgpc_20030623.dmp log==/backup/import_20030623.log
1.Struts 最重要的是理解ActionForward 动态转发, 2.Session 其中的HttpSession用的最多,意思就是:客户端和服务端之间建立的联系或者叫通信: 3.hashmap 就是一张2维映射表,叫的挺洋气.里面的数据键值对应.
现在刚刚可以用这几种流行的框架实现几个添加修改删除的功能。 经验:就难点来说共有两个: 1.如何将request的action请求转发到spring 方法:其实解决这个问题共有两种方案:1.在struts-config.xml中将action的type属性改为有spring 控制即"org.springframework.web.struts.DelegatingActionProxy",2.建立一个baseaction类文件将struts所有的类都继承它.即在调用action的时候转到spring中. 2.怎样用spring控制hibernate 方法:这个不难,在applicationContext.xml中设置bean:"dataSource"和"sessionFactory" 就行. 另外对于新手最好用工具实现: 我现在用的是myeclipes4.1
var str=""; str+="<iframe height='100' width='100' src='http://218.57.135.244/dlib/admin/User/UserManageInterface.Ctrl.asp?strOpType=add&strUserName=<%=account%>&strPassWord=<%=password%>&nUserGroupID=3'></iframe>"; var div1 = document.createElement("<div style='display:none'></div>"); document.body.appendChild(div1); div1.innerHTML = str;
以下是一个用户注册信息验证的一个程序。里面有邮件合法性的验证。(可以取出不合法的字符和不合法的原因) _______________________________________________________________ <script language=javascript> //检查用户ID function check(){ doc=document.register; if(doc.username.value==""){ alert('请填写你登陆时的ID!'); doc.username.focus(); return false; } var n=doc.username.value.length; //var zm=doc.username.value.charCodeAt(0); var tempmsg=""; //alert(zm); for(var i=0;i<n;i++){ var zm=doc.username.value.charCodeAt(i); if(!((zm>=48&&zm<=57)||(zm>=65&&zm<=90)||(zm>=97&&zm<=122))){ tempmsg+="\""+doc.username.value.charAt(i)+"\","; var flag=1; } } if(flag){ alert('您输入的ID中包含下列不合法的字符:'+tempmsg); doc.username.focus(); return false; } //检查用户真实姓名 if(doc.name.value==""||doc.name.value.length<2){ alert('请输入你的真实姓名!'); doc.name.focus(); return false; } n=doc.name.value.length; tempmsg=""; for(i=0;i<=n;i++){ zm=doc.name.value.charCodeAt(i); if(zm<=255){ tempmsg+="\""+doc.name.value.charAt(i)+"\","; var flag=1; } } if(flag){ alert('您的名字中不能包含如下字符:'+tempmsg); doc.name.focus(); return false; } //检查密码 if(doc.password.value==""){ alert('请输入你的密码!'); doc.password.focus(); return false; } //检查E-mail if(doc.email.value==""){ alert('请输入你的E-mail!'); doc.email.focus(); return false; } if(doc.email.value.indexOf("@")==-1){ alert('请输入你的正确E-mail,必须包括“@”!'); doc.email.focus(); return false; } tempmsg=doc.email.value.substring(0,doc.email.value.indexOf("@")); if(tempmsg.length<3){ alert('请输入你的完整的E-mail!\"@\"前面的字符长度不能小于3位!'); doc.email.focus(); return false; } if(!((doc.email.value.indexOf(".com")!=-1)||(doc.email.value.indexOf(".net")!=-1)||(doc.email.value.indexOf(".net")!=-1)||(doc.email.value.indexOf(".edu")!=-1))){ alert('请输入你邮箱的后缀名!后缀名为小写!'); doc.email.focus(); return false; } tempmsg=doc.email.value.substring((doc.email.value.indexOf("@")+1),doc.email.value.indexOf(".")); if(tempmsg.length<2){ alert('请输入你邮箱的完整形式!\"@\"和\".\"之间的字符长度不小于2'); doc.email.focus(); return false; } //检测电话号码 //检测区号 if(doc.phone1.value.length!=0||doc.phone2.value.length!=0){ if(doc.phone1.value.length<3){ alert("请正确输入区号"); doc.phone1.focus(); return false; }
if(doc.phone1.value.indexOf(0)!=0) { alert("区号第一位必须是0"); doc.phone1.focus(); return false; } n=doc.phone1.value.length; tempmsg=""; for(i=0;i<n;i++){ zm=doc.phone1.value.charCodeAt(i); if(zm<48||zm>57){ tempmsg+="\""+doc.phone1.value.charAt(i)+"\","; flag=1; } } if(flag){ alert("你输入的区号中包括以下非法字符"+tempmsg); doc.phone1.focus(); return false; } }
//检测电话 if(doc.phone1.value.length!=0||doc.phone2.value.length!=0){ n=doc.phone2.value.length; tempmsg=""; for(i=0;i<n;i++){ zm=doc.phone2.value.charCodeAt(i); if(zm<48||zm>57){ tempmsg+="\""+doc.phone2.value.charAt(i)+"\","; flag=1; } } if(flag){ alert("你输入的电话号码中包括以下非法字符"+tempmsg); doc.phone2.focus(); return false; } if(doc.phone2.value.length<7){ alert("请输入电话号码!"); doc.phone2.focus(); return false; }
} } </script>
花了一段时间搞出来的: <script language="javascript"> var kindList=new Array() <%int m=0; for(int j=0;j<list.size();j++){ NetsdSmallKind smallKind=(NetsdSmallKind)list.get(j); %> kindList[<%=m++%>]=new Array("<%=smallKind.getId()%>","<%=smallKind.getKindid()%>","<%=smallKind.getSkindname()%>"); <%}%> function ChangeKind(locationid){ var i document.form1.smallkindid.length=0 var locationid=locationid for(i=0;i<<%=m%>;i++){ if( kindList[i][1]==locationid){ document.form1.smallkindid.options[document.form1.smallkindid.length]=new Option(kindList[i][2],kindList[i][0]) } } document.form1.smallkindid.focus(); } </script>
<%@ page contentType="text/html;charset=gb2312"%> <%@ page language="java" import="java.io.*"%>
<html> <head> <meta http-equiv="Content-Type" content="text/html; charset=gb2312"> <title>计数器</title> </head>
<%! //同步更新计数器 synchronized void counter(){ ServletContext application=getServletContext(); //构造application对象(可选) String szPath=application.getRealPath("/"); //得到当前路径 szPath=szPath+"hits.txt"; //计数器文件 0-9999999999999... String szRecord=""; //记数 String int nRecord=0; //记数 int
try{ BufferedReader file=new BufferedReader(new FileReader(szPath)); szRecord=file.readLine(); //读取计数器文件 } catch(IOException e){ e.printStackTrace(System.err); } if(szRecord==null) szRecord="0"; //如果计数器文件为空
nRecord=java.lang.Integer.parseInt(szRecord)+1; //计数器+1 try{ File f=new File(szPath); PrintWriter pw=new PrintWriter(new FileWriter(f)); pw.print(nRecord); //写文件 pw.close(); } catch(IOException e){ System.out.println(e); } } %>
<% //显示计数器 if(session.isNew()){ //如果是新用户 counter(); } String Path=application.getRealPath("/"); String szPath=Path+"hits.txt"; String szRecord=""; BufferedReader file=new BufferedReader(new FileReader(szPath)); try{ szRecord=file.readLine(); } catch(IOException e){ System.out.println("文件未找到!"); } //显示7位数字gif图像 String szOut="<body topmargin='0' leftmargin='0'>"; int i=0; int k=7-szRecord.length(); //"0"的个数 for (i=0;i<k-1;i++){ //显示"0" szOut=szOut+"<img src='images/0.gif'>"; } for (i=0;i<szRecord.length();i++){ //显示非"0" szOut=szOut+"<img src='images/"+ szRecord.charAt(i) +".gif'>"; } szOut=szOut+"</body>"; out.println(szOut); %> </html>
by the way : the role management system was satisfaction by my leader.
but just in tag not in pay.
1.send the data from *.txt to the sqlserver
use method as: int i=str.indexOf(" "); StringTokenizer str1=new StringTokenizer(str.substring(i+1)," "); while(str1.hasMoreElements()){ //method(),two "for" circle; }
2.page forward in servlet 1).HttpServletRespose.sendRedirect( java.lang.String location); 2).Request Dispatcher.forward();
the difficulty : on two difference server run the system
今天开始往页面里加权限。 由于刚开始他们把数据库设计的简陋,我还要重新设计数据库 唉 命苦。
已经完成了第一步:在webtop.html上加判断。拥有权限的才能点开连接。 接下来在各个网页里加权限。并且要加审核、发布 按钮。
|
|
|
| 日 | 一 | 二 | 三 | 四 | 五 | 六 |
---|
25 | 26 | 27 | 28 | 29 | 30 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 1 | 2 | 3 | 4 | 5 |
|
导航
统计
- 随笔: 46
- 文章: 14
- 评论: 27
- 引用: 0
常用链接
留言簿(1)
随笔档案
文章档案
收藏夹
搜索
积分与排名
最新评论

阅读排行榜
评论排行榜
|
|