在Xpage中使用连接池

14 篇文章 0 订阅

        在很久很久以前,笔者曾经发布过一篇小文《Domino支持连接池技术》。那篇文章借用了JnpServer,实用性并不强。在后来的开发实践中学习了一位开发人员实现的连接池技术,并成功用在了Domino平台上,效果很不错,不敢独享!

        这个版本采用了Java的单例模式,将连接池管理者常驻于内存,这样只要是基于DominoJVM的java 代码都可以调用,方便快捷,性能接近Java平台。

        现在用Designer开发Domino的应用越来越像Java项目。在Designer的导航器视图的左侧,仔细看NSF数据库应用的目录结构,是不是非常像一个Java项目?或者说就是一个Java项目。在这些目录结构中,我们要关注的其实是WebContent目录。这分明就是一个Web项目啊。本篇文章所讲述的技术实现也是得益于Designer的进步。

1. 寻找classpath

        本篇所讲的链接池或者是Java平台的连接池都要读取一个配置文件,那么本文中需要的配置文件是db.properties。Java平台是放在{classpath:}目录下,一般就是resources目录。但对于Domino项目来说,肯定不是Resources目录。那么到底在哪里那?在左侧的项目导航里,我们会发现一个文件:build.properties。这个文件是不是没见过?从文件名可以猜测,这是编译的配置参数。太可疑了,打开看看。

source.. = Local/,\

           Code/Java/

output.. = WebContent/WEB-INF/classes/

果然是编译的配置参数。看output,这是java代码编译后放的目录,跟java项目一致。笔者将配置文件放在了classes目录下。悲剧了!

        笔者以为就是这个目录,然后执行了项目的清理操作,然后,什么都没了!再回头看build.properties,是output目录,一切都明白了,这是输出目录,清理操作时要清空的。真是实践出真知啊!那么相对的source就是来源目录了。先试试Local目录,将配置文件拷贝至Local目录下,然后执行清理同时编译,果然配置文件已经被编译进了output指向的目录中。似乎可以结案了。但是笔者还要做个实验,Local目录也是很可疑的,为什么叫Local而不叫其他的?

        笔者将数据库新建了一份拷贝至本地,然后在Designer中打开。再打开Local目录,好了,配置文件没有了。果然命名为Local是有原因的。如此,只能用Code/Java这个目录了。实际上也是,笔者将配置文件拷贝至此目录后,output目录中就出现了相同的文件。一切尘埃落定,终于找到了我们需要的目录来存放配置文件。

        花了这么多时间和精力,为的是什么?其实之前可以将配置文件直接放到domino的程序目录中,java程序也可以读取到。但是这样操作,维护比较麻烦,修改一个参数还需要连接操作系统。尤其是大企业中,访问生产系统是件很麻烦的事情。因此如果能将配置于自己可以管理的范围内,能省很多事。至少放到NSF库中,改起来很方便。

        最后我们还要测试一下,链接池能否在output中读取到配置文件,这样才算完成第一步工作。但是怎么做那?我们试着编写一段程序,让它能访问db.proerties文件就可以了。在本文中使用了Xagent,那是什么?简单说来就是把Xpage做成了Servlet。具体实现方法,不在本文讨论的范围内,如果需要,读者可以在回复中提出要求。好了,我们继续。笔者的思路是利用Xagent访问Java程序,由Java程序通过classLoader获取路径并在此路径下访问db.properties

getClass().getClassLoader().getResource("db.properties").getPath();

我们看看输出是什么:

/app/poolsmanager.nsf/WEB-INF/classes/db.properties

取到了,那也就是意味着在Domino平台下也可以像Java项目那样操作配置文件了。

  2.  jar包放哪了?

传统的jar包都是放在JVM 目录的lib\ext目录下,部署应用时还是比较麻烦的。在Domino新版本明显要向Java项目靠拢,那么有没有可能jar的管理模式也要同Java项目一致那?

