精华内容
下载资源
问答
  • 武汉理工大学中间件平时作业附源码,有需要的可以下载哦。
  • 中间件作业

    2021-05-03 10:56:28
    RMI 框架 和 jdbc myql数据库使用 1. 服务器 连接mysql数据库 rmi接口 使用 gson-2.8.5.jar 和 mysql-8.0.11.jar import java.sql.Connection; import java.sql.DriverManager;...import java.sql.SQLException;...

    RMI 框架 和 jdbc myql数据库使用

    1. 服务器

    • 连接mysql数据库
    • rmi接口
    • 使用 gson-2.8.5.jar 和 mysql-8.0.11.jar
    import java.sql.Connection;
    import java.sql.DriverManager;
    import java.sql.SQLException;
    
    public class DbUtil {
        private String url="jdbc:mysql://localhost:3306/zuoye?allowPublicKeyRetrieval=true&useSSL=false&useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=CONVERT_TO_NULL&serverTimezone=Asia/Shanghai";
        private String dbUser="root";
        private String dbPassword="123456";
        private String dbDriver="com.mysql.cj.jdbc.Driver";
        /**
         * 连接对象
         */
        private Connection connection=null;
    
        public Connection getConnection(){
            try {
                Class.forName(dbDriver);
                connection=DriverManager.getConnection(url,dbUser,dbPassword);
                System.out.println("[SQL]:数据库连接成功,驱动注册成功");
            } catch (ClassNotFoundException e) {
                System.out.println("[SQL]:数据库连接失败,找不到驱动类");
                e.printStackTrace();
            } catch (SQLException throwables) {
                System.out.println("[SQL]:数据库连接失败");
                throwables.printStackTrace();
            }
            return connection;
        }
    
        public void closeConnection(){
            if(connection!=null){
                try {
                    connection.close();
                    System.out.println("[SQL]:数据库连接关闭");
                } catch (SQLException throwables) {
                    System.out.println("[SQL]:数据库连接关闭失败");
                    throwables.printStackTrace();
                }
            }
        }
    
    
    //    /**
    //     * 建立连接
    //     */
    //    private void initConnection(){
    //        try {
    //            /* 注册驱动 */
    //            /*
    //            方法1.注册驱动(3种方法),依赖于驱动jar包的存在,否则无法通过编译
    //            DriverManager.registerDriver(new com.mysql.jdbc.Driver());
    //            方法2:System.setProperties("jdbc.drivers"," com.mysql.cj.jdbc.Driver");
    //            方法3:Class.forName("com.mysql.cj.jdbc.Driver");
    //            */
    //            Class.forName("com.mysql.cj.jdbc.Driver");
    //            /* 建立连接 */
    //            String jdbc="jdbc:mysql://localhost:3306/zuoye?allowPublicKeyRetrieval=true&useSSL=false&useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=CONVERT_TO_NULL&serverTimezone=Asia/Shanghai";
    //            conn= DriverManager.getConnection(jdbc,"jeesite","jeesite");
    //            /* 创建会话 */
    //            statement=conn.createStatement();
    //            System.out.println("[SQL]:数据库连接成功");
    //        } catch (Exception e) {
    //            System.out.println("[SQL]:数据库连接失败");
    //            e.printStackTrace();
    //        }
    //    }
    }
    
    
    import java.sql.Connection;
    
    public class BaseDao<T> {
        private DbUtil dbUtil=new DbUtil();
        public Connection connection= dbUtil.getConnection();
        public void closeConnection(){
            dbUtil.closeConnection();
        }
    }
    
    import java.sql.*;
    import java.util.LinkedList;
    import java.util.List;
    
    public class DBmanager extends BaseDao<StudentScore>{
    
        /**
         * 数据表Student中添加一条数据
         * @param studentScore
         * @return 是否添加成功
         */
        public boolean addItem(StudentScore studentScore){
            String sql="insert into Student(id,name,score) values(null,?,?)";
            try {
                PreparedStatement preparedStatement=connection.prepareStatement(sql);
                preparedStatement.setString(1,studentScore.getName());
                preparedStatement.setFloat(2,studentScore.getScore());
                return preparedStatement.executeUpdate()>0;
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
            return false;
        }
    
        /**
         * 数据表Student中删除一条数据
         * @param studentScore
         * @return 是否删除成功
         */
        public boolean delItem(StudentScore studentScore){
            String sql="delete from Student where name like ?";
            try {
                PreparedStatement preparedStatement=connection.prepareStatement(sql);
                preparedStatement.setString(1,studentScore.getName());
                return preparedStatement.executeUpdate()>0;
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
            return false;
        }
    
        /**
         * 得到数据库中全部数据列表List
         * @return LinkedList<StudentScore>
         */
        public LinkedList<StudentScore> getList(){
            LinkedList<StudentScore> resultList=new LinkedList<>();
            String sql="select * from Student";
            try {
                PreparedStatement preparedStatement=connection.prepareStatement(sql);
                ResultSet resultSet=preparedStatement.executeQuery();
                while(resultSet.next()){
                    int id=resultSet.getInt(1);
                    String name=resultSet.getString(2);
                    float score=resultSet.getFloat(3);
                    resultList.add(new StudentScore(id,name,score));
                }
            } catch (Exception throwables) {
                throwables.printStackTrace();
            }
            return resultList;
        }
    
        /**
         * 更新表中的一条项目Item
         * @param studentScore
         * @return 是否更新成功
         */
        public boolean updateItem(StudentScore studentScore){
            String sql="update Student set name=?, score=? where id=?";
            try {
                PreparedStatement preparedStatement=connection.prepareStatement(sql);
                preparedStatement.setString(1,studentScore.getName());
                preparedStatement.setFloat(2,studentScore.getScore());
                preparedStatement.setInt(3,studentScore.getId());
                return preparedStatement.executeUpdate()>0;
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
            return false;
        }
    
    }
    
    
    import java.rmi.RemoteException;
    import java.rmi.server.UnicastRemoteObject;
    
    public class StudentScore extends UnicastRemoteObject {
        private int id;
        private String name;
        private float score;
    
        public StudentScore(int id, String name, float score) throws RemoteException {
            super();
            this.id = id;
            this.name = name;
            this.score = score;
        }
    
        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 float getScore() {
            return score;
        }
    
        public void setScore(float score) {
            this.score = score;
        }
    }
    
    import java.rmi.Remote;
    import java.rmi.RemoteException;
    
    public interface DataService extends Remote {
        //public double getData() throws RemoteException;
        public String getList() throws RemoteException;
        public boolean addItem(String _name, float _score) throws RemoteException;
        public boolean delItem(String _name, float _score) throws RemoteException;
        public boolean updateItem(int id, String _name, float _score) throws RemoteException;
    
    }
    
    
    import com.google.gson.Gson;
    
    import java.rmi.RemoteException;
    import java.rmi.server.UnicastRemoteObject;
    import java.util.Calendar;
    import java.util.LinkedList;
    import java.util.concurrent.Callable;
    import java.util.concurrent.ExecutionException;
    import java.util.concurrent.FutureTask;
    
    public class DataServiceImpl extends UnicastRemoteObject implements DataService {
        private DBmanager dBmanager=new DBmanager();
    
        public DataServiceImpl() throws RemoteException {
            super();
        }
    
        @Override
        public String getList() throws RemoteException {
            LinkedList<StudentScore> result=null;
            Callable<LinkedList<StudentScore>> getListTask=new Callable<LinkedList<StudentScore>>() {
                @Override
                public LinkedList<StudentScore> call() throws Exception {
                    return dBmanager.getList();
                }
            };
            FutureTask<LinkedList<StudentScore>> futureTask=new FutureTask<>(getListTask);
            new Thread(futureTask).start();
    
            try {
                result=futureTask.get();
            } catch (Exception e) {
                e.printStackTrace();
            }
            String resultJsonString=new Gson().toJson(result);
            return resultJsonString;
        }
    
        @Override
        public boolean addItem(String _name, float _score) throws RemoteException {
            boolean result=false;
            StudentScore studentScore=new StudentScore(0,_name,_score);
            Callable<Boolean> addItemTask=new Callable<Boolean>() {
                @Override
                public Boolean call() throws Exception {
                    return dBmanager.addItem(studentScore);
                }
            };
            FutureTask<Boolean> futureTask=new FutureTask<>(addItemTask);
            new Thread(futureTask).start();
    
            try {
                result=futureTask.get();
            } catch (Exception e) {
                e.printStackTrace();
            }
            return result;
        }
    
        @Override
        public boolean delItem(String _name, float _score) throws RemoteException {
            boolean result=false;
            StudentScore studentScore=new StudentScore(0,_name,_score);
            Callable<Boolean> delItemTask=new Callable<Boolean>() {
                @Override
                public Boolean call() throws Exception {
                    return dBmanager.delItem(studentScore);
                }
            };
            FutureTask<Boolean> futureTask=new FutureTask<>(delItemTask);
            new Thread(futureTask).start();
    
            try {
                result=futureTask.get();
            } catch (Exception e) {
                e.printStackTrace();
            }
            return result;
        }
    
        @Override
        public boolean updateItem(int id, String _name, float _score) throws RemoteException {
            boolean result=false;
            StudentScore studentScore=new StudentScore(id,_name,_score);
            Callable<Boolean> updateItemTask=new Callable<Boolean>() {
                @Override
                public Boolean call() throws Exception {
                    return dBmanager.updateItem(studentScore);
                }
            };
            FutureTask<Boolean> futureTask=new FutureTask<>(updateItemTask);
            new Thread(futureTask).start();
    
            try {
                result=futureTask.get();
            } catch (Exception e) {
                e.printStackTrace();
            }
            return result;
        }
    }
    
    import java.rmi.Naming;
    import java.rmi.RMISecurityManager;
    import java.rmi.registry.LocateRegistry;
    
    public class MainServer {
    
        public MainServer() {
        }
    
        public static void main(String[] args) {
            // 创建并安装安全管理器
            if (System.getSecurityManager() == null) {
                System.setSecurityManager(new RMISecurityManager());
            }
    
            try {
                // 创建远程对象
                DataServiceImpl ds=new DataServiceImpl();
    
                // 启动注册服务,如果没有这个语句,需要手工启动:开始菜单--运行--rmiregistry,默认端口1099
                LocateRegistry.createRegistry(1111);   //这里,服务端口号可任意指定
    
                // 远程对象绑定到服务
                Naming.rebind("//localhost:1111/ds", ds);
    
                System.out.println("[RMI]:服务器正在运行。。。");
            } catch (Exception e) {
                e.printStackTrace();
            }
    
        }
    }
    
    

    客户端

    • rmi接口
    • 使用 gson-2.8.5.jar
    import java.rmi.Remote;
    import java.rmi.RemoteException;
    
    public interface DataService extends Remote
    {
        public String getList() throws RemoteException;
        public boolean addItem(String _name, float _score) throws RemoteException;
        public boolean delItem(String _name, float _score) throws RemoteException;
        public boolean updateItem(int id, String _name, float _score) throws RemoteException;
    }
    
    import com.google.gson.Gson;
    
    import java.rmi.Naming;
    import java.rmi.RMISecurityManager;
    import java.util.List;
    import java.util.Scanner;
    
    public class RmiClient {
        public static void main(String[] args) {
            // 创建并安装安全管理器
            if (System.getSecurityManager() == null) {
                System.setSecurityManager(new RMISecurityManager());
            }
            Scanner scanner=new Scanner(System.in);
            try {
                DataService ds = (DataService) Naming.lookup("//localhost:1111/ds");
                System.out.println("[RMI]: 客户端已接入服务器");
                System.out.println("[TEST]: 测试开始");
                System.out.println("当前服务器中数据:"+ds.getList());
                System.out.println("[TEST]: 插入一条数据");
                System.out.print("请输入学生姓名:");
                String name=scanner.next();
                System.out.println(name);
                System.out.print("请输入学生得分:");
                float score=scanner.nextFloat();
                System.out.println(score);
                ds.addItem(name,score);
                System.out.println("[TEST]: 执行插入操作");
                System.out.println("[TEST]: 查询当前数据库");
                System.out.println("当前服务器中数据:"+ds.getList());
            } catch (Exception e) {
                e.printStackTrace();
            }
    
        }
    }
    
    展开全文
  • 《物联网中间件设计》课程教学大纲
  • Spring家族的新成员Spring Batch批处理作业中间件.zip
  • 行业分类-作业装置-基于中间件的主备节点工作方法及装置、电子设备.7z
  • 作业中间件以对作业进行评分 该软件包包含一个,可以对Laravel应用中的作业进行评分。 支持我们 我们投入了大量资源来创建。 您可以通过来支持我们。 非常感谢您从家乡寄给我们一张明信片,其中提到您使用的是...
  • 行业分类-作业装置-一种针对消息中间件的调优方法及系统.zip
  • 行业分类-作业装置-一种基于物联网中间件的云端组态方法.7z
  • 本文来自于网络,本篇文章详细介绍了分布式定时任务中间件—Elastic-Job以及它是如何实现的,希望文章的介绍可以让大家有个新的认识。在互联网应用中,各式各样的定时任务存于系统各个角落。我们希望由一个平台统一...
  • GOS2 (Grid Operation System)是国内自主开发的一款网格中间件。该文介绍了GOS2的特点和几个主要模块:社区、网程和网程容器、安全机制、网格文件系统、网格批作业系统以及网格记账系统。文中给出了一种基于GOS2系统...
  • 行业分类-作业装置-一种基于消息中间件的数据迁移方法及系统.7z
  • 是一个开源的分布式计算和作业调度框架,它使开发人员可以轻松地在自己的应用程序中调度任务。 有关详细信息,请参阅。 介绍 产品特点 友好的用户界面:提供了页面,开发人员可以管理任务,监视状态,在线检查日志...
  • 应用程序托管环境3是一种轻量级的中间件,可简化用户通过Globus和Unicore以及其他传输服务(例如GSIFTP和WebDAV)对诸如网格基础结构之类的计算资源的访问。 AHE 3使用具有模块化设计的Java实现。 它为最终用户提供...
  • 介绍了中间件MultiDbGate的结构,分为单数据库接口、连接池、作业调度和日志服务4个模块。单数据库接口模块是对活动数据对象(ADO)的封装;连接池模块是中间件的核心,可以让不同的应用共享连接,并屏蔽了底层的分布式...
  • 基于中间件的无线条码出入库作业系统,张晓杰,杨福兴,物联网时代射频识别技术(RFID)得以广泛的推广及应用,在物流作业过程中引入RFID代替传统的条码进行商品的标识,可以充分发挥RFID的
  • Elastic-Job-Lite 目录如下:Elastic-Job-Lite 源码分析 —— 作业配置Elastic-Job-Lite 源码分析 —— 作业初始化Elastic-Job-...

    Elastic-Job-Lite 目录如下:

    Elastic-Job-Cloud 目录如下:

    胖友可以置顶下【芋道源码】公众号,方便第一时间获得相应的源码解析。????艿艿准备 2019 年抽时间,写下 Spring Cloud 相关的源码解析。

    置顶操作步骤如下



    欢迎加入我的知识星球,一起探讨架构,交流源码。加入方式,长按下方二维码噢

    已在知识星球更新源码解析如下:


    如果你喜欢这篇文章,喜欢,转发。

    生活很美好,明天见(。・ω・。)ノ♡

    展开全文
  • 西农中间件课程实验一RMI+JDBC 老学长倾情力荐,供学弟学妹们参考! 我就是想赚点积分,其实实验挺简单的,还是鼓励大家自己动手啊
  • 目的:在完成了软件系统的可行性研究和需求分析的基础上,为了明确软件需求、安排项目规划与进度、组织软件开发与测试,项目小组在考虑了几种可能的解决方案,并与程序员进行了较为深入地探讨和分析之后,提出了这份...
  • 分布式任务DcsSchedule中间件,Github地址:https://github.com/fuzhengwei/schedule-spring-boot-starter 分布式任务DcsSchedule控制台,Github地址:https://github.com/fuzhengwei/itstack-mid...

    微信公众号:bugstack虫洞栈 | 沉淀、分享、成长,让自己和他人都能有所收获!
    分布式任务DcsSchedule中间件,Github地址:https://github.com/fuzhengwei/schedule-spring-boot-starter
    分布式任务DcsSchedule控制台,Github地址:https://github.com/fuzhengwei/itstack-middleware-control
    欢迎⭐Star和使用,你用剑🗡、我用刀🔪,好的代码都很骚😏,望你不吝出招💨!

    演示视频

    开发基于SpringBoot的分布式任务中间件DcsSchedule(为开源贡献力量)

    前言


    @SpringBootApplication
    @EnableScheduling
    public class Application{
        public static void mian(String[] args){
            SpringApplication.run(Application.class,args);
        }
    	
    	@Scheduled(cron = "0/3 * * * * *")
    	public void demoTask() {
    		//...
    	}
    }
    

    咔咔,上面这段代码很熟悉吧,他就是SpringBoot的Schedule定时任务,简单易用。在我们开发中如果需要做一些定时或指定时刻循环执行逻辑时候,基本都会使用到Schedule。

    但是,如果我们的任务是比较大型的,比如;定时跑批T+1结算、商品秒杀前状态变更、刷新数据预热到缓存等等,这些定时任务都相同的特点;作业量大实时性强可用率高。而这时候如果只是单纯使用Schedule就显得不足以控制。

    那么,我们产品需求就出来了,分布式DcsSchedule任务;

    1. 多机器部署任务
    2. 统一控制中心启停
    3. 宕机灾备,自动启动执行
    4. 实时检测任务执行信息:部署数量、任务总量、成功次数、失败次数、执行耗时等

    嗯?有人憋半天了想说可以用Quertz,嗯可以的,但这不是本篇文章的重点。难道你不想看看一个自言开源中间件是怎么诞生的吗,怎么推到中心Maven仓的吗?比如下图;真香不!

    首页监控
    微信公众号:bugstack虫洞栈 & 首页监控

    任务列表
    微信公众号:bugstack虫洞栈 & 任务列表

    😀好了,接下来开始介绍这个中间件如何使用和怎么开发的了!

    中间件使用


    1. 版本记录

    版本发布日期备注
    11.0.0-RELEASE2019-12-07基本功能实现;任务接入、分布式启停
    21.0.1-RELEASE2019-12-07上传测试版本

    2. 环境准备

    1. jdk1.8

    2. StringBoot 2.x

    3. 配置中心zookeeper 3.4.14 {准备好zookeeper服务,如果windows调试可以从这里下载:https://www-eu.apache.org/dist/zookeeper}

    4. 下载后解压,在bin同级路径创建文件夹data、logs

    5. 修改conf/zoo.cfg,修改配置如下;

      dataDir=D:\\Program Files\\apache-zookeeper-3.4.14\\data
      dataLogDir=D:\\Program Files\\apache-zookeeper-3.4.14\\logs
      
    6. 打包部署控制平台

    7. 下载地址:https://github.com/fuzhengwei/itstack-middleware-control.git

    8. 部署访问:http://localhost:7397

    3. 配置POM

    <dependency>
        <groupId>org.itstack.middleware</groupId>
        <artifactId>schedule-spring-boot-starter</artifactId>
        <version>1.0.0-RELEASE</version>
    </dependency>
    

    4. 引入分布式任务DcsSchedule @EnableDcsScheduling

    1. 与SpringBoot的Sceduling非常像,他的注解是;@EnableScheduling,尽可能降低使用难度
    2. 这个注解主要方便给我们自己的中间件一个入口,也是😏扒拉源码发现的可以这么干{我一直说好的代码都很骚气}
    @SpringBootApplication
    @EnableDcsScheduling
    public class HelloWorldApplication {
    
        public static void main(String[] args) {
            SpringApplication.run(HelloWorldApplication.class, args);
        }
    
    }
    

    5. 在任务方法上添加注解

    1. 这个注解也和SpringBoot的Schedule很像,但是多了desc描述和启停初始化控制
    2. cron:执行计划
    3. desc:任务描述
    4. autoStartup:默认启动状态
    5. 如果你的任务需要参数可以通过引入service去调用获取等方式都可以
    @Component("demoTaskThree")
    public class DemoTaskThree {
    	
        @DcsScheduled(cron = "0 0 9,13 * * *", desc = "03定时任务执行测试:taskMethod01", autoStartup = false)
        public void taskMethod01() {
            System.out.println("03定时任务执行测试:taskMethod01");
        }
    
        @DcsScheduled(cron = "0 0/30 8-10 * * *", desc = "03定时任务执行测试:taskMethod02", autoStartup = false)
        public void taskMethod02() {
            System.out.println("03定时任务执行测试:taskMethod02");
        }
    
    }
    

    6. 启动验证

    1. 启动SpringBoot工程即可,autoStartup = true的会自动启动任务(任务是多线程并行执行的)
    2. 启动控制平台:itstack-middleware-control,访问:http://localhost:7397/ 成功界面如下;可以开启/关闭验证了!{功能还在完善}
      微信公众号:bugstack虫洞栈 & 任务列表

    中间件开发


    以SpringBoot为基础开发一款中间件我也是第一次,因为接触SpringBoot也刚刚1个月左右。虽然SpringBoot已经出来挺久的了,但由于我们项目开发并不使用SpringBoot的一套东西,所以一直依赖没有接触。直到上个月开始考虑领域驱动设计才接触,嗯!真的不错,那么就开始了夯实技能、学习思想用到项目里。

    按照我的产品需求,开发这么一款分布式任务的中间件,我脑袋中的模型已经存在了。另外就是需要开发过程中去探索我需要的知识工具,简单包括;

    1. 读取Yml自定义配置
    2. 使用zookeeper作为配置中心,这样如果有机器宕机了就可以通过临时节点监听知道
    3. 通过Spring类;ApplicationContextAware, BeanPostProcessor, ApplicationListener,执行服务启动、注解扫描、节点挂在
    4. 分布式任务统一控制台,来管理任务

    1. 工程模型

    schedule-spring-boot-starter
    └── src
        ├── main
        │   ├── java
        │   │   └── org.itstack.middleware.schedule
        │   │       ├── annotation
        │   │       │	├── DcsScheduled.java	
        │   │       │	└── EnableDcsScheduling.java
        │   │       ├── annotation	
        │   │       │	└── InstructStatus.java	
        │   │       ├── config
        │   │       │	├── DcsSchedulingConfiguration.java	
        │   │       │	├── StarterAutoConfig.java	
        │   │       │	└── StarterServiceProperties.java	
        │   │       ├── domain
        │   │       │	├── DataCollect.java	
        │   │       │	├── DcsScheduleInfo.java	
        │   │       │	├── DcsServerNode.java	
        │   │       │	├── ExecOrder.java	
        │   │       │	└── Instruct.java
        │   │       ├── export	
        │   │       │	└── DcsScheduleResource.java
        │   │       ├── service
        │   │       │	├── HeartbeatService.java	
        │   │       │	└── ZkCuratorServer.java
        │   │       ├── task
        │   │       │	├── TaskScheduler.java	
        │   │       │	├── ScheduledTask.java	
        │   │       │	├── SchedulingConfig.java	
        │   │       │	└── SchedulingRunnable.java	
        │   │       ├── util
        │   │       │	└── StrUtil.java	
        │   │       └── DoJoinPoint.java
        │   └── resources	
        │       └── META_INF
        │           └── spring.factories	
        └── test
            └── java
                └── org.itstack.demo.test
                    └── ApiTest.java
    

    2. 代码讲解

    1. 篇幅较长,只讲解部分重点代码块,如果你愿意参与到开源编写,可以和我申请
    2. 我说过好的代码都很骚气,那么就从这部分入手吧

    2.1 自定义注解

    annotation/EnableDcsScheduling.java & 自定义注解

    这个注解一堆的圈A,这些配置都是为了开始启动执行我们的中间件;

    • Target 标识需要放到类上执行
    • Retention 注释将由编译器记录在类文件中,并且在运行时由VM保留,因此可以反射地读取它们
    • Import 引入入口资源,在程序启动时会执行到自己定义的类中,以方便我们;初始化配置/服务、启动任务、挂在节点
    • ComponentScan 告诉程序扫描位置
    @Target({ElementType.TYPE})
    @Retention(RetentionPolicy.RUNTIME)
    @Import({DcsSchedulingConfiguration.class})
    @ImportAutoConfiguration({SchedulingConfig.class, CronTaskRegister.class, DoJoinPoint.class})
    @ComponentScan("org.itstack.middleware.*")
    public @interface EnableDcsScheduling {
    }
    

    2.2 扫描自定义注解、初始化配置/服务、启动任务、挂在节点

    config/DcsSchedulingConfiguration.java & 初始化配置/服务、启动任务、挂在节点

    • 写到这的时候,我们的自定义注解有了,已经写到方法上了,那么我们怎么拿到呢?
    • 需要通过实现BeanPostProcessor.postProcessAfterInitialization,在每个bean实例化的时候进行扫描
    • 这里遇到一个有趣的问题,一个方法会得到两次,因为有一个CGLIB给代理的,像真假美猴王一样,几乎一毛一样。😏扒了源码才看到,生命注解批注没有。好那就可以判断了!method.getDeclaredAnnotations()
    • 我们将扫描下来的任务信息汇总到Map中,当Spring初始化完成后,在执行我们中间件内容。{太早执行有点喧宾夺主了!主要人家也不让呀,给你抛异常😭。}
    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
    	Class<?> targetClass = AopProxyUtils.ultimateTargetClass(bean);
    	if (this.nonAnnotatedClasses.contains(targetClass)) return bean;
    	Method[] methods = ReflectionUtils.getAllDeclaredMethods(bean.getClass());
    	if (methods == null) return bean;
    	for (Method method : methods) {
    		DcsScheduled dcsScheduled = AnnotationUtils.findAnnotation(method, DcsScheduled.class);
    		if (null == dcsScheduled || 0 == method.getDeclaredAnnotations().length) continue;
    		List<ExecOrder> execOrderList = Constants.execOrderMap.computeIfAbsent(beanName, k -> new ArrayList<>());
    		ExecOrder execOrder = new ExecOrder();
    		execOrder.setBean(bean);
    		execOrder.setBeanName(beanName);
    		execOrder.setMethodName(method.getName());
    		execOrder.setDesc(dcsScheduled.desc());
    		execOrder.setCron(dcsScheduled.cron());
    		execOrder.setAutoStartup(dcsScheduled.autoStartup());
    		execOrderList.add(execOrder);
    		this.nonAnnotatedClasses.add(targetClass);
    	}
    	return bean;
    }
    
    • 初始化服务连接zookeeper配置中心
    • 连接后将创建我们的节点以及添加监听,这个监听主要负责分布式消息通知,收到通知负责控制任务启停
    • 这里包括了循环创建节点以及批量节点删除,似乎!面试题会问😏
    private void init_server(ApplicationContext applicationContext) {
        try {
            //获取zk连接
            CuratorFramework client = ZkCuratorServer.getClient(Constants.Global.zkAddress);
            //节点组装
            path_root_server = StrUtil.joinStr(path_root, LINE, "server", LINE, schedulerServerId);
            path_root_server_ip = StrUtil.joinStr(path_root_server, LINE, "ip", LINE, Constants.Global.ip);
            //创建节点&递归删除本服务IP下的旧内容
            ZkCuratorServer.deletingChildrenIfNeeded(client, path_root_server_ip);
            ZkCuratorServer.createNode(client, path_root_server_ip);
            ZkCuratorServer.setData(client, path_root_server, schedulerServerName);
            //添加节点&监听
            ZkCuratorServer.createNodeSimple(client, Constants.Global.path_root_exec);
            ZkCuratorServer.addTreeCacheListener(applicationContext, client, Constants.Global.path_root_exec);
        } catch (Exception e) {
            logger.error("itstack middleware schedule init server error!", e);
            throw new RuntimeException(e);
        }
    }
    
    • 启动标记了True的Schedule任务
    • Scheduled默认是单线程执行的,这里扩展为多线程并行执行
    private void init_task(ApplicationContext applicationContext) {
        CronTaskRegister cronTaskRegistrar = applicationContext.getBean("itstack-middlware-schedule-cronTaskRegister", CronTaskRegister.class);
        Set<String> beanNames = Constants.execOrderMap.keySet();
        for (String beanName : beanNames) {
            List<ExecOrder> execOrderList = Constants.execOrderMap.get(beanName);
            for (ExecOrder execOrder : execOrderList) {
                if (!execOrder.getAutoStartup()) continue;
                SchedulingRunnable task = new SchedulingRunnable(execOrder.getBean(), execOrder.getBeanName(), execOrder.getMethodName());
                cronTaskRegistrar.addCronTask(task, execOrder.getCron());
            }
        }
    }
    
    • 挂在任务节点到zookeeper挂在
    • 按照不同的场景,有些内容是挂在到虚拟机节点。{😏又来个面试题,虚拟节点数据怎么挂在,创建的是永久节点,那么虚拟值怎么加?}
    • path_root_server_ip_clazz_method;这个结构是:根目录、服务、IP、类、方法
    private void init_node() throws Exception {
    	Set<String> beanNames = Constants.execOrderMap.keySet();
    	for (String beanName : beanNames) {
    		List<ExecOrder> execOrderList = Constants.execOrderMap.get(beanName);
    		for (ExecOrder execOrder : execOrderList) {
    			String path_root_server_ip_clazz = StrUtil.joinStr(path_root_server_ip, LINE, "clazz", LINE, execOrder.getBeanName());
    			String path_root_server_ip_clazz_method = StrUtil.joinStr(path_root_server_ip_clazz, LINE, "method", LINE, execOrder.getMethodName());
    			String path_root_server_ip_clazz_method_status = StrUtil.joinStr(path_root_server_ip_clazz, LINE, "method", LINE, execOrder.getMethodName(), "/status");
    			//添加节点
    			ZkCuratorServer.createNodeSimple(client, path_root_server_ip_clazz);
    			ZkCuratorServer.createNodeSimple(client, path_root_server_ip_clazz_method);
    			ZkCuratorServer.createNodeSimple(client, path_root_server_ip_clazz_method_status);
    			//添加节点数据[临时]
    			ZkCuratorServer.appendPersistentData(client, path_root_server_ip_clazz_method + "/value", JSON.toJSONString(execOrder));
    			//添加节点数据[永久]
    			ZkCuratorServer.setData(client, path_root_server_ip_clazz_method_status, execOrder.getAutoStartup() ? "1" : "0");
    		}
    	}
    }
    

    2.3 zookeeper控制服务

    service/ZkCuratorServer.java & zk服务

    • 这里提供一个zk的方法集合,其中比较重要的方法添加监听
    • zookeeper有一个特性是对这个监听后,当节点内容发生变化时会收到通知,当然宕机也是收得到的,这个也就是我们后面开发灾备的核心触发点
    public static void addTreeCacheListener(final ApplicationContext applicationContext, final CuratorFramework client, String path) throws Exception {
    	TreeCache treeCache = new TreeCache(client, path);
    	treeCache.start();
    	treeCache.getListenable().addListener((curatorFramework, event) -> {
    		//...
    		switch (event.getType()) {
    			case NODE_ADDED:
    			case NODE_UPDATED:
    				if (Constants.Global.ip.equals(instruct.getIp()) && Constants.Global.schedulerServerId.equals(instruct.getSchedulerServerId())) {
    					//执行命令
    					Integer status = instruct.getStatus();
    					switch (status) {
    						case 0: //停止任务
    							cronTaskRegistrar.removeCronTask(instruct.getBeanName() + "_" + instruct.getMethodName());
    							setData(client, path_root_server_ip_clazz_method_status, "0");
    							logger.info("itstack middleware schedule task stop {} {}", instruct.getBeanName(), instruct.getMethodName());
    							break;
    						case 1: //启动任务
    							cronTaskRegistrar.addCronTask(new SchedulingRunnable(scheduleBean, instruct.getBeanName(), instruct.getMethodName()), instruct.getCron());
    							setData(client, path_root_server_ip_clazz_method_status, "1");
    							logger.info("itstack middleware schedule task start {} {}", instruct.getBeanName(), instruct.getMethodName());
    							break;
    						case 2: //刷新任务
    							cronTaskRegistrar.removeCronTask(instruct.getBeanName() + "_" + instruct.getMethodName());
    							cronTaskRegistrar.addCronTask(new SchedulingRunnable(scheduleBean, instruct.getBeanName(), instruct.getMethodName()), instruct.getCron());
    							setData(client, path_root_server_ip_clazz_method_status, "1");
    							logger.info("itstack middleware schedule task refresh {} {}", instruct.getBeanName(), instruct.getMethodName());
    							break;
    					}
    				}
    				break;
    			case NODE_REMOVED:
    				break;
    			default:
    				break;
    		}
    	});
    }
    

    2.4 并行任务注册

    • 由于默认的SpringBoot是单线程的,所以这里改造了下,可以支持多线程并行执行
    • 包括了添加任务和删除任务,也就是执行取消future.cancel(true)
    public void addCronTask(SchedulingRunnable task, String cronExpression) {
        if (null != Constants.scheduledTasks.get(task.taskId())) {
            removeCronTask(task.taskId());
        }
        CronTask cronTask = new CronTask(task, cronExpression);
        Constants.scheduledTasks.put(task.taskId(), scheduleCronTask(cronTask));
    }
    public void removeCronTask(String taskId) {
        ScheduledTask scheduledTask = Constants.scheduledTasks.remove(taskId);
        if (scheduledTask == null) return;
        scheduledTask.cancel();
    }
    

    2.5 待扩展的自定义AOP

    • 我们最开始配置的扫描@ComponentScan(“org.itstack.middleware.*”),主要用到这里的自定义注解,否则是扫描不到的,也就是你自定义切面失效的效果
    • 目前这里的功能并没有扩展,基本只是打印执行耗时,后续完善的任务执行耗时监听等,就需要这里来完善
    @Pointcut("@annotation(org.itstack.middleware.schedule.annotation.DcsScheduled)")
    public void aopPoint() {
    }
    
    @Around("aopPoint()")
    public Object doRouter(ProceedingJoinPoint jp) throws Throwable {
    	long begin = System.currentTimeMillis();
    	Method method = getMethod(jp);
    	try {
    		return jp.proceed();
    	} finally {
    		long end = System.currentTimeMillis();
    		logger.info("\nitstack middleware schedule method:{}.{} take time(m):{}", jp.getTarget().getClass().getSimpleName(), method.getName(), (end - begin));
    	}
    }
    

    3. Jar包发布

    开发完成后还是需要将Jar包发布到manven中心仓库的,这个过程较长单独写了博客;发布Jar包到Maven中央仓库(为开发开源中间件做准备)

    综上总结


    1. 要开发要实现的还很多,一个周末也干不完所有的!而且需要有想法的小猿/媛伴一起加入!🙂 😀 😏
    2. 这里没有讲解分布式任务中间件控制平台itstack-middleware-control,因为比较简单只是使用了中间件的zk功能接口做展示和操作。
    3. 中间件开发是一件非常有意思的事情,不同于业务它更像易筋经,寺庙老僧,剑走偏锋,驰骋纵横,骚招满屏。

    微信公众号:bugstack虫洞栈,欢迎关注&获取源码

    展开全文
  • java中间件

    2021-02-06 14:31:00
    中间件 中间件(Middleware)是处于操作系统和应用程序...为什么要使用中间件? 具体地说,中间件屏蔽了底层操作系统的复杂性,使程序开发人员面对一个简单而统一的开发环境,减少程序设计的复杂性,将注意力集中在自己

    中间件

    中间件(Middleware)是处于操作系统和应用程序之间的软件,也有人认为它应该属于操作系统中的一部分。人们在使用中间件时,往往是一组中间件集成在一起,构成一个平台(包括开发平台和运行平台),但在这组中间件中必须要有一个通信中间件,即中间件=平台+通信,这个定义也限定了只有用于分布式系统中才能称为中间件,同时还可以把它与支撑软件和实用软件区分开来。

    为什么要使用中间件?

    具体地说,中间件屏蔽了底层操作系统的复杂性,使程序开发人员面对一个简单而统一的开发环境,减少程序设计的复杂性,将注意力集中在自己的业务上,不必再为程序在不同系统软件上的移植而重复工作,从而大大减少了技术上的负担。中间件带给应用系统的,不只是开发的简便、开发周期的缩短,也减

    展开全文
  • 第四阶段模块一作业:https://blog.csdn.net/crckerfang/article/details/117993302
  • 18.需要在远程教育中实现试卷、作业在线批改的。 19.需要在html页面中把Word转换为pdf的; 20.需要在html页面中快速打开、显示pdf的; 21.需要在Ajax架构里调用Word/Excel的,包括服务器端和客户端Javascript都适用...
  • 数据库中间件

    千次阅读 2017-12-11 23:52:49
    这里主要介绍互联网行业内有关数据库的相关中间件。数据库相关平台主要解决以下三个方面的问题: 为海量前台数据提供高性能、大容量、高可用性的访问为数据变更的消费提供准实时的保障高效的异地数据同步 应用层...
  • 步入大数据时代之后,致力于解决大规模科学计算问题的高...优化后的信息同步模式在处理2 000条作业状态更新时,延迟时间缩短90%、系统负载降低98%、网络连接数减少90%,为系统维护人员、环境用户带来更好的用户体验。
  • 解决的问题数据库相关平台主要解决以下三个方面的问题为海量前台数据提供高性能、大容量、高可用性的访问为数据变更的消费提供准实时的保障高效的异地数据同步上图的讲解最上层的是分布式数据库分表分库中间件,读写...
  • 源码精品专栏来源:jianshu.com/p/ed7a263a436c前言什么中间件开发?中间件开发人员需要哪些素质?如何成为中间件开发人员?结语基友「莫那鲁道」(本文作者),目前正在开发使用 Java 语言,开发基于 Raft 算法的...
  • 为了使用gridscale,您应该导入与要使用的作业系统相对应的名称空间: import gridscale.pbs._ SBT GridScale是针对scala的服务器版本进行交叉编译的。 要使用其模块,请添加类似的依赖项: libraryDependencies ...
  • .Net常用中间件

    千次阅读 2020-08-04 11:06:05
    什么中间件 中间件是介于操作系统和应用软件之间,为应用软件提供服务功能的软件,有消息中间件,交易中间件,应用服务器等。由于介于两种软件之间,所以,称为中间件。 简单讲,中间件就是非业务的技术类组件。 ...
  • 中间件在ERP中的作用传统的ERP系统从功能上看,有财务管理、销售管理、产品计划管理、采购库存管理、产品数据管理(宏观/微观)、生产作业管理、人力资源管理等。从系统体系结构上看,ERP系统包括了业务模型、数据模型...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 15,214
精华内容 6,085
关键字:

中间件什么作业