在oracle中可以指定的表连接的hint有很多:ordered hint 指示oracle按照from关键字后的表顺序来进行连接;leading hint 指示查询优化器使用指定的表作为连接的首表,即驱动表;use_nl hint指示查询优化器使用nested loops方式连接指定表和其他行源,并且将强制指定表作为inner表。在mysql中就有之对应的straight_join,由于mysql只支持nested loops的连接方式,所以这里的straight_join类似oracle中的use_nl hint。mysql优化器在处理多表的关联的时候,很有可能会选择错误的驱动表进行关联,导致了关联次数的增加,从而使得sql语句执行变得非常的缓慢,这个时候需要有经验的DBA进行判断,选择正确的驱动表,这个时候straight_join就起了作用了,下面我们来看一看使用straight_join进行优化的案例:1.用户实例:spxxxxxx的一条sql执行非常的缓慢,sql如下:73871 | root | 127.0.0.1:49665 | user_app_test | Query | 500 | Sorting result |SELECT DATE(practicetime) date_time,COUNT(DISTINCT a.userid) people_rowsFROM test_log a,USER bWHERE a.userid=b.userid AND b.isfree=0 AND LENGTH(b.username)>4GROUP BY DATE(practicetime)2.查看执行计划:mysql> explain SELECT DATE(practicetime) date_time,COUNT(DISTINCT a.userid) people_rowsFROM test_log a,USER bWHERE a.userid=b.userid AND b.isfree=0 AND LENGTH(b.username)>4GROUP BY DATE(practicetime);mysql> explain SELECT DATE(practicetime) date_time,COUNT(DISTINCT a.userid) people_rows-> FROM test_log a,USER b-> WHERE a.userid=b.userid AND b.isfree=0 AND LENGTH(b.username)>4-> GROUP BY DATE(practicetime)\G;*************************** 1. row ***************************id: 1select_type: SIMPLEtable: atype: ALLpossible_keys: ix_test_log_useridkey: NULLkey_len: NULLref: NULLrows: 416782Extra: Using filesort*************************** 2. row ***************************id: 1select_type: SIMPLEtable: btype: eq_refpossible_keys: PRIMARYkey: PRIMARYkey_len: 96ref: user_app_testnew.a.useridrows: 1Extra: Using where2 rows in set (0.00 sec)3.查看索引:mysql> show index from test_log;+————–+————+————————-+————–+————-+———–+————-+———-++| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment |+————–+————+————————-+————–+————-+———–+————-+———-++| test_log | 0 | ix_test_log_unique_ | 1 | unitid | A | 20 | NULL | NULL | | BTREE | || test_log | 0 | ix_test_log_unique_ | 2 | paperid | A | 20 | NULL | NULL | | BTREE | || test_log | 0 | ix_test_log_unique_ | 3 | qtid | A | 20 | NULL | NULL | | BTREE | || test_log | 0 | ix_test_log_unique_ | 4 | userid | A | 400670 | NULL | NULL | | BTREE | || test_log | 0 | ix_test_log_unique_ | 5 | serial | A | 400670 | NULL | NULL | | BTREE | || test_log | 1 | ix_test_log_unit | 1 | unitid | A | 519 | NULL | NULL | | BTREE | || test_log | 1 | ix_test_log_unit | 2 | paperid | A | 2023 | NULL | NULL | | BTREE | || test_log | 1 | ix_test_log_unit | 3 | qtid | A | 16694 | NULL | NULL | | BTREE | || test_log | 1 | ix_test_log_serial | 1 | serial | A | 133556 | NULL | NULL | | BTREE | || test_log | 1 | ix_test_log_userid | 1 | userid | A | 5892 | NULL | NULL | | BTREE | |+————–+————+————————-+————–+————-+———–+————-+———-+——–+——+——-+4.调整索引,A表优化采用覆盖索引:mysql>alter table test_log drop index ix_test_log_userid,add index ix_test_log_userid(userid,practicetime)5.查看执行计划:mysql> explain SELECT DATE(practicetime) date_time,COUNT(DISTINCT a.userid) people_rowsFROM test_log a,USER bWHERE a.userid=b.userid AND b.isfree=0 AND LENGTH(b.username)>4GROUP BY DATE(practicetime)\G*************************** 1. row ***************************id: 1select_type: SIMPLEtable: atype: indexpossible_keys: ix_test_log_useridkey: ix_test_log_useridkey_len: 105ref: NULLrows: 388451Extra: Using index; Using filesort*************************** 2. row ***************************id: 1select_type: SIMPLEtable: btype: eq_refpossible_keys: PRIMARYkey: PRIMARYkey_len: 96ref: user_app_test.a.useridrows: 1Extra: Using where2 rows in set (0.00 sec)调整后执行稍有效果,但是还不明显,还没有找到要害:SELECT DATE(practicetime) date_time,COUNT(DISTINCT a.userid) people_rowsFROM test_log a,USER bWHERE a.userid=b.userid AND b.isfree=0 AND LENGTH(b.username)>4GROUP BY DATE(practicetime);……………….143 rows in set (1 min 12.62 sec)6.执行时间仍然需要很长,时间的消耗主要耗费在Using filesort中,参与排序的数据量有38W之多,所以需要转换驱动表;尝试采用user表做驱动表:使用straight_join强制连接顺序:mysql> explain SELECT DATE(practicetime) date_time,COUNT(DISTINCT a.userid) people_rowsFROM USER b straight_join test_log aWHERE a.userid=b.userid AND b.isfree=0 AND LENGTH(b.username)>4GROUP BY DATE(practicetime)\G;*************************** 1. row ***************************id: 1select_type: SIMPLEtable: btype: ALLpossible_keys: PRIMARYkey: NULLkey_len: NULLref: NULLrows: 42806Extra: Using where; Using temporary; Using filesort*************************** 2. row ***************************id: 1select_type: SIMPLEtable: atype: refpossible_keys: ix_test_log_useridkey: ix_test_log_useridkey_len: 96ref: user_app_test.b.useridrows: 38Extra: Using index2 rows in set (0.00 sec)执行时间已经有了质的变化,降低到了2.56秒;mysql>SELECT DATE(practicetime) date_time,COUNT(DISTINCT a.userid) people_rowsFROM USER b straight_join test_log aWHERE a.userid=b.userid AND b.isfree=0 AND LENGTH(b.username)>4GROUP BY DATE(practicetime);……..143 rows in set (2.56 sec)7.在分析执行计划的第一步:Using where; Using temporary; Using filesort,user表其实也可以采用覆盖索引来避免using where的出现,所以继续调整索引:mysql> show index from user;+——-+————+——————+————–+————-+———–+————-+———-+——–+——+————+———+| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment |+——-+————+——————+————–+————-+———–+————-+———-+——–+——+————+———+| user | 0 | PRIMARY | 1 | userid | A | 43412 | NULL | NULL | | BTREE | || user | 0 | ix_user_email | 1 | email | A | 43412 | NULL | NULL | | BTREE | || user | 1 | ix_user_username | 1 | username | A | 202 | NULL | NULL | | BTREE | |+——-+————+——————+————–+————-+———–+————-+———-+——–+——+————+———+3 rows in set (0.01 sec)mysql>alter table user drop index ix_user_username,add index ix_user_username(username,isfree);Query OK, 42722 rows affected (0.73 sec)Records: 42722 Duplicates: 0 Warnings: 0mysql>explain SELECT DATE(practicetime) date_time,COUNT(DISTINCT a.userid) people_rowsFROM USER b straight_join test_log aWHERE a.userid=b.userid AND b.isfree=0 AND LENGTH(b.username)>4GROUP BY DATE(practicetime);*************************** 1. row ***************************id: 1select_type: SIMPLEtable: btype: indexpossible_keys: PRIMARYkey: ix_user_usernamekey_len: 125ref: NULLrows: 42466Extra: Using where; Using index; Using temporary; Using filesort*************************** 2. row ***************************id: 1select_type: SIMPLEtable: atype: refpossible_keys: ix_test_log_useridkey: ix_test_log_useridkey_len: 96ref: user_app_test.b.useridrows: 38Extra: Using index2 rows in set (0.00 sec)8.执行时间降低到了1.43秒:mysql>SELECT DATE(practicetime) date_time,COUNT(DISTINCT a.userid) people_rowsFROM USER b straight_join test_log aWHERE a.userid=b.userid AND b.isfree=0 AND LENGTH(b.username)>4GROUP BY DATE(practicetime);。。。。。。。

