Hafeyang's Tech Space

Hafeyang目前从事销售领域系统开发,长于前端开发。乐意分享。

2010年1月12日 #

Spring+CXF配置HTTP代理访问Internet

一个典型的CXF Webservice项目部署到正式环境后,服务器不能访问外网,只能通过代理访问外网,找了很多资料,刚开始想法是不用Spring的配置文件,直接用java编程访问webservice。在java的Http请求中使用代理的方法如下:

String authentication="username:password";//用户+”:”+密码
        String encodedLogin= new BASE64Encoder().encode(authentication.getBytes());
        Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress("IP", PORT));
        
        HttpsURLConnection conn = (HttpsURLConnection) console.openConnection(proxy );
        conn.setRequestProperty("Proxy-Authorization", " Basic " + encodedLogin);

使用JaxWsProxyFactoryBean创建client

System.setProperty("http.proxySet", "true");
        System.setProperty("http.proxyHost", "IP");
        System.setProperty("http.proxyPort", "PORT");
        
        JaxWsProxyFactoryBean f = new JaxWsProxyFactoryBean();
        f.setAddress("THE URL OF WEBSERVICE");
        f.setServiceClass(IService.class);
        IService client = (IService) f.create();

可以使用代理,但是用户名密码是不能像第一种方法中那样设置到HttpConnection里面去的。

又在网上找了很多资料,终于找到了一个配置的方法。

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" 
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
        xmlns:cxf="http://cxf.apache.org/core" 
        xmlns:sec="http://cxf.apache.org/configuration/security" 
        xmlns:http-conf="http://cxf.apache.org/transports/http/configuration" 
        xsi:schemaLocation=" 
                http://www.springframework.org/schema/beans
                http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
                http://cxf.apache.org/core http://cxf.apache.org/schemas/core.xsd
                http://cxf.apache.org/configuration/security
                http://cxf.apache.org/schemas/configuration/security.xsd
                http://cxf.apache.org/transports/http/configuration
                http://cxf.apache.org/schemas/configuration/http-conf.xsd"> 
        <http-conf:conduit name="*.http-conduit"> 
            <http-conf:proxyAuthorization>
            
                    <!-- 用户名 -->
                    <sec:UserName>***</sec:UserName>
                    <!-- 密码 -->
                    <sec:Password>***</sec:Password>
                    
             </http-conf:proxyAuthorization>
            <!--
                ProxyServer IP                ProxyServerPort PORT
                ProxyServerType: HTTP or SOCKS
             -->
            <http-conf:client
                    ProxyServer="192.168.1.4" 
                    ProxyServerPort="808"
                    ProxyServerType="HTTP"
                    Connection="Keep-Alive" 
                    AllowChunking="false"
                    ConnectionTimeout="50000" 
                    ReceiveTimeout="120000"
                    /> 
    </http-conf:conduit> 

    <!-- Client   -->
    </beans>

<http-conf:conduit name="*.http-conduit"> 这里的name为”*.http-conduit”时,将会对所有的client类启用这个代理,如果要配置某个client类使用代理,可以这么写

<http-conf:conduit name="{http://widgets/widgetvendor.net}widgetSOAPPort.http-conduit>
    ...
  </http-conf:conduit>

{}里面的内容是webservice的wsdl的<wsdl:definitions name="serviceName" targetNamespace="http://hafeyang.blogjava.net"的targetNamespace属性

{}之后.之前的内容是

<wsdl:port name="BasicHttpBinding_IService" binding="i0:BasicHttpBinding_IService">

<soap:address location="the address" />

</wsdl:port>

的name属性。

上述wsdl对应的配置是

<http-conf:conduit name="{http://hafeyang.blogjava.net}BasicHttpBinding_IService.http-conduit> ... </http-conf:conduit>

参考资料

http://fusesource.com/docs/framework/2.2/bind_trans/HTTPConsumerConfig.html

http://topic.csdn.net/u/20090331/09/f3ce02e0-29be-40cc-a534-9f2e5ac23f9e.html

