Springboot+Kettle(Spoon)

article/2025/10/30 21:18:30

Springboot集成kettle实战

  • 介绍
  • 项目截图
  • java+kettle实战代码
      • 1 pom.xml
      • 2 kettleUtil
      • 3 业务层方法
        • a 资源库业务
        • b 转换的相关业务
        • c 完整代码

介绍

kettle就不介绍了,Web界面极其简单、丑陋,生产环境无法投入使用.所以这篇实战内容是springboot结合kettle的web端执行已经在spoon客户端做好的ktr和kjb(既:这里不包括web页面制作ktr和kjb).主要功能如下:

  1. web页面选择本地文件夹作为资源库
  2. 从已配置好的资源库里选择ktr和kjb保存到系统
  3. 配置ktr和kjb的日志级别,可执行的角色(数据权限)
  4. 立即执行ktr,kjb
  5. 定时执行ktr,kjb
  6. 查看执行日志

项目截图

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

java+kettle实战代码

1 pom.xml

这里只贴了kettle的相关依赖.完整的请看后面的完整代码

<!-- kettle核心依赖 --><dependency><groupId>pentaho-kettle</groupId><artifactId>kettle-core</artifactId><version>${kettle-version}</version></dependency><dependency><groupId>pentaho-kettle</groupId><artifactId>kettle-engine</artifactId><version>${kettle-version}</version></dependency><dependency><groupId>pentaho-kettle</groupId><artifactId>kettle-dbdialog</artifactId><version>${kettle-version}</version></dependency><dependency><groupId>org.pentaho.di.plugins</groupId><artifactId>kettle-sap-plugin-core</artifactId><version>${kettle-version}</version></dependency><dependency><groupId>pentaho-kettle</groupId><artifactId>kettle-ui-swt</artifactId><version>${kettle-version}</version></dependency><!--kettle执行复杂脚本需要此包,如执行js组件--><dependency><groupId>org.codehaus.janino</groupId><artifactId>janino</artifactId><version>${janino-version}</version></dependency><dependency><groupId>org.eclipse.birt.runtime.3_7_1</groupId><artifactId>org.mozilla.javascript</artifactId><version>${javascript-version}</version></dependency><!-- kettle plugin excel--><dependency><groupId>net.sourceforge.jexcelapi</groupId><artifactId>jxl</artifactId><version>${jxl-version}</version></dependency><!-- 降低MySQL版本,kettle中连接mysql资源库使用的是低版本驱动 --><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.11</version></dependency><!--  org.gjt.mm.mysql.Driver      --><dependency><groupId>mm.mysql</groupId><artifactId>mm.mysql</artifactId><version>2.0.7</version></dependency><!--        sqlserver(native)连接方式驱动--><dependency><groupId>com.microsoft.sqlserver</groupId><artifactId>sqljdbc4</artifactId><version>4.0</version></dependency><!--        sqlser连接驱动--><dependency><groupId>net.sourceforge.jtds</groupId><artifactId>jtds</artifactId><version>1.2.4</version></dependency>

2 kettleUtil