Hash分区是通过对分区键运用Hash算法从而决定数据的分区归属。使用Hash分区有什么优点呢?常用的分区表所具有的优点:如提高数据可用行,减少管理负担,改善语句性能等优点,hash分区同样拥有。此外,由于Hash分区表是按分区键的hash计算结果来决定其分区的,而特定的分区键其hash值是固定的,也就是说Hash分区表的数据是按分区键值来聚集的,同样的分区键肯定在同一分区。比如,在证券行业,我们经常查询某一只股票的K线,假设表的结构如下:复制代码 代码如下:create table equity(id number,trade_date date,……);Equity表可能会很大,对equity表的查询通常都是指定id,查询某一交易日期或者某段时期内的其他信息。这种情况下我们需要如何为equity表选择分区呢?单从表本身结构来看,似乎trade_date列很适合被选择用来作范围分区。但如果我们这样分区的话,前面需求中的查询:指定某一id,查询其某一范围内的交易信息,比如看1年内的K线,则这种查询常常需要跨分区。我们知道,对分区表作跨分区查询,很多时候其性能并不会太好,特别是这种查询很可能还要跨很多分区。你也可能会说,我们再在id, trade_date列上建个索引不就行了,仔细想想是不是这样呢?这时候的equity表中的数据是按trade_date值来聚集的,同样trade_date值的数据常常在一个数据块中,这样前面需求中所描述的查询即使通过索引访问,最终读表时也常常是去读离散的数据块,即每一条记录需要对应读一个表数据块。如果建成Hash分区表,则数据按hash分区键聚集,就更适合需求中描述的查询,因为同样id的记录必定在同一分区,同时,同样 id值的记录落在同一数据块的几率也增大了,从而“一定程度上”减少了IO。上面对hash分区减少IO的描述加了引号,因为仅依靠Hash分区表试图实现大范围减少IO操作是不现实的,特别是当equity表中记录的股票数非常多时,同一股票发生在不同交易日的记录在物理上也很难聚集到相同数据块中。实际上,如果我们在Hash分区的基础上再对equity表采用IOT表的组织方式,则前面描述的查询性能就可大为提高。IOT表不在该文讨论的范围之内,这里就不作进一步讨论了。当我们决定使用Hash表之前,我们还需要确定我们的所选择的分区键值是连续分布的,或者接近连续分区,此外,分区的个数需要是2的整数幂,比如2,4,8… 这些要求是由Hash函数的特点决定的,这样我们分区表的各个分区所包含的数据量才会比较平均。Hash分区表的扩展:Hash分区表是通过add partition命令来增加分区的。Oracle推荐分区的个数是2的幂,比如,2,4,8..等等,这样可以确保数据在各个分区中分布比较均匀。当然,如前所述,还需要分区键值是连续分布的,或接近连续分布。增加新分区时,需要将一些原有的数据从旧的分区划分到新的分区中,那么这种数据划分时来源分区选择遵循什么原则呢?要点如下:如果要增加的分区是第N个分区,大于等于N的最小2的整数幂为M,则当增加第N个分区时,这个分区的数据来源于分区N-M/2。比如,现在有个Hash分区表共有100个分区,我们想为其增加一个分区,则它是101个分区,即上面公式中的N为101,而大于101的最小2的整数幂为128,则M为128,于是,这个101分区的数据来源就应该是101-128/2=37分区。换个角度来说,当我们在增加第101分区的时候,是需要锁定37分区的,因为我们需要将该分区中的部分数据插入到新的101分区中。下面,我们用一个实例来验证上面的说法,同时看看在实际操作中有什么需要注意的事项:Commodity表是我们系统中的一个大表,几年前在为该表创建Hash分区表时,当时的DBA在选择分区数时指定了100个分区:复制代码 代码如下:select TABLE_NAME,PARTITION_POSITION,PARTITION_NAME,NUM_ROWS from user_tab_partitions where table_name=\'COMMODITY\' order by PARTITION_POSITION;TABLE_NAME PARTITION_POSITION PARTITION_NAME NUM_ROWS-------------- ------------------ ---------------------- ----------COMMODITY 1 COT_IND01_P1 4405650COMMODITY 2 COT_IND01_P2 5046650COMMODITY 3 COT_IND01_P3 5107550……COMMODITY 36 COT_IND01_P36 5718800COMMODITY 37 COT_IND01_P37 9905200COMMODITY 38 COT_IND01_P38 10118400COMMODITY 39 COT_IND01_P39 10404950COMMODITY 40 COT_IND01_P40 9730850COMMODITY 41 COT_IND01_P41 9457300COMMODITY 42 COT_IND01_P42 9717950COMMODITY 43 COT_IND01_P43 9643900COMMODITY 44 COT_IND01_P44 11138000COMMODITY 45 COT_IND01_P45 9381300COMMODITY 46 COT_IND01_P46 10101150COMMODITY 47 COT_IND01_P47 8809950COMMODITY 48 COT_IND01_P48 10611050COMMODITY 49 COT_IND01_P49 10010600COMMODITY 50 COT_IND01_P50 8252600COMMODITY 51 COT_IND01_P51 9709900COMMODITY 52 COT_IND01_P52 8983200COMMODITY 53 COT_IND01_P53 9012750COMMODITY 54 COT_IND01_P54 9310650COMMODITY 55 COT_IND01_P55 8966450COMMODITY 56 COT_IND01_P56 8832650COMMODITY 57 COT_IND01_P57 9470600COMMODITY 58 COT_IND01_P58 8932450COMMODITY 59 COT_IND01_P59 9994850COMMODITY 60 COT_IND01_P60 9617450COMMODITY 61 COT_IND01_P61 10278850COMMODITY 62 COT_IND01_P62 9277600COMMODITY 63 COT_IND01_P63 8136300COMMODITY 64 COT_IND01_P64 10064600COMMODITY 65 COT_IND01_P65 3710900……COMMODITY 99 COT_IND01_P99 5273800COMMODITY 100 COT_IND01_P100 5293350100 rows selected.查询各个分区的数据分布,我们可以看到,从分区37 ~ 64的28个分区的记录数大概是其他分区的两倍。由于100不是2的整数幂,所以Oracle的hash函数是无法保证数据是平均分布的。我们为该表添加一个新的分区COT_IND01_P101:复制代码 代码如下:alter table nts_commodity_ts add partition COT_IND01_P101;Table altered.Elapsed: 00:06:58.52收集统计信息后查询新的分区记录数:复制代码 代码如下:select TABLE_NAME,PARTITION_POSITION,PARTITION_NAME,NUM_ROWS from user_tab_partitions where table_name=\'COMMODITY\' and partition_name in (\'COT_IOT_IND01_P37\',\'COT_IOT_IND01_P101\');TABLE_NAME PARTITION_POSITION PARTITION_NAME NUM_ROWS------------------ ------------------ --------------------- ----------COMMODITY 37 COT__IND01_P37 4905200COMMODITY 101 COT_IND01_P101 5107550这时,我们可以看到,分区37中的数据被接近于平分到了分区37和101中。监控增加分区过程中session锁的情况,我们发现期间有两个对象被以exclusive模式锁定了:复制代码 代码如下:SQL> select * from v$lock where sid=1239 and type=\'TM\' and LMODE=6 order by sid,lmode;ADDR                KADDR          SID TY ID1    ID2 LMODE REQUEST CTIME BLOCK---------------- ---------------- ---------- -- ---------- ---------- ---------- ---------- ---------- ----------FFFFFFFF7D764828 FFFFFFFF7D764888 1239 TM 4004126 0  6 0 72 2FFFFFFFF7D764828 FFFFFFFF7D764888 1239 TM 4004063 0  6 0 72 2它们分别是什么对象呢?select OBJECT_NAME,SUBOBJECT_NAME,OBJECT_ID from user_objects where object_id in (4004126,4004063)OBJECT_NAME SUBOBJECT_NAME OBJECT_ID --------------------- ------------------------------ ---------- COMMODITY COT_IND01_P100 4004126COMMODITY COT_IND01_P37 4004063可以看到,分区37和100都被锁定了。锁定37分区是意料中的事,因为要从该表转移数据。那为什么要锁定第100个分区,也就是最后一个分区呢?我的理解是:新增加分区的位置101是由原分区表的分区数100确定的,如果在增加分区的过程中允许对原表最后一个分区100作DDL操作,如coalesce操作,则新加的101分区就不一定是从原来的分区37分配数据了,101分区本身应该是新的第100分区,这样就引起混乱了。到这里,你可能会说,按这理解,是不是其他的分区也应该锁定呢?其实不用,因为hash分区表是不支持drop partition操作的,而只支持coalesce操作来实现类似的操作,但coalesce只能从最后一个分区开始收缩。了解了增加hash表分区过程中锁信息的实际指导意义是什么呢?继续上例中的讨论,由于分区37和最后一个分区100会被排他锁定,因此在添加分区过程中这两个分区是不能作DML操作的,因为DML操作需要在分区上申请共享锁(mode为3)。也就是操作这两个分区的应用会受到影响。Hash表增加分区不会像其他类型分区表,如range分区那样能够迅速完成,因为这里添加分区的过程中是要有IO操作的,要转移数据到新的分区。其实这还不是最主要的,由于Hash表是根据分区键Hash函数值来决定分区的,添加分区的主要时间其实是花在了计算hash值上。在上面的测试中,添加新分区操作的消耗时间是6分58秒,从下面的10046统计信息可以看到,其中6分钟都是花在了CPU操作上,相信主要是Hash运算引起的。[code]OVERALL TOTALS FOR ALL RECURSIVE STATEMENTS call     count       cpu    elapsed       disk      query    current        rows------- ------  -------- ---------- ---------- ---------- ----------  ----------Parse      328      0.17       0.27          0          0        148           0Execute   1520    360.14     396.30     456820   11416202      26357    11565252Fetch     1767      5.42      21.18      21421      26540          0        2862------- ------  -------- ---------- ---------- ---------- ----------  ----------total     3615    365.73     417.76     478241   11442742      26505    11568114该测试案例中分区COT_IND01_P37中共有接近1千万条数据,耗时接近7分钟,假设分区数据达到了1亿条,则耗时应该在1个小时以上。如果我们的Hash分区数按Oracle的建议为2的整数幂,则我们在增加分区时是要增加原有分区一倍的新分区,比如原分区为128个,扩展的时候需要增加128个分区,乘以每次添加分区需要的时间,则为Hash表增加分区将是一个很恐怖的操作。总之,Hash分区有其优势,但也有严重的缺陷,比如这里描述的分区扩展问题。因此在项目设计之初,我们就需要慎重选择分区数。但是随着数据量的增加,我们又很难避免为分区表增加分区的操作,这种操作是很耗资源的操作,操作过程中由于锁的问题会影响对原有某些分区的操作。但如果我们因为畏惧前面存在的问题拖着不作分区扩展,则越是往后,随着数据量的增加,这种增加分区的操作越难以实施。