http://old.nabble.com/http:conduit-Proxy-td20462360.html

http://mail-archives.apache.org/mod_mbox/servicemix-users/200807.mbox/<4885FCBB.5070506@gmail.com>

posted @ 2010-01-12 17:10 阳衡锋 阅读(93) | 评论 (0)编辑 收藏

2010年1月9日 #

Oracle索引,真的用上了么?

最近发现了一个Oracle索引的小细节。

如果索引是建立在多个列上, 只有在它的第一个列(leading column)被where子句引用时,优化器才会选择使用该索引。

这也是一条简单而重要的规则。见以下实例。

SQL> create table multiindexusage ( inda number , indb number , descr varchar2(10));

Table created。

SQL> create index multindex on multiindexusage(inda,indb);

Index created。

SQL> set autotrace traceonly

SQL> select * from multiindexusage where inda = 1;

Execution Plan

----------------------------------------------------------

0 SELECT STATEMENT Optimizer=CHOOSE

1 0 TABLE ACCESS (BY INDEX ROWID) OF 'MULTIINDEXUSAGE'

2 1 INDEX (RANGE SCAN) OF 'MULTINDEX' (NON-UNIQUE)

(只使用索引的第一个字段查询,可以利用索引)

SQL> select * from multiindexusage where indb = 1;

Execution Plan

----------------------------------------------------------

0 SELECT STATEMENT Optimizer=CHOOSE

1 0 TABLE ACCESS (FULL) OF 'MULTIINDEXUSAGE'

(只使用索引的第二个字段查询,将不会利用索引)

很明显, 当仅引用索引的第二个列时,优化器使用了全表扫描而忽略了索引。

posted @ 2010-01-09 11:12 阳衡锋 阅读(54) | 评论 (0)编辑 收藏

2009年12月25日 #

架构之路(3)-永恒的话题-CRUD

前面说过所谓的业务大多数是crud。那从这个入手,我发现要把这个配置出来,配置的结果不言而喻,能生成crud的页面。我们其实只需要一些元数据(meta information)。元数据就相当于我们平常用的hibernate 里面的cfg.xml之类的东西。用来描述实体/字段的一些信息。从业务的需要来讲,单凭这个xml的配置还不能生成crud的页面。还需要很多的信息。下面是这些字段信息的整理。

TABLENAME

表名
TCOLUMNSNAME 表字段名
TCOLUMNSTYPE 表字段类型
ECOLUMNSNAME 实体字段名
ECOLUMNSTYPE 实体字段java类型
COLUMNSLENGTH 字段长度
COLUMNSNULLABLE 是否允许为空
ISPRIMARYKEY 是否主键
STATE 启用状态
DESCRIPTION 描述
COLUMNID 字段序号
LABELTEXT 字段label名称
DEFAULTVALUE 字段默认值
CANSEARCH 是否为查询字段
SEARCHINPUTTYPE 查询呈现方式,文本框/下拉框/..
SEARCHOPERATOR 默认查询运算符,等于/大于/..
FORMAT 字段显示格式,日期格式/小数格式/货币格式
CSSCLASS 呈现css class
READONLY 编辑时是否只读
EDITINPUTTYPE 编辑呈现方式 文本框/下拉框/..
CREATESHOW 新增时是否显示
UPDATESHOW 更新时是否显示
VIEWSHOW 查看时是否显示
BLANKMSG 值为空警告
VALIDATETYPE 校验类型,小数/整数/正整数/..
INVALIDMSG 校验不通过警告
MAPPING 数据字典,其实就是配置下拉框的通用的数据源。比如通常{1:是,0:否}。
MAXVALUE 最大值
MINVALUE 最小值
VALIDATEOP 校验比较类型
VALIDATETO 校验比较对象表达式
VALIDATEREGEXP 校验正则表达式
VALIDATEIF 校验禁用条件
CTABLE 约束表,这4个属性生成下拉框数据源。
CCOEDECOLUMN 约束值字段
CVALUECOLUMN 约束文本字段
CCONDITION 约束文本字段

