diff --git a/canal-admin/canal-admin-server/pom.xml b/canal-admin/canal-admin-server/pom.xml
index 65a2da76..3e031738 100644
--- a/canal-admin/canal-admin-server/pom.xml
+++ b/canal-admin/canal-admin-server/pom.xml
@@ -20,6 +20,10 @@
org.springframework.boot
spring-boot-starter-jdbc
+
+ org.springframework.boot
+ spring-boot-starter-test
+
mysql
@@ -33,6 +37,21 @@
com.github.ben-manes.caffeine
caffeine
+
+
+ io.ebean
+ ebean
+ 11.41.1
+
+
+
+ commons-beanutils
+ commons-beanutils
+
+
+ commons-lang
+ commons-lang
+
@@ -87,6 +106,17 @@
+
+ io.repaint.maven
+ tiles-maven-plugin
+ 2.12
+ true
+
+
+ io.ebean.tile:enhancement:11.41.1
+
+
+
diff --git a/canal-admin/canal-admin-server/src/main/java/com/alibaba/otter/canal/admin/CanalAdminApplication.java b/canal-admin/canal-admin-server/src/main/java/com/alibaba/otter/canal/admin/CanalAdminApplication.java
index 5de3dfa3..4ff5f70c 100644
--- a/canal-admin/canal-admin-server/src/main/java/com/alibaba/otter/canal/admin/CanalAdminApplication.java
+++ b/canal-admin/canal-admin-server/src/main/java/com/alibaba/otter/canal/admin/CanalAdminApplication.java
@@ -18,4 +18,9 @@ public class CanalAdminApplication {
application.setBannerMode(Banner.Mode.OFF);
application.run(args);
}
+
+ // public static void main(String[] args) throws Exception {
+ // UserAgent userAgent = new UserAgent();
+ //// HelloAgent helloAgent = new HelloAgent
+ // }
}
diff --git a/canal-admin/canal-admin-server/src/main/java/com/alibaba/otter/canal/admin/config/Config.java b/canal-admin/canal-admin-server/src/main/java/com/alibaba/otter/canal/admin/config/Config.java
index 7f856a9a..1a25bc13 100644
--- a/canal-admin/canal-admin-server/src/main/java/com/alibaba/otter/canal/admin/config/Config.java
+++ b/canal-admin/canal-admin-server/src/main/java/com/alibaba/otter/canal/admin/config/Config.java
@@ -1,15 +1,23 @@
package com.alibaba.otter.canal.admin.config;
-import org.apache.commons.dbutils.QueryRunner;
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-
import javax.sql.DataSource;
+import io.ebean.EbeanServer;
+import org.apache.commons.dbutils.QueryRunner;
+import org.springframework.beans.factory.FactoryBean;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
@Configuration
public class Config {
+
@Bean
public QueryRunner queryRunner(DataSource dataSource) {
return new QueryRunner(dataSource);
}
+
+// @Bean("ebeanServer")
+// public FactoryBean ebeanServer(DataSource dataSource) {
+// return new EbeanServerFactory(dataSource);
+// }
}
diff --git a/canal-admin/canal-admin-server/src/main/java/com/alibaba/otter/canal/admin/config/EbeanConfig.java b/canal-admin/canal-admin-server/src/main/java/com/alibaba/otter/canal/admin/config/EbeanConfig.java
new file mode 100644
index 00000000..aec83c04
--- /dev/null
+++ b/canal-admin/canal-admin-server/src/main/java/com/alibaba/otter/canal/admin/config/EbeanConfig.java
@@ -0,0 +1,34 @@
+package com.alibaba.otter.canal.admin.config;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.sql.DataSource;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+import io.ebean.EbeanServer;
+import io.ebean.EbeanServerFactory;
+import io.ebean.config.ServerConfig;
+import io.ebean.config.UnderscoreNamingConvention;
+
+@Configuration
+public class EbeanConfig {
+
+ @Bean("ebeanServer")
+ public EbeanServer ebeanServer(DataSource dataSource) {
+ ServerConfig serverConfig = new ServerConfig();
+ serverConfig.setDefaultServer(true);
+ serverConfig.setNamingConvention(new UnderscoreNamingConvention());
+ List packages = new ArrayList<>();
+ packages.add("com.alibaba.otter.canal.admin.model");
+ serverConfig.setPackages(packages);
+ serverConfig.setName("ebeanServer");
+ serverConfig.setDataSource(dataSource);
+ serverConfig.setDatabaseSequenceBatchSize(1);
+ serverConfig.setDdlGenerate(false);
+ serverConfig.setDdlRun(false);
+ return EbeanServerFactory.create(serverConfig);
+ }
+}
diff --git a/canal-admin/canal-admin-server/src/main/java/com/alibaba/otter/canal/admin/config/WebConfig.java b/canal-admin/canal-admin-server/src/main/java/com/alibaba/otter/canal/admin/config/WebConfig.java
index 9133c24d..25fe2e9b 100644
--- a/canal-admin/canal-admin-server/src/main/java/com/alibaba/otter/canal/admin/config/WebConfig.java
+++ b/canal-admin/canal-admin-server/src/main/java/com/alibaba/otter/canal/admin/config/WebConfig.java
@@ -43,37 +43,37 @@ public class WebConfig implements WebMvcConfigurer {
}
}).addPathPatterns("/api/**");
- registry.addInterceptor(new HandlerInterceptor() {
-
- @Override
- public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse,
- Object o) throws Exception {
- String token = httpServletRequest.getHeader("X-Token");
- boolean valid = false;
- if (token != null) {
- User user = UserController.loginUsers.getIfPresent(token);
- if (user != null) {
- valid = true;
- }
- }
- if (!valid) {
- BaseModel baseModel = BaseModel.getInstance(null);
- baseModel.setCode(50014);
- baseModel.setMessage("Expired token");
- ObjectMapper mapper = new ObjectMapper();
- String json = mapper.writeValueAsString(baseModel);
- try {
- httpServletResponse.setContentType("application/json;charset=UTF-8");
- PrintWriter out = httpServletResponse.getWriter();
- out.print(json);
- } catch (Exception e) {
- e.printStackTrace();
- }
- return false;
- }
-
- return true;
- }
- }).addPathPatterns("/api/**").excludePathPatterns("/api/**/user/**");
+// registry.addInterceptor(new HandlerInterceptor() {
+//
+// @Override
+// public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse,
+// Object o) throws Exception {
+// String token = httpServletRequest.getHeader("X-Token");
+// boolean valid = false;
+// if (token != null) {
+// User user = UserController.loginUsers.getIfPresent(token);
+// if (user != null) {
+// valid = true;
+// }
+// }
+// if (!valid) {
+// BaseModel baseModel = BaseModel.getInstance(null);
+// baseModel.setCode(50014);
+// baseModel.setMessage("Expired token");
+// ObjectMapper mapper = new ObjectMapper();
+// String json = mapper.writeValueAsString(baseModel);
+// try {
+// httpServletResponse.setContentType("application/json;charset=UTF-8");
+// PrintWriter out = httpServletResponse.getWriter();
+// out.print(json);
+// } catch (Exception e) {
+// e.printStackTrace();
+// }
+// return false;
+// }
+//
+// return true;
+// }
+// }).addPathPatterns("/api/**").excludePathPatterns("/api/**/user/**");
}
}
diff --git a/canal-admin/canal-admin-server/src/main/java/com/alibaba/otter/canal/admin/controller/NodeServerController.java b/canal-admin/canal-admin-server/src/main/java/com/alibaba/otter/canal/admin/controller/NodeServerController.java
new file mode 100644
index 00000000..f29d1a16
--- /dev/null
+++ b/canal-admin/canal-admin-server/src/main/java/com/alibaba/otter/canal/admin/controller/NodeServerController.java
@@ -0,0 +1,45 @@
+package com.alibaba.otter.canal.admin.controller;
+
+import java.util.List;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+
+import com.alibaba.otter.canal.admin.model.BaseModel;
+import com.alibaba.otter.canal.admin.model.NodeServer;
+import com.alibaba.otter.canal.admin.service.NodeServerService;
+
+@RestController
+@RequestMapping("/api/{env}")
+public class NodeServerController {
+
+ @Autowired
+ NodeServerService nodeServerService;
+
+ @GetMapping(value = "/nodeServers")
+ public BaseModel> nodeServers(NodeServer nodeServer, @PathVariable String env) {
+ return BaseModel.getInstance(nodeServerService.findList(nodeServer));
+ }
+
+ @DeleteMapping(value = "/nodeServer/{id}")
+ public BaseModel delete(@PathVariable Long id, @PathVariable String env) {
+ nodeServerService.delete(id);
+ return BaseModel.getInstance("success");
+ }
+
+ @PostMapping(value = "/nodeServer")
+ public BaseModel save(@RequestBody NodeServer nodeServer, @PathVariable String env) {
+ nodeServerService.save(nodeServer);
+ return BaseModel.getInstance("success");
+ }
+
+ @GetMapping(value = "/nodeServer/{id}")
+ public BaseModel detail(@PathVariable Long id, @PathVariable String env) {
+ return BaseModel.getInstance(nodeServerService.detail(id));
+ }
+
+ @GetMapping(value = "/nodeServer/status")
+ public BaseModel status(@RequestParam String ip, @RequestParam Integer port, @PathVariable String env) {
+ return BaseModel.getInstance(nodeServerService.remoteNodeStatus(ip,port));
+ }
+}
diff --git a/canal-admin/canal-admin-server/src/main/java/com/alibaba/otter/canal/admin/dao/CanalConfigDao.java b/canal-admin/canal-admin-server/src/main/java/com/alibaba/otter/canal/admin/dao/CanalConfigDao.java
deleted file mode 100644
index 71f177c0..00000000
--- a/canal-admin/canal-admin-server/src/main/java/com/alibaba/otter/canal/admin/dao/CanalConfigDao.java
+++ /dev/null
@@ -1,35 +0,0 @@
-package com.alibaba.otter.canal.admin.dao;
-
-import com.alibaba.otter.canal.admin.model.CanalConfig;
-import org.apache.commons.dbutils.QueryRunner;
-import org.apache.commons.dbutils.handlers.BeanHandler;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Repository;
-
-import java.sql.SQLException;
-import java.util.Date;
-
-@Repository
-public class CanalConfigDao {
-
- @Autowired
- private QueryRunner runner;
-
- public CanalConfig findById(Long id) {
- try {
- String sql = "select id,name,content,modified_time as modifiedTime" + " from canal_config where id=?";
- return runner.query(sql, new BeanHandler<>(CanalConfig.class), id);
- } catch (SQLException e) {
- throw new RuntimeException(e.getMessage(), e);
- }
- }
-
- public int updateContent(CanalConfig canalConfig){
- try {
- String sql = "update canal_config set content=?, modified_time=? where id=?";
- return runner.update(sql, canalConfig.getContent(), new Date(), canalConfig.getId());
- } catch (SQLException e) {
- throw new RuntimeException(e.getMessage(), e);
- }
- }
-}
diff --git a/canal-admin/canal-admin-server/src/main/java/com/alibaba/otter/canal/admin/handler/CustomExceptionHandler.java b/canal-admin/canal-admin-server/src/main/java/com/alibaba/otter/canal/admin/handler/CustomExceptionHandler.java
new file mode 100644
index 00000000..bcb70a5c
--- /dev/null
+++ b/canal-admin/canal-admin-server/src/main/java/com/alibaba/otter/canal/admin/handler/CustomExceptionHandler.java
@@ -0,0 +1,32 @@
+package com.alibaba.otter.canal.admin.handler;
+
+import com.alibaba.otter.canal.admin.common.exception.ServiceException;
+import com.alibaba.otter.canal.admin.model.BaseModel;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.http.HttpStatus;
+import org.springframework.web.bind.annotation.ControllerAdvice;
+import org.springframework.web.bind.annotation.ExceptionHandler;
+import org.springframework.web.bind.annotation.ResponseBody;
+import org.springframework.web.bind.annotation.ResponseStatus;
+
+@ControllerAdvice(annotations = ResponseBody.class)
+public class CustomExceptionHandler {
+
+ private static Logger logger = LoggerFactory.getLogger(CustomExceptionHandler.class);
+
+ @ResponseBody
+ @ResponseStatus(HttpStatus.OK)
+ @ExceptionHandler(value = Exception.class)
+ public BaseModel commonExceptionHandle(Exception e) {
+ if (e instanceof ServiceException) {
+ logger.error(e.getMessage());
+ } else {
+ logger.error(e.getMessage(), e);
+ }
+ BaseModel res = new BaseModel();
+ res.setCode(50000);
+ res.setMessage(e.getMessage());
+ return res;
+ }
+}
diff --git a/canal-admin/canal-admin-server/src/main/java/com/alibaba/otter/canal/admin/jmx/CanalServerMXBean.java b/canal-admin/canal-admin-server/src/main/java/com/alibaba/otter/canal/admin/jmx/CanalServerMXBean.java
new file mode 100644
index 00000000..c3a7089a
--- /dev/null
+++ b/canal-admin/canal-admin-server/src/main/java/com/alibaba/otter/canal/admin/jmx/CanalServerMXBean.java
@@ -0,0 +1,22 @@
+package com.alibaba.otter.canal.admin.jmx;
+
+public interface CanalServerMXBean {
+
+ int getStatus();
+
+ boolean start();
+
+ boolean stop();
+
+ boolean restart();
+
+ boolean exit();
+
+ boolean startInstance(String destination);
+
+ boolean stopInstance(String destination);
+
+ boolean reloadInstance(String destination);
+
+ String getRunningInstances();
+}
diff --git a/canal-admin/canal-admin-server/src/main/java/com/alibaba/otter/canal/admin/jmx/JMXConnection.java b/canal-admin/canal-admin-server/src/main/java/com/alibaba/otter/canal/admin/jmx/JMXConnection.java
new file mode 100644
index 00000000..6e4140ed
--- /dev/null
+++ b/canal-admin/canal-admin-server/src/main/java/com/alibaba/otter/canal/admin/jmx/JMXConnection.java
@@ -0,0 +1,115 @@
+package com.alibaba.otter.canal.admin.jmx;
+
+import com.alibaba.otter.canal.admin.common.exception.ServiceException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.management.*;
+import javax.management.remote.JMXConnector;
+import javax.management.remote.JMXConnectorFactory;
+import javax.management.remote.JMXServiceURL;
+import java.io.IOException;
+import java.io.InterruptedIOException;
+import java.net.SocketTimeoutException;
+import java.util.concurrent.*;
+
+public class JMXConnection {
+
+ private Logger logger = LoggerFactory.getLogger(JMXConnection.class);
+
+ private String ip;
+ private Integer port;
+ private JMXConnector jmxc;
+ private CanalServerMXBean canalServerMXBean;
+
+ public JMXConnection(String ip, Integer port){
+ this.ip = ip;
+ this.port = port;
+ }
+
+ public void connect() {
+ try {
+ JMXServiceURL url = new JMXServiceURL("service:jmx:rmi:///jndi/rmi://" + ip + ":" + port + "/jmxrmi");
+ // jmxc = JMXConnectorFactory.connect(url, null);
+ jmxc = connectWithTimeout(url, 3, TimeUnit.SECONDS);
+ MBeanServerConnection mBeanServerConnection = jmxc.getMBeanServerConnection();
+ ObjectName name = new ObjectName("CanalServerAgent:type=CanalServerStatus");
+ mBeanServerConnection.addNotificationListener(name, (notification, handback) -> {
+ }, null, null);
+ canalServerMXBean = MBeanServerInvocationHandler
+ .newProxyInstance(mBeanServerConnection, name, CanalServerMXBean.class, false);
+ } catch (Exception e) {
+ throw new ServiceException(e.getMessage(), e);
+ }
+ }
+
+ private static JMXConnector connectWithTimeout(final JMXServiceURL url, long timeout,
+ TimeUnit unit) throws IOException {
+ final BlockingQueue