apache 的commons下有个DBUtils, 封装了jdbc的实现(c3p0和QueryRunner的结合使用)

 dbutils  apache 的commons下有个DBUtils, 封装了jdbc的实现(c3p0和QueryRunner的结合使用)已关闭评论
6月 012018
 

最近刚发现apache 的commons下有个DBUtils, 封装了jdbc的实现,用起来真方便,分享一篇文章:https://www.cnblogs.com/biehongli/p/6536072.html

1DBUtils中的QueryRunner的使用:

1.1QueryRunner中提供了对SQL语句操作的api

1.2:主要有三个方法:

1.2.1query():用于执行select(查询);

1.2.2update():用于执行insert(插入)/update(更新)/delete(删除);

1.2.3batch():批处理;

2c3p0QueryRunner的结合使用:

2.1:首先导包,如下所示的包;

c3p0-0.9.1.2.jar
commons-dbutils-1.6.jar
mysql-connector-java-5.1.12-bin.jar

  2.2:当然导包之前你需要创建好数据库和数据表哦!~~~

  
src目录下面记住配置c3p0-config.xml文件

<c3p0-config>
    
    <!– c3p0默认配置,下面还可以配置多个数据库 –>
    <default-config>
        <property name=”jdbcUrl”>jdbc:mysql://localhost:3306/test
        </property>
        <property name=”driverClass”>com.mysql.jdbc.Driver</property>
        <property name=”user”>root</property>
        <property name=”password”>123456</property>
        <property name=”initialPoolSize”>6</property>
        <property name=”maxPoolSize”>50</property>
        <property name=”maxIdleTime”>1000</property>
    </default-config>

</c3p0-config>

2.3:创建实体类,如User.java,源码如下,

package com.bie.po;
/** 
* @author BieHongLi 
* @version 创建时间:2017年3月11日 下午12:55:21 

*/
public class User {

    private int id;
    private String name;
    private String password;
    private String email;
    private String phone;
    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getPassword() {
        return password;
    }
    public void setPassword(String password) {
        this.password = password;
    }
    public String getEmail() {
        return email;
    }
    public void setEmail(String email) {
        this.email = email;
    }
    public String getPhone() {
        return phone;
    }
    public void setPhone(String phone) {
        this.phone = phone;
    }
    @Override
    public String toString() {
        return “User [id=” + id + “, name=” + name + “, password=” + password + “, email=” + email + “, phone=” + phone
                + “]”;
    }
    
    
}

2.4:创建好实体类之后就可以根据MVC模式分层进行开发,这里只是模拟,所以创建dao层和servic层和test层。test层进行测试;

所以先创建dao层进行创建接口,再创建实现接口的类,当然实现c3p0QueryRunner的关键代码就是dao层哦,切记;

当然了还有工具类utils层提取的公共的方法;

package com.bie.dao;

import java.util.List;

import com.bie.po.User;

/** 
* @author BieHongLi 
* @version 创建时间:2017年3月11日 下午5:46:38 

*/
public interface UserDao {

    /***
     * 查询所有的用户信息
     * @return
     */
    public List<User> selectUser();
    
    /***
     * 根据编号查询
     * @param id
     * @return
     */
    public User selectUserId(int id);
    
    
    /***
     * 根据条件查询信息
     * @param user
     * @return
     */
    public List<User> select(String sql,List<Object> list);
    
    
}

package com.bie.dao.impl;

import java.util.List;

import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanHandler;
import org.apache.commons.dbutils.handlers.BeanListHandler;

import com.bie.dao.UserDao;
import com.bie.po.User;
import com.bie.util.BaseUtils;

/** 
* @author BieHongLi 
* @version 创建时间:2017年3月11日 下午5:47:35 

*/
public class UserDaoImpl implements UserDao{