我估计很多人看了这些属性后笑了,的确,很多人这么做过。后来发现这样做很不灵活,无法满足需要,其实这个问题很简单,为什么不应用一种表达式,ognl,el之类的表达式放在配置项里,这些属性就灵活很多。siebel这样的产品,不也有一些地方需要些一个脚本,比如escript之类的东西么。想想我们天天琢磨的业务,不就是这些东西么。把它配置到数据库里面,接下来就是怎么生成页面的么。我看到的目前大多数的做法是做一个代码生成器,我认为这种做法很不好,代码生成器本身是解决了很多机械活,但是关键还是你生成的代码本身的质量。没错,你可以用代码生成器去免去上万行代码要手写的尴尬,我不仅要问,为什么会弄成上万行的代码?有的人还喜欢吹嘘我写过上万行的Java代码,我更是嗤之以鼻,这不是你的骄傲,这恰是你的悲哀。上万行的代码,我见过的有两种可能性,一个是java/jsp代码没有重构,没有封装。二是数据库的设计有问题,一个表200个字段,页面能不复杂么。第一种是架构师要解决的问题,第二种那据是设计时要注意的事情了。扯远了。界面是怎么出来的。至少不是用代码生成器跑出来的。接触过ruby on rails 或者grails的朋友肯定知道里面的activerecord/scanffold组合快速实现crud。不过他说白了也是在生成页面+改代码,我还是不喜欢。因为界面确实是太灵活。我的思路分两个个方面入手:1.封装字段,根据上述字段属性封装成jsp的tag。这个tag通过字段名读取元数据属性,生成浏览器执行的html,javascript。2:所谓页面不久是指定这个页面有哪几个字段不就得了。查询页面,那几个字段是查询条件,读取字段的查询属性。编辑页面,无非是指定编辑哪些字段就行,在这个基础上做一个小工具,页面就很容易出来。当然,好的框架还要解决一个问题,就是变更。怎样能以最少的代价做变更。这个我是这么想的。比如说,某个表删除一个字段,我们可以提供一个工具查询哪些页面引用了这个字段,然后用程序一并删除,其实这个实现也不难,因为每个字段无非就是jsp页面的一个tag么。大不了用个全文搜索。用正则一替换就完了。

上面是我总结的快速实现crud的一些想法。这部分其实是很多重复性劳动的根源,把这些工夫省下来了。开发效率高很多。

posted @ 2009-12-25 16:52 阳衡锋 阅读(50) | 评论 (0)编辑 收藏

架构之路(2)-我所理解的业务和技术

在过去的开发过程中,我发现所谓的业务,在企业级应用的背景下,最终的实现操作都是数据库的增删改查,或者说通俗点说都是数据库的操作,其他的业务类型多多少少是在围绕数据库的操作。在用户的需求最终转化成设计再到代码的实现。

我这里说的业务可能是一个有别于技术的东西,有些东西纯粹是靠技术来实现的,用户没有概念,跟他说也没有用,比如做接口,你可能用web service 。用TCP通信等等。这些很多是用户是看不见的。

我认为一个比较理想的业务系统应该是业务驾临在技术之上,二者相得益彰。技术需要解决的问题是他有一个平台,能让业务方便的在这个平台上实现。所以我们在做架构的时候要分清楚哪些是业务需要解决的问题,哪些是技术需要解决的问题。

从业务的角度看技术,我希望业务能够非常方便的在这个平台上实现,不仅如此,我还希望我的业务变更了。能够以最少的改动或者不改动就能够实现变更。理想的做法我希望业务都是配置进去的,我在变更的时候只需要修改相应的配置就可以了。当然100%的配置出来也不太现实,据我所知,在sap,siebel里面的报表是必须开发的。因为报表主要是查询,查询就非常灵活,单靠配置能难达到目的。

从技术的角度去看业务,再好的技术加上一个不入流的设计,都为成为教科书上一个很好的反面教材。业务人员需要在对业务的把握上设计软件。