打开导航器,在WebContent目录下有个WEB-INF目录,挺熟悉的啊。再开发WEB-INF,有两个目录classes,lib。classes目录不用说了,编译后的输出目录。这个lib目录不就是Java项目中的第三方jar包吗?放几个jar包进去看看,能不能访问到,确认一下jvm的ext下没有此项目需要的jar包,免得弄混了。

在资源管理器中选中需要的jar包,再选择lib目录,将jar包拷贝进来。编写一段java程序测试一下。Xagent中输出到终端的都是JSON数据,所以先试试JSON转换的工具包fastjson吧。

拷贝fastjson-1.2.80.jar包到lib目录下,然后在Code/Java目录下新建一个Pojo类,再新建一个应用类,在这个类中创建Pojo实例,并返回实例的JSON数据。

public String getJSON(){

App app = new App();

app.setAppname("App1");

app.setAppserver("AppServer");

return JSON.toJSONString(app);

}

新建一个Xpage,改成Xagent模式,调用这个应用类。

sjson = poolsService.getJSON();

writer.write(sjson);

writer.endDocument();

切换到浏览器中,输入访问Xpage的URL地址,看看输出是什么:

{"appname":"App1","appserver":"AppServer"}

输出的是我们想要的JSON数据,那么看来这个lib目录跟笔者的猜想是一致的,那这样比部署到ext目录下要方便多了,至少不用重启服务器了。

3. 让连接池跑起来

两个最基本的问题解决了,连接池也更有希望了。笔者准备的运行环境是Dommino12.0 ,关系数据库是MySQL8.0。在代码/Java新建Java类空体(不能直接引入Java类),再将DBConnectionManager.java代码拷贝进去。编写一个调用连接池的Java类,编写调用连接池的方法:

public String getMySQLData(){

String sSQL = "SELECT * FROM `ry-cloud`.sys_menu;";

    List<SysMenu> menulist = new ArrayList<SysMenu>();

    Result result;

    try{

     dbmanager = DBConnectionManager.getInstance();

     Connection conn = dbmanager.getConnection("jtds_root");

            Statement stmt = conn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);

            ResultSet rs = stmt.executeQuery(sSQL);

           

            while(rs.next()){

             SysMenu menu = new SysMenu();

             menu.setMenuId(rs.getLong("menu_id"));

             menulist.add(menu);

            }

            rs.close();

            stmt.close();

     dbmanager.freeConnection("jtds_root", conn);

     result = Result.ok(menulist);

    }catch(Exception e){

     e.printStackTrace();

     result =  Result.error(e.getMessage());

    }

    return JSON.toJSONString(result);

}

Java类建好了,要面向HTTP协议编写访问接口。

新建一个Xpage,修改为Xagent。然后在它的afterRenderResponse事件中编写调用连接池的代码,返回JSON结构数据即可:

var externalContext = facesContext.getExternalContext();

var writer = facesContext.getResponseWriter();

var response = externalContext.getResponse();

var request = externalContext.getRequest();

  

// Set content type

response.setContentType("application/json");  

response.setHeader("Cache-Control", "no-cache");

var sjson = "";

var poolsService = new PoolsManagerService(session,sessionScope);

sjson = poolsService.getMySQLData();

writer.write(sjson);

writer.endDocument();

在浏览器中访问这个接口,正常情况下回返回一个JSON的数据集。反复刷新这个地址,也不会反复创建到mysql的连接,而是从连接池中取可用连接反复使用。

文中代码链接:

DBConnectionManager.java

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
XPAGE学习笔记 1 Theme 2 2 在Xpage使用Dojo 2 2.1 加载dojo.js 2 2.2 设置应用程序主题引入tundra.css 2 2.3 设置xpage属性引入dojo模块 3 2.4 Xpage的页面html代码 4 2.5 在xpage使用dojo编程 4 2.5.1 按钮(dijit.form.Button) 4 2.5.1.1 通过插入<div>标签生成dojo按钮 5 2.5.1.2 使用xpage按钮控件 7 2.5.1.3 在按钮控件上使用事件处理程序控件 7 2.5.2 Xpage使用 Spinner(dijit.form.NumberSpinner) 9 2.5.3 在xpage使用ProgressBar(dijit.ProgressBar) 10 2.5.4 在Xpage使用树(dijit.Tree) 10 2.5.4.1 JSON与XML数据源 11 2.5.4.2 Box树与Order树 12 2.5.4.3 对树进行添加、删除及重命名操作 13 2.5.4.4 将树的操作记录到后台数据库 14 2.5.4.5 树的拖放 15 3 在Xpage如何查找控件 16 3.1 理解document.getElementById 16 3.2 理解dojo.byId 17 3.3 理解dijit.byId 17 3.4 理解XSP.getElementById 17 3.5 理解getComponent 17 4 Xpage VS 表单 18 5 使用oneui主题 18 6 参考 18 6.1 JSON与String转换 18 6.2 XPage调试代码 18 1 Theme 主题在Domino的路径:D:\IBM\Lotus\Domino\xsp\nsf\themes 2 在Xpage使用Dojo  Xpage自动加载dojo.js  通过设置应用程序主题将tundra.css引用到xpage  设置xpage属性,引用dojo模块  在xpage使用dojo编程 2.1 加载dojo.js Xpage会自动加载dojo.js,默认情况下xpage自动查找data\domino\js下的最新版本。也可以通过设置xsp.properties文件来修改dojo版本,重命名xsp.properties.sample 文件(D:\IBM\Lotus\Domino\data\properties\ xsp.properties.sample) 2.2 设置应用程序主题引入tundra.css 通过设置应用程序主题将tundra.css引用到xpage 2.3 设置xpage属性引入dojo模块 2.4 Xpage的页面html代码 2.5 在xpage使用dojo编程 2.5.1 按钮(dijit.form.Button)  通过插入<div>标签生成dojo按钮  使用xpage按钮控件  在按钮控件上使用事件处理程序控件 2.5.1.1 通过插入<div>标签生成dojo按钮 第一步:在xpage插入<div dojoType=”dijit.form.Button” id=”dojoBtn”></div> 第二步:在xpage插入<xp:scriptBlock></xp:scriptBlock> 第三步:编写客户端javascript <div dojoType="dijit.form.Button" id="dojoBtn"></div> <xp:scriptBlock> <xp:this.value><![CDATA[function showDia(){ var dia = new dijit.Dialog({title:"dojo按钮演示",style:"width:150px"}); var pane = document.createElement("div"); pane.innerHTML = "<span>Hello Dojo!</span>"; dia.setContent(pane); dia.show(); } function btnDemo(){ var dojoBtn = dijit.byId("dojoBtn"); var dojoBtnNode = dojo.byId("dojoBtn"); dojoBtn.setLabel("Dojo Button"); // dojo.connect(dojoBtn.domNode,"onclick","showDia"); dojo.connect(dojoBtnNode,"onclick","showDia"); } dojo.addOnLoad(btnDemo);]]></xp:this.value> </xp:scriptBlock> 2.5.1.2 使用xpage按钮控件 <xp:button id="button1" value="按钮控件"> <xp:this.onclick> <![CDATA[ var dia = new dijit.Dialog({title:"提示:",style:"width:150px;"}); var pane = document.createElement("div"); pane.innerHTML = "<span>dojo按钮演示!</span>"; dia.setContent(pane); dia.show(); ]]> </xp:this.onclick> </xp:button> 2.5.1.3 在按钮控件上使用事件处理程序控件 将事件处理程序控件拖放到按钮控件上 2.5.2 Xpage使用 Spinner(dijit.form.NumberSpinner) <xp:inputText id="numSales"></xp:inputText> <xp:scriptBlock> <xp:this.value><![CDATA[ dojo.addOnLoad(function(){ new dijit.form.NumberSpinner({ name:"#{id:numSales}", value:50, smallDelta:1, min:0, places:0},XSP.getElementById("#{id:numSales}")); }); ]]></xp:this.value> </xp:scriptBlock> var myvalue = "#{javascript: var value; if(getComponent("numSales").getValue() != null){ value = getComponent("numSales").getValue().intValue(); }else{ value = 50; } return value.toFixed(0);}"; new dijit.form.NumberSpinner({name:"#{id:numSales}", value:myvalue, smallDelta:1, constraints:{min:0,places:0}}, XSP.getElementById("#{id:numSales}")); 2.5.3 在xpage使用ProgressBar(dijit.ProgressBar) <div dojoType="dijit.ProgressBar" style="width:300px" jsId="jsProgress" id="div1"> </div> <xp:button value="Start" id="button2"> <xp:eventHandler event="onclick" submit="false"> <xp:this.handlers> <xp:handler type="text/javascript"> <xp:this.script><![CDATA[ var numParts = Math.floor(100/7); jsProgress.update({ maximum: numParts, progress:0 }); for (var i=0; i<=numParts; i++){ setTimeout("jsProgress.update({ progress: " + i + " })",(i+1)*100 + Math.floor(Math.random()*100)); } ]]></xp:this.script> </xp:handler> </xp:this.handlers> </xp:eventHandler> </xp:button> 2.5.4 在Xpage使用树(dijit.Tree)  JSON与XML数据源  Box树与Order树  对树进行添加、删除及重命名操作  将树的操作记录到后台数据库  树的拖放 2.5.4.1 JSON与XML数据源 box.json文件 { identifier:'id', label:'name', items:[ {id:1,name:"盒子1",type:"box",weight:0} ] } order.xml文件 <orders> <order> <orderNumber>001</orderNumber> <description>订单001</description> <priority>航运</priority> <line> <orderNumber>001-1</orderNumber> <qty>1</qty> <sku>11761</sku> <description>精通DOJO</description> </line> <line> <orderNumber>001-2</orderNumber> <qty>3</qty> <sku>11789</sku> <description>项目管理那些事儿</description> </line> </order> <order> <orderNumber>002</orderNumber> <description>订单002</description> <priority>快递</priority> <line> <orderNumber>002-1</orderNumber> <qty>10</qty> <sku>11763</sku> <description>精通J2EE</description> </line> <line> <orderNumber>002-2</orderNumber> <qty>30</qty> <sku>11799</sku> <description>超越对手</description> </line> </order> </orders> 2.5.4.2 Box树与Order树 <div dojoType="dojo.data.ItemFileWriteStore" jsId="boxStore" url="/tree/box.json"> </div> <div dojoType="dojox.data.XmlStore" jsId="orderStore" label="description" keyAttribute="orderNumber" url="/tree/order.xml"> </div> <div dojoType="dijit.tree.ForestStoreModel" jsId="boxModel" store="boxStore" rootLabel="退货物品" childrenAttrs="orders,items"> </div> <div dojoType="dijit.tree.ForestStoreModel" jsId="orderModel" store="orderStore" rootLabel="订单" childrenAttrs="line,order"> </div> <xp:td style="height:200.0px" valign="top"> <xp:panel> <div dojoType="dijit.Tree" id="boxTree" model="boxModel"> <script type="dojo/method" event="onClick" args="item"> lastBoxSelected = item; </script> </div> </xp:panel> </xp:td> <xp:td style="height:200.0px" valign="top"> <xp:panel> <div dojoType="dijit.Tree" id="orderTree" model="orderModel"> </div> </xp:panel> </xp:td> 2.5.4.3 对树进行添加、删除及重命名操作 <xp:table> <xp:tr> <xp:td> <div dojoType="dijit.form.Button" id="addBtn"> 添加 <script type="dojo/method" event="onClick"> boxStore.newItem({id:2,name:"盒子2",type:"box",weight:0,orders:[]}); </script> </div> </xp:td> <xp:td> <div dojoType="dijit.form.Button" id="delBtn"> 删除 <script type="dojo/method" event="onClick"> if(boxStore.isItem(lastBoxSelected)){ boxStore.deleteItem(lastBoxSelected); } </script> </div> </xp:td> <xp:td> <div dojoType="dijit.form.Button" id="reBtn">重命名 <script type="dojo/method" event="onClick"> if(boxStore.isItem(lastBoxSelected)){ boxStore.setValue(lastBoxSelected,"name","新盒子"); } </script> </div> </xp:td> </xp:tr> </xp:table> 2.5.4.4 将树的操作记录到后台数据库 <div dojoType="dojo.data.ItemFileWriteStore" jsId="boxStore" url="/tree/box.json"> <script type="dojo/connect" event="onNew" args="newItem"> var itemId = this.getValue(newItem,"id"); var itemName = this.getValue(newItem,"name"); dojo.xhrPost({ url:"agCreateNewBox?OpenAgent", content:{id:itemId,name:itemName}, timeout:10000, error:function(){alert("对不起,出错啦!");}, load:function(){alert("数据保存成功!");console.debug("数据保存成功!");} }); </script> <script type=”dojo/connect” event=”onDelete” args=”delItem”> </script> </div> 2.5.4.5 树的拖放 要使树具有拖放功能,仅仅需要设置dndController属性(dijit._tree.dndSource已废弃): 要限制拖放的行为,仅仅需要实现checkAcceptance或checkItemAcceptance处理函数即可: 以上已经实现了树的拖放功能了! 但是,如果要将拖放的结果保存起来,也就是说要改变树的模型并将模型数据保存,那么应该编写onDndDrop的处理函数(通过增加jsId获得dndController会出现this.avaria is null 错误,所以下面通过小部件初始化时将dndController传递给变量controller): 在boxDrop与checkAcceptance一样可以得到target与source,另外,onDndDrop的source与nodes有些相似source.selection[something]=nodes[somethin] 结合ItemFileWriteStore 可以实现对模型数据的保存 3 在Xpage如何查找控件 3.1 理解document.getElementById 得到node,创建node可以用document.createElement 这样访问或设置节点的所有属性 node.innerHTML = “” node.value=”” var id = node.id var style = node.style 3.2 理解dojo.byId 得到node,也可以通过dijit.byId().domNode得到节点 dojo.byId(“myid”).value dojo.byid(“myid”).id dojo.attr(node,attribute) 如读取dojo.attr(node,”id”) dojo.attr(node,attribute,value) 如设置dojo.attr(node,”id”,”myid”) dojo.hasAttr(node,attribute) 如判断 dojo.hasAttr(node,”id”) dojo.connect(node,”onclick”,handler) dojo.removeClass(node,”myclass”) 3.3 理解dijit.byId 得到dojo控件对象,也可以通过dijit.byNode(dojo.byId())得到对象 不同的控件的getValue()返回值类型不一样 在xpage对于<div>标签可能使用期dijit.byId(“myid”),对于<xp:>标签是不可以的 dijit.byId().getValue() dijit.byId().setValue() 3.4 理解XSP.getElementById 这是XSPClientDojo 库定义的,XSP全局变量相当于document对象,为客户端访问xpage控件提供方法 XSP.getElementById(“#{id:myid}”)使用JSF表达式查询控件 var xid = XSP.getElementById(“#{id:myid}”) xid.value = “myvalue” xid.name = “myname” xid.disabled = false 3.5 理解getComponent javascript服务器端访问控件 getComponet(“myid”).getValue(); getComponet(“myid”).getSubmittedValue(); getComponent(“myid”).setValue(); getComponent(“myid”).setSubmittedValue(); 4 Xpage VS 表单 5 使用oneui主题 6 参考 6.1 JSON与String转换 dojo.fromJson(string) 返回json对象 dojo.toJson(object) 返回string对象 eval(‘(‘+string+’)’) 返回json对象 6.2 XPage调试代码 window.alert 函数不可用于服务器脚本。 使用以下函数写入服务器上的 console.log(例如 C:\Notes\Data\IBM_TECHNICAL_SUPPORT\console.log): print(string) 写入一个字符串。 _dump(object) 写入表示对象的字符串。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值