封装了一些常用的方法,贴了执行转换的,job类似

    /*** 执行文件资源库转换* @param transPath 转换路径(相对于资源库)* @param transName 转换名称(不需要后缀)* @param namedParams 命名参数* @param clParams 命令行参数*/public void callTrans(String transPath, String transName, Map<String,String> namedParams, String[] clParams) throws Exception {KettleEnv.init();DatabaseMeta databaseMeta=new DatabaseMeta("kettle_trans_log", "mysql", "Native(JDBC)","xxx.xxx.x.xx","bps?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=GMT%2B8", "3306", "root", "password");String msg;KettleFileRepository repo = this.fileRepositoryCon();TransMeta transMeta = this.loadTrans(repo, transPath, transName);transMeta.addDatabase(databaseMeta);VariableSpace space=new Variables();TransLogTable jobLogTable= TransLogTable.getDefault(space,transMeta,null);jobLogTable.setTableName("kettle_trans_log");jobLogTable.setConnectionName("kettle_trans_log");transMeta.setTransLogTable(jobLogTable);//transMeta.getTransLogTable().setTableName(repInitialization.transLog);//转换Trans trans = new Trans(transMeta);//设置命名参数if(null != namedParams) {//namedParams.forEach(trans::setParameterValue);/*for (Map.Entry<String, String> entry : namedParams.entrySet()) {trans.setParameterValue(entry.getKey(), entry.getValue());}*/for(Iterator<Map.Entry<String, String>> it = namedParams.entrySet().iterator(); it.hasNext();){Map.Entry<String, String> entry = it.next();trans.setParameterValue(entry.getKey(), entry.getValue());}}trans.setLogLevel(this.getLogerLevel(KETTLE_LOG_LEVEL));//执行trans.execute(clParams);trans.waitUntilFinished();KettleLogStore.discardLines(trans.getLogChannelId(),true);//记录日志String logChannelId = trans.getLogChannelId();LoggingBuffer appender = KettleLogStore.getAppender();String logText = appender.getBuffer(logChannelId, true).toString();log.info("[logTextlogText:"+logText+":logTextlogText]");//抛出异常if (trans.getErrors() > 0) {msg = "There are errors during transformation exception!(转换过程中发生异常)";log.error(msg);throw new Exception(msg);}}

3 业务层方法

a 资源库业务

/*** 资源库Service业务层处理* * @author kone* @date 2021-07-12*/
@Service
public class XRepositoryServiceImpl implements IXRepositoryService 
{@Autowiredprivate XRepositoryMapper xRepositoryMapper;/*** 查询资源库* * @param id 资源库ID* @return 资源库*/@Overridepublic XRepository selectXRepositoryById(Long id){return xRepositoryMapper.selectXRepositoryById(id);}/*** 查询资源库列表* * @param xRepository 资源库* @return 资源库*/@Overridepublic List<XRepository> selectXRepositoryList(XRepository xRepository){return xRepositoryMapper.selectXRepositoryList(xRepository);}/*** 新增资源库* * @param xRepository 资源库* @return 结果*/@Overridepublic int insertXRepository(XRepository xRepository){String userName = (String) PermissionUtils.getPrincipalProperty("userName");xRepository.setCreatedBy(userName);xRepository.setUpdateBy(userName);xRepository.setType("File");return xRepositoryMapper.insertXRepository(xRepository);}/*** 修改资源库* * @param xRepository 资源库* @return 结果*/@Overridepublic int updateXRepository(XRepository xRepository){String userName = (String) PermissionUtils.getPrincipalProperty("userName");xRepository.setUpdateTime(DateUtils.getNowDate());xRepository.setUpdateBy(userName);return xRepositoryMapper.updateXRepository(xRepository);}/*** 删除资源库对象* * @param ids 需要删除的数据ID* @return 结果*/@Overridepublic int deleteXRepositoryByIds(String ids){return xRepositoryMapper.updateIsDelBatch(Convert.toStrArray(ids));// return xRepositoryMapper.deleteXRepositoryByIds(Convert.toStrArray(ids));}/*** 删除资源库信息* * @param id 资源库ID* @return 结果*/@Overridepublic int deleteXRepositoryById(Long id){return xRepositoryMapper.updateIsDel(id);//return xRepositoryMapper.deleteXRepositoryById(id);}@Overridepublic List<RepoTree> selectRepoRoot(XRepository repository) {List<XRepository> repositoryList = xRepositoryMapper.selectXRepositoryList(repository);List<RepoTree> ztrees = initZtree2(repositoryList);return ztrees;}@Overridepublic List<RepoTree> selectRepoTree(Long id) {XRepository xrs = xRepositoryMapper.selectXRepositoryById(id);List<RepositoryTree> repositoryTrees = getRepoTress(xrs);List<RepositoryTree> subTrees = new ArrayList<>();String type=null;String pId=String.valueOf(xrs.getId());List<RepoTree> ztrees = initZtree(repositoryTrees,String.valueOf(id));return ztrees;}public List<RepoTree> initZtree(List<RepositoryTree> repositoryList ,String parentId){List<RepoTree> ztrees = new ArrayList<RepoTree>();for (RepositoryTree rt : repositoryList) {if(rt.getId().equals(parentId) || rt.getText().equals("/")){continue;}RepoTree ztree = new RepoTree();ztree.setId(rt.getId());ztree.setpId(rt.getParent());ztree.setName(rt.getText());ztree.setTitle(rt.getPath());ztrees.add(ztree);}return ztrees;}public List<RepoTree> initZtree2(List<XRepository> repositoryList ){List<RepoTree> ztrees = new ArrayList<RepoTree>();for (XRepository rt : repositoryList){RepoTree ztree = new RepoTree();ztree.setId(String.valueOf(rt.getId()));ztree.setpId(" ");ztree.setName(rt.getRepoName());ztree.setTitle(rt.getBaseDir());ztrees.add(ztree);}return ztrees;}private List<RepositoryTree> getRepoTress(XRepository xr) {List<RepositoryTree> repositoryTrees = new ArrayList<>();List<XRepository> xRepositoryList =xRepositoryMapper.selectXRepositoryList(xr);if (!CollectionUtils.isEmpty(xRepositoryList)) {xRepositoryList.forEach(item -> {List<RepositoryTree> tmpRepositoryList = new ArrayList<>();String type = item.getType();if (type.equalsIgnoreCase("File")) {// 文件库String baseDir = item.getBaseDir();try {KettleFileRepository repository = (KettleFileRepository) KettleUtil_2.conFileRep(String.valueOf(item.getId()), item.getRepoName(), baseDir);XRepoManager.getAllDirectoryTreeList(String.valueOf(item.getId()), repository, "/", tmpRepositoryList);if (tmpRepositoryList.size() > 0) {RepositoryDirectoryInterface rDirectory = repository.loadRepositoryDirectoryTree().findDirectory("/");RepositoryTree repositoryTree = new RepositoryTree();repositoryTree.setParent(String.valueOf(item.getId()));repositoryTree.setId(item.getRepoId() + "@" + rDirectory.getObjectId().toString());//repositoryTree.setId(String.valueOf(item.getId()));repositoryTree.setText(rDirectory.getName().equals("\\/") ? "基础路径" : rDirectory.getName());repositoryTree.setLasted(false);repositoryTree.setType("tree");repositoryTree.setPath("file");tmpRepositoryList.add(repositoryTree);}} catch (KettleException e) {StringWriter sw = new StringWriter();e.printStackTrace(new PrintWriter(sw));}}repositoryTrees.addAll(tmpRepositoryList);});}return repositoryTrees;}}

b 转换的相关业务

注释应该还算清楚(有点不自信/(ㄒoㄒ)/~~)


/*** 转换Service业务层处理* * @author kone* @date 2021-07-14*/
@Service("kettleTransServiceImpl")
public class KettleTransServiceImpl implements IKettleTransService
{@Autowiredprivate KettleTransMapper kettleTransMapper;@Autowiredprivate XRepositoryMapper repositoryMapper;@Autowiredprivate KettleUtil kettleUtil;/*** 查询转换** @param id 转换ID* @return 转换*/@Overridepublic KettleTrans selectKettleTransById(Long id){return kettleTransMapper.selectKettleTransById(id);}/*** 查询转换列表** @param kettleTrans 转换* @return 转换*/@Overridepublic List<KettleTrans> selectKettleTransList(KettleTrans kettleTrans){Object o=PermissionUtils.getPrincipalProperty("roles");List<SysRole> roleList=new ArrayList<>();// roleList= (List<SysRole>) PermissionUtils.getPrincipalProperty("roles");if(o != null && o instanceof List<?>){for(Object r:(List<?>)o){roleList.add(SysRole.class.cast(r));}}//当前用户的roleKeyList<String> roleKeys=roleList.stream().map(SysRole::getRoleKey).collect(Collectors.toList());return kettleTransMapper.selectKettleTransList(kettleTrans,roleKeys);}/*** 新增转换** @param kettleTrans 转换* @return 结果*/@Overridepublic AjaxResult insertKettleTrans(KettleTrans kettleTrans){String transName=kettleTrans.getTransName();if(kettleTransMapper.selectKettleTransByTransName(transName)>0){return AjaxResult.error("已存在同名转换");}String userName = (String) PermissionUtils.getPrincipalProperty("userName");if(kettleTrans.getRoleKey()==null){kettleTrans.setRoleKey("admin");}else{if(!kettleTrans.getRoleKey().contains("admin")){kettleTrans.setRoleKey(kettleTrans.getRoleKey().concat(",admin"));}}kettleTrans.setCreatedBy(userName);kettleTrans.setUpdateBy(userName);kettleTrans.setTransType("File");return  AjaxResult.success(kettleTransMapper.insertKettleTrans(kettleTrans));}/*** 修改转换** @param kettleTrans 转换* @return 结果*/@Overridepublic int updateKettleTrans(KettleTrans kettleTrans){String userName = (String) PermissionUtils.getPrincipalProperty("userName");kettleTrans.setUpdateBy(userName);kettleTrans.setUpdateTime(DateUtils.getNowDate());kettleTrans.setTransType("File");if(kettleTrans.getRoleKey()==null){kettleTrans.setRoleKey("admin");}else{if(!kettleTrans.getRoleKey().contains("admin")){kettleTrans.setRoleKey(kettleTrans.getRoleKey().concat(",admin"));}}        return kettleTransMapper.updateKettleTrans(kettleTrans);}/*** 删除转换对象** @param ids 需要删除的数据ID* @return 结果*/@Overridepublic int deleteKettleTransByIds(String ids){return kettleTransMapper.deleteKettleTransByIds(Convert.toStrArray(ids));}/*** 删除转换信息** @param id 转换ID* @return 结果*/@Overridepublic int deleteKettleTransById(Long id){return kettleTransMapper.deleteKettleTransById(id);}/*** @Description:立即执行一次转换* @Author: Kone.wang* @Date: 2021/7/15 14:31* @param trans :* @return: void**/@Overridepublic AjaxResult run(KettleTrans trans) {Long id = trans.getId();KettleTrans kettleTrans = kettleTransMapper.selectKettleTransById(id);if(kettleTrans ==null){return AjaxResult.error("转换不存在!");}XRepository repository=repositoryMapper.selectXRepositoryById(kettleTrans.getTransRepositoryId());if(repository==null){return AjaxResult.error("资源库不存在!");}String path = kettleTrans.getTransPath();try {kettleUtil.KETTLE_LOG_LEVEL=kettleTrans.getTransLogLevel();kettleUtil.KETTLE_REPO_ID=String.valueOf(kettleTrans.getTransRepositoryId());kettleUtil.KETTLE_REPO_NAME=repository.getRepoName();kettleUtil.KETTLE_REPO_PATH=repository.getBaseDir();kettleUtil.callTrans(path,kettleTrans.getTransName(),null,null);} catch (Exception e) {e.printStackTrace();}return AjaxResult.success("执行成功!");}/*** @Description:查询抓换执行日志* @Author: Kone.wang* @Date: 2021/7/28 16:24* @param kettleTrans:* @return: java.util.List<java.lang.String>**/@Overridepublic List<String> queryTransLog(KettleTrans kettleTrans)  {List<String> transLogs=kettleTransMapper.queryTransLog(kettleTrans.getTransName());return transLogs;}/*** @Description:设置定时执行转换* @Author: Kone.wang* @Date: 2021/7/21 14:59* @param id:* @param transName:* @return: com.ruoyi.common.core.domain.AjaxResult**/@Overridepublic AjaxResult runTransQuartz(String id, String transName) {KettleTrans kettleTrans = kettleTransMapper.selectKettleTransById(Long.valueOf(id));return run(kettleTrans);}/*** @Description:检查该转换是否设置了定时任务* @Author: Kone.wang* @Date: 2021/7/21 16:37* @param checkStr:* @return: int**/@Overridepublic Long checkQuartzExist(String checkStr) {return kettleTransMapper.checkQuartzExist(checkStr);}
}

job和定时任务的细节代码就不贴了,要不然全屏都是这些鬼东西.

c 完整代码

码云:点这里


http://chatgpt.dhexx.cn/article/8W3AIOcS.shtml

相关文章

spoon新手入门教程

Kettle是一款国外开源的ETL工具&#xff0c;纯java编写&#xff0c;可以在Window、Linux、Unix上运行&#xff0c;数据抽取高效稳定。Kettle 中文名称叫水壶&#xff0c;该项目的主程序员MATT 希望把各种数据放到一个壶里&#xff0c;然后以一种指定的格式流出。Kettle这个ETL工…

集线器、交换机与路由器有什么区别?

转发自&#xff1a;https://mp.weixin.qq.com/s/YXWBw3aFTSEFvkg_oN9eQA 我相信我们都玩过一款特别火的游戏&#xff1a;帝国时代。小时候想要玩帝国时代&#xff0c;需要到软件城购买盗版光盘安装&#xff08;大概3块钱一张左右的样子&#xff0c;当时已经觉得很便宜了&#…

集线器和中继器

首先要明白&#xff0c;集线器和中继器两者都属于物理层的设备。物理层设备和其他层次的设备(如&#xff1a;交换机、网桥、路由器)最大的区别在于&#xff1a;集线器和中继器工作在同一个网段下的&#xff0c;而交换机、路由器等设备是工作在不同网段下的。 网段&#xff1a;…

# 网络中的一些基本概念 网卡、集线器、网桥(自学用)

# 网络中的一些基本概念 网卡、集线器、网桥 1. 网卡 1. 有几个网卡就有几个MAC地址 2. 计算机上的网卡来接收数据&#xff0c;网卡将数据传递给上一层 3. 发送数据&#xff1a;需要知道IP地址&#xff0c;但最终是根据MAC地址&#xff08;网卡地址&#xff09;&#xff0c;输送…

【计算机网络-数据链路层】集线器、网桥、交换机

本文许多文字和图片使用了湖科大教书匠&#xff08;高军老师&#xff09;的 PPT&#xff0c;在此表示感谢。正是他让非科班的我能以奇妙的方式走进网络的世界。 文章目录 1 【物理层】集线器&#xff08;Hub&#xff09;——共享式以太网1.1 为什么使用集线器&#xff1f;1.2 …

【计网】(一) 集线器、网桥、交换机、路由器等概念

这篇文章将介绍计算机网络中的一些基础概念&#xff0c;以及生活中我们所常见的一些设备&#xff08;交换机、路由器等&#xff09;的作用。 目录 ✅ 互联网的概念✅ 什么是网络协议✅ 网络互联模型✅ 计算机之间是如何通信的&#x1f43e; 网线直连&#x1f43e; 同轴电缆(Co…

扩展以太网——集线器

一、集线器 1、集线器组建的以太网其实是一个冲突域&#xff0c;因为其共享信道&#xff0c;会存在信号冲突。 2、集线器是物理层设备&#xff0c;信号经过它的时候直接传输&#xff0c;没有存储再转发的过程。 3、集线器和网线一样工作在物理层。 二、集线器的优缺点 1、…

集线器、交换机与路由器有什么区别和联系?

转载&#xff1a;集线器、交换机与路由器有什么区别&#xff1f; 我相信我们都玩过一款特别火的游戏&#xff1a;帝国时代。小时候想要玩帝国时代&#xff0c;需要到软件城购买盗版光盘安装&#xff08;大概3块钱一张左右的样子&#xff0c;当时已经觉得很便宜了&#xff0c;谁…

中继器、集线器、网桥、交换机、路由器

全家福 两台主机如何连接起来&#xff1f; 在网络诞生之前&#xff0c;电脑之间都是单机运行&#xff0c;没有网卡、没有网线、没有协议栈&#xff0c;数据传输主要通过软盘、光盘等介质。 网线来了 【网线网卡协议栈】三要素&#xff0c;是组成“最小单元网络”的基础&#x…

集线器、交换机、路由器有什么区别?

作者&#xff1a;薛定谔不在家 来源&#xff1a;https://www.zhihu.com/question/22007235/answer/402261894 帝国时代 我相信我们都玩过一款特别火的游戏&#xff1a;帝国时代。小时候想要玩帝国时代&#xff0c;需要到软件城购买盗版光盘安装&#xff0c;大概3块钱一张左右的…

集线器、交换机和路由器之间有何不同?

集线器、交换机和路由器都是用于构建网络的设备&#xff0c;且分别在不同层次发挥着其作用 。但目前&#xff0c;许多人对集线器、交换机和路由器的认识并不充分&#xff0c;甚至不知道这三者之间有什么区别。下面将重点为您介绍集线器、交换机和路由器&#xff0c;并阐明它们之…

集线器、网桥、交换机、路由器

目录 计算机之间的通信基础 计算机之间的连接方式 网线直连 同轴电缆 集线器&#xff08;Hub&#xff09; 网桥&#xff08;Bridge&#xff09; 交换机 路由器 本文参照小码哥的网络协议视频记录 计算机之间的通信基础 需要得知对方的IP地址。最终是根据MAC地址&#x…

交换机和集线器的区别是什么?

换机工作在数据链路层&#xff0c;通过MAC地址转发数据。集线器工作在物理层&#xff0c;通过广播的形式转发数据。目前&#xff0c;集线器已经被交换机取代&#xff0c;组网中很少使用集线器了。下文具体说一说。 方法/步骤 区别1&#xff1a;工作层次 集线器工作在物理层…

计算机网络——集线器与交换机

&#x1f49f;&#x1f49f;前言 ​ 友友们大家好&#xff0c;我是你们的小王同学&#x1f617;&#x1f617; 今天给大家打来的是 计算机网络——集线器与交换机 希望能给大家带来有用的知识 觉得小王写的不错的话麻烦动动小手 点赞&#x1f44d; 收藏⭐ 评论&#x1f4c4; 小…

计算机网络实验三 集线器、交换机、路由器与ARP

实验目的和要求 1&#xff09;集线器、交换机和路由器和 ARP 的基本工作原理 2&#xff09;掌握使用 PacketTracer 模拟网络场景的基本方法&#xff0c;加深对网络环境、网络设备和网 络协议交互过程等方面的理解。 实验环境 1&#xff09;运行 Windows 2008 Server/XP/7 操…

集线器、交换机、路由器

文章目录 1.集线器Hub [ 物理层 ]2.交换机 Switch [ 数据链路层 ]交换机自学习算法以太网交换机的2种交换模式:直通式、存储转发式3.路由器 Router [ 网络层 ]1.集线器Hub [ 物理层 ] 物理层设备:中继器、集线器既不能隔离冲突域,更不能隔离广播域2.交换机 Switch [ 数据链路…

集线器、路由器与交换机

1. 集线器、交换机与路由器的区别 1.1. 集线器、交换机和路由器的定义 集线器&#xff08;HUB&#xff09;属于数据通信系统中的基础设备&#xff0c;它和双绞线等传输介质一样&#xff0c;是一种不需任何软件支持或只需很少管理软件管理的硬件设备。 它被广泛应用到各种场合…

集线器、网桥、交换机简介

一.集线器 集线器&#xff08;HUB&#xff09;&#xff0c;它是工作在物理层的设备&#xff0c; 由于它只是工作在物理层的设备&#xff0c;所以它并不关心也不可能关心OSI上面几层所涉及的&#xff0c;它的工作机制流程是&#xff1a;从一个端口接收到数据包时&#xff0c;会…

集线器与交换机

文章目录 集线器与交换机集线器交换机集线器与交换机的区别单播帧广播帧多主机同时发送单播帧扩展以太网 总结 以太网交换机自学习 集线器与交换机 集线器 使用集线器的以太网在逻辑上仍是一个总线网&#xff0c;各站共享总线资源&#xff0c;使用的还是CSMA/CD协议;集线器只…

集线器

集线器&#xff08;HUB&#xff09;属于数据通信系统中的基础设备&#xff0c;它和双绞线等传输介质一样&#xff0c;是一种不需任何软件支持或只需很少管理软件管理的硬件设备。它被广泛应用到各种场合。集线器工作在局域网(LAN)环境&#xff0c;像网卡一样&#xff0c;应用于…