既然要复用,要能够用配置实现业务,那配置些什么东西了?那些地方可以配置。这个就是框架要做的事情了。说到框架大家最喜欢议论的就是怎么快速实现crud了。毕竟,一个系统的很大部分都是在做这个事情。

posted @ 2009-12-25 16:51 阳衡锋 阅读(40) | 评论 (0)编辑 收藏

架构之路(1)-开篇

不知道多久没有更新blog了。一直以来都想写写我在架构方面的思考。在过去的将近两年的时间里,我从一个实习生到一个自称的架构师。我一直在不断的学习,在学习中融入我的思考。

背景

应该说我从事的是企业管理软件开发,blog标题也说了。做销售领域,怎么说现在的客户也是在国内很有名气的。现在的公司也专注的在的企业信息化的工作。我们面对的业务主要是销售领域,我们部门也曾经做过一些不太成功的crm。售前/售后的领域,想想我们天天说的是企业级应用我认为也算得上了。在我的理解里面,企业级的应用在业务上是一个很专业的领域,需要对软件开发商具有相当的业务能力,公司喜欢把我们的业务人员叫业务顾问,大抵的意思就是我们能提供一个行之有效的解决方案吧。这更说明我们对业务要有相当的了解。所以我们可以专注的做一个行业,做一个领域,把这个领域做精做强了,才能主导市场。说大了。这些当然不是我现在考虑的问题。我只是介绍一下我的业务背景。技术方面,用的是j2ee环境。

我们面临的问题

主要还是两个方面吧。一个是业务方面的,需求不确定啦,永远不停止的变更啦,客户的抱怨啦,迟迟不能上线啦。一个方面是技术方面,代码都是copy/paste啦,大量的无聊的重复性劳动,写代码慢慢的成了体力活。其实这些都是大家经常遇到的问题。

我的看法

这些问题都很宽泛,不是我一个在叽叽喳喳几天就能够全部解决的。我想解决的问题是怎样通过技术手段实现业务的实现,从而形成一个高效的复用的解决方案。领导也想把我们的这个领域做成一个解决方案,形成一个产品,可以拿来实施。其实这个与我最自己的目标还是蛮相近的,我也希望我能从0开始做出一个产品,从技术走向市场,这是公司为用户创造价值的更好的体现,也是我个人的能力的体现。

写作计划

这个话题我想说的很多,都是自己在实践中的思考,我的想法是从技术的角度切入,然后到设计,最终我想形成一个我认为比较理想的业务实现框架。下面是这个系列的索引。

posted @ 2009-12-25 15:23 阳衡锋 阅读(46) | 评论 (0)编辑 收藏

2009年5月1日 #

struts2中的mode-driven体验

在很久之前我就体验(所谓体验,就是写一个demo跑跑,算不上学习)过一把struts2。但是我发现虽然struts2相对struts1.x有很大的不同,但是还是没有解决困扰我的这个问题。就是model就究竟怎么写。在一个spring-hibernate-struts的典型项目中,通常会在Hibernate中定义一个pojo实体类做ORM,但是在struts的Action同样要定义model,不会再把那个实体类再写一遍,我觉得很难受,我知道可以在Action里面声明一个实体类,但是这样总觉得不是很优雅,因为在我看来,实体类没有得到很好的复用,我曾经对struts2很冷漠。但是最近了解到struts2里面有一个Model-Driven,虽然对模型驱动开发了之甚少,但是通过自己做的简单的代码,我发现这个世界真的是缺少发现。

这也是第一次用上了maven2,最开始用到maven2是因为他可以管理依赖(dependency),我们只要在maven2的pom.xml 文件中添加一个依赖,maven 就会自动到网上下载struts所依赖的包并设置好classpath。

tip:要使用maven2的eclipse插件m2eclipse必须将eclipse3.4升级到最新的版本,不然会被报错的,update站点为:http://m2eclipse.sonatype.org/update/

