mane n tail箭牌 -r -n 如何使用 例子

C语言编程实例100题_百度文库
两大类热门资源免费畅读
续费一年阅读会员,立省24元!
评价文档:
53页免费24页免费8页免费57页免费60页免费4页免费127页免费132页免费39页1下载券192页1下载券
喜欢此文档的还喜欢533页1下载券
C语言编程实例100题|C​语​言
把文档贴到Blog、BBS或个人站等:
普通尺寸(450*500pix)
较大尺寸(630*500pix)
你可能喜欢netty从入门到精通——范例篇(一)_redmine1.1装配_spring jta运用__脚本百事通
稍等,加载中……
^_^请注意,有可能下面的2篇文章才是您想要的内容:
netty从入门到精通——范例篇(一)
redmine1.1装配
spring jta运用
netty从入门到精通——范例篇(一)
netty从入门到精通——实例篇(一)
前面了解了netty的基本用法与几个核心概念,从本文开始会通过一些实例(主要参考源码example包)来进一步学习netty的使用方法以及其中的原理。
先来实现一个简单的功能:服务端如果接收到客户端的连接,则返回字符串”success”,客户端读到该消息打印出来。
服务端的方法改写了第一篇blogNetty从入门到精通—入门篇中的handler,具体如下:
class MyChannelHandler extends SimpleChannelHandler {
public void channelConnected(ChannelHandlerContext ctx,
ChannelStateEvent e) throws Exception {
System.out.println("Channel connected " + e);
Channel ch = e.getChannel();
ChannelBuffer cb = ChannelBuffers.wrappedBuffer("success".getBytes()) ;
ch.write(cb);
客户端的编码如下:
package com.netty.
import java.net.InetSocketA
import java.util.concurrent.E
import org.jboss.netty.bootstrap.ClientB
import org.jboss.netty.buffer.ChannelB
import org.jboss.netty.channel.ChannelH
import org.jboss.netty.channel.ChannelHandlerC
import org.jboss.netty.channel.ChannelP
import org.jboss.netty.channel.ChannelPipelineF
import org.jboss.netty.channel.ChannelStateE
import org.jboss.netty.channel.C
import org.jboss.netty.channel.MessageE
import org.jboss.netty.channel.SimpleChannelUpstreamH
import org.jboss.netty.channel.socket.nio.NioClientSocketChannelF
public class NettyClient {
final static String host = "127.0.0.1";
final static int port = 8080;
public static void main(String[] args) {
Client client = new Client();
client.config(host, port).start();
class Client {
ChannelHandler myHandler = new MyClientHandler();
public Client() {
bootstrap = new ClientBootstrap(
new NioClientSocketChannelFactory(
Executors.newCachedThreadPool(),
Executors.newCachedThreadPool()));
bootstrap.setPipelineFactory(new ChannelPipelineFactory() {
public ChannelPipeline getPipeline() throws Exception {
return Channels.pipeline(myHandler);
Client config(String host, int port) {
this.host =
this.port =
bootstrap.setOption("remoteAddress", new InetSocketAddress(this.host, this.port));
void start() {
bootstrap.connect();
class MyClientHandler extends SimpleChannelUpstreamHandler {
public void channelClosed(ChannelHandlerContext ctx, ChannelStateEvent e)
throws Exception {
System.out.println("Client Channel closed " + e);
public void channelConnected(ChannelHandlerContext ctx,
ChannelStateEvent e) throws Exception {
System.out.println("Client Channel connected " + e);
public void messageReceived(ChannelHandlerContext ctx, MessageEvent e)
throws Exception {
ChannelBuffer buf = (ChannelBuffer) e.getMessage();
byte[] bytes = buf.array();
System.out.println("Client reseived message : " + new String(bytes));
} catch (Exception ex) {
ex.printStackTrace();
依次启动NettyServer、NettyClient。
Server端console打印:
Channel connected [id: 0xcb6626ea, /127.0.0.1:49503 =& /127.0.0.1:8080] CONNECTED: /127.0.0.1:49503
Client端console打印:
Client Channel connected [id: 0xc4c911b3, /127.0.0.1:49503 =& /127.0.0.1:8080] CONNECTED: /127.0.0.1:8080
Client reseived message : success
在Server的处理器MyChannelHandler中,回写消息调用了Channel.write(Object)方法。
Channel ch = e.getChannel();
ChannelBuffer cb = ChannelBuffers.wrappedBuffer("success".getBytes()) ;
ch.write(cb);
既然write方法的参数为Object,为什么这里不能直接传入字符串”success”呢,而是封装到ChannelBuffer类型的对象中,ChannelBuffer是做什么的。概念篇没有提到,而放在这里刚好合适。
NIO中的Buffer
前面提到过,在NIO中同样存在一个缓冲区,叫做ByteBuffer,来配合Channel的使用。在ByteBuffer内部存储数据的实质为一个字节数组,如:final
byte[] hb,并定义了四个标记来管理它。其中包括:mark
&= position &= limit &= capacity。其中capacity用来表示缓冲区的大小;position用来标识下一个可读取或者写入的位置;limit表示读取或者写入的上限位置,如果要在&=limit的位置做读写操作会抛出异常;mark用来记录当前position的值,记录之后position随着读写发生变化,在调用reset()方法时,会将position恢复为mark记录的值。在buffer中提供了很多put、get方法来放入和读取数据,这里不多做介绍,可以查看API。但其中有几个重要的方法需要关注:
flip()方法:在读取或者写入n个字节(position + n & limit)后,position += n。如果是先读取数据到buffer后写入到Channel,必须将position的值回退到起初的值,并且将limit设置为有效位置,才能让读入的数据真正的写入Channel。调用flip()方法后,buffer中的四个标记会发生以下变化:
position = 0;
mark = -1;
clear()方法:同样的,将buffer中的数据写入Channel后,再读取一些数据到buffer中,此时往往需要将各标记的值归位,当做一个新的buffer来使用(当然也有特殊情况)。调用clear()方法后,标记变化如下:
position = 0;
mark = -1;
rewind()方法:如果发现刚才从Channel读取的数据需要重新读取,可以调用该方法。调用后标记变化如下:
position = 0;
mark = -1;
尤其是flip()和clear()方法,在使用的过程中会频繁用到,否则会造成读取和写入的错乱。
ByteBuffer主要有两个继承的类分别是:HeapByteBuffer和MappedByteBuffer。他们的不同之处在于HeapByteBuffer会在JVM的堆上分配内存资源,而MappedByteBuffer的资源则会由JVM之外的操作系统内核来分配。DirectByteBuffer继承了MappedByteBuffer,采用了直接内存映射的方式,将文件直接映射到虚拟内存,同时减少在内核缓冲区和用户缓冲区之间的调用,尤其在处理大文件方面有很大的性能优势。但是在使用内存映射的时候会造成文件句柄一直被占用而无法删除的情况,网上也有很多介绍。
Netty中的Buffer
Netty中使用ChannelBuffer来处理读写,之所以废弃ByteBuffer,官方说法是ChannelBuffer简单易用并且有性能方面的优势。在ChannelBuffer中使用ByteBuffer或者byte[]来存储数据。同样的,ChannelBuffer也提供了几个标记来控制读写并以此取代ByteBuffer的position和limit,分别是:
readerIndex &= writerIndex &= capacity,同时也有类似于mark的markedReaderIndex和markedWriterIndex。当写入buffer时,writerIndex增加,从buffer中读取数据时readerIndex增加,而不能超过writerIndex。有了这两个变量后,就不用每次写入buffer后调用flip()方法,方便了很多。在ChannelBuffer中有几个重要的类继承,如下图:
AbstractChannelBuffer中实现了基本的方法;HeapChannelBuffer是对NIO中heapBuffer的封装,它有两个继承类:BigEndianHeapChannelBuffer和LittleEndianHeapChannelBuffer(试想,我们将一个int类型(32位)的数据放入内存中,内存会以什么样的顺序放入这32位的数据呢?这就分为big-endian和little-endian的字节序,big-endian就是说将数据的高位放在内存地址更小的位置,little-endian是将低位放在内存地址更小的位置,选择和所用硬件和操作系统相同的字节序有利于提高性能);ByteBufferBackedChannelBuffer是对NIO中derectBuffer的封装;DynamicChannelBuffer继承于AbstractChannelBuffer,实现了buffer的自动扩容;CompositeChannelBuffer也是继承于AbstractChannelBuffer,抽象了操作多个buffer的情况,将多个buffer有序的放入数组中,通过计算找出要操作的buffer的下标,而不是将多个buffer复制到一个更大的buffer中;实现WrappedChannelBuffer接口的类主要是对buffer进行进一步的包装,一般由netty框架内部调用;ReplayingDecoderBuffer用于封装了解码时常有的处理,配合ReplayDecoder使用,后面会对编码解码做专门研究。
ChannelBuffer往往由BufferFactory或者ChannelBuffers类来创建实例。
回到本实例,netty在读取到客户端的msg时,根据用户配置的BufferFactory的不同会将消息封装成derectBuffer或者heapBuffer。所以,当我们在接收数据时,pipline中第一个upstreamHandler拿到的msg(e.getMessage())虽然是Object类型,但是肯定是这两种形式的buffer。那么,我们在写回数据的时候能不能直接使用其他类型呢,答案是:pipline中第一个downstreamHandler不能随意的放入其他对象,原因是pipline中downstream事件是从tail端往上执行的,所以第一个downstreamHandler调用的channel.write()或者channels.write()方法传入的object会直接传递给netty底层处理,而在netty的写入出口中,只接收两种类型的对象:ChannelBuffer和FileRegion(FileRegion可用于0-copy的文件传输,一般情况下,应用程序向socket发送文件流时,操作系统需要先将文件的字节流存储到内核缓冲区(file_read_buffer),然后拷贝到用户缓冲区,在由用户缓冲区拷贝到内核缓冲区(socket_buffer)由协议引擎发送。这样会创建四个缓冲区,两次复制的过程。所谓零拷贝是指:内核通过DMA引擎,直接将file_read_buffer的数据copy到socket_buffer中,而在后面的改进中废除了复制的操作,给socket_buffer增加了数据的位置和长度信息描述,直接将数据从file_read_buffer传递给协议引擎。在netty中只有选择NIO模型才能支持0-copy,当然JDK版本或者操作系统不支持也是不行的)。所以本实例先将字符串”success”方法放入到ChannelBuffer中,然后在调用write方法。
再来看看Client端,在接收到数据后也需要从ChannelBuffer中取出字节,然后再转换成我们想要的String。当然ChannnelBuffer提供了很多如何取出一些基本类型数据的方法,在必要的时候可以使用。但是这样还是不太方便,我们能不能直接获得一个String对象呢?这里就可以使用前面介绍过的在pipline中添加一个handler专门用来解码,转换成我们所需要的String类型,再传递给MyClientHandler。
首先添加一个解码的handler:
class StringClientHandler extends SimpleChannelUpstreamHandler {
public void messageReceived(ChannelHandlerContext ctx, MessageEvent e)
throws Exception {
ChannelBuffer buf = (ChannelBuffer) e.getMessage();
byte[] bytes = buf.array();
System.out
.println("Client reseived message and convert it to a String!");
Channels.fireMessageReceived(e.getChannel(), new String(bytes));
} catch (Exception ex) {
ex.printStackTrace();
修改MyClientHandler的messageReceived方法,直接将收到的msg当做字符串来处理。
class MyClientHandler extends SimpleChannelUpstreamHandler {
public void messageReceived(ChannelHandlerContext ctx, MessageEvent e)
throws Exception {
String msg = (String) e.getMessage();
System.out.println("Client reseived message : " + msg);
} catch (Exception ex) {
ex.printStackTrace();
将StringClientHandler放到pipline中的第一个位置:
class Client {
StringClientHandler stringHandler = new StringClientHandler();
public Client() {
bootstrap.setPipelineFactory(new ChannelPipelineFactory() {
public ChannelPipeline getPipeline() throws Exception {
return Channels.pipeline(stringHandler, myHandler);
这样再次运行程序,客户端就会有这样的信息打印出来:
Client reseived message and convert it to a String!
Client reseived message : success
StringClientHandler中首先处理了接收到的ChannelBuffer,然后转换成String,在通过方法Channels.fireMessageReceived(ctx,
String(bytes));向下传递消息。注意这个方法,如果没有调用,对于msg的处理就会到此为止,MyClientHandler将不会运行。Channels为我们提供了很多方法用于向上或者向下传递事件,对应于概念篇中讲到的各种事件。其中以fire开头方法用于upstream事件,而例如write这样的方法主要用于downstream事件。而这些方法往往是成对出现的,例如:fireChannelOpen(Channel
channel)、fireChannelOpen(ChannelHandlerContext
ctx)等,由于这两个方法有不同的参数,造成了流程的不同,如果参数是Channel,则整个流程会从pipline的head
upstreamHandler开始重新执行,如果参数是ChannelHandlerContext,则会直接执行下一个upstreamHandler。同样,write(Channel
channel, Object message)、write(ChannelHandlerContext
ctx, ChannelFuture future, Object message)等方法,出了多了一个future外,和前面的两个方法相同,流程也会相同,如果没有传入ChannelFuture,则会在方法中的第一步中创建一个future来支持netty的异步事件处理机制。
所以,如果我们将Channels.fireMessageReceived(ctx,
String(bytes));改为Channels.fireMessageReceived(e.getChannel(),
String(bytes));则会出现下面的异常:
java.lang.ClassCastException: java.lang.String cannot be cast to org.jboss.netty.buffer.ChannelBuffer
这是因为在第一次接收到数据后,将msg转换为String类了,并调用Channels.fireMessageReceived(e.getChannel(),
String(bytes));,通知pipline从头upstreamHandler开始执行,即执行StringClientHandler.messageReseived,此时msg已经是String类型了,所以转换成ChannelBuffer就会报错。如果在应用程序中没有打印异常信息,而我们应用的日志级别在WARN以上的话,我们将看不到异常信息,所以最好的方式是在handler中实现exceptionCaught方法来处理异常。
redmine1.1装配
redmine1.1安装花了一下午的时间终于把redmine1.1配置通了,由于1.1为11年1月9日才推出的,所以在安装配置的过程中发现很多东西都不兼容,在这我就把我安装的过程说明一下,希望能帮助redmine安装新版本的朋友们. 1.InstantRails-2.0-win:
下载地址:http://rubyforge.org/projects/instantrails/ 2.redmine-1.1.0
下载地址:http://rubyforge.org/projects/redmine/ 3.下载InstantRails,解压缩. 4.下载Redmine,解压缩. 5.将Redmine解压缩的文件夹直接拷贝到InstantRails目录的rails_apps目录下. 6.InstantRails是一个Rails应用的集成包括了ruby运行时需要的Rails框架、PhpMyAdmin、Apache、Mysql等,这样就不需要分别下载需要的东西.其中Apache版本为1.3,主要用于运行phpMyAdmin(Mysql的管理工具).
7.启动InstantRails,在启动的过程中,apche监听的端口号默认为80,也许会与你本地应用程序监听的端口所占用,这时instantRails会提示你修改apche监听的端口,根据自己所好来设置吧,当启动好了你会发现InstantRails已经帮你启动apache与mysql服务了.
8.现在我们进入PhpMyAdmin,打开InstantRails.exe中的I→Configure→database(via PhpMyAdmin)
9.创建数据库,登陆mysql后:使用sql语句创建数据库,create database redmine character set utf8; 10.将config目录下的database.yml.example文件重命名为database.yml
11.往数据库里导入数据,点击InstantRails的界面I→Rails Application→Open Ruby Console Window就会进入rails_apps目录下
cd redmine-1.1.0
rake db:migrate RAILES_ENV="production"
rake load_default_data RAILS_ENV="production"
其中rake db:migrate RAILES_ENV="production"是会创建相关的47个书库表(可以在PhpMyAdmin查看);
rake load_default_data
RAILS_ENV="production"是指明当前项目运行环境为production,中间会提示选择语言,选择zh(中文).
&!--EndFragment--&12.这时你会看见没有反应,会提示你Minssing the i18n 0.4.2 gem.
Please 'gem install -v=0.4.2 i18n',这是提示你安装vsrsion为0.4.2的 i18n,所以按照他的提示就继续在命令行里输入gem install -v=0.4.2 i18n,这时又会报一个错是http response 302 fetching http://gems.rubyforge.org/yaml,我当时安装到这的时候头疼了,后来发现Rails的版本太低了,InstantRails自带的Rails版本是2.3的,这时我们要安装最新版本3.0.3的rails了,输入gem install rails.遭了,又报错了,error installing rails:activesupport requires Ruby version &=1.8.7 这个错一看就明白了吧,就是说安装3.0.3的rails必须要ruby的版本&=1.8.7,然而InstantRails自带的ruby版本为1.8.6的,这时我们要去下载&=1.8.7的Ruby,下载地址:http://www.ruby-lang.org/en/downloads/ 笔者下载的版本为1.9.2,安装好后将ruby1.9.2中的所有文件拷贝到InstantRails下ruby文件下,1.9.2中的文件替换掉IstantRails下ruby的文件.这时我们在输入命令gem install rails,这时看到命令行里已经在给你安装3.0.3版本的Rails了.
13.到这一步我们还要安装一个东西就是rack,因为自带的rack版本为1.0.0,目前最新的版本为1.2.1,但是安装1.2.1的rack会出错,具体什么情况笔者也不是很清楚,反正要求版本必须是1.0.1,在命令行中输入gem install rack -v=1.0.1.
14.再执行一次gem install -v=0.4.2 i18n.
15.以上步骤都成功后,我们再执行rake db:migrate RAILES_ENV="production",遭了,又报错了,错误为:A key is required to write a cookie containing the session data. Use config.action_controller.session = { :key =& "_myapp_session", :secret =& "some secret phrase" } in config/environment.rb,这时我们要执行另外一条指令,rake config/initializers/session_store.rb,执行完这条指令后必须还要安装最新版本的mysql驱动,因为IstantRails自带的mysql不兼容目前的redmine,所以我们在安装新版本的mysql,执行指令gem install mysql,安装的mysql驱动版本为2.8.1.
16.这时我们再执行rake db:migrate RAILES_ENV="production",将会看到成功了,已经将database.yml中的表全部导入到redmine数据库中了,共有47张表.再执行 rake load_default_data RAILS_ENV="production", 会给出一些提示叫你选择语言,输入zh,好了,到此为止我们已经将redmine安装成功了.
17.启动redmine服务,进入redmine目录下,输入ruby script/server -e production,这时redmine服务已经开启了,在浏览器中输入http://localhost:3000进入你的redmine服务世界吧.
最后再根据自己的需要来增加相应的redmine服务吧.
fanfq 写道
为什么我装的redmine当多人访问的时候会很卡,要等好长时间才能刷新一次页面。
你是用的sqlite数据库吗?换成mysql或者PostgreSQL试试。
用的mysql。其他的也不会用。
fanfq 写道
为什么我装的redmine当多人访问的时候会很卡,要等好长时间才能刷新一次页面。
你是用的sqlite数据库吗?换成mysql或者PostgreSQL试试。
用的mysql。其他的也不会用。
服务器只开一个进程吧?
很好,刚好正在配这个,按照楼主的步骤成功了,为了避免有人和我一样近视:创建表的命令里 rake db:migrate RAILES_ENV="production"RAILES_ENV 应为 RAILS_ENV
我的错,确实在写文章的时候疏漏了,改一下就好.选择语言的时候rake load_default_data RAILS_ENV="production"这个命令会提示该指令过时了,应该用rake redmine:load_default_data RAILS_ENV="production"
不妨试下bitinami redmind
bitinami redmine 目前里附的redmine的版本最新的好像是1.0的吧,1.1有很多新功能的.
不妨试下bitinami redmind同推荐。5分钟内绝对可以安装成功,运行起来。
fanfq 写道
fanfq 写道
为什么我装的redmine当多人访问的时候会很卡,要等好长时间才能刷新一次页面。
你是用的sqlite数据库吗?换成mysql或者PostgreSQL试试。
用的mysql。其他的也不会用。
服务器只开一个进程吧?
是默认的服务器性能太差,换mongle?就好
atian25 写道
不妨试下bitinami redmind同推荐。5分钟内绝对可以安装成功,运行起来。
还是这个最省心,100多m有点大,不过不用折腾。分享地址:http://bitnami.org/files/stacks/redmine/1.1.1-0/bitnami-redmine-1.1.1-0-windows-installer.exe
请教:我按照原帖1-17步安装,在设数据库为中文时报错,“再执行 rake load_default_data RAILS_ENV="production", 会给出一些提示叫你选择语言,输入zh,”“rake aborted!
can't convert ActiveRecord::RecordInvalid into String”详细见如下:&------------------------------------------------F:\installInstantRails\rails_apps\redmine-1.1.0-&rake redmine:load_default_dataRAILS_ENV="development"(in F:/installInstantRails/rails_apps/redmine-1.1.0-)Select language: bg, bs, ca, cs, da, de, el, en, en-GB, es, eu, fi, fr, gl, he,hr, hu, id, it, ja, ko, lt, lv, mk, mn, nl, no, pl, pt, pt-BR, ro, ru, sk, sl, sr, sr-YU, sv, th, tr, uk, vi, zh, zh-TW [en] zh====================================rake aborted!can't convert ActiveRecord::RecordInvalid into StringF:/installInstantRails/rails_apps/redmine-1.1.0-/vendor/rails/activesupport/lib/active_support/core_ext/string/output_safety.rb:25:in `+'F:/installInstantRails/rails_apps/redmine-1.1.0-/vendor/rails/activesupport/lib/active_support/core_ext/string/output_safety.rb:25:in `add_with_safety'F:/installInstantRails/rails_apps/redmine-1.1.0-/lib/tasks/load_default_data.rake:31:in `rescue in block (2 levels) in &top (required)&'F:/installInstantRails/rails_apps/redmine-1.1.0-/lib/tasks/load_default_data.rake:25:in `block (2 levels) in &top (required)&'F:/installInstantRails/ruby/lib/ruby/1.9.1/rake.rb:634:in `call'F:/installInstantRails/ruby/lib/ruby/1.9.1/rake.rb:634:in `block in execute'F:/installInstantRails/ruby/lib/ruby/1.9.1/rake.rb:629:in `each'F:/installInstantRails/ruby/lib/ruby/1.9.1/rake.rb:629:in `execute'F:/installInstantRails/ruby/lib/ruby/1.9.1/rake.rb:595:in `block in invoke_with_call_chain'F:/installInstantRails/ruby/lib/ruby/1.9.1/monitor.rb:201:in `mon_synchronize'F:/installInstantRails/ruby/lib/ruby/1.9.1/rake.rb:588:in `invoke_with_call_chain'F:/installInstantRails/ruby/lib/ruby/1.9.1/rake.rb:581:in `invoke'F:/installInstantRails/ruby/lib/ruby/1.9.1/rake.rb:2041:in `invoke_task'F:/installInstantRails/ruby/lib/ruby/1.9.1/rake.rb:2019:in `block (2 levels) intop_level'F:/installInstantRails/ruby/lib/ruby/1.9.1/rake.rb:2019:in `each'F:/installInstantRails/ruby/lib/ruby/1.9.1/rake.rb:2019:in `block in top_level'F:/installInstantRails/ruby/lib/ruby/1.9.1/rake.rb:2058:in `standard_exception_handling'F:/installInstantRails/ruby/lib/ruby/1.9.1/rake.rb:2013:in `top_level'F:/installInstantRails/ruby/lib/ruby/1.9.1/rake.rb:1992:in `run'F:/installInstantRails/ruby/bin/rake:31:in `&main&'F:\installInstantRails\rails_apps\redmine-1.1.0-&---------------------------------------------------&安装后redmine1.1.0版虽可运行,但如新建项目或问题名为中文就会报错,也许是因为以上设数据库为中文时报错导致,&---------------------------------------------------Encoding::CompatibilityError in Projects#settingsShowing app/views/projects/_form.rhtml where line #5 raised:incompatible character encodings: UTF-8 and ASCII-8BITExtracted source (around line #5):2: 3: &div class="box"&4: &!--[form:project]--&5: &p&&%= f.text_field :name, :required =& true, :size =& 60 %&&/p&6: 7: &% unless @project.pact.empty? %&8:
&p&&%= label(:project, :parent_id, l(:field_parent)) %&&%= parent_project_select_tag(@project) %&&/p&Trace of template inclusion: app/views/projects/_edit.rhtml, app/views/common/_tabs.rhtml, app/views/projects/settings.rhtmlRAILS_ROOT: F:/installInstantRails/rails_apps/redmine-1.1.0-Application Trace | Framework Trace | Full TraceF:/installInstantRails/rails_apps/redmine-1.1.0-/vendor/rails/activesupport/lib/active_support/core_ext/string/output_safety.rb:25:in `+'F:/installInstantRails/rails_apps/redmine-1.1.0-/vendor/rails/activesupport/lib/active_support/core_ext/string/output_safety.rb:25:in `add_with_safety'F:/installInstantRails/rails_apps/redmine-1.1.0-/lib/tabular_form_builder.rb:35:in `text_field'F:/installInstantRails/rails_apps/redmine-1.1.0-/app/views/projects/_form.rhtml:5:in `_run_rhtml_app47views47projects47_form46rhtml_locals_f_form_object'F:/installInstantRails/rails_apps/redmine-1.1.0-/app/views/projects/_edit.rhtml:2:in `block in _run_rhtml_app47views47projects47_edit46rhtml_locals_edit_object_tab'F:/installInstantRails/rails_apps/redmine-1.1.0-/app/helpers/application_helper.rb:756:in `labelled_tabular_form_for'F:/installInstantRails/rails_apps/redmine-1.1.0-/app/views/projects/_edit.rhtml:1:in `_run_rhtml_app47views47projects47_edit46rhtml_locals_edit_object_tab'F:/installInstantRails/rails_apps/redmine-1.1.0-/app/views/common/_tabs.rhtml:24:in `block in _run_rhtml_app47views47common47_tabs46rhtml_locals_object_tabs'F:/installInstantRails/rails_apps/redmine-1.1.0-/app/views/common/_tabs.rhtml:23:in `each'F:/installInstantRails/rails_apps/redmine-1.1.0-/app/views/common/_tabs.rhtml:23:in `_run_rhtml_app47views47common47_tabs46rhtml_locals_object_tabs'F:/installInstantRails/rails_apps/redmine-1.1.0-/app/helpers/application_helper.rb:204:in `render_tabs'F:/installInstantRails/rails_apps/redmine-1.1.0-/app/views/projects/settings.rhtml:3:in `_run_rhtml_app47views47projects47settings46rhtml'RequestParameters:{"id"=&"a1"}Show session dumpResponseHeaders:{"Cache-Control"=&"no-cache", "Content-Type"=&""}---------------------------------------------------&
我也遇到这个问题.求解...能设置的编码我都设置了.我甚至修改了mysql每张表的type类型。(type设置成为MyISAM而不是InnoDB。 )可还是不行那个
按照楼主的安装步骤 我执行到第16步.执行rake db:migrate RAILS_ENV="production",就失败了呢,楼主知道是什么原因吗?很有挫折感啊。。。。。请各位指教错误如下:C:\InstantRails-2.0-win\rails_apps\redmine-1.1.0&rake db:migrate RAILS_ENV= "production"(in C:/InstantRails-2.0-win/rails_apps/redmine-1.1.0)rake aborted!undefined local variable or method `version_requirements' for #&Rails::GemDependency:0x14038c8&C:/InstantRails-2.0-win/rails_apps/redmine-1.1.0/vendor/rails/railties/lib/rails/gem_dependency.rb:119:in `requirement'C:/InstantRails-2.0-win/ruby/lib/ruby/site_ruby/1.9.1/rubygems.rb:254:in `activate'C:/InstantRails-2.0-win/ruby/lib/ruby/site_ruby/1.9.1/rubygems.rb:1204:in `gem'
gem install rack --version=1.0.1
试下这条语句
按照楼主的安装步骤 我执行到第16步.执行rake db:migrate RAILS_ENV="production",就失败了呢,楼主知道是什么原因吗?很有挫折感啊。。。。。请各位指教错误如下:C:\InstantRails-2.0-win\rails_apps\redmine-1.1.0&rake db:migrate RAILS_ENV= "production"(in C:/InstantRails-2.0-win/rails_apps/redmine-1.1.0)rake aborted!undefined local variable or method `version_requirements' for #&Rails::GemDependency:0x14038c8&C:/InstantRails-2.0-win/rails_apps/redmine-1.1.0/vendor/rails/railties/lib/rails/gem_dependency.rb:119:in `requirement'C:/InstantRails-2.0-win/ruby/lib/ruby/site_ruby/1.9.1/rubygems.rb:254:in `activate'C:/InstantRails-2.0-win/ruby/lib/ruby/site_ruby/1.9.1/rubygems.rb:1204:in `gem'
先执行gem install rack --version=1.0.1再rake db:migrate RAILS_ENV= "production" 希望对你有帮助
qimo601 写道
按照楼主的安装步骤 我执行到第16步.执行rake db:migrate RAILS_ENV="production",就失败了呢,楼主知道是什么原因吗?很有挫折感啊。。。。。请各位指教错误如下:C:\InstantRails-2.0-win\rails_apps\redmine-1.1.0&rake db:migrate RAILS_ENV= "production"(in C:/InstantRails-2.0-win/rails_apps/redmine-1.1.0)rake aborted!undefined local variable or method `version_requirements' for #&Rails::GemDependency:0x14038c8&C:/InstantRails-2.0-win/rails_apps/redmine-1.1.0/vendor/rails/railties/lib/rails/gem_dependency.rb:119:in `requirement'C:/InstantRails-2.0-win/ruby/lib/ruby/site_ruby/1.9.1/rubygems.rb:254:in `activate'C:/InstantRails-2.0-win/ruby/lib/ruby/site_ruby/1.9.1/rubygems.rb:1204:in `gem'
先执行gem install rack --version=1.0.1再rake db:migrate RAILS_ENV= "production" 希望对你有帮助
我执行了的,没用的,还是同样的错误。楼主的第13步,也有这个指令gem install rack -v=1.0.1 1、我还想问在楼主的第12步骤中,是直接将ruby1.9.2中的所有文件拷贝到InstantRails/ruby文件下覆盖旧文件吧?不需要先清空吧?2、我很想知道我执行rake db:migrate RAILS_ENV= "production" 这个命令出错,是不是libmysql.dll的问题。我也换过旧版本的也还是这个错误。安装redmine,我按照网上安装策略,换过好多版本的思路了,都在执行这个命令时候,失败了。。。到底怎么回事啊?
鹤惊昆仑 写道
atian25 写道
不妨试下bitinami redmind同推荐。5分钟内绝对可以安装成功,运行起来。
还是这个最省心,100多m有点大,不过不用折腾。分享地址:http://bitnami.org/files/stacks/redmine/1.1.1-0/bitnami-redmine-1.1.1-0-windows-installer.exe
我也用了这个,但是发现有中文乱码,如何解决呢?
Hooopo 写道
fanfq 写道
fanfq 写道
为什么我装的redmine当多人访问的时候会很卡,要等好长时间才能刷新一次页面。
你是用的sqlite数据库吗?换成mysql或者PostgreSQL试试。
用的mysql。其他的也不会用。
服务器只开一个进程吧?
是默认的服务器性能太差,换mongle?就好
不是服务器性能的问题我遇到过同样的问题我用好几个版本rails 用mongle,passenger等等都试过了,一样很慢,我的web服务器是nginx后来在看log的时候,是nginx的一个代理的文件夹的写权限的问题,改了权限就好了
spring jta运用
spring jta应用
关于Spring JTA的介绍非常多了,这里就不再一再阐述其优越性怎么怎么了,直接开始正题。一个大致的需求如下,用户在进行增删改操作时,会同时更新2至3个数据库的数据表,操作需要事务来包裹,以便在操作其中一个数据库的数据表失败时,可以将其他数据库已执行的动作回滚。 由于主框架是Spring,所以将研究的重点放在Spring所提供的的JTA事务上,google了很多资料,发现有几种实现的技术,如JOTM,Atomikos,以及J2EE容器所提供的JTA实现,如JBOSS也都提供了JTA的实现,不过个人喜好来讲,非常厌恶使用JNDI来访问容器组件,所以,重点放在JOTM和Atoimikos两种技术上面,JOTM网上很多资料介绍,配置也非常简单,相信大家通过google就可以快速的上手,本着研究的原则,少少了解了另一种实现技术Atomikos,发现使用方法也很简单,下面就用一个简单的例子来详细说明一下他们在Spring中的配置和使用方法。需要说明的一点是,这个例子也是当时学习两种技术,然后测试的例子,仅仅最后做了一些整理。 初步的设想:一个包括Dao/Service/Test三层的简单应用,事务配置在service层.用来同时插入两个数据库(test,test2)的数据表xa_test,表结构非常简单,包含两个字段id,name,其中test2数据库中表xa_test的name字段不允许为空。 使用的数据库为Mysql 5.0,数据库连接驱动版本5.0.8,这里需要注意,过低版本的Mysql或驱动可能不支持XA Datasource。 Database test ddl Java代码
1.CREATE TABLE `xa_test` (
`id` int(11) NOT NULL,
`name` varchar(20) default NULL
4.) ENGINE=InnoDB DEFAULT CHARSET=latin1;
CREATE TABLE `xa_test` (
`id` int(11) NOT NULL,
`name` varchar(20) default NULL) ENGINE=InnoDB DEFAULT CHARSET=latin1;Database test2 ddl Java代码
1.CREATE TABLE `xa_test` (
`id` int(11) NOT NULL,
`name` varchar(20) NOT NULL
4.) ENGINE=InnoDB DEFAULT CHARSET=latin1;
CREATE TABLE `xa_test` (
`id` int(11) NOT NULL,
`name` varchar(20) NOT NULL) ENGINE=InnoDB DEFAULT CHARSET=latin1;UserDao,这里使用了两个,UserDao1和UserDao2,用以操作两个不同数据库的数据表(画蛇添足了,呵呵,为了描述清晰).Dao都继承自Spring的JdbcDaoSupport,使用JdbcTemplate进行数据库读写. UserDao1.java Java代码
1.package com.xa.
3.import org.springframework.jdbc.core.support.JdbcDaoS
5.public class UserDao1 extends JdbcDaoSupport {
public void insertData(String id, String name) {
getJdbcTemplate().execute("insert into xa_test values('" + id + "'," + name + ")");
package com.xa.import org.springframework.jdbc.core.support.JdbcDaoSpublic class UserDao1 extends JdbcDaoSupport {
public void insertData(String id, String name) {
getJdbcTemplate().execute("insert into xa_test values('" + id + "'," + name + ")");
}}UserDao2.java Java代码
1.package com.xa.
3.import org.springframework.jdbc.core.support.JdbcDaoS
5.public class UserDao2 extends JdbcDaoSupport
public void insertData(String id,String name){
getJdbcTemplate().execute("insert into xa_test values('"+ id +"',"+name+")");
package com.xa.import org.springframework.jdbc.core.support.JdbcDaoSpublic class UserDao2 extends JdbcDaoSupport{ public void insertData(String id,String name){
getJdbcTemplate().execute("insert into xa_test values('"+ id +"',"+name+")"); }}然后创建UserService和UserServiceImpl,在UserServiceImpl中,将调用Dao1和Dao2的insertData的方法同时插入两个数据库的内容,稍后,会将事务配置在service层. UserService.java Java代码
1.package com.xa.
3.public interface UserService
public void insertBothDatabase(String id,String name) throws E
package com.xa.public interface UserService{ public void insertBothDatabase(String id,String name) throws E}UserServiceImpl.java Java代码
1.package com.xa.
3.import com.xa.dao.UserDao1;
4.import com.xa.dao.UserDao2;
6.public class UserServiceImpl implements UserService
private UserDao1 dao1;
private UserDao2 dao2;
public void insertBothDatabase(String id, String name) throws Exception {
dao1.insertData(id, name);
dao2.insertData(id, name);
public UserDao1 getDao1() {
return dao1;
public void setDao1(UserDao1 dao1) {
this.dao1 = dao1;
public UserDao2 getDao2() {
return dao2;
public void setDao2(UserDao2 dao2) {
this.dao2 = dao2;
package com.xa.import com.xa.dao.UserDao1;import com.xa.dao.UserDao2;public class UserServiceImpl implements UserService{ private UserDao1 dao1; private UserDao2 dao2; public void insertBothDatabase(String id, String name) throws Exception {
dao1.insertData(id, name);
dao2.insertData(id, name); } public UserDao1 getDao1() {
return dao1; } public void setDao1(UserDao1 dao1) {
this.dao1 = dao1; } public UserDao2 getDao2() {
return dao2; } public void setDao2(UserDao2 dao2) {
this.dao2 = dao2; }}UserServiceImpl.java的代码可以看到,在insertBothDatabase方法中,调用了两个Dao的方法. 一个JOTM(Java Open Transaction Manager)是ObjectWeb的一个开源JTA实现,本身也是开源应用程序服务器JOnAS(Java Open Application Server)的一部分,为其提供JTA分布式事务的功能。Spring对JOTM提供了较好的支持,提供了一个org.springframework.transaction.jta.JotmFactoryBean的支持类,在Spring2.0中也包含了JOTM相关的一些library。 jotm的下载地址为http://jotm.objectweb.org,最新版本为2.0.10. 下载完成后解压缩,然后打开jotm下面conf文件夹,拷贝carol.properties文件到classpath中,并修改这个文件如下 carol.properties Java代码
1.# do not use CAROL JNDI wrapper
2.carol.start.jndi=false
4.# do not start a name server
5.carol.start.ns=false
7.# Naming Factory
8.carol.jndi.java.naming.factory.url.pkgs=org.apache.naming
# do not use CAROL JNDI wrapper
carol.start.jndi=false
# do not start a name server
carol.start.ns=false
# Naming Factorycarol.jndi.java.naming.factory.url.pkgs=org.apache.naming上面配置文件的目的是不使用JNDI的方式来加载JOTM的配置,当然也可以根据需要选择其它的一些配置,例如JTOM所提供的默认配置。 然后开始在Spring上下文中配置JOTM,在classpath中建立一个ApplicationContext-jotm.xml,配置如下 ApplicationContext-jotm.xml Java代码
1.&?xml version="1.0" encoding="UTF-8"?&
2.&beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd"&
&bean id="jotm" class="org.springframework.transaction.jta.JotmFactoryBean"/&
&bean id="txManager" class="org.springframework.transaction.jta.JtaTransactionManager"&
&property name="userTransaction" ref="jotm" /&
&bean id="ds1" class="org.enhydra.jdbc.pool.StandardXAPoolDataSource" destroy-method="shutdown"&
&property name="dataSource"&
&bean class="org.enhydra.jdbc.standard.StandardXADataSource" destroy-method="shutdown"&
&property name="transactionManager" ref="jotm" /&
&property name="driverName" value="com.mysql.jdbc.Driver" /&
&property name="url" value="jdbc:MySQL://localhost:3306/test" /&
&/property&
&property name="user" value="root" /&
&property name="password" value="admin" /&
&bean id="ds2" class="org.enhydra.jdbc.pool.StandardXAPoolDataSource" destroy-method="shutdown"&
&property name="dataSource"&
&bean class="org.enhydra.jdbc.standard.StandardXADataSource" destroy-method="shutdown"&
&property name="transactionManager" ref="jotm" /&
&property name="driverName" value="com.mysql.jdbc.Driver" /&
&property name="url" value="jdbc:MySQL://localhost:3306/test2" /&
&/property&
&property name="user" value="root" /&
&property name="password" value="admin" /&
&bean id="template1" class="org.springframework.jdbc.core.JdbcTemplate"&
&property name="dataSource" ref="ds1" /&
&bean id="template2" class="org.springframework.jdbc.core.JdbcTemplate"&
&property name="dataSource" ref="ds2" /&
&bean id="dao1" class="com.xa.dao.UserDao1"&
&property name="jdbcTemplate"&
&ref bean="template1"&&/ref&
&/property&
&bean id="dao2" class="com.xa.dao.UserDao2"&
&property name="jdbcTemplate"&
&ref bean="template2"&&/ref&
&/property&
&bean id="userServiceTarget" class="com.xa.service.UserServiceImpl"&
&property name="dao1" ref="dao1"/&
&property name="dao2" ref="dao2"/&
&bean id="userTest" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"&
&property name="transactionManager"&
&ref bean="txManager"/&
&/property&
&property name="target"&
&ref bean="userServiceTarget"/&
&/property&
&property name="transactionAttributes"&
&prop key="insert*"&PROPAGATION_REQUIRED,-Exception&/prop&
&/property&
75.&/beans&
&?xml version="1.0" encoding="UTF-8"?&&beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd"& &bean id="jotm" class="org.springframework.transaction.jta.JotmFactoryBean"/& &bean id="txManager" class="org.springframework.transaction.jta.JtaTransactionManager"&
&property name="userTransaction" ref="jotm" /& &/bean& &bean id="ds1" class="org.enhydra.jdbc.pool.StandardXAPoolDataSource" destroy-method="shutdown"&
&property name="dataSource"&
&bean class="org.enhydra.jdbc.standard.StandardXADataSource" destroy-method="shutdown"&
&property name="transactionManager" ref="jotm" /&
&property name="driverName" value="com.mysql.jdbc.Driver" /&
&property name="url" value="jdbc:MySQL://localhost:3306/test" /&
&/property&
&property name="user" value="root" /&
&property name="password" value="admin" /& &/bean& &bean id="ds2" class="org.enhydra.jdbc.pool.StandardXAPoolDataSource" destroy-method="shutdown"&
&property name="dataSource"&
&bean class="org.enhydra.jdbc.standard.StandardXADataSource" destroy-method="shutdown"&
&property name="transactionManager" ref="jotm" /&
&property name="driverName" value="com.mysql.jdbc.Driver" /&
&property name="url" value="jdbc:MySQL://localhost:3306/test2" /&
&/property&
&property name="user" value="root" /&
&property name="password" value="admin" /& &/bean& &bean id="template1" class="org.springframework.jdbc.core.JdbcTemplate"&
&property name="dataSource" ref="ds1" /& &/bean& &bean id="template2" class="org.springframework.jdbc.core.JdbcTemplate"&
&property name="dataSource" ref="ds2" /& &/bean& &bean id="dao1" class="com.xa.dao.UserDao1"&
&property name="jdbcTemplate"&
&ref bean="template1"&&/ref&
&/property& &/bean& &bean id="dao2" class="com.xa.dao.UserDao2"&
&property name="jdbcTemplate"&
&ref bean="template2"&&/ref&
&/property& &/bean& &bean id="userServiceTarget" class="com.xa.service.UserServiceImpl"&
&property name="dao1" ref="dao1"/&
&property name="dao2" ref="dao2"/& &/bean& &bean id="userTest" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"&
&property name="transactionManager"&
&ref bean="txManager"/&
&/property&
&property name="target"&
&ref bean="userServiceTarget"/&
&/property&
&property name="transactionAttributes"&
&prop key="insert*"&PROPAGATION_REQUIRED,-Exception&/prop&
&/property& &/bean&&/beans&上面是一个完整的Spring上下文配置,可以看第一个bean “jotm”,实际上引用了Spring内部所提供的对JOTM支持的工厂类,参考下面的配置代码段 Java代码
1.&bean id="jotm" class="org.springframework.transaction.jta.JotmFactoryBean"/&
&bean id="jotm" class="org.springframework.transaction.jta.JotmFactoryBean"/&随后,配置了JTA事务管理器,并且在管理器中使用上面所配置的jotm,如下面的代码 Java代码
1.&bean id="txManager" class="org.springframework.transaction.jta.JtaTransactionManager"&
&property name="userTransaction" ref="jotm" /&
&bean id="txManager" class="org.springframework.transaction.jta.JtaTransactionManager"& &property name="userTransaction" ref="jotm" /&&/bean&再接下来就是配置多个数据源了,使用jotm提供的org.enhydra.jdbc.pool.StandardXAPoolDataSource类,根据类名可以明确地看出它是用以配置多个数据源的啦,配置的代码如下 Java代码
1.&bean id="ds1" class="org.enhydra.jdbc.pool.StandardXAPoolDataSource" destroy-method="shutdown"&
&property name="dataSource"&
&bean class="org.enhydra.jdbc.standard.StandardXADataSource" destroy-method="shutdown"&
&property name="transactionManager" ref="jotm" /&
&property name="driverName" value="com.mysql.jdbc.Driver" /&
&property name="url" value="jdbc:MySQL://localhost:3306/test" /&
&/property&
&property name="user" value="root" /&
&property name="password" value="admin" /&
&bean id="ds2" class="org.enhydra.jdbc.pool.StandardXAPoolDataSource" destroy-method="shutdown"&
&property name="dataSource"&
&bean class="org.enhydra.jdbc.standard.StandardXADataSource" destroy-method="shutdown"&
&property name="transactionManager" ref="jotm" /&
&property name="driverName" value="com.mysql.jdbc.Driver" /&
&property name="url" value="jdbc:MySQL://localhost:3306/test2" /&
&/property&
&property name="user" value="root" /&
&property name="password" value="admin" /&
&bean id="ds1" class="org.enhydra.jdbc.pool.StandardXAPoolDataSource" destroy-method="shutdown"&
&property name="dataSource"&
&bean class="org.enhydra.jdbc.standard.StandardXADataSource" destroy-method="shutdown"&
&property name="transactionManager" ref="jotm" /&
&property name="driverName" value="com.mysql.jdbc.Driver" /&
&property name="url" value="jdbc:MySQL://localhost:3306/test" /&
&/property&
&property name="user" value="root" /&
&property name="password" value="admin" /& &/bean& &bean id="ds2" class="org.enhydra.jdbc.pool.StandardXAPoolDataSource" destroy-method="shutdown"&
&property name="dataSource"&
&bean class="org.enhydra.jdbc.standard.StandardXADataSource" destroy-method="shutdown"&
&property name="transactionManager" ref="jotm" /&
&property name="driverName" value="com.mysql.jdbc.Driver" /&
&property name="url" value="jdbc:MySQL://localhost:3306/test2" /&
&/property&
&property name="user" value="root" /&
&property name="password" value="admin" /& &/bean&这里配置的两个数据源都连接到本地的mysql,实际上可以连接到不同的db server和不同类型的数据库,已经经过测试,这里为了方便,在本地建立了两个不同的数据库(test,test2)做测试。 随后的配置基本上和普通的Spring上下文配置相同了,根据不同的数据源配置两个jdbcTemplate,两个dao分别引用不同的jdbcTemplate, 将两个dao注入到UserService中, 最后将service纳入事务管理,并在事务代理配置中配置回滚规则,意思为如遇异常,则强制回滚内容。配置如下所示 Java代码
1.&property name="transactionAttributes"&
&prop key="insert*"&PROPAGATION_REQUIRED,-Exception&/prop&
5.&/property&
&property name="transactionAttributes"&
&prop key="insert*"&PROPAGATION_REQUIRED,-Exception&/prop&
&/props&&/property&这样,一个使用JOTM JTA事务的简单应用算大致成型了,最后,写一个JUnit,来测试一下结果 TestXa.java Java代码
1.package com.
3.import org.springframework.context.ApplicationC
4.import org.springframework.test.AbstractDependencyInjectionSpringContextT
6.import com.xa.service.UserS
8.public class TestXa extends AbstractDependencyInjectionSpringContextTests
protected String[] getConfigLocations() {
return new String[] { "classpath:ApplicationContext-jotm.xml" };
public void testInsertBothDatabase() {
ApplicationContext ctx = this.getApplicationContext();
UserService ut = (UserService)ctx.getBean("userTest");
ut.insertBothDatabase("1", null);
catch (Exception e) {
e.printStackTrace();
package com.import org.springframework.context.ApplicationCimport org.springframework.test.AbstractDependencyInjectionSpringContextTimport com.xa.service.UserSpublic class TestXa extends AbstractDependencyInjectionSpringContextTests{ protected String[] getConfigLocations() {
return new String[] { "classpath:ApplicationContext-jotm.xml" }; } public void testInsertBothDatabase() {
ApplicationContext ctx = this.getApplicationContext();
UserService ut = (UserService)ctx.getBean("userTest");
ut.insertBothDatabase("1", null);
catch (Exception e) {
e.printStackTrace();
} }}在test中,调用了UserService的insertBothDatabase方法,有两个参数,userId和UserName,另外在方法的实现中调用了两个使用不同数据源dao,分别向两个不同的数据库插入输入,而test2数据库的xa_test表中,name字段是不允许为空的,因此,在插入test2数据库时会失败. 运行这个test,然后察看数据库结果:),test和test2数据库中都没有插入成功,看serviceImpl中的代码可以知道,逻辑上dao1会先于dao2执行,但是由于JTA事务,在dao2插入数据出现异常时整个事务被回滚,由于事务被配置在service层,dao1和dao2都被纳入一个事务进行管理,呵呵。修改一下方法的参数,修改为 Java代码
1.ut.insertBothDatabase("1", "name1");
ut.insertBothDatabase("1", "name1");然后再试试test看数据库结果,如何? 第三节将简单介绍Atomikos在Spring中的配置和使用。 简单的应用已经建立,随后下一节将说明如何配置JOTM以及在Spring中的相关配置.前面简单介绍了JOTM如何在Spring中配置,并如何使用它的JTA事务,本节将介绍Atomikos如何与Spring集成,并使用它的JTA事务。 Atomikos,是一个基于Java的开源事务管理器,提供了事务管理和连接池,不需要应用服务器支持,支持JDBC和JMS事务,能提供对Spring,Hibernate的集成,有兴趣多了解的可以直接参考说明文当,有详细的介绍和使用说明。 Atomikos可以到/products.html#ate下载,最新版本是3.2.0 首先,仍然是一个相关的配置文件,用来设置相关的环境,打开解压缩后Atomikos根目录,拷贝jta.properties到classpath中,并修改为如下内容 jta.properties Java代码
<.atomikos.icatch.service=com.atomikos.icatch.standalone.UserTransactionServiceFactory
<.atomikos.icatch.console_file_name = tm.out
<.atomikos.icatch.log_base_name = tmlog
<.atomikos.icatch.tm_unique_name = com.atomikos.spring.jdbc.tm
<.atomikos.icatch.console_log_level = INFO
com.atomikos.icatch.service=com.atomikos.icatch.standalone.UserTransactionServiceFactorycom.atomikos.icatch.console_file_name = tm.outcom.atomikos.icatch.log_base_name = tmlogcom.atomikos.icatch.tm_unique_name = com.atomikos.spring.jdbc.tmcom.atomikos.icatch.console_log_level = INFO 随后,是Spring上下文配置,建立一个名为ApplicationContext-atomikos.xml的Spring上下文 ApplicationContext-atomikos.xml Java代码
1.&?xml version="1.0" encoding="UTF-8"?&
2.&beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd"&
&!-- XA Datasource --&
&bean id="datasource1" class="com.atomikos.jdbc.SimpleDataSourceBean" init-method="init" destroy-method="close"&
&property name="uniqueResourceName"&
&value&mysql/main&/value&
&/property&
&property name="xaDataSourceClassName"&
&value&com.mysql.jdbc.jdbc2.optional.MysqlXADataSource&/value&
&/property&
&property name="xaDataSourceProperties"&
&value&URL=jdbc:mysql://localhost:3306/user=password=admin&/value&
&/property&
&property name="exclusiveConnectionMode"&
&value&true&/value&
&/property&
&property name="connectionPoolSize"&
&value&3&/value&
&/property&
&property name="validatingQuery"&
&value&SELECT 1&/value&
&/property&
&bean id="datasource2" class="com.atomikos.jdbc.SimpleDataSourceBean" init-method="init" destroy-method="close"&
&property name="uniqueResourceName"&
&value&mysql/news&/value&
&/property&
&property name="xaDataSourceClassName"&
&value&com.mysql.jdbc.jdbc2.optional.MysqlXADataSource&/value&
&/property&
&property name="xaDataSourceProperties"&
&value&URL=jdbc:mysql://localhost:3306/test2;user=password=admin&/value&
&/property&
&property name="exclusiveConnectionMode"&
&value&true&/value&
&/property&
&property name="connectionPoolSize"&
&value&3&/value&
&/property&
&property name="validatingQuery"&
&value&SELECT 1&/value&
&/property&
&bean id="template1" class="org.springframework.jdbc.core.JdbcTemplate"&
&property name="dataSource" ref="datasource1" /&
&bean id="template2" class="org.springframework.jdbc.core.JdbcTemplate"&
&property name="dataSource" ref="datasource2" /&
&bean id="atomikosTransactionManager" class="com.atomikos.icatch.jta.UserTransactionManager" init-method="init" destroy-method="close"&
&property name="forceShutdown"&&value&true&/value&&/property&
&bean id="atomikosUserTransaction" class="com.atomikos.icatch.jta.UserTransactionImp"&
&property name="transactionTimeout" value="300"/&
&bean id="springTransactionManager" class="org.springframework.transaction.jta.JtaTransactionManager"&
&property name="transactionManager"&&ref bean="atomikosTransactionManager"
/&&/property&
&property name="userTransaction"&&ref bean="atomikosUserTransaction"
/&&/property&
&bean id="dao1" class="com.xa.dao.UserDao1"&
&property name="jdbcTemplate"&
&ref bean="template1"&&/ref&
&/property&
&bean id="dao2" class="com.xa.dao.UserDao2"&
&property name="jdbcTemplate"&
&ref bean="template2"&&/ref&
&/property&
&bean id="userServiceTarget" class="com.xa.service.UserServiceImpl"&
&property name="dao1" ref="dao1"/&
&property name="dao2" ref="dao2"/&
&bean id="userTest" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"&
&property name="transactionManager"&
&ref bean="springTransactionManager"/&
&/property&
&property name="target"&
&ref bean="userServiceTarget"/&
&/property&
&property name="transactionAttributes"&
&prop key="insert*"&PROPAGATION_REQUIRED,-Exception&/prop&
&/property&
99.&/beans&
&?xml version="1.0" encoding="UTF-8"?&&beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd"& &!-- XA Datasource --& &bean id="datasource1" class="com.atomikos.jdbc.SimpleDataSourceBean" init-method="init" destroy-method="close"&
&property name="uniqueResourceName"&
&value&mysql/main&/value&
&/property&
&property name="xaDataSourceClassName"&
&value&com.mysql.jdbc.jdbc2.optional.MysqlXADataSource&/value&
&/property&
&property name="xaDataSourceProperties"&
&value&URL=jdbc:mysql://localhost:3306/user=password=admin&/value&
&/property&
&property name="exclusiveConnectionMode"&
&value&true&/value&
&/property&
&property name="connectionPoolSize"&
&value&3&/value&
&/property&
&property name="validatingQuery"&
&value&SELECT 1&/value&
&/property&
&/bean& &bean id="datasource2" class="com.atomikos.jdbc.SimpleDataSourceBean" init-method="init" destroy-method="close"&
&property name="uniqueResourceName"&
&value&mysql/news&/value&
&/property&
&property name="xaDataSourceClassName"&
&value&com.mysql.jdbc.jdbc2.optional.MysqlXADataSource&/value&
&/property&
&property name="xaDataSourceProperties"&
&value&URL=jdbc:mysql://localhost:3306/test2;user=password=admin&/value&
&/property&
&property name="exclusiveConnectionMode"&
&value&true&/value&
&/property&
&property name="connectionPoolSize"&
&value&3&/value&
&/property&
&property name="validatingQuery"&
&value&SELECT 1&/value&
&/property&
&/bean& &bean id="template1" class="org.springframework.jdbc.core.JdbcTemplate"&
&property name="dataSource" ref="datasource1" /& &/bean& &bean id="template2" class="org.springframework.jdbc.core.JdbcTemplate"&
&property name="dataSource" ref="datasource2" /& &/bean& &bean id="atomikosTransactionManager" class="com.atomikos.icatch.jta.UserTransactionManager" init-method="init" destroy-method="close"&
&property name="forceShutdown"&&value&true&/value&&/property& &/bean& &bean id="atomikosUserTransaction" class="com.atomikos.icatch.jta.UserTransactionImp"&
&property name="transactionTimeout" value="300"/&
&/bean& &bean id="springTransactionManager" class="org.springframework.transaction.jta.JtaTransactionManager"&
&property name="transactionManager"&&ref bean="atomikosTransactionManager"
/&&/property&
&property name="userTransaction"&&ref bean="atomikosUserTransaction"
/&&/property& &/bean& &bean id="dao1" class="com.xa.dao.UserDao1"&
&property name="jdbcTemplate"&
&ref bean="template1"&&/ref&
&/property& &/bean& &bean id="dao2" class="com.xa.dao.UserDao2"&
&property name="jdbcTemplate"&
&ref bean="template2"&&/ref&
&/property& &/bean& &!-- --& &bean id="userServiceTarget" class="com.xa.service.UserServiceImpl"&
&property name="dao1" ref="dao1"/&
&property name="dao2" ref="dao2"/& &/bean& &bean id="userTest" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"&
&property name="transactionManager"&
&ref bean="springTransactionManager"/&
&/property&
&property name="target"&
&ref bean="userServiceTarget"/&
&/property&
&property name="transactionAttributes"&
&prop key="insert*"&PROPAGATION_REQUIRED,-Exception&/prop&
&/property& &/bean&&/beans&看上下文中的代码,很大部分和JOTM的相似,atomikos使用com.atomikos.jdbc.SimpleDataSourceBean类来创建datasource bean,这里需要特别注意 Java代码
1.&property name="uniqueResourceName"&
&value&mysql/main&/value&
3.&/property&
&property name="uniqueResourceName"&
&value&mysql/main&/value&
&/property&
1.&property name="uniqueResourceName"&
&value&mysql/news&/value&
3.&/property&
&property name="uniqueResourceName"&
&value&mysql/news&/value&&/property&上面的代码为每个Datasource配置了一个唯一的名称,名称不允许相同,否则将会使用同一个datasource,而不会出现异常。 另外在配置文件中定义了Atomikos的事务管理器,并在Spring的JtaTransactionManager中引用 Java代码
1.&bean id="atomikosTransactionManager" class="com.atomikos.icatch.jta.UserTransactionManager" init-method="init" destroy-method="close"&
&property name="forceShutdown"&&value&true&/value&&/property&
&bean id="atomikosUserTransaction" class="com.atomikos.icatch.jta.UserTransactionImp"&
&property name="transactionTimeout" value="300"/&
&bean id="springTransactionManager" class="org.springframework.transaction.jta.JtaTransactionManager"&
&property name="transactionManager"&&ref bean="atomikosTransactionManager"
/&&/property&
&property name="userTransaction"&&ref bean="atomikosUserTransaction"
/&&/property&
&bean id="atomikosTransactionManager" class="com.atomikos.icatch.jta.UserTransactionManager" init-method="init" destroy-method="close"&
&property name="forceShutdown"&&value&true&/value&&/property& &/bean& &bean id="atomikosUserTransaction" class="com.atomikos.icatch.jta.UserTransactionImp"&
&property name="transactionTimeout" value="300"/&
&/bean& &bean id="springTransactionManager" class="org.springframework.transaction.jta.JtaTransactionManager"&
&property name="transactionManager"&&ref bean="atomikosTransactionManager"
/&&/property&
&property name="userTransaction"&&ref bean="atomikosUserTransaction"
/&&/property& &/bean&其它的代码没什么特别,和JOTM配置基本相同,JdbcTemplate,DAO,Service,事务代理等等.... 仍然使用TestXa.java,修改成引用ApplicationContext-atomikos.xml的上下文配置 Java代码
1.protected String[] getConfigLocations() {
//return new String[] { "classpath:ApplicationContext-jotm.xml" };
return new String[] { "classpath:ApplicationContext-atomikos.xml" };
protected String[] getConfigLocations() { //return new String[] { "classpath:ApplicationContext-jotm.xml" }; return new String[] { "classpath:ApplicationContext-atomikos.xml" };}运行test,然后查看数据库状态, 然后修改方法参数使其不违反数据库约束,再运行Test观察数据库 :)。
如果您想提高自己的技术水平,欢迎加入本站官方1号QQ群:&&,&&2号QQ群:,在群里结识技术精英和交流技术^_^
本站联系邮箱:}

我要回帖

更多关于 ngui例子 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信