    @Override
    public List<User> selectUser() {
        //创建QueryRunner
        //记住查询是BeanListHandler区别增删改的方法BeanHandler
        QueryRunner qr=BaseUtils.getQueryRunner();
        try {
            String sql=”select * from user “;
            //这句话就相当于之前写的下面这一长串代码,这就是QueryRunner的方便之处
            /***
             *User user=new User();
               user.setId(rs.getInt(“id”));
               user.setName(rs.getString(“name”));
               user.setPassword(rs.getString(“password”));
               user.setEmail(rs.getString(“email”));
               user.setPhone(rs.getString(“phone”));
             */
            return qr.query(sql, new BeanListHandler<User>(User.class));
            
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    @Override
    public User selectUserId(int id) {
        //创建QueryRunner
        QueryRunner qr=BaseUtils.getQueryRunner();
        String sql=”select * from user where id=? “;
        try {
            //使用QueryRunner的强大之处在于此处。
            return qr.query(sql,new BeanHandler<User>(User.class), id);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public List<User> select(String sql,List<Object> list) {
        //创建QueryRunner
        QueryRunner qr=BaseUtils.getQueryRunner();
        try {
            //第一个参数是传来的sql,第二个是实现实体类的设置,第三个是集合转化为数组
            return qr.query(sql, new BeanListHandler<User>(User.class), list.toArray());
            
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    
}

这里将BaseUtils类写到这里,因为这个也是c3p0QueryRunner的核心

package com.bie.util;

import java.sql.SQLException;
import java.util.List;

import javax.sql.DataSource;

import org.apache.commons.dbutils.QueryRunner;

import com.mchange.v2.c3p0.ComboPooledDataSource;

/** 
* @author BieHongLi 
* @version 创建时间:2017年3月11日 下午1:29:50 
* 数据库连接工具类
*/
public class BaseUtils {

    //初始化c3p0
    private static DataSource dataSource=null;
    
    static{
        //自动加载src目录下面的c3p0的配置文件,【c3p0-config.xml】
        dataSource = new ComboPooledDataSource();
    }
    
    public static QueryRunner getQueryRunner(){
        //第一步:创建QueryRunner对象,传入连接池对象
        //在创建QueryRunner对象的时候,如果传入数据对象dataSource,
        //那么在使用QueryRunner对象的方法时候,就不需要传入连接对象
        QueryRunner query=new QueryRunner(dataSource);
        //第二步:会自动从数据源中获取连接(不用关闭连接)
        return query;
    }
    
    /***
     * 实现增删改的公共方法
     * @param sql
     * @param arr
     * @return
     */
    public static boolean addUpdateDelete(String sql,Object[] arr){
        QueryRunner qr=getQueryRunner();
        int count;
        try {
            count = qr.update(sql, arr);
            if(count>0){
                return true;
            }else{
                return false;
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return false;
    }
    
}

2.5:完成dao层和BaseUtils层之后可以直接在service层进行增删改,

package com.bie.service;

import java.util.List;

import com.bie.po.User;

/** 
* @author BieHongLi 
* @version 创建时间:2017年3月11日 下午7:10:32 

*/
public interface UserService {

    /***
     * 根据条件查询用户信息
     * @param user
     * @return
     */
    public List<User> select(User user);
    
    /***
     * 添加用户信息
     * @param user
     * @return
     */
    public boolean insertUser(User user);
    
    /***
     * 修改用户的信息
     * @param user
     * @return
     */
    public boolean updateUser(User user);
    
    /***
     * 删除用户信息
     * @param id
     * @return
     */
    public boolean deleteUser(int id);
}

package com.bie.service.impl;

import java.util.ArrayList;
import java.util.List;

import com.bie.dao.UserDao;
import com.bie.dao.impl.UserDaoImpl;
import com.bie.po.User;
import com.bie.service.UserService;
import com.bie.util.BaseUtils;

/** 
* @author BieHongLi 
* @version 创建时间:2017年3月11日 下午7:10:48 

*/
public class UserServiceImpl implements UserService{
    
    private UserDao dao=new UserDaoImpl();
    
    @Override
    public List<User> select(User user) {
        StringBuilder sql=new StringBuilder(“select * from user where 1=1 “);
        List<Object> list=new ArrayList<Object>();
        if(user!=null){
            //根据编号查询
            if(user.getId()!=0 && !””.equals(user.getId())){
                sql.append(” and id = ? “);
                list.add(user.getId());
            }
            
            //根据名称模糊查询,模糊查询”” %% “” ++
            if(user.getName()!=null && !””.equals(user.getName())){
                sql.append(” and name like ? “);
                list.add(“%”+user.getName()+”%”);
            }
        }
        
        return dao.select(sql.toString(), list);
    }

    @Override
    public boolean insertUser(User user) {
        String sql=”insert into user values(0,?,?,?,?)”;
        List<Object> list=new ArrayList<>();
        if(user!=null){
            list.add(user.getName());
            list.add(user.getPassword());
            list.add(user.getEmail());
            list.add(user.getPhone());
        }
        try {
            return BaseUtils.addUpdateDelete(sql, list.toArray());
        } catch (Exception e) {
            e.printStackTrace();
        }
        return false;
    }

    @Override
    public boolean updateUser(User user) {
        String sql=”update user set name=?,password=?,email=?,phone=? where id=? “;
        List<Object> list=new ArrayList<>();
        if(user!=null){
            list.add(user.getName());
            list.add(user.getPassword());
            list.add(user.getEmail());
            list.add(user.getPhone());
            
            //根据编号修改信息
            list.add(user.getId());
        }
        
        try {
            return BaseUtils.addUpdateDelete(sql, list.toArray());
        } catch (Exception e) {
            e.printStackTrace();
        }
        return false;
    }

    @Override
    public boolean deleteUser(int id) {
        String sql=”delete from user where id=? “;
        List<Object> list=new ArrayList<>();
        if(id!=0){
            //根据编号修改信息
            list.add(id);
        }
        
        try {
            return BaseUtils.addUpdateDelete(sql, list.toArray());
        } catch (Exception e) {
            e.printStackTrace();
        }
        return false;
    }

    
}

2.6:使用junit测试,完成使用c3p0QueryRunner的练习;

package com.bie.test;

import java.util.List;

import org.junit.Test;

import com.bie.dao.UserDao;
import com.bie.dao.impl.UserDaoImpl;
import com.bie.po.User;
import com.bie.service.UserService;
import com.bie.service.impl.UserServiceImpl;

/** 
* @author BieHongLi 
* @version 创建时间:2017年3月11日 下午5:57:25 

*/
public class QueryRunnerTest {

    private UserDao dao=new UserDaoImpl();
    private UserService service=new UserServiceImpl();
    
    //查询所有信息的测试
    @Test
    public void selectUser(){
        List<User> list=dao.selectUser();
        for(User u:list){
            System.out.println(u);
        }
    }
    
    //根绝id查询的信息
    @Test
    public void selectUserId(){
        User user=dao.selectUserId(1);
        System.out.println(user);
    }
    
    //根据条件查询信息
    @Test
    public void select(){
        User user=new User();
        user.setName(“张三”);
        List<User> list=service.select(user);
        for(User u:list){
            System.out.println(u);
        }
    }
    
    @Test
    public void insertUser(){
        User user=new User();
        user.setName(“张三”);
        user.setPassword(“123456”);
        user.setEmail(“[email protected]”);
        user.setPhone(“11223”);
        
        boolean mark=service.insertUser(user);
        if(mark){
            System.out.println(“插入成功”);
        }else{
            System.out.println(“插入失败”);
        }
    }
    
    
    @Test
    public void update(){
        User user=new User();
        user.setName(“李四”);
        user.setId(1);
        
        boolean mark=service.updateUser(user);
        if(mark){
            System.out.println(“修改成功”);
        }else{
            System.out.println(“修改失败”);
        }
    }
    
    @Test
    public void delete(){
        boolean mark=service.deleteUser(1);
        if(mark){
            System.out.println(“用户信息删除成功”);
        }else{
            System.out.println(“用户信息删除失败”);
        }
    }
    
}

处理Apache日志的Bash脚本

 log  处理Apache日志的Bash脚本已关闭评论
12月 142016
 

来自阮一峰的博客,学习了, 转自:http://www.ruanyifeng.com/blog/2012/01/a_bash_script_of_apache_log_analysis.html

以往,我用的是AWStats日志分析软件。它可以生成很详细的报表,但是不太容易定制,得不到某些想要的信息。所以,我就决定自己写一个Bash脚本,统计服务器的日志,顺便温习一下脚本知识。

事实证明,这件事比我预想的难。虽然最终脚本只有20多行,但花了我整整一天,反复查看手册,确认用法和合适的参数。下面就是我的日志分析脚本,虽然它还不是通用的,但是我相信里面用到的命令,足以满足一般的日志分析需求,同时也是很好的学习Bash的实例。如果下面的每一个命令你都知道,我觉得可以堪称熟练使用Bash了。

一、操作环境

在介绍脚本之前,先讲一下我的服务器环境。

我的网络服务器软件是Apache,它会对每一个http请求留下记录,就像下面这一条:

203.218.148.99 – – [01/Feb/2011:00:02:09 +0800] “GET /blog/2009/11/an_autobiography_of_yang_xianyi.html HTTP/1.1” 200 84058 “http://www.ruanyifeng.com/blog/2009/11/freenomics.html” “Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-TW; rv:1.9.2.13) Gecko/20101203 Firefox/3.6.13”

它的意思是2011年2月1日,IP地址为203.218.148.99的访问者,向服务器请求访问网址/blog/2009/11/an_autobiography_of_yang_xianyi.html。

当天所有的访问记录,组成一个日志。过去一年,一共生成了365个日志文件。它们存放在12个目录中,每一个目录表示一个月(2011-01、2011-02、……2011-12),里面的日志文件依次为www-01.log、www-02.log、……www-31.log(假定该月有31天)。

在不压缩的情况下,365个日志文件加起来,要占掉10GB空间。我的目标就是分析这10GB日志,最后得到一个如下形式的访问量排名:

访问量 网址1
访问量 网址2
访问量 网址3
…… ……

二、为什么要用Bash

很多计算机语言,都可以用来完成这个任务。但是,如果只是简单的日志分析,我觉得Bash脚本是最合适的工具。

主要原因有两个:一是”开发快”,Bash脚本是各种Linux命令的组合,只要知道这些命令怎么用,就可以写脚本,基本上不用学习新的语法,而且它不用编译,直接运行,可以边写边试,对开发非常友好。二是”功能强”,Bash脚本的设计目的,就是为了处理输入和输出,尤其是单行的文本,所以非常合适处理日志文件,各种现成的参数加上管道机制,威力无穷。

前面已经说过,最终的脚本我只用了20多行,处理10GB的日志,20秒左右就得到了结果。考虑到排序的巨大计算量,这样的结果非常令人满意,充分证明了Bash的威力。

三、总体思路

我的总体处理思路是这样的:

第一步,处理单个日志。统计每一天各篇文章的访问量。

第二步,生成月度排名。将每一天的统计结果汇总,得到月度访问量。

第三步,生成年度排名。将12个月的统计结果汇总,进行年度访问量的排序。

四、处理单个日志

以2011年1月1日的日志为例,它在目录2011-01之中,文件名是www-01.log,里面有10万条如下格式的记录:

203.218.148.99 – – [01/Feb/2011:00:02:09 +0800] “GET /blog/2009/11/an_autobiography_of_yang_xianyi.html HTTP/1.1” 200 84058 “http://www.ruanyifeng.com/blog/2009/11/freenomics.html” “Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-TW; rv:1.9.2.13) Gecko/20101203 Firefox/3.6.13”

处理这个日志,我只用了一行代码:

awk ‘$9 == 200 {print $7}’ www-01.log | grep -i ‘^/blog/2011/.*\.html$’ | sort | uniq -c | sed ‘s/^ *//g’ > www-01.log.result

它用管道连接了5个命令,每一个都很简单,我们依次来看:

(1) awk ‘$9 == 200 {print $7}’ www-01.log

awk命令默认用空格,将每一行文本分割成若干个字段。仔细数一下,我们需要的只是第7个字段,即http请求的网址,{print $7}表示将第7个字段输出,结果就是:

/blog/2009/11/an_autobiography_of_yang_xianyi.html

考虑到我们只统计成功的请求,因此再加一个限制条件,服务器的状态代码必须是200(表示成功),写成”$9 == 200″,即第9个字段必须是200,否则不输出第7个字段。

更精细的统计,还应该区分网络蜘蛛和真实访问者,由于我想不出简单的分辨方法,这里只好忽略了。

(2)grep -i ‘^/blog/2011/.*\.html$’

在输出的所有记录的第7个字段之中,并不是每一条记录都需要统计的。根据我的文章的命名特点,它们的网址应该都以”/blog/2011/”开头,以”.html”结尾。所以,我用一个正则表达式”^/blog/2011/.*\.html$”,找出这些记录。参数i表示不区分大小写。

(3)sort

这时,所有需要统计的记录应该都列出来了,但是它们的次序是杂乱的。接着,使用sort命令,不过目的不是为了排序,而是把相同的网址排列在一起,为后面使用uniq命令创造条件。

(4)uniq -c

uniq的作用是过滤重复的记录,只保留一行。c参数的作用,是在每行的开头添加该记录的出现次数。处理之后的输出应该是这样的:

32 /blog/2011/01/guidelines_for_english_translations_in_public_places.html
32 /blog/2011/01/api_for_google_s_url_shortener.html
30 /blog/2011/01/brief_history_of_arm.html

它表示以上三篇文章,在1月1日的日志中,分别有32条、32条、30条的访问记录(即访问次数)。

(5)sed ‘s/^ *//g’ > www-01.log.result

上一步uniq命令添加的访问次数,是有前导空格的。也就是说,在上例的32、32、30之前有一连串空格,为了后续操作的方便,这里把前导空格删去。sed命令是一个处理行文本的编辑器,’s/^ *//g’是一个正则表达式(^和*之间有一个空格),表示将行首的连续空格替换为空(即删除)。接着,将排序结果重定向到文件www-01.result。单个日志分析就完成了。

五、月度汇总排名

经过上一步之后,1月份的31个日志文件,生成了31个对应的分析结果文件。为了汇总整个月的情况,必须把这31个结果文件合并。

(6)合并分析结果

for i in www-*.log.result 
do 
cat $i >> log.result
done

这是一个循环结构,把所有www-01.log.result形式的文件,都写进log.result文件。

然后,我用一行语句,计算月度排名。

sort -k2 log.result | uniq -f1 –all-repeated=separate |./log.awk |sort -rn > final.log.result

这行语句由3个命令和1个awk脚本组成:

(7)sort -k2 log.result

由于是31个文件汇总,log.result文件里面的记录是无序的,必须用sort命令,将相同网址的记录归类在一起。但是此时,访问次数是第一个字段,网址是第二个字段,因此参数k2表示根据第二个字段进行排序。

(8)uniq -f1 –all-repeated=separate

uniq的作用是过滤重复的记录,参数f1表示忽略第一个字段(访问次数),只考虑后面的字段(网址);参数表示all-repeated=separate,表示过滤掉所有只出现一次的记录,保留所有重复的记录,并且每一组之间用一个空行分隔。这一步完成以后,输出结果变成如下的形式:

617 /blog/2011/01/guidelines_for_english_translations_in_public_places.html
455 /blog/2011/01/guidelines_for_english_translations_in_public_places.html

223 /blog/2011/01/2010_my_blogging_summary.html
253 /blog/2011/01/2010_my_blogging_summary.html

相同网址都归在一组,组间用空行分割。为了简洁,上面的例子每一组只包含两条记录,实际上每一组都包含31条记录(分别代表当月每天的访问次数)。

(9)log.awk脚本

为了将31天的访问次数加总,我动了很多脑筋。最后发现,唯一的方法就是用awk命令,而且必须另写一个awk脚本。

#!/usr/bin/awk -f

BEGIN {
RS=”” #将多行记录的分隔符定为一个空行
}

{
sum=0 #定义一个表示总和的变量,初值为0
for(i=1;i<=NF;i++){ #遍历所有字段
if((i%2)!=0){ #判断是否为奇数字段
sum += $i #如果是的话,累加这些字段的值
}
}
print sum,$2 #输出总和,后面跟上对应的网址 
}

我已经对上面这个log.awk脚本加了详细注释。这里再说明几点:首先,默认情况下,awk将”\n”作为记录的分隔符,设置RS=””表示改为将空行作为分隔符,因此形成了一个多行记录;其次,NF是一个awk的内置变量,表示当前行的字段总数。由于输入文件之中,每一行都包含两个字段,第一个是访问数,第二个是网址,所以这里做一个条件判断,只要是奇数字段就累加,偶数字段则一律跳过。最后,每个记录输出一个累加值和网址,它们之间用空格分割。

(10)sort -rn > final.log.result

对awk脚本的处理结果进行排序,sort默认使用第一个字段,参数r表示逆序,从大往小排;参数n表示以数值形式排序,不以默认的字典形式排序,否则会出现10小于2的结果。排序结果重定向到final.log.result。至此,月度排名完成。

六、脚本文件

用一个脚本,包含上面两节所有的内容。

#!/bin/bash

if ls ./*.result &> /dev/null #判断当前目录中是否有后缀名为result的文件存在
then
rm *.result #如果有的话,删除这些文件
fi

touch log.result #创建一个空文件

for i in www-*.log #遍历当前目录中所有log文件
do 
echo $i … #输出一行字,表示开始处理当前文件
awk ‘$9 == 200 {print $7}’ $i|grep -i ‘^/blog/2011/.*\.html$’|sort|uniq -c|sed ‘s/^ *//g’ > $i.result #生成当前日志的处理结果
cat $i.result >> log.result #将处理结果追加到log.result文件
echo $i.result finished #输出一行字,表示结束处理当前文件
done

echo final.log.result … #输出一行字,表示最终统计开始

sort -k2 log.result | uniq -f1 –all-repeated=separate |./log.awk |sort -rn > final.log.result #生成最终的结果文件final.log.result

echo final.log.result finished #输出一行字,表示最终统计结束

开源Apache Camel简化SOA实施进程(转)

 apache-camel  开源Apache Camel简化SOA实施进程(转)已关闭评论
4月 012013
 

在过去的几年中,整合技术得到了突飞猛进的发展。XML/REST/Web 服务/面向服务架构(SOA)的革命不断的促使工程师们和软件公司去创造丰富的协议、适配器、传输器、容器、标准,最佳实践···应有尽有。

无可否认的,现有的这些代码是非常复杂的、多样化的,几乎没有什么它们不可以做到的事情。但这些软件包都是从技术上来建立的,从而使得如何有效的使用其功能成为了读者很大的挑战。

目前,众多读者都完成了这一项挑战。丰富的经验和成千上万的成功案例促进了许多基础架构设计模式定义的形成,从而帮助开发者在整合时能够开门见山,少走弯路。其中,有一套设计模式在业界引起了注意,那就是Hohpe 和 Woolf's企业整合模式。这些模式包含了一些技术上无关的词汇来描述大量整合的解决方案。他们并不是侧重于低层次的编程,而是采取自上而下的方案来开发一个异步的、以信息为基础的架构。

一致的词汇是很好的,而易于使用的框架在实际建立基础架构的时候岂不是更好吗?

这正是Apache的开源Camel项目背后的理念。现在,行之有效的并且真实的一套模式已可以获得了,很明显,下一步就是要去创造一个能够以最简单的方式来实施这个模式的驱动器。

Camel 是一个代码先行的工具,它允许开发者在无须学习厂商定制和复杂的底层技术的情况下进行精密的大规模集成。Camel使用Java领域说明性专用语言来连接信息系统和配置路由和调解规则,在POJO基础上实施企业整合模式。这样,就能使得开发人员不必阅读一页又一页的诸如JMS或JBI之类的技术规范,也不用处理较低级别的Spring框架就可以直接设计和建立面向服务架构(SOA)。

Apache Camel是从Apache其他项目尤其是Apache ActiveMQ 以及Apache ServiceMix的代码和灵感有机的衍生出来的。该项目的成员们发现:人们在许多不同的情况下都想要建立或是使用企业集成模式书中的模式。因此,Camel团队就这样明确的目的开始建立这样的框架。

Camel 概况:

建立Camel的第一步是解偶底层框架中的模式。一些人想要利用企业服务总线(ESB)中的模式,还有一些人则选择Message Broker中的模式,而其他人需要使用应用程序自身的模式或信息提供者间进行对话。仍然有一些人想要在Web服务框架下或是其他沟通平台上使用。比起将此路由代码与特定的Message Broker或企业服务总线(ESB)绑定来说,Camel选择提取此代码作为独立的框架, 这样一来它就能被应用到任何的项目中去。Camel有一个脚本――不管是在Servlet, 或是Web服务包中,全面企业服务总线(ESB),还是信息应用程序中,任何地方都可以做到重新利用。

Camel的最初也是主要的优势在于开发团队无须为了连接系统在容器上下功夫。很多人会认为从容器上下功夫是一个正确的途径,甚至是当成对勇气的考验,但对于越来越多的团队来说这些阻碍成为了不必要的障碍。有了Apache Camel,开发人员就能在完成任务的过程中将无关的任务减少到最低。如果其他要求得到保证的话,Camel还可以在JBI容器中实施,但这并不是必要的。

为了简化编程,Camel还支持特定的Java和XML域语言,使得企业集成模式你那个在所有的Java IDE或Spring XML中使用。这种更高层次的提取能更有效的解决问题。

Camel重新利用了许多Spring 2 的特性,如说明性交易,控制配置倒置,以及众多为了与JMS和JDBC,Java Persistence API (JPA)结合工作的实用层面的东西。这提高了抽取的水平,简化了编程,减少了需要编写的XML,但如果人们要是追根究底花些功夫的话,也会发现其实Camel仍然暴露了线级访问。

Camel示例

我们分别解释不同的方式实现Apache Camel的配置,首先将使用Java DSL(领域特定语言),接下来是Spring XML配置。

Java DSL 配置

如下的列子就是实现了当你想在一个目录结构中从JMS对列里得到信息。首先,我们需要创建一个CamelContext对象:

CamelContext context = new DefaultCamelContext();

这里远不止一种方法向CamelContext添加组件。你也可以在我们创建好路由之后再添加组件,正如一下示例所示: 

context.addRoutes(new RouteBuilder() { 
  public void configure() { 
  from("test-jms:queue:test.queue").to("file://test"); 
  // set up a listener on the file component 
  from("file://test").process(new Processor() { 
  public void process(Exchange e) { 
  System.out.println("Received exchange: " + e.getIn()); 
  } 
  }); 
  } 
  });

或者明确的加入JMS组件,如下所示:  

ConnectionFactory connectionFactory = new ActiveMQConnectionFactory("vm://localhost?broker.persistent=false"); 
  // note we can explicity name the component 
  context.addComponent("test-jms", JmsComponent.jmsComponentAutoAcknowledge(connectionFactory));

下次你必须要启动Camel context。如果你使用Spring去配置Camel context这将会为你实现自动化过程,如果你是使用纯Java的话那就必须用先调用start()的方法:

camelContext.start();

这将启动所有的配置路由规则。

当我们完全启动CamelContext后我们可以输入一些对象至Camel。

在通常的使用中,更多的情况往往是通过一些功能组件,外部系统将一些信息或是事件直接输入到Camel中,但是在这里我们将使用CamelTemplate,这也是一个最简单的方法用以测试之前的配置是否正确。

CamelTemplate template = new CamelTemplate(context);

这时我们可以使用CamelTemplate通过JMS发送一些测试消息:  

for (int i = 0; i < 10; i++) { 
  template.sendBody("test-jms:queue:test.queue", "Test Message: " + i); 
  }

我们从CamelTemplate中发送对象(此时通常为文本对象)纳入CamelContext中并提供给测试组件:jms:queue:test.queue。这些文本对象会自动修改进JMS信息中,并在JMS对列中以test.queue张贴出来。当我们创建好路线我们配置好FileComponent去接收test.queue。 

FileComponent文件将从对列中提取信息并保存在一个名为test的目录中。每一条信息都会存放在一个与其目的地或是信息ID相对应的文件中。

最后,我们配置自己的listener并从FileComponent获得通知,以文本的形式打印出来。

Spring XML配置

这个示例将使用Spring XML配置实现文件的转换,利用XQuery从目录中将结果发送至JMS 对列。它从目录中选取文件进行解析,然后使用XQuery进行转换,再发送至消息对列。当然,为了更清楚的看到生成文件,我们也会有一些别的方法去从JMS对列中选取内容再写到一个输出目录中。

运行示例

让我们用Camel Maven插件来运行这段示例。举例来说,通过开源软件的源代码版或可执行版即可实现以下操作:  

cd examples/camel-example-spring-xquery 
  mvn camel:run

你现在应该可以看到在target/outputFiles目录下所生成的文件内容,这就是从JMS对列中所读出的转化信息。 

代码走查

需要做的是用那些定义在类下的 META-INF/spring/camelContext.xml文件正常启动Spring应用。这是应用Camel的XML配置进行配置CamelContext的规范Spring XML文档。

请务必注意这段XML示例文件底部,我们明确的配置了ActiveMQ组件以及关于如何连接代理的详细内容。

关键的Spring XML代码内容如下所示:

<camelContext useJmx="true" xmlns="http://activemq.apache.org/camel/schema/spring"> 

   <!– lets parse files, transform them with XQuery and send them to JMS –> 
   <route> 
     <from uri="file:src/data?noop=true"/> 
     <to uri="xquery:myTransform.xquery"/> 
     <to uri="jms:MyQueue"/> 
   </route> 

   <!– now lets write messages from the queue to a directory –> 
   <route> 
     <from uri="jms:MyQueue"/> 
     <to uri="file:target/outputFiles"/> 
   </route> 

</camelContext> 

<!– lets configure the default ActiveMQ broker URL –> 
<bean id="jms" class="org.apache.camel.component.jms.JmsComponent"> 
   <property name="connectionFactory"> 
     <bean class="org.apache.activemq.ActiveMQConnectionFactory"> 
       <property name="brokerURL" value="vm://localhost?broker.persistent=false"/> 
     </bean> 
   </property> 
</bean> 

希望这篇文章能够让你真正认识到使用Apache Camel来实现企业应用整合是一件多么实际的事。 

转自:http://www.uml.org.cn/soa/200910162.asp