新建完项目之后,在项目的右键菜单中 maven2 -> add maven2 management。整个项目的目录结构都会有变化,注意两点,添加了maven2支持后,在build path中的source没有了,需要手动添加文件夹。还有一个问题就是你必须在"Order and export"中将maven dependencies勾上,否则部署tomcat上面的时候会有包缺失。

进入正题:其实model-driven在strtus中的用法没有什么特别的地方。就是在定义Action的时候稍有不同。

 1 public class UserAction  extends ActionSupport  implements ModelDriven{
 2 
 3     private static final long serialVersionUID = 6863420763993646296L;
 4     private User user=new User();
 5 
    
 6     public
 Object getModel() {
 7         return
 user;
 8 
    }
 9 
10     public String execute() {
11         if(this.user.getAge()==20this.user.setAge(22);
12         return SUCCESS;
13     }
14 }

其实变化就是在定义Action的时候实现ModelDriven接口实现getModel方法。注意在声明实体对象的时候需要实例化。但是在jsp页面上也是有不同的。

1 <s:form action="UserAction" theme="css_xhtml">
2     <s:textfield name="name" label="姓名"></s:textfield>
3     <s:textfield name="age" label="年龄"></s:textfield>
4     <s:submit value="GO"></s:submit>
5 </s:form>


如果按照通常的做法在Action中定义一个User对象,那么在jsp页面上文本框的属性就应该是user.name,user.age.这样做显然更加简单。

结论

使用model-driven的方式能够将现有的实体类简单的复用为mvc模型中的model,减少代码。

疑问:虽然解决了这么个问题,但是我还是对struts有些不放心,就是tag生成的html,很难获得dom的id属性,这样给javascript的一些逻辑控制带来了麻烦,这也是我对struts不太放心的地方,不知道大家在这方面是怎么做的。


posted @ 2009-05-01 23:29 阳衡锋 阅读(1364) | 评论 (2)编辑 收藏

2009年4月16日 #

IE 8 css Hack写法备忘

<style type="text/css">
  #hack{ width:200px; height:100px; border: 1px solid red; 
    background-color:blue;/*all browsers */
    background-color:gray\9;/*IE8 IE7 IE6*/
    *background-color:yellow;/*IE7 IE6*/
    _background-color:#ccc;/*IE6*/
    
  }
</style>

效果:

csshack

posted @ 2009-04-16 09:57 阳衡锋 阅读(237) | 评论 (0)编辑 收藏

2009年4月12日 #

企业级b/s应用系统采用怎样的javascript框架

在过去的很长的一段时间,我都从事b/s应用系统开发,我要做的事情就是怎样做界面规范以保证UI风格统一,同时保证开发的高效性。具体而言,我要做的工作需要把css写好,开发者做界面时能方便的写html和样式。可更多的经历我都花在javascript上。

问题一:要不要采用javascript框架?

我刚到公司的时候,我们的技术架构师是不同意使用javascript 框架。理由很多,javascript 没有得到应有的重视是主要的原因,他一直强调我们做的是应用系统。所以他只在网上找到几个js放在项目下面,然后页面上很乱,要写一颗树展现真是麻烦又麻烦。而且大家的javascript水平都很一般,基本只是稍微了解一点。用的最多的还是数据校验,写的方法还是document.form1.formname,document.add['id']之类的写法。这让我这个天天关注界面的技术人员(冒昧自称技术人员,其实只是在界面层上有点研究而已)真是抓狂。很讽刺的是,为了使用一个小窗口弹出错误信息,把jqeury+ui搬出来。整个项目也只有这么一个地方用到jquery,去年的时候jquery的人气正在攀升。我来了之后,由于自己辈分小,在技术上说不上话,后来大家界面上开发的时候遇到这个那个问题解决不了的时候,大家慢慢的认识到了我的价值。新的项目领导让我负责界面规范这块,公司也想把这个项目做成一个产品。经过很多次“力荐”,我终于说服了大家,我们不能再"IE only" 了。

