|
置顶随笔
需求描述:一个表已经上线,但是上线之后发现该表的数据量很大,而且会删除历史数据,该表上要建立多个唯一索引,现在的问题就是在建表的时候是建立了一个普通表,现在需要将普通表转化为分区表,并尽量减少对应用的影响1、使用ctas的方式来建立create table t1(ID VARCHAR2(60) not null,a VARCHAR2(60) not null,b VARCHAR2(60) not null,create_time TIMESTAMP(6) not null,d NUMBER(2) not null,e VARCHAR2(400) not null,OUTER_ID VARCHAR2(100))----原表---建立分区表:create table t1_new(ID_1 ,a ,b ,create_time ,d ,e ,OUTER_ID )partition by range (ID_1)(partition p_t1_new values less than ('201204'),partition p_t2_new values less than ('201205'))asselect * from t1;----此时应用还是不断的往t1表中插入数据-alter table t1_new add constraints pk_t1_new primary key (id) using tablespace local index_tablespace;----建立本地索引为了删除历史数据/alter table t1_new add constraints pk_t1_new primary key (id_1) using index local ;但是应用还在outer_id上建立唯一索引create unique index IDX_t1_new_2 on t1_new (OUTER_ID) LOCAL ;此时报ORA-14039: 分区列必须构成 UNIQUE 索引的关键字列子集原来oracle不支持在分区表上创建PK主键时主键列不包含分区列,创建另外的约束(unique)也不可以。为了解决这个问题,两种方法1、将分区键加到唯一索引里面2、将local索引变为global索引----此时当进行历史数据删除的时候会导致索引失效权衡之后在outer_id上建立普通索引alter table t1 rename to t1_bak;alter table t1_new rename to t1;在进行ctas之后需要进行数据完整新检查,而且在进行rename的时候会导致应用连接失效(也有可能在进行alter的时候获取不到表锁而失败)---适用于修改不很频繁的表2、使用交换分区的方式----原表create table t1(ID VARCHAR2(60) not null,a VARCHAR2(60) not null,b VARCHAR2(60) not null,create_time TIMESTAMP(6) not null,d NUMBER(2) not null,e VARCHAR2(400) not null,OUTER_ID VARCHAR2(100))alter table t1 add constraints pk_t1 primary key(id) ;新表create table t1_new(ID_1 ,a ,b ,create_time ,d ,e ,OUTER_ID )partition by range (ID_1)(partition p_t1_new values less than ('201204'),partition p_t2_new values less than ('201205'))alter table t1_new add constraints pk_t1_new primary key (id_1) using index local ;ALTER TABLE t1_new EXCHANGE PARTITION p_t1_new WITH TABLE t1 without validation;----要不要加上without validation(加上的话就是不验证数据是否有效,直接全部放在p_t1_new分区中)然后进行rename操作优点:只是对数据字典中分区和表的定义进行了修改,没有数据的修改或复制,效率最高。如果对数据在分区中的分布没有进一步要求的话,实现比较简单。在执行完RENAME操作后,可以检查T_OLD中是否存在数据,如果存在的话,直接将这些数据插入到T中,可以保证对T插入的操作不会丢失。不足:仍然存在一致性问题,交换分区之后RENAME T_NEW TO T之前,查询、更新和删除会出现错误或访问不到数据。如果要求数据分布到多个分区中,则需要进行分区的SPLIT操作,会增加操作的复杂度,效率也会降低。适用于包含大数据量的表转到分区表中的一个分区的操作。应尽量在闲时进行操作。3、在线重定义----原表create table t1(ID VARCHAR2(60) not null,a VARCHAR2(60) not null,b VARCHAR2(60) not null,create_time TIMESTAMP(6) not null,d NUMBER(2) not null,e VARCHAR2(400) not null,OUTER_ID VARCHAR2(100))alter table t1 add constraints pk_t1 primary key(id) ;新表create table t1_new(ID_1 ,a ,b ,create_time ,d ,e ,OUTER_ID )partition by range (ID_1)(partition p_t1_new values less than ('201204'),partition p_t2_new values less than ('201205'))alter table t1_new add constraints pk_t1_new primary key (id_1) using index local ;EXEC DBMS_REDEFINITION.CAN_REDEF_TABLE(USER, 'T1', DBMS_REDEFINITION.CONS_USE_PK);
EXEC DBMS_REDEFINITION.START_REDEF_TABLE(USER, 'T1', 'T1_NEW',DBMS_REDEFINITION.CONS_USE_PK); (转载请注明出处:[url=http://www.k6567.com]e世博[/url] [url=http://www.d9732.com]澳门博彩[/url])
尽管httpservletresponse.sendredirect方法和requestdispatcher.forward方法都可以让浏览器获得另外一个url所指向的资源,但两者的内部运行机制有着很大的区别。下面是httpservletresponse.sendredirect方法实现的请求重定向与requestdispatcher.forward方法实现的请求转发的总结比较:
(1)requestdispatcher.forward方法只能将请求转发给同一个web应用中的组件;而httpservletresponse.sendredirect 方法不仅可以重定向到当前应用程序中的其他资源,还可以重定向到同一个站点上的其他应用程序中的资源,甚至是使用绝对url重定向到其他站点的资源。如果传递给httpservletresponse.sendredirect 方法的相对url以“/”开头,它是相对于整个web站点的根目录;如果创建requestdispatcher对象时指定的相对url以“/”开头,它是相对于当前web应用程序的根目录。
(2)调用httpservletresponse.sendredirect方法重定向的访问过程结束后,浏览器地址栏中显示的url会发生改变,由初始的url地址变成重定向的目标url;而调用requestdispatcher.forward 方法的请求转发过程结束后,浏览器地址栏保持初始的url地址不变。
(3)httpservletresponse.sendredirect方法对浏览器的请求直接作出响应,响应的结果就是告诉浏览器去重新发出对另外一个url的 访问请求,这个过程好比有个绰号叫“浏览器”的人写信找张三借钱,张三回信说没有钱,让“浏览器”去找李四借,并将李四现在的通信地址告诉给了“浏览器”。于是,“浏览器”又按张三提供通信地址给李四写信借钱,李四收到信后就把钱汇给了“浏览器”。可见,“浏览器”一共发出了两封信和收到了两次回复, “浏览器”也知道他借到的钱出自李四之手。requestdispatcher.forward方 法在服务器端内部将请求转发给另外一个资源,浏览器只知道发出了请求并得到了响应结果,并不知道在服务器程序内部发生了转发行为。这个过程好比绰号叫“浏览器”的人写信找张三借钱,张三没有钱,于是张三找李四借了一些钱,甚至还可以加上自己的一些钱,然后再将这些钱汇给了“浏览器”。可见,“浏览器”只发 出了一封信和收到了一次回复,他只知道从张三那里借到了钱,并不知道有一部分钱出自李四之手。
(4)requestdispatcher.forward方法的调用者与被调用者之间共享相同的request对象和response对象,它们属于同一个访问请求和响应过程;而httpservletresponse.sendredirect方法调用者与被调用者使用各自的request对象和response对象,它们属于两个独立的访问请求和响应过程。对于同一个web应用程序的内部资源之间的跳转,特别是跳转之前要对请求进行一些前期预处理,并要使用httpservletrequest.setattribute方法传递预处理结果,那就应该使用requestdispatcher.forward方法。不同web应用程序之间的重定向,特别是要重定向到另外一个web站点上的资源的情况,都应该使用httpservletresponse.sendredirect方法。
(5)无论是requestdispatcher.forward方法,还是httpservletresponse.sendredirect方法,在调用它们之前,都不能有内容已经被实际输出到了客户端。如果缓冲区中已经有了一些内容,这些内容将被从缓冲区中清除。 (转载请注明出处:[url=http://www.a9832.com]博彩网[/url][url=http://www.tswa.org]博彩通[/url])
在java.lang包当中定义了一个Runtime类,在java中对于Runtime类的定义如下:public class Runtimeextends Object每个 Java 应用程序都有一个 Runtime 类实例,使应用程序能够与其运行的环境相连接。可以通过 getRuntime 方法获取当前运行时。应用程序不能创建自己的 Runtime 类实例。根据上面的话,我们知道对于每一个java程序来说都只有一个Runtime类实例,而且不能由用户创建一个Runtime实例,既然不能创建那么这个类的实例的作用是什么呢?它提供了应用程序和应用程序正在运行的环境的一个接口。Runtime不能由我们创建,我们可以通过Runtime类的一个静态方法,得到一个Runtime类的实例。获取了这个实例之后我们就可以获取java虚拟机的自由内存、也可以获取这个java虚拟机的总的内存等(具体的方法可以参照java帮助文档Runtime类的方法学习),也就是说这个类提供了应用程序了环境的接口。下面我们举一个例子程序:Runtime rt=Runtime.getRuntime();System.out.println(rt.freeMemory());System.out.println(rt.totalMemory());//结果返回的是数字Runtime类还有一个好处就是可以执行一个外部的程序,可以调用Runtime类的exec()方法传入一个命令(exec()方法有几个重载的方法,可以自己学习),创建一个子进程,结果返货一个Process类的实例,通过这个实例我们可以管理创建的子进程。对于Process类在java帮助文档中描述如下:public abstract class Processextends ObjectProcessBuilder.start() 和 Runtime.exec 方法创建一个本机进程,并返回 Process 子类的一个实例,该实例可用来控制进程并获得相关信息。Process 类提供了执行从进程输入、执行输出到进程、等待进程完成、检查进程的退出状态以及销毁(杀掉)进程的方法。public abstract class Processextends ObjectProcessBuilder.start() 和 Runtime.exec 方法创建一个本机进程,并返回 Process 子类的一个实例,该实例可用来控制进程并获得相关信息。Process 类提供了执行从进程输入、执行输出到进程、等待进程完成、检查进程的退出状态以及销毁(杀掉)进程的方法。下面我们接着上面的代码继续写:try{rt.exec("notepad");}catch(Exception e){e.printStackTrace;}//在使用exec()方法的时候会抛出一个异常,我们需要捕获这段代码,是运行在windows上的,它调用了windows系统的记事本程序。举一反三我们同样可以用这个方法去编译java的文件,只是传入的参数是“javac ***.java”。对于Process类的实例主要作用是创建一个可以管理的进程,并对它进行管理。Process类还有几个方法分别是destroy() 杀掉子进程、exitValue()返回子进程的出口值、getErrorStream()获取子进程的错误流,错误流获得由该 Process 对象表示的进程的错误输出流传送的数据,还有获取输入流输出流请读者自己参照java帮助文档学习。这是自己在接触Runtime类和Process类的时候学到的一些东西,分享出来希望对大家有用,大家看见了若是有不对的地方,请指出来。 (转载请注明出处:[url=http://www.live588.org]淘金盈[/url][url=http://www.10086money.com]时尚资讯[/url])
许多人对于程序、进程、线程这几个概念许多人都分的不是很清楚,下面我们就简单的介绍一下它们的区别。 程序是计算机指令的集合,它以文件的形式存储在磁盘上。程序是通常我们所写好的存储于计算机上没有执行的指令的集合,通俗的讲就是我们自己写的代码。我们写的代码不可能只是为了存储吧,必须运行才不会浪费我们的辛苦,等到我们将我们的代码运行了,就产生了进程。 进程:是一个程序在其自身的地址空间中的一次执行活动。通常的程序是不能并发执行的。为了使程序能够独立运行,应该为之配置一些进程控制块,即PCB;而由程序段,相关数据段和PCB三部分构成了进程实体。通常我们并不区分进程和进程实体,基本上就代表同一事物。进程是资源申请、调度和独立运行的单位,因此,它使用系统中的运行资源;而程序不能申请系统资源,不能被系统调度,也不能作为独立运行的单位,因此,它不占用系统的运行资源。 20世纪60年代人们提出了进程的概念,在OS中一直都是以进程作为能独立运行和拥有资源的基本单位。但是进程间的切换比较麻烦费时,所以在20世纪80年代人们为了提高系统内程序并发执行的程度,进一步提高系统的吞吐量,提出了比进程更小的能独立运行的基本单位。线程又称为轻量级进程,它和进程一样拥有独立的执行控制,由操作系统负责调度,区别在于线程没有独立的存储空间,而是和所属进程中的其它线程共享一个存储空间,这使得线程间的通信远较进程简单。一个进程可以同时拥有一个或者多个线程,这几个线程共享同样的数据。 现在的CPU几乎都是多核的了,这样多线程的程序,运行起来就更加流畅。下面我们通过图片来比较一下单线程和多线程:
这个就好比我们算一道数学题(2+3)*(5-3),如果我们使用左边的单线程,只能是先算2+3然后算5-3,最后结果相加。但是如果我们使用右边的多线程,我们可以同时对2+3和5-3进行运算,然后再对最后的结果相加。我想哪个运行的比较快就不用说了,另外多线程在图像处理,多用户通信等方面用户都很多。 可能读者会说如果我们用的是单CPU的PC那么他们就差别不大了,但是现在的事实是现在的PC基本都是多核了,所以多线程是为了我们更好的将程序移植到多核的CPU上。还有一点就是对于线程的切换,比进程的切换速度快的多,多线程更好的发挥CPU的效率。 写的不好,如果哪里错了希望大家指出。希望对你有帮助。 (转载请注明出处:[url=http://www.6rfd.com]澳门博彩[/url] [url=http://www.9gds.com]易博网[/url])
用java读取Properties文件来改变实现类的Demo:public abstract class Vehicle {public abstract void run();}public class Car extends Vehicle{public void run(){System.out.println("with Car");}}public class Broom extends Vehicle {@Overridepublic void run() {System.out.println("Broom");}}test.properties 中:VehicleType=abstractfactory.step4properties.Broom注意:该文件要放在src目录下,且等号两边不可有空格import java.util.Properties;public class Test {public static void main(String[] args) throws Exception{Properties pros = new Properties();///配置文件编译之后放在bin目录下//每个class的类,都会被当作Class对象。getClassLoader:拿到了装载这个Class的装载器///把它当作一个流读进来,默认路径是根目录。读出来之后,把它转化为一个properties对象,然后,等号左边的就是key,等号右边的就是valuepros.load(Test.class.getClassLoader().getResourceAsStream("abstractfactory/step4properties/spring.properties"));String vehicleTypeName = pros.getProperty("VehicleType");System.out.println(vehicleTypeName);///现在,得到的字符串,我们想把字符串代表的类,产生一个对象,用到反射///Class.forName把字符串所代表的表装到内存,newInstance:生成对象,得到的是个ObjectVehicle v = (Vehicle)Class.forName(vehicleTypeName).newInstance();v.run();//只要改变test.properties中的VehicleType=factory.step4Spring.Broom,即可实现改变实现类的功能。}} (转载请注明出处:[url=http://www.k6567.com]e世博[/url][url=http://www.d9732.com]澳门博彩[/url])
用JAVA/JSP做开发很久了,也见过许多朋友做过,有很大一部分用的是MYSQL的数据库,现在MYSQL数据库版本5.0及以上的都已经被用的很广泛了,但一直有一个问题,使刚入门的朋友费劲心思.就是JSP连接MYSQL5数据库的时候的一些中文问题.于是网络上也出现了很多相关的帖子.由些大家对MYSQL5数据库的配制文件MY.INI也有了些了解.甚至一些朋友就直接问:你们的MYSQL是什么编码的?你们的TOMCAT是什么样的编码,可能不是很规范的问法,但说明了编码问题的确影响了大家的使用. 下面的讲解是在MYSQL5.0.18,TOMCAT5.0.28,驱动为mysql-connector-java-3.2.0-alpha-bin.jar及以上版本的情况下测试的 JSP连接数据库的乱码问题,分两部分来看 1 数据库中是不是乱码? 我们需要保证数据库保存的不是"?????"形式的乱码,如何保证呢? 我们在管理MYSQL数据库的时候,需要用一个客户端,无论你用MYSQL-FRONT,EMS SQL Manager for MySQL,还是MYSQL命令行,这些都是客户端,也是程序连接了数据库,我们现在用客户端EMS SQL Manager for MySQL连接数据库,连接的时候一定要设置客户端字符集为GBK或者GB2312,这样你才能知道数据库里面是不是乱码.这一编码设置很重要,不然,就算数据库里是中文,你看到的还是乱码 这样连接后,我们看下我们做测试的表格,里面的汉字就是正常的,这个时候也可以直接在上面的记录中进入中文的修改 若这里没有选择编码的话,一般默认的就是UTF8的了,连接后再看这个表格,就会出现乱码 而这个时候就会出现不能插入中文的问题,若您插入中文的话,就会出现下列错误 这个时候大家什么不要误解,不是不能插入中文,也不是你插入的字符太长, 更改下连接编码就OK了.下面是这个表格的SQL语句 CREATE TABLE `test` ( `name` varchar(100) default NULL, `adesc` varchar(100) default NULL ) ENGINE=InnoDB DEFAULT CHARSET=gb2312; 二.程序连接数据时,也要设置好连接时候的编码,JSP连接MYSQL数据库时候,有个URL参数,jdbc:mysql://localhost:3307/sssdb?user=demoUser&password=demoPwd&useUnicode=true&characterEncoding=UTF-8,在这里需要设置成UTF-8, 下面是连接数据库的程序代码 <%@ page contentType="text/html;charset=GB2312" language="java"%> <%@ page import="java.io.*" %> <%@ page import="java.util.*" %> <%@ page import="java.sql.*" %> <% out.println("您的数据库某表格中的内容如下<br>"); try { Class.forName("com.mysql.jdbc.Driver").newInstance(); String url ="jdbc:mysql://localhost:3307/sssdb?user=demoUser&password=demoPwd&useUnicode=true&characterEncoding=UTF-8"; //testDB为你的数据库名 Connection conn= DriverManager.getConnection(url); Statement stmt=conn.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,ResultSet.CONCUR_UPDATABLE); String sql="select * from test"; ResultSet rs=stmt.executeQuery(sql); while(rs.next()) { out.println("第一个字段内容:<font color=red>"+rs.getString(1)+"</font> 第二个字段内容:<font color=red>"+rs.getString(2)+"</font><br>"); } out.print("数据库操作成功,恭喜你"); sql = "insert into test (name,adesc) values ('中文','汉字')"; stmt.execute(sql); rs.close(); stmt.close(); conn.close(); } catch(Exception e){ System.out.println("数据库连接不成功"+e.toString()); } %>
上面的经验是经过多次尝试总结出来的,不管是MYSQL的客户端还是程序连接MYSQL数据库,在本质上都是程序连接数据库,可以自己在本地多试验下,有时候有可能是驱动太旧. (转载请注明出处:[url=http://www.a9832.com]博彩网[/url] [url=http://www.tswa.org]博彩通[/url])
qtp录制鼠标右键单击事件要通过模拟键盘操作来实现step 1,修改replaytype为2,一般情况默认设置是1的。(1 – 使用浏览器事件运行鼠标操作。 2 – 使用鼠标运行鼠标操作)setting.webpackage(”replaytype”) = 2step 2,鼠标右键单击事件(附:click的事件有三种 micleftbtn 0 鼠标左键。 micrightbtn 1 鼠标右键。 micmiddlebtn 2 鼠标中键)browser(”支付宝 – 网上支付 安全快速!”).page(”支付宝 – 网上支付 安全快速!”).link(”返回我要付款”).click , , micrightbtnstep 3,点击右键弹出的菜单(采用键盘事件来模拟)set wshshell = createobject(”wscript.shell”)wshshell.sendkeys “{down}” //键盘向下的箭头wshshell.sendkeys “{down}”wshshell.sendkeys “{enter}” //回车键step 4,修改replaytype为1(使用浏览器事件运行鼠标操作)setting.webpackage(”replaytype”) = 1good to go now. (转载请注明出处:[url=http://www.live588.org]淘金盈[/url][url=http://www.10086money.com]时尚资讯[/url])
摘要: $("#父窗口元素ID",window.parent.document); 对应javascript版本为window.parent.document.getElementByIdx_x("父窗口元素ID"); 取父窗口的元素方法:$(selector, window.parent.document); 那么你取父窗口的父窗口的元素就可以用:$(selector, w... 阅读全文
摘要: C#代码 using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawin... 阅读全文
摘要: 1.可以在servlet的init方法里 String path = getServletContext().getRealPath("/"); 这将获取web项目的全路径 例如 :E:\eclipseM9\workspace\tree\ tree是我web项目的根目录 2.你也可以随时在任意的class里调用 this.getClass... 阅读全文
摘要: Maven带有超过40+个Maven模板,让开发者快速开始一个新的Java项目。这一章,演示怎样使用Maven的命令“mvn archetype:generate”生成一个新的Java Web项目。 下面是使用Maven模板生成项目的步骤。 1、mvn archetype:generate命令 定位到要生成的项目的目录下,如“D:\... 阅读全文
Spring也提供了声明式事务管理。这是通过Spring AOP实现的。 Spring 中进行事务管理的通常方式是利用AOP(面向切片编程)的方式,为普通java类封装事务控制,它是通过动态代理实现的,由于接口是延迟实例化的, spring在这段时间内通过拦截器,加载事务切片。原理就是这样,具体细节请参考jdk中有关动态代理的文档。本文主要讲解如何在spring中进行事务控制。 动态代理的一个重要特征是,它是针对接口的,所以我们的dao要通过动态代理来让spring接管事务,就必须在dao前面抽象出一个接口,当然如果没有这样的接口,那么spring会使用CGLIB来解决问题,但这不是spring推荐的方式,所以不做讨论. 大多数Spring用户选择声明式事务管理。这是最少影响应用代码的选择, 因而这是和非侵入性的轻量级容器的观念是一致的。 从考虑EJB CMT和Spring声明式事务管理的相似以及不同之处出发是很有益的。 它们的基本方法是相似的:都可以指定事务管理到单独的方法;如果需要可以在事务上 下文调用setRollbackOnly()方法。不同之处如下: 不象EJB CMT绑定在JTA上,Spring声明式事务管理可以在任何环境下使用。 只需更改配置文件,它就可以和JDBC、JDO、Hibernate或其他的事务机制一起工作 Spring可以使声明式事务管理应用到普通Java对象,不仅仅是特殊的类,如EJB Spring提供声明式回滚规则:EJB没有对应的特性, 我们将在下面讨论这个特性。回滚可以声明式控制,不仅仅是编程式的 Spring允许你通过AOP定制事务行为。例如,如果需要,你可以在事务 回滚中插入定制的行为。你也可以增加任意的通知,就象事务通知一样。使用 EJB CMT,除了使用setRollbackOnly(),你没有办法能 够影响容器的事务管理 Spring不提供高端应用服务器提供的跨越远程调用的事务上下文传播。如 果你需要这些特性,我们推荐你使用EJB。然而,不要轻易使用这些特性。通常我 们并不希望事务跨越远程调用 回滚规则的概念是很重要的:它们使得我们可以指定哪些异常应该发起自 动回滚。我们在配置文件中,而不是Java代码中,以声明的方式指定。因此,虽然我们仍 然可以编程调用TransactionStatus对象的 setRollbackOnly()方法来回滚当前事务,多数时候我们可以 指定规则,如MyApplicationException应该导致回滚。 这有显著的优点,业务对象不需要依赖事务基础设施。例如,它们通常不需要引 入任何Spring API,事务或其他任何东西。 EJB的默认行为是遇到系统异常(通常是运行时异常), EJB容器自动回滚事务。EJB CMT遇到应用程序异常 (除了java.rmi.RemoteException外的checked异常)时不 会自动回滚事务。虽然Spring声明式事务管理沿用EJB的约定(遇到unchecked 异常自动回滚事务),但是这是可以定制的。 按照我们的测试,Spring声明式事务管理的性能要胜过EJB CMT。 通常通过TransactionProxyFactoryBean设置Spring事务代理。我们需要一个目标对象包装在事务代理中。这个目标对象一般是一个普通Java对象的bean。当我们定义TransactionProxyFactoryBean时,必须提供一个相关的 PlatformTransactionManager的引用和事务属性。 事务属性含有上面描述的事务定义。 <bean id="petStore" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"> <property name="transactionManager"><ref bean="transactionManager"/></property> <property name="target"><ref bean="petStoreTarget"/></property> <property name="transactionAttributes"> <props> <prop key="insert*">PROPAGATION_REQUIRED,-MyCheckedException</prop> <prop key="update*">PROPAGATION_REQUIRED</prop> <prop key="*">PROPAGATION_REQUIRED,readOnly</prop> </props> </property></bean> code] 事务代理会实现目标对象的接口:这里是id为petStoreTarget的bean。(使用 CGLIB也可以实现具体类的代理。只要设置proxyTargetClass属性为true就可以。如果目标对象没有实现任何接口,这将自动设置该属性为true。通常,我们希望面向接口而不是类编程。)使用proxyInterfaces属性来限定事务代理来代 理指定接口也是可以的(一般来说是个好想法)。也可以通过从 org.springframework.aop.framework.ProxyConfig继承或所有AOP代理工厂共享 的属性来定制TransactionProxyFactoryBean的行为。 这里的transactionAttributes属性定义在 org.springframework.transaction.interceptor.NameMatchTransactionAttributeSource 中的属性格式来设置。这个包括通配符的方法名称映射是很直观的。注意 insert*的映射的值包括回滚规则。添加的-MyCheckedException 指定如果方法抛出MyCheckedException或它的子类,事务将 会自动回滚。可以用逗号分隔定义多个回滚规则。-前缀强制回滚,+前缀指定提交(这允许即使抛出unchecked异常时也可以提交事务,当然你自己要明白自己 在做什么)。 TransactionProxyFactoryBean允许你通过 “preInterceptors”和“postInterceptors”属性设置“前”或“后”通知来提供额外的 拦截行为。可以设置任意数量的“前”和“后”通知,它们的类型可以是 Advisor(可以包含一个切入点), MethodInterceptor或被当前Spring配置支持的通知类型 (例如ThrowAdvice, AfterReturningtAdvice或BeforeAdvice, 这些都是默认支持的)。这些通知必须支持实例共享模式。如果你需要高级AOP特 性来使用事务,如有状态的maxin,那最好使用通用的 org.springframework.aop.framework.ProxyFactoryBean, 而不是TransactionProxyFactoryBean实用代理创建者。 也可以设置自动代理:配置AOP框架,不需要单独的代理定义类就可以生成类的 代理。 附两个spring的事务配置例子: <prop key="add"> PROPAGATION_REQUIRES_NEW, -MyException </prop> 注:上面的意思是add方法将独占一个事务,当事务处理过程中产生MyException异常或者该异常的子类将回滚该事务。 <prop key="loadAll"> PROPAGATION_SUPPORTS, ISOLATION_READ_COMMITED, Readonly </prop> 注:表示loadAll方法支持事务,而且不会读取没有提交事务的数据。它的数据为只读(这样有助于提高读取的性能) 附A Spring中的所有事务策略 PROPAGATION_MANDATORY PROPAGATION_NESTED PROPAGATION_NEVER PROPAGATION_NOT_SUPPORTED PROPAGATION_REQUIRED PROPAGATION_REQUIRED_NEW PROPAGATION_SUPPORTS 附B Spring中所有的隔离策略: ISOLATION_DEFAULT ISOLATION_READ_UNCOMMITED ISOLATION_COMMITED ISOLATION_REPEATABLE_READ ISOLATION_SERIALIZABL (转载请注明出处:[url=http://www.a9832.com]博彩网[/url] [url=http://www.tswa.org]博彩通[/url])
摘要: java反射与代理 一. 关于数据库. 当今的数据处理大致可以分成两大类:联机事务处理OLTP(on-line transaction processing)、联机分析处理OLAP(On-Line Analytical Processing)。OLTP是传统的关系型数据库的主要应用,主要是基本的、日常的事务处理,例如银行交易。OLAP是数据仓库系统的主要应用,支持复杂的分析操作... 阅读全文
众所周知,当多个消息消费者(MessageConsumer)同时监听同一个消息队列(Queue)的时候,JMS提供者会在它们之间提供一种负载均衡机制,从而达到可以同时处理多个消息的目的。图一是一个简单的示意图,当消息生产者发送多个消息时,JMS提供者会把这些消息均匀的分发到不同的消息消费者。 图一 JMS负载均衡示意图
一、WebService负载均衡 要在原来的WebService上应用负载均衡,首先应该明确一个前提,就是客户端和服务端应尽可能的不做修改。另外还需要确保可以方便的添加和删除一个Service节点,而不会影响整个应用的运行。庆幸的是WebService调用通常都是无状态的,类似于无状态会话 Bean(Stateless Session Bean)的远程调用,服务端和客户端不需要维持一个会话,也就是说同一个客户端调用多次WebService请求,每个请求可以由不同的Service 为它服务,这样就可以避免Session复制的问题,如果一个Service崩溃了,另一个Service可以继续为客户端服务。 二、将JMS负载均衡应用到WebService中 接下来就把JMS的负载均衡机制应用到WebService当中去,图二是一个整体的框架图,Proxy作为一个WebService的代理来和客户端交互, 而Listener会去掉用具体的WebService,来完成一次WebService方法的调用。 图二 整体框架图
与客户端直接交互的是Proxy,它是一个简单的Servlet,它的作用就是拦截客户端发送过来的请求,提取请求中的SOAP包的内容,然后把它封装成一个消息发送到指定的Queue中去,同时它会等待消息的回复,因为回复的消息中包含着WebService调用返回的结果,后面会详细讲到。当Proxy收到回复消息之后,读取其中的内容并把它返回给客户端,从而完成一个WebService的调用。另外需要注意的是,在这里Proxy需要区分出客户端发出的是GET请求,还是POST请求。如果是GET请求,就有可能是客户端正在获取WebService的WSDL。如果是POST请求,那么通常就是客户端在调用一个WebService方法了。下面是一个简单的Proxy实现: 1 public class ServiceProxy extends HttpServlet { 2 3 private ConnectionFactory factory; 4 5 private Connection connection; 6 7 private Queue queue; 8 9 public void init() throws ServletException { 10 11 super.init(); 12 13 try { 14 15 //在这里为了简单起见,采用了ActiveMQ。在实际的J2EE应用中应通过JNDI查找相应的ConnectionFactory和Queue。||| 16 17 factory = new ActiveMQConnectionFactory("vm://localhost"); 18 19 connection = factory.createConnection(); 20 21 connection.start(); 22 23 queue = new ActiveMQQueue("testQueue"); 24 25 } catch (JMSException e) { 26 27 e.printStackTrace(); 28 29 } 30 31 } 32 33 protected void doGet(HttpServletRequest req, HttpServletResponse resp) { 34 35 if (req.getQueryString().endsWith("wsdl") || req.getQueryString().endsWith("WSDL")) { 36 37 try { 38 39 Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE); 40 41 Message message = session.createMessage(); 42 43 //这个属性用来标示请求是否是WSDL请求,后面的Listener会根据它来调用具体的WebService。 44 45 message.setBooleanProperty("isWsdl", true); 46 47 message.setJMSReplyTo(session.createTemporaryQueue()); 48 49 session.createProducer(queue).send(message); 50 51 //等待回复消息,它里面包含Service返回的WSDL,这里使用了一个选择器。 52 53 String selector = String.format("JMSCorrelationID=‘%s‘", message.getJMSMessageID()); 54 55 MessageConsumer consumer = session.createConsumer(message.getJMSReplyTo(), selector); 56 57 TextMessage replyMessage = (TextMessage) consumer.receive(); 58 59 //将WSDL返回给客户端。 60 61 resp.getWriter().write(replyMessage.getText()); 62 63 } catch (Exception e) { 64 65 e.printStackTrace(); 66 67 } 68 69 } 70 71 } 72 73 protected void doPost(HttpServletRequest req, HttpServletResponse resp) { 74 75 try { 76 77 //首先从客户端请求中得到SOAP请求部分。 78 79 StringBuffer payLoad = new StringBuffer(); 80 81 BufferedReader reader = req.getReader(); 82 83 String temp; 84 85 while ((temp = reader.readLine()) != null) { 86 87 payLoad.append(temp); 88 89 } 90 91 //将SOAP请求封装成一个消息,发送到Queue。 92 93 Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE); 94 95 Message message = session.createTextMessage(payLoad.toString()); 96 97 message.setBooleanProperty("isWsdl", false); 98 99 message.setJMSReplyTo(session.createTemporaryQueue()); 100||| 101 session.createProducer(queue).send(message); 102 103 //等待回复,回复的消息中包含着服务端返回的SOAP响应。 104 105 String selector = String.format("JMSCorrelationID=‘%s‘", message.getJMSMessageID()); 106 107 MessageConsumer consumer = session.createConsumer(message.getJMSReplyTo(), selector); 108 109 TextMessage replyMessage = (TextMessage) consumer.receive(); 110 111 //将SOAP响应返回给客户端。 112 113 resp.getWriter().write(replyMessage.getText()); 114 115 } catch (Exception e) { 116 117 e.printStackTrace(); 118 119 } 120 121 } 122 123 } 接下来需要看一下Listener了。对于每一个Service都有一个Listener与之相对应,当一个Listener从Queue中取得一个消息之后,首先应该判断是否是WSDL请求。如果是WSDL请求,则向WebService发送一个GET请求,并将请求的结果,也就是WSDL封装成一个Message回复给Proxy。如果是SOAP请求,则从中取出SOAP请求部分并通过POST方法发送给Service,所得到的返回结果即为Service的SOAP响应,把它回复给Proxy,进而回复给客户端。 下面是Listener的一个简单实现,在这里我们使用了HttpClient来发送GET和POST请求。 1 public class Listener { 2 3 private ConnectionFactory factory; 4 5 private Connection connection; 6 7 private Queue queue; 8 9 private Session session; 10 11 public Listener() throws Exception { 12 13 //为了简单,还是采用了ActiveMQ。 14 15 factory = new ActiveMQConnectionFactory("vm://localhost"); 16 17 connection = factory.createConnection(); 18 19 connection.start(); 20 21 queue = new ActiveMQQueue("testQueue"); 22 23 session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE); 24 25 } 26 27 public void startUp() throws Exception { 28 29 MessageConsumer consumer = session.createConsumer(queue); 30 31 consumer.setMessageListener(new MessageListener() { 32 33 public void onMessage(Message message) { 34 35 try { 36 37 String response; 38 39 //通过判断isWSDL这个属性来判断是否是WSDL请求。 40 41 if (message.getBooleanProperty("isWsdl")) { 42 43 //如果是WSDL请求,则向服务器发送一个GET请求,并等待WSDL响应结果。 44 45 HttpClient client = new HttpClient();||| 46 47 //具体Service的地址,可以使用properties文件等。 48 49 GetMethod m = new GetMethod("http://localhost:8081/hello?wsdl"); 50 51 client.executeMethod(m); 52 53 response = m.getResponseBodyAsString(); 54 55 } else { 56 57 //如果是SOAP请求,则将SOAP包发送给服务器,并等待SOAP响应。 58 59 HttpClient client = new HttpClient(); 60 61 PostMethod m = new PostMethod("http://localhost:8081/hello"); 62 63 m.setRequestBody(((TextMessage) message).getText()); 64 65 client.executeMethod(m); 66 67 response = m.getResponseBodyAsString(); 68 69 } 70 71 //将WSDL响应或SOAP响应封装成一个消息,回复给Proxy。 72 73 MessageProducer producer = session.createProducer(message.getJMSReplyTo()); 74 75 TextMessage replyMessage = session.createTextMessage(response); 76 77 //设置JMSCorrelationID,Proxy通过它来得到该回复消息。 78 79 replyMessage.setJMSCorrelationID(message.getJMSCorrelationID()); 80 81 producer.send(replyMessage); 82 83 } catch (Exception ex) { 84 85 ex.printStackTrace(); 86 87 } 88 89 } 90 91 }); 92 93 } 94 95 } 三、还需要考虑的 1,如果其中一个Service崩溃,我们需要停止相应的Listener,这一点可以在Listener中做到,例如当Listener访问 Service时出错,它可以等待一段时间以后再去监听Queue,同时把已经取得的消息重新发回到Queue中去,以便让其他的Listener处理。当然也可以将Listener放置到Service端,这样Service崩溃,Listener也就跟着不可用了。 2,如果某一时刻,所有的Service都不可用,Proxy也不应该无限等待下去,而应该设置一个等待回复消息的超时期限,如果这个期限内没有收到回复消息,则表明Service都不可用,同时通知客户端。 3,过期消息的处理,如同上一点,当Service不可用时,Proxy通知客户端出错,但是此时Proxy已经向Queue中发送了一条消息,当Service恢复时,这条消息会被重新处理。我们应该避免这种情况发生,因为这条消息已经过期了。可以设置消息的过期期限小于Proxy等待回复消息的期限,以确保它不会被重新处理。 4,最糟糕的情况就是,Proxy或者Queue崩溃,这样就算Service正常,客户端也会调用失败。 5,效率,既然我们选择了WebService和负载均衡,那就表示我们应该接受它效率相对低下的弱点,在这里需要说明的是JMS并不是效率的瓶颈,因为Listener只负责拿到消息并发送给Service,这时Service还是运行在多线程下的。 (转载请注明出处:[url=http://www.6rfd.com]澳门博彩[/url] [url=http://www.9gds.com]易博网[/url])
hashCode就是我们所说的散列码,使用hashCode算法可以帮助我们进行高效率的查找,例如HashMap,说hashCode之前,先来看看Object类。 我们知道,Object类是java程序中所有类的直接或间接父类,处于类层次的最高点。在Object类里定义了很多我们常见的方法,包括我们要讲的hashCode方法,如下 - public final native Class<?> getClass();
- public native int hashCode();
- public boolean equals(Object obj) {
- return (this == obj);
- }
- public String toString() {
- return getClass().getName() + "@" + Integer.toHexString(hashCode());
- }
注意到hashCode方法前面有个native的修饰符,这表示hashCode方法是由非java语言实现的,具体的方法实现在外部,返回内存对象的地址。
在java的很多类中都会重写equals和hashCode方法,这是为什么呢?最常见的String类,比如我定义两个字符相同的字符串,那么对它们进行比较时,我想要的结果应该是相等的,如果你不重写equals和hashCode方法,他们肯定是不会相等的,因为两个对象的内存地址不一样。
String类的重写的hashCode方法 - public int hashCode() {
- int h = hash;
- if (h == 0) {
- int off = offset;
- char val[] = value;
- int len = count;
-
- for (int i = 0; i < len; i++) {
- h = 31*h + val[off++];
- }
- hash = h;
- }
- return h;
- }
1、这段代码究竟是什么意思? 其实这段代码是这个数学表达式的实现 - s[0]*31^(n-1) + s[1]*31^(n-2) + ... + s[n-1]
s[i]是string的第i个字符,n是String的长度。那为什么这里用31,而不是其它数呢?《Effective Java》是这样说的:之所以选择31,是因为它是个奇素数,如果乘数是偶数,并且乘法溢出的话,信息就会丢失,因为与2相乘等价于移位运算。使用素数的好处并不是很明显,但是习惯上都使用素数来计算散列结果。31有个很好的特性,就是用移位和减法来代替乘法,可以得到更好的性能:31*i==(i<<5)-i。现在的VM可以自动完成这种优化。
2、它返回的hashCode有什么特点呢? 可以看到,String类是用它的value值作为参数来计算hashCode的,也就是说,相同的value就一定会有相同的hashCode值。这点也很容易理解,因为value值相同,那么用equals比较也是相等的,equals方法比较相等,则hashCode一定相等。反过来不一定成立。它不保证相同的hashCode一定有相同的对象。
一个好的hash函数应该是这样的:为不相同的对象产生不相等的hashCode。 在理想情况下,hash函数应该把集合中不相等的实例均匀分布到所有可能的hashCode上,要想达到这种理想情形是非常困难的,至少java没有达到。因为我们可以看到,hashCode是非随机生成的,它有一定的规律,就是上面的数学等式,我们可以构造一些具有相同hashCode但value值不一样的,比如说:Aa和BB的hashCode是一样的。
说到这里,你可能会想,原来构造hash冲突那么简单啊,那我是不是可以对HashMap函数构造很多<key,value>不都一样,但具有相同的hashCode,这样的话可以把HashMap函数变成一条单向链表,运行时间由线性变为平方级呢?虽然HashMap重写的hashCode方法比String类的要复杂些,但理论上说是可以这么做的。这也是最近比较热门的Hash Collision DoS事件。 HashMap里重写的hashCode方法 - public final int hashCode() {
- return (key==null ? 0 : key.hashCode()) ^
- (value==null ? 0 : value.hashCode());
- }
(转载请注明出处:[url=http://www.k8764.com]博彩通[/url]
[url=http://www.5sfd.com]e世博[/url])
由于工作需要,要在JS端将JSON对象转化为字符串,并写到用户的COOKIE中,用来保存用户的一些个人操作习惯。便在网上搜寻了一遍,发现方法有很多,有些代码不清晰,看得乱,有些考虑不周全,生成的字符串有问题,便整合了一些好的写法,自己改进了一下。可能还是考虑得不周全,但是感觉常用的类型都考虑了,望大家多多拍砖指点! JSON.stringify(jsonobj),本来是最简便的方法,可是存在浏览器兼容问题(仅适用于IE8+,Chrome 1+,FF 3+)。 var O2String = function (O) {
//return JSON.stringify(jsonobj);
var S = [];
var J = "";
if (Object.prototype.toString.apply(O) === '[object Array]') {
for (var i = 0; i < O.length; i++)
S.push(O2String(O[i]));
J = '[' + S.join(',') + ']';
}
else if (Object.prototype.toString.apply(O) === '[object Date]') {
J = "new Date(" + O.getTime() + ")";
}
else if (Object.prototype.toString.apply(O) === '[object RegExp]' || Object.prototype.toString.apply(O) === '[object Function]') {
J = O.toString();
}
else if (Object.prototype.toString.apply(O) === '[object Object]') {
for (var i in O) {
O[i] = typeof (O[i]) == 'string' ? '"' + O[i] + '"' : (typeof (O[i]) === 'object' ? O2String(O[i]) : O[i]);
S.push(i + ':' + O[i]);
}
J = '{' + S.join(',') + '}';
}
return J;
};
/*-----------------------以下是测试代码-----------------------*/
var jsonStr = O2String(
[
{
"Page": "plan",
"Custom":
[
{
"ItemName": "CustomLabel1",
"ItemContent": 1,
"IsItem": true,
"ItemDate": new Date(1320774905467),
"ItemReg": /[\w]*?/gi,
"ItemFunc": function () { alert("ItemFunc"); }
},
{
"ItemName": "CustomLabel1",
"ItemContent": 1,
"IsItem": true,
"ItemDate": new Date(1320774905467),
"ItemReg": /[\w]*?/gi,
"ItemFunc": function () { alert("ItemFunc"); }
}
]
},
{
"Page": "project",
"Custom":
[
{
"ItemName": "CustomLabel2",
"ItemContent": 2,
"IsItem": false,
"ItemDate": new Date(1320774905467),
"ItemReg": /[\w]*?/gi,
"ItemFunc": function () { alert("ItemFunc"); }
},
{
"ItemName": "CustomLabel2",
"ItemContent": 2,
"IsItem": false,
"ItemDate": new Date(1320774905467),
"ItemReg": /[\w]*?/gi,
"ItemFunc": function () { alert("ItemFunc"); }
}
]
}
]
);
alert(jsonStr);
var jsonObj = eval("(" + jsonStr + ")");
alert(jsonObj.length);
(转载请注明出处:[url=http://www.tdtf.org]易博网 [/url] [url=http://www.k5048.com]博彩网[/url])
现象: 系统突然报连接数过高,基本的现象就是有什么东西被锁了,导致后续的连接都在等待,那么到底是那个会话导致了阻塞那? 可以查看视图v$session ,关注以下几个字段 sid-------------------------被阻塞的进程id status--------------------被阻塞的进程状态 COMMAND--------------被阻塞的进程执行的命令 ROW_WAIT_FILE#----被阻塞的进程对应的rowid所在的数据文件id row_wait_block#-----row_wait_row#对应的rowid所在的表的object id row_wait_obj#-------row_wait_row#对应的rowid所在的表的object id row_wait_row#-----Current row being locked. This column is valid only if the session is currently waiting for another transaction to commit and the value of ROW_WAIT_OBJ# is not -1 .但是准确的说是对应的于rowid的rownum,并非是单纯的rownum blocking_session -----阻塞进程id STATE-------------------被阻塞进程的状态 EVENT#----------------被阻塞进程等待的事件号 EVENT------------------被阻塞进程等待的事件 -----注意create_time是程序自动添加的select t.sid,t.status,t.COMMAND,t.ROW_WAIT_FILE#,t.row_wait_block#,t.row_wait_obj#,t.row_wait_row#,t.blocking_session ,t.STATE,t.EVENT#,t.EVENT from temp_session t where t.BLOCKING_SESSION_STATUS='VALID' and t.create_time=to_date('2012/3/20 18:47:16','yyyy/mm/dd hh24:mi:ss'); SID STATUS COMMAND ROW_WAIT_FILE# ROW_WAIT_BLOCK# ROW_WAIT_OBJ# ROW_WAIT_ROW# BLOCKING_SESSION STATE EVENT# EVENT175 620 ACTIVE 3 8 571147 77418 17 885 WAITING 239 enq: TX - row lock contention174 616 ACTIVE 3 8 571147 77418 17 885 WAITING 239 enq: TX - row lock contention173 615 ACTIVE 3 8 571147 77418 17 885 WAITING 239 enq: TX - row lock contention333 1050 ACTIVE 3 8 571147 77418 17 885 WAITING 239 enq: TX - row lock contention179 632 ACTIVE 3 8 571147 77418 17 885 WAITING 239 enq: TX - row lock contention178 629 ACTIVE 3 8 571147 77418 17 885 WAITING 239 enq: TX - row lock contention332 1049 ACTIVE 3 8 571147 77418 17 885 WAITING 239 enq: TX - row lock contention171 610 ACTIVE 3 8 571147 77418 17 885 WAITING 239 enq: TX - row lock contention166 592 ACTIVE 3 8 571147 77418 17 885 WAITING 239 enq: TX - row lock contention165 591 ACTIVE 3 8 571147 77418 17 885 WAITING 239 enq: TX - row lock contention164 589 ACTIVE 3 8 571147 77418 17 885 WAITING 239 enq: TX - row lock contention现在可以看到885进程阻塞了好多进程,那么要获得到底是那条记录被锁定了那?想要知道某一个表具体被锁定的是哪一行,可以利用上面这几个值,查找出被锁定行的rowid。使用dbms_rowidb包的一个子过程(Subprograms)rowid_createDBMS_ROWID.ROWID_CREATE (rowid_type IN NUMBER,object_number IN NUMBER,relative_fno IN NUMBER,block_number IN NUMBER,row_number IN NUMBER)RETURN ROWID;其中rowid_type的取值为 0 表示生成一个restricted ROWID(pre-oracle8 format); 取值为1 表示生成一个extended ROWID.object_number取值是dba_objects视图中的data_object_id,并不是object_id,也就是说不能用row_wait_obj#.relative_fno取值是Relative文件号,在dba_data_files里可以查到block_number取值是数据文件的块号,也就是v$session中的row_wait_block#的值row_number通过rowid对应出来的rownum,也就是row_wait_row#的值。 接下来找到这些数据rowid_type=1(11g) object_number selectdata_object_id from dba_objects where object_id='77418'
OBJECT_ID TT_BIGINT NOT NULL Dictionary object number of the object.DATA_OBJECT_ID TT_BIGINT Is ignored.----这是11g的文档说明,可以看出,使用object_id就可以relative_fno=8 block_number=row_wait_block# row_number =row_wait_row# select * from table_name t where rowid=(select DBMS_ROWID.ROWID_CREATE(1,77418,8,571147,17) from dual);---得到被锁定的记录;此时查看885进程在做神马?kill之就可以 (转载请注明出处:[url=http://www.k6567.com]e世博[/url] [url=http://www.d9732.com]澳门博彩[/url])
#include <windows.h> #include <stdio.h> LRESULT CALLBACK WinSunProc(//名字可以更改。参数类型不能变 HWND hwnd, // handle to window 窗口句柄 UINT uMsg, // message identifier WPARAM wParam, // first message parameter 消息参数 LPARAM lParam // second message parameter ); /* int WINAPI WinMain( HINSTANCE hInstance, // handle to current instance HINSTANCE hPrevInstance, // handle to previous instance LPSTR lpCmdLine, // pointer to command line int nCmdShow // show state of window ); */ int WINAPI WinMain(//Windows程序的入口函数 HINSTANCE hInstance, // handle to current instance 当前实例句柄 HINSTANCE hPrevInstance, // handle to previous instance 前次实例句柄 LPSTR lpCmdLine, // command line 命令行参数 int nCmdShow // show state 显示方式 ) { /* 创建一个完整的窗口需要经过下面四个操作步骤: 1、设计一个窗口类; 2、注册窗口类; 3、创建窗口; 4、显示及更新窗口。 typedef struct _WNDCLASS { UINT style; //类的类型 WNDPROClpfnWndProc; //longpointfunction函数指针 int cbClsExtra; //类的附加内存 int cbWndExtra; //窗口附加内存 HANDLE hInstance; //实例号(句柄) HICON hIcon; //图标句柄 HCURSOR hCursor; //光标句柄 HBRUSH hbrBackground; //画刷句柄 LPCTSTR lpszMenuName; //菜单的名字 LPCTSTR lpszClassName; //类的名字 } WNDCLASS; */ //1、设计一个窗口类; WNDCLASS wndcls;//窗口类 wndcls.style=CS_HREDRAW | CS_VREDRAW;//重画垂直方向、水平方向 wndcls.lpfnWndProc=WinSunProc;//函数地址 wndcls.cbClsExtra=0;//类的附加内存 wndcls.cbWndExtra=0;//窗口的附加内存 wndcls.hInstance=hInstance;//实例号 wndcls.hIcon=LoadIcon(NULL,IDI_ERROR);//图标 设置 wndcls.hCursor=LoadCursor(NULL,IDC_CROSS);//光标 设置 wndcls.hbrBackground=(HBRUSH)GetStockObject(WHITE_BRUSH);//画刷的句柄 wndcls.lpszMenuName=NULL;//(菜单名字) wndcls.lpszClassName="VCXTU";//注册类名(longpoint命令行参数)
//2、注册窗口类; RegisterClass(&wndcls);//注册类 /* HWND CreateWindow( LPCTSTR lpClassName, // pointer to registered class name LPCTSTR lpWindowName, // pointer to window name DWORD dwStyle, // window style int x, // horizontal position of window int y, // vertical position of window int nWidth, // window width int nHeight, // window height HWND hWndParent, // handle to parent or owner window HMENU hMenu, // handle to menu or child-window identifier HANDLE hInstance, // handle to application instance LPVOID lpParam // pointer to window-creation data ); */ //3、创建窗口; HWND hwnd;//窗口句柄 hwnd=CreateWindow( "VCXTU",//注册类名(lpszClassName) "湖南省湘潭市湘潭大学",//窗口名字 /* WS_OVERLAPPEDWINDOW: 窗口风格 WS_OVERLAPPED 层叠的 具有标题栏和边框 WS_CAPTION 有标题栏 WS_SYSMENU 带有系统菜单 WS_THICKFRAME 具有可调边框 WS_MINIMIZEBOX 具有最小化按钮 WS_MAXIMIZEBOX) 具有最大化按钮 */ WS_OVERLAPPEDWINDOW,//窗口风格 CW_USEDEFAULT,//窗口水平坐标(缺省的) CW_USEDEFAULT,//窗口垂直坐标(缺省的) 600,//窗口宽度 400,//窗口高度 NULL,// 父窗口句柄(hWndParent/handle to parent or owner window) NULL,// 菜单句柄(handle to menu or child-window identifier) hInstance,//句柄(handle to application instance) NULL//窗口参数(pointer to window-creation data) ); /* BOOL ShowWindow( HWND hWnd, // handle to window int nCmdShow // show state of window ); */ //4、显示及更新窗口。 ShowWindow( hwnd,//窗口句柄 SW_SHOWNORMAL//显示状态 show state of window ); UpdateWindow(hwnd);//可有可无 /* 操作系统将每个事件都包装成一个称为消息的结构体MSG来传递给应用程序 MSG结构定义如下: typedef struct tagMSG { HWND hwnd; UINT message; WPARAM wParam; LPARAM lParam; DWORD time; POINT pt; } MSG; */ //消息循环 MSG msg; /* BOOL GetMessage( LPMSG lpMsg, // address of structure with message HWND hWnd, // handle of window UINT wMsgFilterMin, // first message UINT wMsgFilterMax // last message ); */ while( GetMessage( &msg, NULL, 0,//设成0。表示对所有消息都有兴趣 0 ) ) { /* 转换消息。可以将WM_KEYUP/WM_KEYDOWN转换为WM_CHAR消息、产生新消息并放到队列中 BOOL TranslateMessage( CONST MSG *lpMsg // address of structure with message ); */ TranslateMessage(&msg); /* 将收到的消息传到窗口的回调函数:wndcls.lpfnWndProc=WinSunProc;回调函数:WinSunProc LONG DispatchMessage( CONST MSG *lpmsg // pointer to structure with message ); */ DispatchMessage(&msg); } return 0; } LRESULT CALLBACK WinSunProc( HWND hwnd, // handle to window UINT uMsg, // message identifier WPARAM wParam, // first message parameter LPARAM lParam // second message parameter ) { switch(uMsg) { case WM_CHAR://表示按下了某个字符按键 char szChar[20]; sprintf(szChar,"char is %d",wParam);//格式化消息。WM_CHAR中的wParam参数 /* int MessageBox( HWND hWnd, //拥有消息的父窗口 handle of owner window LPCTSTR lpText, //文本 address of text in message box LPCTSTR lpCaption, //标题 address of title of message box UINT uType //消息框的风格 style of message box ); */ MessageBox( hwnd, szChar, "湘潭大学",//标题 MB_OKCANCEL//MB_YESNO//消息框的风格 ); break; case WM_LBUTTONDOWN: MessageBox(hwnd,"鼠标左键点击了","湘潭大学",MB_OKCANCEL); HDC hdc;//句柄 handle to device context /* HDC GetDC( HWND hWnd // handle to a window ); */ hdc=GetDC(hwnd); /* BOOL TextOut( HDC hdc, // handle to device context int nXStart, // x-coordinate of starting position int nYStart, // y-coordinate of starting position LPCTSTR lpString, // pointer to string int cbString // number of characters in string ); */ TextOut(hdc,0,50,"湖南省湘潭市湘潭大学1",strlen("湖南省湘潭市湘潭大学1")); ReleaseDC(hwnd,hdc);//释放DC break; case WM_PAINT://窗口重绘 HDC hDC; PAINTSTRUCT ps; /* HDC BeginPaint( HWND hwnd, // handle to window LPPAINTSTRUCT lpPaint // pointer to structure for paint information ); */ hDC=BeginPaint(hwnd,&ps);//只能在WM_PAINT里面使用 TextOut(hDC,0,0,"湖南省湘潭市湘潭大学hDC",strlen("湖南省湘潭市湘潭大学hDC")); EndPaint(hwnd,&ps);//只能在WM_PAINT里面使用 break; case WM_CLOSE://关闭窗口时响应 if(IDYES==MessageBox(hwnd,"是否真的结束?","湘潭大学",MB_YESNO)) { DestroyWindow(hwnd);//销掉hwnd窗口 还会发送 WM_DESTROY、WM_NCDESTROY 消息 } break; case WM_DESTROY: PostQuitMessage(0);//退出程序 break; default: return DefWindowProc(hwnd,uMsg,wParam,lParam); } return 0; } (转载请注明出处:[url=http://www.live588.org]淘金盈[/url] [url=http://www.10086money.com]时尚资讯[/url])
1、查询v$sql视图 selectsql_id, sql_text, bind_data,HASH_VALUE from v$sql where sql_text Like '%select * from test where id1%'; 它的记录频率受_cursor_bind_capture_interval 隐含参数控制,默认值900,表示每900秒记录一次绑定值,可以通过alter system set "_cursor_bind_capture_interval"=10;
此时查询到的data值得形式是这样的:BEDA0B2002004F8482D10065FFFF0F00000000000000000000C0021602C102C0021602C102F0018003691532303132303431313032504F443834363135313635F0018003691532303132303431313032504F443834363135313730F0018003691532303132303431313032504F443834363135313731F0018003691532303132303431313032504F443834363135313734F0018003691532303132303431313032504F443834363135313735F0018003691532303132303431313032504F443834363135313739F0018003691532303132303431313032504F443834363135313830F0018003691532303132303431313032504F443834363135313833F0018003691532303132303431313032504F443834363135313834F0018003691532303132303431313032504F443834363135313838F0018003691532303132303431313032504F443834363135313839F0018003691532303132303431313032504F443834363135313933F0018003691532303132303431313032504F443834363135313934F0018003691532303132303431313032504F443834363135313937F0018003691532303132303431313032504F443834363135313938F0018003691532303132303431313032504F443834363135323033F0018003691532303132303431313032504F443834363135323034F0018003691532303132303431313032504F443834363135323037 这样肯定是没法看懂的
需哟进行转换 select dbms_sqltune.extract_binds(bind_data) bind from v$sql WHERE SQL_TEXT LIKE '%FROM TEST11%';
2、查询SELECT VALUE_STRING FROM V$SQL_BIND_CAPTURE WHERE SQL_ID='abhf6n1xqgrr0'; 通过v$sql_bind_capture视图,可以查看绑定变量,但是这个视图不太给力,只能捕获最后一次记录的绑定变量值。
而且两次捕获的间隔有一个隐含参数控制。默认是900秒,才会重新开始捕获。在900内,绑定变量值的改变不会反应在这个视图中。 10G以后可以通过如下方法查看AWR报告里记录的SQL的绑定变量值。 select snap_id, name, position, value_string,last_captured,WAS_CAPTUREDfrom dba_hist_sqlbind where sql_id = '576c1s91gua19' and snap_id='20433'; ----------SNAP_ID就是AWR报告的快照ID。 ----------name,绑定变量的名称 ----------position,绑定值在SQL语句中的位置,以1,2,3进行标注 ---------value_string,就是绑定变量值 ---------,last_captured,最后捕获到的时间 ---------WAS_CAPTURED,是否绑定被捕获,where子句前面的绑定不进行捕获。 dba_hist_sqlbind视图强大的地方在于,它记录了每个AWR报告里的SQL的绑定变量值,当然这个绑定变量值也是AWR生成的时候从v$sql_bind_capture采样获得的。 通过这个视图,我们能够获得比较多的绑定变量值,对于我们排查问题,这些值一般足够了。 还有一个需要注意的地方是,这两个视图中记录的绑定变量只对where条件后面的绑定进行捕获,这点需要使用的时候注意。 3、查询dba_hist_sqlbind VALUE_STRING列
DBA_HIST_SQLBIND是视图V$SQL_BIND_CAPTURE历史快照 4、查询wrh$_sqlstat select dbms_sqltune.extract_bind(bind_data, 1).value_stringfrom wrh$_sqlstatwhere sql_id = '88dz0k2qvg876'----根据绑定变量的多少增加dbms_sqltune.extract_bind(bind_data, 2).value_string等 (转载请注明出处:[url=http://www.6rfd.com]澳门博彩[/url] [url=http://www.9gds.com]易博网[/url])
2012年4月19日
需求描述:一个表已经上线,但是上线之后发现该表的数据量很大,而且会删除历史数据,该表上要建立多个唯一索引,现在的问题就是在建表的时候是建立了一个普通表,现在需要将普通表转化为分区表,并尽量减少对应用的影响1、使用ctas的方式来建立create table t1(ID VARCHAR2(60) not null,a VARCHAR2(60) not null,b VARCHAR2(60) not null,create_time TIMESTAMP(6) not null,d NUMBER(2) not null,e VARCHAR2(400) not null,OUTER_ID VARCHAR2(100))----原表---建立分区表:create table t1_new(ID_1 ,a ,b ,create_time ,d ,e ,OUTER_ID )partition by range (ID_1)(partition p_t1_new values less than ('201204'),partition p_t2_new values less than ('201205'))asselect * from t1;----此时应用还是不断的往t1表中插入数据-alter table t1_new add constraints pk_t1_new primary key (id) using tablespace local index_tablespace;----建立本地索引为了删除历史数据/alter table t1_new add constraints pk_t1_new primary key (id_1) using index local ;但是应用还在outer_id上建立唯一索引create unique index IDX_t1_new_2 on t1_new (OUTER_ID) LOCAL ;此时报ORA-14039: 分区列必须构成 UNIQUE 索引的关键字列子集原来oracle不支持在分区表上创建PK主键时主键列不包含分区列,创建另外的约束(unique)也不可以。为了解决这个问题,两种方法1、将分区键加到唯一索引里面2、将local索引变为global索引----此时当进行历史数据删除的时候会导致索引失效权衡之后在outer_id上建立普通索引alter table t1 rename to t1_bak;alter table t1_new rename to t1;在进行ctas之后需要进行数据完整新检查,而且在进行rename的时候会导致应用连接失效(也有可能在进行alter的时候获取不到表锁而失败)---适用于修改不很频繁的表2、使用交换分区的方式----原表create table t1(ID VARCHAR2(60) not null,a VARCHAR2(60) not null,b VARCHAR2(60) not null,create_time TIMESTAMP(6) not null,d NUMBER(2) not null,e VARCHAR2(400) not null,OUTER_ID VARCHAR2(100))alter table t1 add constraints pk_t1 primary key(id) ;新表create table t1_new(ID_1 ,a ,b ,create_time ,d ,e ,OUTER_ID )partition by range (ID_1)(partition p_t1_new values less than ('201204'),partition p_t2_new values less than ('201205'))alter table t1_new add constraints pk_t1_new primary key (id_1) using index local ;ALTER TABLE t1_new EXCHANGE PARTITION p_t1_new WITH TABLE t1 without validation;----要不要加上without validation(加上的话就是不验证数据是否有效,直接全部放在p_t1_new分区中)然后进行rename操作优点:只是对数据字典中分区和表的定义进行了修改,没有数据的修改或复制,效率最高。如果对数据在分区中的分布没有进一步要求的话,实现比较简单。在执行完RENAME操作后,可以检查T_OLD中是否存在数据,如果存在的话,直接将这些数据插入到T中,可以保证对T插入的操作不会丢失。不足:仍然存在一致性问题,交换分区之后RENAME T_NEW TO T之前,查询、更新和删除会出现错误或访问不到数据。如果要求数据分布到多个分区中,则需要进行分区的SPLIT操作,会增加操作的复杂度,效率也会降低。适用于包含大数据量的表转到分区表中的一个分区的操作。应尽量在闲时进行操作。3、在线重定义----原表create table t1(ID VARCHAR2(60) not null,a VARCHAR2(60) not null,b VARCHAR2(60) not null,create_time TIMESTAMP(6) not null,d NUMBER(2) not null,e VARCHAR2(400) not null,OUTER_ID VARCHAR2(100))alter table t1 add constraints pk_t1 primary key(id) ;新表create table t1_new(ID_1 ,a ,b ,create_time ,d ,e ,OUTER_ID )partition by range (ID_1)(partition p_t1_new values less than ('201204'),partition p_t2_new values less than ('201205'))alter table t1_new add constraints pk_t1_new primary key (id_1) using index local ;EXEC DBMS_REDEFINITION.CAN_REDEF_TABLE(USER, 'T1', DBMS_REDEFINITION.CONS_USE_PK);
EXEC DBMS_REDEFINITION.START_REDEF_TABLE(USER, 'T1', 'T1_NEW',DBMS_REDEFINITION.CONS_USE_PK); (转载请注明出处:[url=http://www.k6567.com]e世博[/url] [url=http://www.d9732.com]澳门博彩[/url])
尽管httpservletresponse.sendredirect方法和requestdispatcher.forward方法都可以让浏览器获得另外一个url所指向的资源,但两者的内部运行机制有着很大的区别。下面是httpservletresponse.sendredirect方法实现的请求重定向与requestdispatcher.forward方法实现的请求转发的总结比较:
(1)requestdispatcher.forward方法只能将请求转发给同一个web应用中的组件;而httpservletresponse.sendredirect 方法不仅可以重定向到当前应用程序中的其他资源,还可以重定向到同一个站点上的其他应用程序中的资源,甚至是使用绝对url重定向到其他站点的资源。如果传递给httpservletresponse.sendredirect 方法的相对url以“/”开头,它是相对于整个web站点的根目录;如果创建requestdispatcher对象时指定的相对url以“/”开头,它是相对于当前web应用程序的根目录。
(2)调用httpservletresponse.sendredirect方法重定向的访问过程结束后,浏览器地址栏中显示的url会发生改变,由初始的url地址变成重定向的目标url;而调用requestdispatcher.forward 方法的请求转发过程结束后,浏览器地址栏保持初始的url地址不变。
(3)httpservletresponse.sendredirect方法对浏览器的请求直接作出响应,响应的结果就是告诉浏览器去重新发出对另外一个url的 访问请求,这个过程好比有个绰号叫“浏览器”的人写信找张三借钱,张三回信说没有钱,让“浏览器”去找李四借,并将李四现在的通信地址告诉给了“浏览器”。于是,“浏览器”又按张三提供通信地址给李四写信借钱,李四收到信后就把钱汇给了“浏览器”。可见,“浏览器”一共发出了两封信和收到了两次回复, “浏览器”也知道他借到的钱出自李四之手。requestdispatcher.forward方 法在服务器端内部将请求转发给另外一个资源,浏览器只知道发出了请求并得到了响应结果,并不知道在服务器程序内部发生了转发行为。这个过程好比绰号叫“浏览器”的人写信找张三借钱,张三没有钱,于是张三找李四借了一些钱,甚至还可以加上自己的一些钱,然后再将这些钱汇给了“浏览器”。可见,“浏览器”只发 出了一封信和收到了一次回复,他只知道从张三那里借到了钱,并不知道有一部分钱出自李四之手。
(4)requestdispatcher.forward方法的调用者与被调用者之间共享相同的request对象和response对象,它们属于同一个访问请求和响应过程;而httpservletresponse.sendredirect方法调用者与被调用者使用各自的request对象和response对象,它们属于两个独立的访问请求和响应过程。对于同一个web应用程序的内部资源之间的跳转,特别是跳转之前要对请求进行一些前期预处理,并要使用httpservletrequest.setattribute方法传递预处理结果,那就应该使用requestdispatcher.forward方法。不同web应用程序之间的重定向,特别是要重定向到另外一个web站点上的资源的情况,都应该使用httpservletresponse.sendredirect方法。
(5)无论是requestdispatcher.forward方法,还是httpservletresponse.sendredirect方法,在调用它们之前,都不能有内容已经被实际输出到了客户端。如果缓冲区中已经有了一些内容,这些内容将被从缓冲区中清除。 (转载请注明出处:[url=http://www.a9832.com]博彩网[/url][url=http://www.tswa.org]博彩通[/url])
在java.lang包当中定义了一个Runtime类,在java中对于Runtime类的定义如下:public class Runtimeextends Object每个 Java 应用程序都有一个 Runtime 类实例,使应用程序能够与其运行的环境相连接。可以通过 getRuntime 方法获取当前运行时。应用程序不能创建自己的 Runtime 类实例。根据上面的话,我们知道对于每一个java程序来说都只有一个Runtime类实例,而且不能由用户创建一个Runtime实例,既然不能创建那么这个类的实例的作用是什么呢?它提供了应用程序和应用程序正在运行的环境的一个接口。Runtime不能由我们创建,我们可以通过Runtime类的一个静态方法,得到一个Runtime类的实例。获取了这个实例之后我们就可以获取java虚拟机的自由内存、也可以获取这个java虚拟机的总的内存等(具体的方法可以参照java帮助文档Runtime类的方法学习),也就是说这个类提供了应用程序了环境的接口。下面我们举一个例子程序:Runtime rt=Runtime.getRuntime();System.out.println(rt.freeMemory());System.out.println(rt.totalMemory());//结果返回的是数字Runtime类还有一个好处就是可以执行一个外部的程序,可以调用Runtime类的exec()方法传入一个命令(exec()方法有几个重载的方法,可以自己学习),创建一个子进程,结果返货一个Process类的实例,通过这个实例我们可以管理创建的子进程。对于Process类在java帮助文档中描述如下:public abstract class Processextends ObjectProcessBuilder.start() 和 Runtime.exec 方法创建一个本机进程,并返回 Process 子类的一个实例,该实例可用来控制进程并获得相关信息。Process 类提供了执行从进程输入、执行输出到进程、等待进程完成、检查进程的退出状态以及销毁(杀掉)进程的方法。public abstract class Processextends ObjectProcessBuilder.start() 和 Runtime.exec 方法创建一个本机进程,并返回 Process 子类的一个实例,该实例可用来控制进程并获得相关信息。Process 类提供了执行从进程输入、执行输出到进程、等待进程完成、检查进程的退出状态以及销毁(杀掉)进程的方法。下面我们接着上面的代码继续写:try{rt.exec("notepad");}catch(Exception e){e.printStackTrace;}//在使用exec()方法的时候会抛出一个异常,我们需要捕获这段代码,是运行在windows上的,它调用了windows系统的记事本程序。举一反三我们同样可以用这个方法去编译java的文件,只是传入的参数是“javac ***.java”。对于Process类的实例主要作用是创建一个可以管理的进程,并对它进行管理。Process类还有几个方法分别是destroy() 杀掉子进程、exitValue()返回子进程的出口值、getErrorStream()获取子进程的错误流,错误流获得由该 Process 对象表示的进程的错误输出流传送的数据,还有获取输入流输出流请读者自己参照java帮助文档学习。这是自己在接触Runtime类和Process类的时候学到的一些东西,分享出来希望对大家有用,大家看见了若是有不对的地方,请指出来。 (转载请注明出处:[url=http://www.live588.org]淘金盈[/url][url=http://www.10086money.com]时尚资讯[/url])
许多人对于程序、进程、线程这几个概念许多人都分的不是很清楚,下面我们就简单的介绍一下它们的区别。 程序是计算机指令的集合,它以文件的形式存储在磁盘上。程序是通常我们所写好的存储于计算机上没有执行的指令的集合,通俗的讲就是我们自己写的代码。我们写的代码不可能只是为了存储吧,必须运行才不会浪费我们的辛苦,等到我们将我们的代码运行了,就产生了进程。 进程:是一个程序在其自身的地址空间中的一次执行活动。通常的程序是不能并发执行的。为了使程序能够独立运行,应该为之配置一些进程控制块,即PCB;而由程序段,相关数据段和PCB三部分构成了进程实体。通常我们并不区分进程和进程实体,基本上就代表同一事物。进程是资源申请、调度和独立运行的单位,因此,它使用系统中的运行资源;而程序不能申请系统资源,不能被系统调度,也不能作为独立运行的单位,因此,它不占用系统的运行资源。 20世纪60年代人们提出了进程的概念,在OS中一直都是以进程作为能独立运行和拥有资源的基本单位。但是进程间的切换比较麻烦费时,所以在20世纪80年代人们为了提高系统内程序并发执行的程度,进一步提高系统的吞吐量,提出了比进程更小的能独立运行的基本单位。线程又称为轻量级进程,它和进程一样拥有独立的执行控制,由操作系统负责调度,区别在于线程没有独立的存储空间,而是和所属进程中的其它线程共享一个存储空间,这使得线程间的通信远较进程简单。一个进程可以同时拥有一个或者多个线程,这几个线程共享同样的数据。 现在的CPU几乎都是多核的了,这样多线程的程序,运行起来就更加流畅。下面我们通过图片来比较一下单线程和多线程:
这个就好比我们算一道数学题(2+3)*(5-3),如果我们使用左边的单线程,只能是先算2+3然后算5-3,最后结果相加。但是如果我们使用右边的多线程,我们可以同时对2+3和5-3进行运算,然后再对最后的结果相加。我想哪个运行的比较快就不用说了,另外多线程在图像处理,多用户通信等方面用户都很多。 可能读者会说如果我们用的是单CPU的PC那么他们就差别不大了,但是现在的事实是现在的PC基本都是多核了,所以多线程是为了我们更好的将程序移植到多核的CPU上。还有一点就是对于线程的切换,比进程的切换速度快的多,多线程更好的发挥CPU的效率。 写的不好,如果哪里错了希望大家指出。希望对你有帮助。 (转载请注明出处:[url=http://www.6rfd.com]澳门博彩[/url] [url=http://www.9gds.com]易博网[/url])
当面临一个问题,有多种实现算途径的时候,要想到java中的核心:多态。 多态的思想:
概括地讲,在运用父类引用指向子类对象的情况下,基本上就用到了多态了。
最简单的多态应该是继承: public class Tank { public void move() { System.out.println("I am father"); } }
public class Tank2 extends Tank{ @Override public void move(){ System.out.println("I am child a"); }
public class Client {public static void main(String[] args) {Tank t2 = new Tank2(); ///父类引用指向了子类对象t2.move(); ///父类中的move方法,但实际具体的实现是tank2对象对move的实现。} } 接口和抽象类的例子: 对于抽象类和接口,有许多类实现这个接口(或者继承这个抽象类)。 在调用的时候,用父类引用指向子类对象的方法。然后,调用对象的方法,编译器就会自动根据这个对象实际属于哪个实现类, 来调出这个类对于接口或者抽象类的具体实现。
例: public class Address { private String name; public Address(String name){ this.name = name; } public String getName() { return name; } public void setName(String name) { this.name = name; } }
定义基类(抽象类): public abstract class Vehicle { abstract void go(Address address); }
Car对于基类的实现: public class Car extends Vehicle{ @Override public void go(Address address){ System.out.println("Car to " + address.getName()); } }
Plane对于基类的实现: public class Plane extends Vehicle{ @Override void go(Address address) { System.out.println("Plane to " + address.getName()); } }
Driver中多态: public void drive(Vehicle v){ ///多态,父类引用指向子类对象,实际传过来的是抽象类Vehicle的子类,或者实现类,然后编译器会根据具体实现类,来找实现方法。 v.go(new Address("杭州(abstract)")); ///此方法在具体的实现中被重写 }
Test: public static void main(String[] args) { Driver d = new Driver(); d.drive(new Plane()); //实际是Plane对象,则编译器就会找到Plane中,对go的实现 d.drive(new Car()); //实际是Car对象,则编译器就会找到Plane中,对go的实现 }
输出结果: Plane to 杭州(abstract) Car to 杭州(abstract)
事实上,这就是多态所起的作用,可以实现控制反转这在大量的J2EE轻量级框架中被用到,比如Spring的依赖注射机制。 (通过注入不同的bean,来得到不同的实现类)
接口与抽象类的区别:
有个概念,但还没有想到具体实现。 对于一些共用的,已经有实现了,可以设计成接口。
上面是抽象类,下面把它转化为接口:
IVehicle.java public interface IVehicle { public void go(Address address); }
CarImpl.java public class CarImpl implements IVehicle{ public void go(Address address) { System.out.println("CarImpl to " +address.getName()); } }
PlameImpl.java public class PlaneImpl implements IVehicle{ public void go(Address address) { System.out.println("PlaneImpl to " + address.getName()); } }
Driver.java ////多态之接口 public void driveI(IVehicle v){ v.go(new Address("杭州(interface)")); }
Test.java ////用接口实现 d.driveI(new PlaneImpl()); d.driveI(new PlaneImpl());
打印结果: PlaneImpl to 杭州(interface) PlaneImpl to 杭州(interface)
多态的三要素:1.继承 2.重写 3.父类引用指向子类对象 以上就是我目前学习中的总结,如有不足之处,还望多多赐教。 (转载请注明出处:[url=http://www.k8764.com]博彩通[/url] [url=http://www.5sfd.com]e世博[/url])
用java读取Properties文件来改变实现类的Demo:public abstract class Vehicle {public abstract void run();}public class Car extends Vehicle{public void run(){System.out.println("with Car");}}public class Broom extends Vehicle {@Overridepublic void run() {System.out.println("Broom");}}test.properties 中:VehicleType=abstractfactory.step4properties.Broom注意:该文件要放在src目录下,且等号两边不可有空格import java.util.Properties;public class Test {public static void main(String[] args) throws Exception{Properties pros = new Properties();///配置文件编译之后放在bin目录下//每个class的类,都会被当作Class对象。getClassLoader:拿到了装载这个Class的装载器///把它当作一个流读进来,默认路径是根目录。读出来之后,把它转化为一个properties对象,然后,等号左边的就是key,等号右边的就是valuepros.load(Test.class.getClassLoader().getResourceAsStream("abstractfactory/step4properties/spring.properties"));String vehicleTypeName = pros.getProperty("VehicleType");System.out.println(vehicleTypeName);///现在,得到的字符串,我们想把字符串代表的类,产生一个对象,用到反射///Class.forName把字符串所代表的表装到内存,newInstance:生成对象,得到的是个ObjectVehicle v = (Vehicle)Class.forName(vehicleTypeName).newInstance();v.run();//只要改变test.properties中的VehicleType=factory.step4Spring.Broom,即可实现改变实现类的功能。}} (转载请注明出处:[url=http://www.k6567.com]e世博[/url][url=http://www.d9732.com]澳门博彩[/url])
用JAVA/JSP做开发很久了,也见过许多朋友做过,有很大一部分用的是MYSQL的数据库,现在MYSQL数据库版本5.0及以上的都已经被用的很广泛了,但一直有一个问题,使刚入门的朋友费劲心思.就是JSP连接MYSQL5数据库的时候的一些中文问题.于是网络上也出现了很多相关的帖子.由些大家对MYSQL5数据库的配制文件MY.INI也有了些了解.甚至一些朋友就直接问:你们的MYSQL是什么编码的?你们的TOMCAT是什么样的编码,可能不是很规范的问法,但说明了编码问题的确影响了大家的使用. 下面的讲解是在MYSQL5.0.18,TOMCAT5.0.28,驱动为mysql-connector-java-3.2.0-alpha-bin.jar及以上版本的情况下测试的 JSP连接数据库的乱码问题,分两部分来看 1 数据库中是不是乱码? 我们需要保证数据库保存的不是"?????"形式的乱码,如何保证呢? 我们在管理MYSQL数据库的时候,需要用一个客户端,无论你用MYSQL-FRONT,EMS SQL Manager for MySQL,还是MYSQL命令行,这些都是客户端,也是程序连接了数据库,我们现在用客户端EMS SQL Manager for MySQL连接数据库,连接的时候一定要设置客户端字符集为GBK或者GB2312,这样你才能知道数据库里面是不是乱码.这一编码设置很重要,不然,就算数据库里是中文,你看到的还是乱码 这样连接后,我们看下我们做测试的表格,里面的汉字就是正常的,这个时候也可以直接在上面的记录中进入中文的修改 若这里没有选择编码的话,一般默认的就是UTF8的了,连接后再看这个表格,就会出现乱码 而这个时候就会出现不能插入中文的问题,若您插入中文的话,就会出现下列错误 这个时候大家什么不要误解,不是不能插入中文,也不是你插入的字符太长, 更改下连接编码就OK了.下面是这个表格的SQL语句 CREATE TABLE `test` ( `name` varchar(100) default NULL, `adesc` varchar(100) default NULL ) ENGINE=InnoDB DEFAULT CHARSET=gb2312; 二.程序连接数据时,也要设置好连接时候的编码,JSP连接MYSQL数据库时候,有个URL参数,jdbc:mysql://localhost:3307/sssdb?user=demoUser&password=demoPwd&useUnicode=true&characterEncoding=UTF-8,在这里需要设置成UTF-8, 下面是连接数据库的程序代码 <%@ page contentType="text/html;charset=GB2312" language="java"%> <%@ page import="java.io.*" %> <%@ page import="java.util.*" %> <%@ page import="java.sql.*" %> <% out.println("您的数据库某表格中的内容如下<br>"); try { Class.forName("com.mysql.jdbc.Driver").newInstance(); String url ="jdbc:mysql://localhost:3307/sssdb?user=demoUser&password=demoPwd&useUnicode=true&characterEncoding=UTF-8"; //testDB为你的数据库名 Connection conn= DriverManager.getConnection(url); Statement stmt=conn.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,ResultSet.CONCUR_UPDATABLE); String sql="select * from test"; ResultSet rs=stmt.executeQuery(sql); while(rs.next()) { out.println("第一个字段内容:<font color=red>"+rs.getString(1)+"</font> 第二个字段内容:<font color=red>"+rs.getString(2)+"</font><br>"); } out.print("数据库操作成功,恭喜你"); sql = "insert into test (name,adesc) values ('中文','汉字')"; stmt.execute(sql); rs.close(); stmt.close(); conn.close(); } catch(Exception e){ System.out.println("数据库连接不成功"+e.toString()); } %>
上面的经验是经过多次尝试总结出来的,不管是MYSQL的客户端还是程序连接MYSQL数据库,在本质上都是程序连接数据库,可以自己在本地多试验下,有时候有可能是驱动太旧. (转载请注明出处:[url=http://www.a9832.com]博彩网[/url] [url=http://www.tswa.org]博彩通[/url])
qtp录制鼠标右键单击事件要通过模拟键盘操作来实现step 1,修改replaytype为2,一般情况默认设置是1的。(1 – 使用浏览器事件运行鼠标操作。 2 – 使用鼠标运行鼠标操作)setting.webpackage(”replaytype”) = 2step 2,鼠标右键单击事件(附:click的事件有三种 micleftbtn 0 鼠标左键。 micrightbtn 1 鼠标右键。 micmiddlebtn 2 鼠标中键)browser(”支付宝 – 网上支付 安全快速!”).page(”支付宝 – 网上支付 安全快速!”).link(”返回我要付款”).click , , micrightbtnstep 3,点击右键弹出的菜单(采用键盘事件来模拟)set wshshell = createobject(”wscript.shell”)wshshell.sendkeys “{down}” //键盘向下的箭头wshshell.sendkeys “{down}”wshshell.sendkeys “{enter}” //回车键step 4,修改replaytype为1(使用浏览器事件运行鼠标操作)setting.webpackage(”replaytype”) = 1good to go now. (转载请注明出处:[url=http://www.live588.org]淘金盈[/url][url=http://www.10086money.com]时尚资讯[/url])
摘要: $("#父窗口元素ID",window.parent.document); 对应javascript版本为window.parent.document.getElementByIdx_x("父窗口元素ID"); 取父窗口的元素方法:$(selector, window.parent.document); 那么你取父窗口的父窗口的元素就可以用:$(selector, w... 阅读全文
摘要: C#代码 using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawin... 阅读全文
|