string agent = request.getheader("user-agent"); stringtokenizer st = new stringtokenizer(agent,";"); st.nexttoken(); //得到用户的浏览器名 string userbrowser = st.nexttoken(); //得到用户的操作系统名 string useros = st.nexttoken(); 取得本机的信息也可以这样: 操作系统信息 system.getproperty("os.name"); //win2003竟然是win xp? system.getproperty("os.version"); system.getproperty("os.arch"); 瀏覽器: request.getheader("user-agent") 再送个红包 request.getheader(“user-agent”)返回客户端浏览器的版本号、类型 getheader(string name):获得http协议定义的传送文件头信息, request. getmethod():获得客户端向服务器端传送数据的方法有get、post、put等类型 request. getrequesturi():获得发出请求字符串的客户端地址 request. getservletpath():获得客户端所请求的脚本文件的文件路径 request. getservername():获得服务器的名字 request.getserverport():获得服务器的端口号 request.getremoteaddr():获得客户端的ip地址 request.getremotehost():获得客户端电脑的名字,若失败,则返回客户端电脑的ip地址 request.getprotocol(): request.getheadernames():返回所有request header的名字,结果集是一个enumeration(枚举)类的实例 request.getheaders(string name):返回指定名字的request header的所有值,

一、 JSP 技术概述    在 Sun 正式发布 JSP(JavaServer Pages) 之后,这种新的 Web 应用开发技术很快引起了人们的关注。 JSP 为创建高度动态的 Web 应用提供了一个独特的开发环境。按照 Sun 的说法, JSP 能够适应市场上包括 Apache WebServer 、 IIS4.0 在内的 85% 的服务器产品。即使您对 ASP "一往情深",我们认为,关注 JSP 的发展仍旧很有必要。    ㈠ JSP 与 ASP 的简单比较    JSP 与 Microsoft 的 ASP 技术非常相似。两者都提供在 HTML 代码中混合某种程序代码、由语言引擎解释执行程序代码的能力。在 ASP 或 JSP 环境下, HTML 代码主要负责描述信息的显示样式,而程序代码则用来描述处理逻辑。普通的 HTML 页面只依赖于 Web 服务器,而 ASP 和 JSP 页面需要附加的语言引擎分析和执行程序代码。程序代码的执行结果被重新嵌入到 HTML 代码中,然后一起发送给浏览器。 ASP 和 JSP 都是面向 Web 服务器的技术,客户端浏览器不需要任何附加的软件支持。    ASP 的编程语言是 VBScript 之类的脚本语言, JSP 使用的是 Java ,这是两者最明显的区别。此外, ASP 与 JSP 还有一个更为本质的区别:两种语言引擎用完全不同的方式处理页面中嵌入的程序代码。在 ASP 下, VBScript 代码被 ASP 引擎解释执行;在 JSP 下,代码被编译成 Servlet 并由 Java 虚拟机执行,这种编译操作仅在对 JSP 页面的第一次请求时发生。    ㈡运行环境    Sun 公司的 JSP 主页在 http://www.javasoft.com/products/jsp/index.html ,从这里还可以下载 JSP 规范,这些规范定义了供应商在创建 JSP 引擎时所必须遵从的一些规则。    执行 JSP 代码需要在服务器上安装 JSP 引擎。此处我们使用的是 Sun 的 JavaServer Web Development Kit ( JSWDK )。为便于学习,这个软件包提供了大量可供修改的示例。安装 JSWDK 之后,只需执行 startserver 命令即可启动服务器。在默认配置下服务器在端口 8080 监听,使用 http://localhost:8080 即可打开缺省页面。    在运行 JSP 示例页面之前,请注意一下安装 JSWDK 的目录,特别是" work "子目录下的内容。执行示例页面时,可以在这里看到 JSP 页面如何被转换成 Java 源文件,然后又被编译成 class 文件(即 Servlet )。 JSWDK 软件包中的示例页面分为两类,它们或者是 JSP 文件,或者是包含一个表单的 HTML 文件,这些表单均由 JSP 代码处理。与 ASP 一样, JSP 中的 Java 代码均在服务器端执行。因此,在浏览器中使用"查看源文件"菜单是无法看到 JSP 源代码的,只能看到结果 HTML 代码。所有示例的源代码均通过一个单独的" examples "页面提供。    ㈢ JSP 页面示例    下面我们分析一个简单的 JSP 页面。您可以在 JSWDK 的 examples 目录下创建另外一个目录存放此文件,文件名字可以任意,但扩展名必须为 .jsp 。从下面的代码清单中可以看到, JSP 页面除了比普通 HTML 页面多一些 Java 代码外,两者具有基本相同的结构。 Java 代码是通过 < % 和 %> 符号加入到 HTML 代码中间的,它的主要功能是生成并显示一个从 0 到 9 的字符串。在这个字符串的前面和后面都是一些通过 HTML 代码输出的文本。   < HTML>   < HEAD>< TITLE>JSP 页面 < /TITLE>< /HEAD>   < BODY>   < %@ page language="java" %>   < %! String str="0"; %>   < % for (int i=1; i < 10; i++) {   str = str + i;   } %>   JSP 输出之前。   < P>   < %= str %>   < P>   JSP 输出之后。   < /BODY>   < /HTML>    这个 JSP 页面可以分成几个部分来分析。 首先是 JSP 指令。它描述的是页面的基本信息,如所使用的语言、是否维持会话状态、是否使用缓冲等。 JSP 指令由 < %@ 开始, %> 结束。在本例中,指令" < %@ page language="java" %> "只简单地定义了本例使用的是 Java 语言(当前,在 JSP 规范中 Java 是唯一被支持的语言)。 接下来的是 JSP 声明。 JSP 声明可以看成是定义类这一层次的变量和方法的地方。 JSP 声明由 < %! 开始, %> 结束。如本例中的" < %! String str="0"; %> "定义了一个字符串变量。在每一项声明的后面都必须有一个分号,就象在普通 Java 类中声明成员变量一样。 位于 < % 和 %> 之间的代码块是描述 JSP 页面处理逻辑的 Java 代码,如本例中的 for 循环所示。 最后,位于 < %= 和 %> 之间的代码称为 JSP 表达式,如本例中的" < %= str %> "所示。 JSP 表达式提供了一种将 JSP 生成的数值嵌入 HTML 页面的简单方法。    会话状态维持是 Web 应用开发者必须面对的问题。有多种方法可以用来解决这个问题,如使用 Cookies 、隐藏的表单输入域,或直接将状态信息附加到 URL 中。 Java Servlet 提供了一个在多个请求之间持续有效的会话对象,该对象允许用户存储和提取会话状态信息。 JSP 也同样支持 Servlet 中的这个概念。    在 Sun 的 JSP 指南 中可以看到许多有关隐含对象的说明(隐含的含义是,这些对象可以直接引用,不需要显式地声明,也不需要专门的代码创建其实例)。例如 request 对象,它是 HttpServletRequest 的一个子类。该对象包含了所有有关当前浏览器请求的信息,包括 Cookies , HTML 表单变量等等。 session 对象也是这样一个隐含对象。这个对象在第一个 JSP 页面被装载时自动创建,并被关联到 request 对象上。与 ASP 中的会话对象相似, JSP 中的 session 对象对于那些希望通过多个页面完成一个事务的应用是非常有用的。    为说明 session 对象的具体应用,接下来我们用三个页面模拟一个多页面的 Web 应用。第一个页面( q1.html )仅包含一个要求输入用户名字的 HTML 表单,代码如下:   < HTML>   < BODY>   < FORM METHOD=POST ACTION="q2.jsp">  请输入您的姓名:   < INPUT TYPE=TEXT NAME="thename">   < INPUT TYPE=SUBMIT VALUE="SUBMIT">   < /FORM>   < /BODY>   < /HTML>    第二个页面是一个 JSP 页面( q2.jsp ),它通过 request 对象提取 q1.html 表单中的 thename 值,将它存储为 name 变量,然后将这个 name 值保存到 session 对象中。 session 对象是一个名字 / 值对的集合,在这里,名字 / 值对中的名字为" thename ",值即为 name 变量的值。由于 session 对象在会话期间是一直有效的,因此这里保存的变量对后继的页面也有效。 q2.jsp 的另外一个任务是询问第二个问题。下面是它的代码:   < HTML>   < BODY>   < %@ page language="java" %>   < %! String name=""; %>   < %   name = request.getParameter("thename");   session.putValue("thename", name);   %>  您的姓名是: < %= name %>   < p>   < FORM METHOD=POST ACTION="q3.jsp">  您喜欢吃什么 ?   < INPUT TYPE=TEXT NAME="food">   < P>   < INPUT TYPE=SUBMIT VALUE="SUBMIT">   < /FORM>   < /BODY>   < /HTML>    第三个页面也是一个 JSP 页面( q3.jsp ),主要任务是显示问答结果。它从 session 对象提取 thename 的值并显示它,以此证明虽然该值在第一个页面输入,但通过 session 对象得以保留。 q3.jsp 的另外一个任务是提取在第二个页面中的用户输入并显示它:   < HTML>   < BODY>   < %@ page language="java" %>   < %! String food=""; %>   < %   food = request.getParameter("food");   String name = (String) session.getValue("thename");   %>  您的姓名是: < %= name %>   < P>  您喜欢吃: < %= food %>   < /BODY>   < /HTML>    JavaBean 是一种基于 Java 的软件组件。 JSP 对于在 Web 应用中集成 JavaBean 组件提供了完善的支持。这种支持不仅能缩短开发时间(可以直接利用经测试和可信任的已有组件,避免了重复开发),也为 JSP 应用带来了更多的可伸缩性。 JavaBean 组件可以用来执行复杂的计算任务,或负责与数据库的交互以及数据提取等。如果我们有三个 JavaBean ,它们分别具有显示新闻、股票价格、天气情况的功能,则创建包含所有这三种功能的 Web 页面只需要实例化这三个 Bean ,使用 HTML 表格将它们依次定位就可以了。    为说明在 JSP 环境下 JavaBean 的应用,我们创建了一个名为 TaxRate 的 Bean 。它有两个属性,即 Product (产品)和 Rate (税率)。两个 set 方法分别用来设置这两个属性,两个 get 方法则用于提取这两个属性。在实际应用中,这种 Bean 一般应当从数据库提取税率值,此处我们简化了这个过程,允许任意设定税率。下面是这个 Bean 的代码清单:   package tax;   public class TaxRate {   String Product;   double Rate;   public TaxRate() {   this.Product = "A001";   this.Rate = 5;   }   public void setProduct (String ProductName) {   this.Product = ProductName;   }   public String getProduct() {   return (this.Product);   }   public void setRate (double rateValue) {   this.Rate = rateValue;   }   public double getRate () {   return (this.Rate);   }   }    在 JSP 页面中应用上述 Bean 要用到 < jsp:useBean> 标记。依赖于具体使用的 JSP 引擎的不同,在何处配置以及如何配置 Bean 的方法也可能略有不同。本文将这个 Bean 的 .class 文件放在 c:jswdk-1.0examplesWEB-INFjspeans ax 目录下,这里的 tax 是一个专门存放该 Bean 的目录。下面是一个应用上述 Bean 的示例页面:   < HTML>   < BODY>   < %@ page language="java" %>   < jsp:useBean id="taxbean" scope="application" class="tax.TaxRate" />   < % taxbean.setProduct("A002");   taxbean.setRate(17);   %>  使用方法 1 : < p>  产品 : < %= taxbean.getProduct() %> < br>  税率 : < %= taxbean.getRate() %>   < p>   < % taxbean.setProduct("A003");   taxbean.setRate(3);   %>   < b> 使用方法 2 : < /b> < p>  产品 : < jsp:getProperty name="taxbean" property="Product" />   < br>  税率 : < jsp:getProperty name="taxbean" property="Rate" />   < /BODY>   < /HTML>    在 < jsp:useBean> 标记内定义了几个属性,其中 id 是整个 JSP 页面内该 Bean 的标识, scope 属性定义了该 Bean 的生存时间, class 属性说明了该 Bean 的类文件(从包名开始)。    这个 JSP 页面不仅使用了 Bean 的 set 和 get 方法设置和提取属性值,还用到了提取 Bean 属性值的第二种方法,即使用 < jsp:getProperty> 标记。 < jsp:getProperty> 中的 name 属性即为 < jsp:useBean> 中定义的 Bean 的 id ,它的 property 属性指定的是目标属性的名字。    事实证明, Java Servlet 是一种开发 Web 应用的理想构架。 JSP 以 Servlet 技术为基础,又在许多方面作了改进。 JSP 页面看起来象普通 HTML 页面,但它允许嵌入执行代码,在这一点上,它和 ASP 技术非常相似。利用跨平台运行的 JavaBean 组件, JSP 为分离处理逻辑与显示样式提供了卓越的解决方案。 JSP 必将成为 ASP 技术的有力竞争者。

SQL Server 2008R2中增加了新的智能提示的功能简化了输入,非常方便。但突然有一天智能提示没有了,好郁闷!折腾了半天终于将智能提示找回来了,下面是我解决本问题的思路:1.查看工具选项中Enable Intellisense是否打开?选择Tools-->Options打开选项页面,依次展开Text Editor-->Transact-SQL-->IntelliSense显示如下图所示的配置页面,检查是否勾选了Enable IntelliSense选项。注意修改配置后要打开新的查询页面才起作用。如果勾选后仍旧不起作用则进行下一步。2.如果前面的Enable IntelliSense已经勾选,则有可能是缓存被占满。选择菜单Edit-->IntelliSense-->Refresh Local Cash清空缓存。3.一般来说经过以上两步就可以了,但我的仍旧不起作用。上网查询后发现有提示说如果安装了Visual Studio 2010 SP1的补丁后智能提示会消失,要求安装SQL Server 2008R2 SP1。我虽然没有安装Visual Studio 2010 SP1,但最近安装了Team Explorer 2008,想来是一样的问题。下载SQL Server 2008R2 SP1安装后问题果然解决。下载地址:http://www.microsoft.com/en-us/download/details.aspx?

分类:腾博会手机版下载

时间:2016-02-15 13:12:06