我认为使用的理由: 一,我们要有兼容各种浏览器的能力,现在新的浏览器大战正在打响,将来的浏览器市场还很难说。在css这方面 我借鉴了ext 的兼容思想,在body标签上加上class "IE IE6",这样我们不要使用hack 去兼容浏览器了。对于javascript上,基本上只有IE和非IE的差别了。主流的javascript框架都提供了很好的浏览器支持。二,用javascript框架的目的是提高开发效率。这与主流的javascript不谋而合。三,web应用正在飞速发展,界面层应用越来越复杂,javascript不在一个校验数据的脚本了,ajax的应用能很好的提升用户体验,有些场合使用ajax,用户操作更加方便。举个很简单的例子,很多的记录需要排序,虽然在数据上来看,只要改变排序值能解决问题,但在界面上,难道要用户去填写排序值,这样用户会觉得很难操作,而用上sortable,这个问题不仅简单,而且操作起来不知道清晰多少。我们从传统的c/s走到b/s不仅是因为b/s 不需要安装,升级容易。还是因为b/s具有更前的表现力。

当然,反对使用javascript框架的理由也很尖锐。一,开发人员的水平很难以掌握现有的javascript框架。二,大家坚持认为,其实现在用的javascript的地方还不是很多。从需求上将屈指可数,tree,borderlayout,grid,calendar。

对此,我提出的想法就是,大家如果觉得难以使用的话,我在javascript框架上做一次封装,降低使用难度。第二个理由更好说,虽然现在使用的地方就那么几个,那好,你能拿出更好的方案么。曾经架构师说,我们希望每一个界面控件都是单独的,能单独使用。当然现在的主流javascript 都是这样的。这样,我就在大家仍用怀疑的眼光注视我的时候开始了javascript框架之旅。

问题二:用哪个javascript框架?

这个问题不是在讨论或者争执哪个好哪个不好,未免大家再又争执,我让他们自己找javascript框架,甚至可以把他们最熟悉的拿出来使用。大伙都说没有时间,这样我也不担心有人说后话了。

我把目前主流的javascript分为三类。

诸如:prototype/jquery/mootools这样的javascript框架,只能是javascript工具。他的优势就是扩展性强,社区支持很好,尤其是jquery

第二类就是:yui/ext/dojo/qooxdoo这样的框架。他们是一套全系列的纯客户端的ui解决方案,使用方便,能满足我们的需要。缺点是入口很高,适用于做富客户端。虽然我们现在的应用还是很多,但是还没有到那个地步。

还有一类就是与服务器端技术结合的ajax框架,他只能叫ajax框架,他基本只做数据交换。事实上只要做一个简单的servlet(j2ee)或者HttpHanlder(.Net)再在客户端加以封装,使用起来也是很方便的。所以这类ajax框架我认为不需要考虑。

在我看来,并不是那个框架绝对的好坏,而是什么样的框架能最好的满足你的需求。

论个人阅历上来讲,三类的多个框架我都知道一二。但是我最喜欢jquery,所以使用了jquery了,他的好处就是轻量级,扩展性强,现有的插件足以满足需要。代码非常简介而且执行效率高。于是我找了一大堆jquery插件。再自己封装城稍微简单的方法。本着不重复发明轮子的原则。很多的界面问题都能解决了。

问题三:真的是那样么?

时至2009,项目完了,到了需要再次封装城产品的时候,麻烦也就来了。我发现虽然jquery插件很多,很全,但是由于是百花齐放,我就不想修改里面的代码。慢慢的使用发现很多插件不是很稳定,像jstree,jquery ui 由于先前用的版本比较低,导致很有的bug自己写一些修正。现在回过头来看那时候做的东西,发现新的版本已经修复了这些功能。而换上新版本的jquery,变化还是蛮多,比如jquery.browser就不推荐使用了,怎么办。

将来。

本文就是在使用jquery之后,发现维护工作量也不小的背景下写下来的。我不知道是不是我当初选择jquery是错误的。是不是应该选择ext 之类的有着更强表现能力,更稳定的框架么?现在的代码还是不是那么理想。由于很多的历史原因,大家还在用ecside ,jscalendar。使用ecside是因为历史原因。使用jscalendar是因为jquery还没有一个日历控件能支持时间的。我一个人的精力有限,而且我很多的时间都在写项目代码(说到底还是领导不重视)。我担心我当时做的决定会对将来造成负面影响。

冒昧发在首页上,真诚的希望大家提出自己的看法,在企业级应用系统上界面层应该怎样做,文中的有些观点如有不对的地方还请大家指教

posted @ 2009-04-12 17:25 阳衡锋 阅读(1856) | 评论 (6)编辑 收藏

2009年4月3日 #

Sql server 2000 jdbc 查询分页解决方案

(今天看自己的blog,发现上次更新已经是3-20,坚持每周更新blog! )

之所以要把sql server 2000 jdbc 分页单独来说说,又两个地方还是值得一提,一者是sql server 2000要实现数据库分页是比较麻烦的事情。二者是jdbc查询出多个ResultSet 的取法。

先在项目的classpath中添加msbase.jar,mssqlserver.jar,msutil.jar 怎么来的就不多废话了。需要说的是我最先用的sql server 2005 jdbc驱动sqljdbc.jar放到项目中,后来的程序是报错的。回头想想,报错有理,sql server 2005 已经支持rownum 分页了。

先说说sql server 2000的分页的实现,目前实现方法大概是那三种。我个人还是喜欢使用存储过程,原因是使用非常方便,至于使用的存储过程,这里还是放出来看看,估计大家用的都大同小异。

IF NOT EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'[dbo].[Pr_QueryByPage]') AND OBJECTPROPERTY(id,N'IsProcedure') = 1)
BEGIN
EXEC dbo.sp_executesql @statement = N'create     procedure   [dbo].[Pr_QueryByPage]   
@sqlstr   nvarchar(4000),   --查询sql  
@currentpage   int, --第页记录条数  
@pagesize   int --每页显示记录 
as   
set   nocount   on   
declare   @P1   int, --P1是游标的ID  
@rowcount   int   
exec   sp_cursoropen   @P1   output,@sqlstr,@scrollopt=1,@ccopt=1,@rowcount=@rowcount   output   
select   ceiling(1.0*@rowcount/@pagesize)   as TotalPage,@rowcount as [RowCount] 
set   @currentpage=(@currentpage-1)*@pagesize+1   
exec   sp_cursorfetch   @P1,16,@currentpage,@pagesize     
exec   sp_cursorclose   @P1   
set   nocount   off  ' 
END
GO

这个存储过程的实现,使用了三个系统存储过程sp_cursoropen ,sp_cursorfetch ,sp_cursorclose 从字面上的意思大概是他叫结果集使用游标打开,然后读取其中的@pageSize条记录,所以单从查询上来讲,性能是不及使用select top 之类的实现。

 

使用起来非常容易,exec Pr_QueryByPage 'select * from yourtable',1,10  就可以了麻烦的是他返回的是三张表。第一张表是查询的表,但是没有记录。第二个表一行两列,第一个列是总页数,第二个列是总记录条数。第三张表才是需要的数据。这就造成了取的时候有点小麻烦,因为之前只知道,在.net中可以直接fill(DataSet),然后DataSet里面可取DataTable。但是在jdbc里面我映像中ResultSet 只能容一张表。后来找了一些资料,原来PreparedStatement,CallableStatement,Statement都支持查询返回多个ResultSet ,好了,非常好。 下面是我使用CallableStatemnt取到的结果集。

 

CallableStatement cs = conn.prepareCall("exec Pr_QueryByPage 'select * from ckdmzd',1,10");
            ResultSet rs = null;
            /**
             * execute returns :
             *     true : returns ResultSet(s)
             *  false: returns rows affected
             */
            boolean hasResultSet = cs.execute();
            if(hasResultSet){
                /**
                 * skip the first ResultSet
                 */
                rs=cs.getResultSet();
                /**
                 * second ResultSet : pageCount & recordCount
                 */
                if(cs.getMoreResults()){
                    rs=cs.getResultSet();
                    while(rs.next()){
                        String pageCount=rs.getString(1);
                        String recordCount=rs.getString(2);
                    }
                }
                /**
                 * the thrid one is the paged result
                 */
                if(cs.getMoreResults()){
                    rs=cs.getResultSet();
                    while(rs.next()){
                        // do somthing with ResultSet
                    }
                }
            }

这样就实现了分页,网上很多人测试了,这个方法的性能不及别的方法,这里我要指出的是,别的方法是不能返回总的记录条数的。而要知道总的记录条数,通常需要select count(*) from ( your sql) 这两次查询叫起来的时间未必会少。

总结

使用上述方法实现sql server 2000 jdbc 分页,使用方便,性能还说的过去。我不知道sql server 2005 的查询性能是否又提升。

posted @ 2009-04-03 16:55 阳衡锋 阅读(1186) | 评论 (0)编辑 收藏

2009年3月20日 #

IE8 Web开发新特性

今天发布了IE8简体中文正式版,我在第一时间下载并使用。这篇博文将介绍IE8开发新特性。

W3C标准支持


IE8是一个标准的浏览器。IE8终于通过了acid 的测试,虽然分数不高,但是微软能在标准前让步,实属难得。为了兼容之前浏览器,IE8提供了兼容视图,我用默认的IE8视图浏览了一些网页,还基本正常。我的项目在IE8下页没有问题。

性能改善

IE8每一个标签都是一个独立的进程,这样任何一个标签奔溃都不会影响别的标签,同时IE8提供了奔溃恢复功能。这点总算赶上了别的浏览器。

开发人员工具

IE8自带了 Internet Explorer Developer Toolbar ,可以用F12激活。下面将一一介绍其新特性。

工具栏菜单上多了验证项:

shutcut1

快速切换浏览器模式,包括 IE8 IE7 IE8兼容性 三个试图。

任何一个标签都有搜索功能。可以方便的搜索HTML CSS javascript 文本。

多了标签栏。有四个标签 HTML CSS 脚本 探查器,探查功能与之前的版本无异,只是探查器标签好像没有什么用,和HTML标签的功能是一样的。

在探测了一个DOM节点之后,工具对样式的支持堪比Firebug,同样可以查看currentStyle,跟踪样式:

shutcut3

布局功能是新增的,可以查看DOM的盒模型。

shutcut4

最令人兴奋的是,终于支持脚本调试,下面的篇幅重点介绍脚本调试功能。

要启用脚本调试功能,和之前的版本一样,需要在Internet 选项->高级->"禁用脚本调试" 两个选项不勾选。

我先写了一段简单的调试代码:

window.onload=function (){
    alert(undefinedVar);
}

用浏览器打开后,会提示如下对话框:

shutcut5

点击"是",工具会自动跳至出错处:

shutcut6

和一般的调试器一样,可以单步,逐过程,跳出,运行功能 在局部变量里面可以查看当前scopeChain中的变量值。

还可以添加监视,监视的内容很多,体现了很多IE特性。下面的截图是我监视document的结果:

shutcut7 

还记得以前我们常用alert调试脚本的日子么,忘了他吧,IE8可以直接在代码中敲debugger;了,以前的版本我发现的调试工具当然是visual studio 了,也非常好用,不过体积非常大,装上vs 去调试javascript无疑是大材小用。还好我有.net情节。修改刚才的那个页面:

window.onload=function (){
    dubugger;
    alert(undefinedVar);
}

如果你需要在debugger;处停止运行你的程序,必须将"脚本"标签中的"启动调试"按钮。

 

总结

IE8是一个很好的浏览器,其开发特性也是前所未有的,能支持javascript调试是次版本工具中一大亮点。相信这些新特性能让开发者的的开发更加轻松便利。

posted @ 2009-03-20 15:23 阳衡锋 阅读(1661) | 评论 (6)编辑 收藏

仅列出标题  下一页