专栏首页品茗ITJAVA代码的热部署,动态语言Groovy使用的三种方式

JAVA代码的热部署,动态语言Groovy使用的三种方式

JAVA代码的热部署,动态语言Groovy使用的三种方式

一、概述

Groovy是构建在JVM上的一个轻量级却强大的动态语言, 它结合了Python、Ruby和Smalltalk的许多强大的特性.

Groovy就是用Java写的 , Groovy语法与Java语法类似, Groovy 代码能够与 Java 代码很好地结合,也能用于扩展现有代码, 相对于Java, 它在编写代码的灵活性上有非常明显的提升,Groovy 可以使用其他 Java 语言编写的库.

Groovy通常是被用来扩展现有的代码,就是说,当你需要某个实现类动态生成的时候,就可以使用Groovy来完成,比如:

  1. 动态类实现从文件生成,改动后能立即检测到。
  2. 动态类实现从数据库中生成,改动后能立即检测到。
  3. 动态类作为Spring的bean被管理起来,改动后能立即检测到。

这次,我要讲的就是这三种方式。

二、准备工作

本篇的使用场景是:假设有一个规则接口,它的实现可以是本地的JAVA代码实现,也可以是groovy文件实现,也可以通过数据库存储的Groovy脚本实现,也可以是Spring管理的bean。然后这多种不同的规则实现,放到一个列表中,统一执行。

在xxl-job中,所有的任务都要实现IJobHandler接口,它的web Glue方式就是基于Groovy实现的。

2.1 规则接口IRule

IRule定义了这个规则接口。

IRule:

package cn.pomit.skill.groovy.rule;

public interface IRule {
	static final int NORMAL_TYPE = 0;
	static final int GROOVY_FILE_TYPE = 1;
	static final int GROOVY_DB_TYPE = 2;
	static final int GROOVY_SPRING_TYPE = 3;
	
	int getType();
	
	void printInfo();
}

2.2 普通的JAVA实现

如果是普通的Java实现,就很简单。

NormalJavaRule:

package cn.pomit.skill.groovy.rule.normal;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import cn.pomit.skill.groovy.rule.IRule;

public class NormalJavaRule implements IRule {
	private Logger log = LoggerFactory.getLogger(this.getClass());
	@Override
	public int getType() {
		return NORMAL_TYPE;
	}

	@Override
	public void printInfo() {
		log.info("这是正常的JAVA代码");
		printInfoHigh();
	}
	
	//加这段是为了测试改动后输出是否有变化,在ide里,只靠上面的打印看不出来效果
	public void printInfoHigh() {
		log.info("这是正常的JAVA代码的代码");
	}
}

三、非Spring环境Groovy文件方式

3.1 Groovy文件

定义一个GroovyFileRule的Groovy文件,执行自己的规则。

GroovyFileRule:

package cn.pomit.skill.groovy.rule.file;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import cn.pomit.skill.groovy.rule.IRule;

class GroovyFileRule implements IRule {
	private Logger log = LoggerFactory.getLogger(this.getClass());
	
	@Override
	public int getType() {
		return GROOVY_FILE_TYPE;
	}

	@Override
	public void printInfo() {
		log.info("这是一段来自Groovy文件的代码");
		printInfoHigh();
	}
	
	public void printInfoHigh() {
		log.info("这是一段来自Groovy文件的代码的代码");
	}
}

3.2 读取并生成实例

我这里定义了一个GroovyFactory,用来实现将Groovy文件生成IRule的实现.

GroovyFactory :

package cn.pomit.skill.groovy.rule;

import java.net.URL;

import groovy.lang.GroovyClassLoader;
import groovy.lang.GroovyCodeSource;

public class GroovyFactory {
	private static GroovyFactory groovyFactory = new GroovyFactory();
	private GroovyClassLoader groovyClassLoader = new GroovyClassLoader();

	public static GroovyFactory getInstance() {
		return groovyFactory;
	}

	/**
	 * 根据groovy文件路径生成IRule的实现
	 * @param packagePath
	 * @return
	 * @throws Exception
	 */
	public IRule getIRuleFromPackage(String filePath) throws Exception {
		URL url = this.getClass().getClassLoader().getResource(filePath);
		Class<?> clazz = groovyClassLoader.parseClass(new GroovyCodeSource(url));
		if (clazz != null) {
			Object instance = clazz.newInstance();
			if (instance != null) {
				if (instance instanceof IRule) {
					return (IRule) instance;
				}
			}
		}
		throw new IllegalArgumentException("读取groovy文件异常");
	}

}

3.3 使用这个实现

		//调用普通的JAVA实现做对比
		List<IRule> rules = new ArrayList<>();
		NormalJavaRule normalJavaRule = new NormalJavaRule();
		rules.add(normalJavaRule);

		//直接读取Groovy文件生成IRule实现
		IRule groovyFile = GroovyFactory.getInstance()
				.getIRuleFromPackage("cn/pomit/skill/groovy/rule/file/GroovyFileRule.groovy");
		rules.add(groovyFile);

执行并调用list里面元素的printInfo方法,结论:

2020-01-02 12:16:25,738 [http-nio-8086-exec-1][IP:|USER:][INFO  cn.pomit.skill.groovy.rule.normal.NormalJavaRule] 这是正常的JAVA代码
2020-01-02 12:16:25,739 [http-nio-8086-exec-1][IP:|USER:][INFO  cn.pomit.skill.groovy.rule.normal.NormalJavaRule] 这是正常的JAVA代码的代码
2020-01-02 12:16:25,744 [http-nio-8086-exec-1][IP:|USER:][INFO  cn.pomit.skill.groovy.rule.file.GroovyFileRule] 这是一段来自Groovy文件的代码
2020-01-02 12:16:25,745 [http-nio-8086-exec-1][IP:|USER:][INFO  cn.pomit.skill.groovy.rule.file.GroovyFileRule] 这是一段来自Groovy文件的代码的代码

改动JAVA普通的实现,打印的东西不会改动(如果只是改变打印内容,ide可能会做优化,可以直接改动逻辑,会更明显)。

改动Groovy文件,打印的东西马上就做改动了。

四、数据库Groovy脚本方式

4.1 Groovy脚本

定义一个GroovyDbRule 的脚本,执行自己的规则。GroovyDbRule 脚本存储在数据库中,

GroovyDbRule脚本如下:

package cn.pomit.skill.groovy.rule.file;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import cn.pomit.skill.groovy.rule.IRule;

class GroovyDbRule implements IRule {
	private Logger log = LoggerFactory.getLogger(this.getClass());
	
	@Override
	public int getType() {
		return GROOVY_DB_TYPE;
	}

	@Override
	public void printInfo() {
		log.info("这是一段来自数据库的Groovy脚本");
		printInfoHigh();
	}
	
	public void printInfoHigh() {
		log.info("这是一段来自数据库的Groovy脚本的代码");
	}
}

建表语句及插入以上脚本:

CREATE TABLE `pomit_rule`  (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
  `rule` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci,
  `create_time` timestamp(0) DEFAULT CURRENT_TIMESTAMP,
  `update_time` timestamp(0) DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP(0),
  `visible` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 6 CHARACTER SET = latin1 COLLATE = latin1_swedish_ci ROW_FORMAT = Dynamic;

-- ----------------------------
-- Records of pomit_rule
-- ----------------------------
INSERT INTO `pomit_rule` VALUES (5, 'GroovyDbRule', 'package cn.pomit.skill.groovy.rule.file;\r\n\r\nimport org.slf4j.Logger;\r\nimport org.slf4j.LoggerFactory;\r\n\r\nimport cn.pomit.skill.groovy.rule.IRule;\r\n\r\nclass GroovyDbRule implements IRule {\r\n	private Logger log = LoggerFactory.getLogger(this.getClass());\r\n	\r\n	@Override\r\n	public int getType() {\r\n		return GROOVY_DB_TYPE;\r\n	}\r\n\r\n	@Override\r\n	public void printInfo() {\r\n		log.info(\"这是一段来自数据库的Groovy脚本\");\r\n		printInfoHigh();\r\n	}\r\n	\r\n	public void printInfoHigh() {\r\n		log.info(\"这是一段来自数据库的Groovy脚本的代码\");\r\n	}\r\n}\r\n', '2020-01-02 10:36:01', '2020-01-02 10:36:01', NULL);

4.2 读取并生成实例

在GroovyFactory,加入从字符串生成IRule实现的方法.

在上面3.2中的GroovyFactory 中,加入下面的代码:

/**
	 * 根据脚本内容生成IRule的实现
	 * @param code
	 * @return
	 * @throws Exception
	 */
	public IRule getIRuleFromCode(String code) throws Exception {
		Class<?> clazz = groovyClassLoader.parseClass(code);
		if (clazz != null) {
			Object instance = clazz.newInstance();
			if (instance != null) {
				if (instance instanceof IRule) {
					return (IRule) instance;
				}
			}
		}
		throw new IllegalArgumentException("读取groovy脚本异常");
	}

4.3 使用这个实现

这里使用到了数据库,所以要使用ORM框架,我使用了Mybatis。RulesDao是Mybatis对4.1中表pomit_rule操作的一个Mapper。

		//调用普通的JAVA实现做对比
		List<IRule> rules = new ArrayList<>();
		NormalJavaRule normalJavaRule = new NormalJavaRule();
		rules.add(normalJavaRule);

		//直接读取Groovy文件生成IRule实现
		IRule groovyFile = GroovyFactory.getInstance()
				.getIRuleFromPackage("cn/pomit/skill/groovy/rule/file/GroovyFileRule.groovy");
		rules.add(groovyFile);

		//从Db的Groovy脚本中生成IRule实现
		Rules ruleGroovy = rulesDao.getByName("GroovyDbRule");
		if (ruleGroovy != null) {
			IRule groovyDb = GroovyFactory.getInstance().getIRuleFromCode(ruleGroovy.getRule());
			rules.add(groovyDb);
		}

执行并调用list里面元素的printInfo方法,结论:

2020-01-02 12:16:25,738 [http-nio-8086-exec-1][IP:|USER:][INFO  cn.pomit.skill.groovy.rule.normal.NormalJavaRule] 这是正常的JAVA代码
2020-01-02 12:16:25,739 [http-nio-8086-exec-1][IP:|USER:][INFO  cn.pomit.skill.groovy.rule.normal.NormalJavaRule] 这是正常的JAVA代码的代码
2020-01-02 12:16:25,744 [http-nio-8086-exec-1][IP:|USER:][INFO  cn.pomit.skill.groovy.rule.file.GroovyFileRule] 这是一段来自Groovy文件的代码
2020-01-02 12:16:25,745 [http-nio-8086-exec-1][IP:|USER:][INFO  cn.pomit.skill.groovy.rule.file.GroovyFileRule] 这是一段来自Groovy文件的代码的代码
2020-01-02 12:16:25,745 [http-nio-8086-exec-1][IP:|USER:][INFO  cn.pomit.skill.groovy.rule.file.GroovyDbRule] 这是一段来自数据库的Groovy脚本
2020-01-02 12:16:25,745 [http-nio-8086-exec-1][IP:|USER:][INFO  cn.pomit.skill.groovy.rule.file.GroovyDbRule] 这是一段来自数据库的Groovy脚本的代码

改动JAVA普通的实现,打印的东西不会改动(如果只是改变打印内容,ide可能会做优化,可以直接改动逻辑,会更明显)。

改动Groovy文件,打印的东西马上就做改动了。

改动数据库中的Groovy脚本,打印的东西马上就做改动了。

五、Spring中使用Groovy的方式

5.1 Groovy文件

定义一个SpringGroovyRule 文件,执行自己的规则。这里拿它来测试Spring是如何将Groovy文件作为Bean来使用,不再手动读取Groovy文件。

SpringGroovyRule如下:

package cn.pomit.skill.groovy.rule.spring;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import cn.pomit.skill.groovy.rule.IRule;
import org.springframework.stereotype.Service;

public class SpringGroovyRule implements IRule {
	private Logger log = LoggerFactory.getLogger(this.getClass());
	@Override
	public int getType() {
		return GROOVY_SPRING_TYPE;
	}

	@Override
	public void printInfo() {
		log.info("这是一段Spring的Groovy代码");
		printInfoHigh();
	}

	public void printInfoHigh() {
		log.info("这是一段Spring的Groovy代码的代码");
	}
}

5.2 读取并生成实例

建立Spring的配置文件(SpringBoot也要这样玩,因为Groovy文件没有JAVA配置的方式生成Bean):spring-groovy.xml。

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:lang="http://www.springframework.org/schema/lang"
	xsi:schemaLocation="http://www.springframework.org/schema/beans 
						http://www.springframework.org/schema/beans/spring-beans.xsd
					    http://www.springframework.org/schema/lang 
					    http://www.springframework.org/schema/lang/spring-lang.xsd">

	<lang:defaults refresh-check-delay="60000" />

	<!-- groovy文件定义为bean -->
	<lang:groovy id="springGroovyRule"
		script-source="classpath:cn/pomit/skill/groovy/rule/spring/SpringGroovyRule.groovy">
	</lang:groovy>
</beans>

5.3 使用这个实现

如果是在SpringBoot下,需要引入上面的xml文件:@ImportResource(locations={"classpath:spring-groovy.xml"})

注入这个bean:

	@Resource(name = "springGroovyRule")
	IRule springGroovyRule;

可以将它放到之前定义的List<IRule> rules中,并调用里面元素的printInfo方法,执行完成如下:

2020-01-02 12:16:25,738 [http-nio-8086-exec-1][IP:|USER:][INFO  cn.pomit.skill.groovy.rule.normal.NormalJavaRule] 这是正常的JAVA代码
2020-01-02 12:16:25,739 [http-nio-8086-exec-1][IP:|USER:][INFO  cn.pomit.skill.groovy.rule.normal.NormalJavaRule] 这是正常的JAVA代码的代码
2020-01-02 12:16:25,744 [http-nio-8086-exec-1][IP:|USER:][INFO  cn.pomit.skill.groovy.rule.file.GroovyFileRule] 这是一段来自Groovy文件的代码
2020-01-02 12:16:25,745 [http-nio-8086-exec-1][IP:|USER:][INFO  cn.pomit.skill.groovy.rule.file.GroovyFileRule] 这是一段来自Groovy文件的代码的代码
2020-01-02 12:16:25,745 [http-nio-8086-exec-1][IP:|USER:][INFO  cn.pomit.skill.groovy.rule.file.GroovyDbRule] 这是一段来自数据库的Groovy脚本
2020-01-02 12:16:25,745 [http-nio-8086-exec-1][IP:|USER:][INFO  cn.pomit.skill.groovy.rule.file.GroovyDbRule] 这是一段来自数据库的Groovy脚本的代码
2020-01-02 12:16:25,747 [http-nio-8086-exec-1][IP:|USER:][INFO  cn.pomit.skill.groovy.rule.spring.SpringGroovyRule] 这是一段Spring的Groovy代码
2020-01-02 12:16:25,748 [http-nio-8086-exec-1][IP:|USER:][INFO  cn.pomit.skill.groovy.rule.spring.SpringGroovyRule] 这是一段Spring的Groovy代码的代码

六、过程中用到的其他文件

6.1 完整的GroovyFactory

package cn.pomit.skill.groovy.rule;

import java.net.URL;

import groovy.lang.GroovyClassLoader;
import groovy.lang.GroovyCodeSource;

public class GroovyFactory {
	private static GroovyFactory groovyFactory = new GroovyFactory();
	private GroovyClassLoader groovyClassLoader = new GroovyClassLoader();

	public static GroovyFactory getInstance() {
		return groovyFactory;
	}

	/**
	 * 根据groovy文件路径生成IRule的实现
	 * @param packagePath
	 * @return
	 * @throws Exception
	 */
	public IRule getIRuleFromPackage(String filePath) throws Exception {
		URL url = this.getClass().getClassLoader().getResource(filePath);
		Class<?> clazz = groovyClassLoader.parseClass(new GroovyCodeSource(url));
		if (clazz != null) {
			Object instance = clazz.newInstance();
			if (instance != null) {
				if (instance instanceof IRule) {
					return (IRule) instance;
				}
			}
		}
		throw new IllegalArgumentException("读取groovy文件异常");
	}
	
	/**
	 * 根据脚本内容生成IRule的实现
	 * @param code
	 * @return
	 * @throws Exception
	 */
	public IRule getIRuleFromCode(String code) throws Exception {
		Class<?> clazz = groovyClassLoader.parseClass(code);
		if (clazz != null) {
			Object instance = clazz.newInstance();
			if (instance != null) {
				if (instance instanceof IRule) {
					return (IRule) instance;
				}
			}
		}
		throw new IllegalArgumentException("读取groovy脚本异常");
	}
}

6.2 完整的RuleFactory

package cn.pomit.skill.groovy.rule;

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

import cn.pomit.skill.groovy.rule.db.Rules;
import cn.pomit.skill.groovy.rule.db.RulesDao;
import cn.pomit.skill.groovy.rule.normal.NormalJavaRule;

public class RuleFactory {
	private static volatile RuleFactory singleton = null;

	private RuleFactory() {
	}
	public static RuleFactory getInstance() {
		// 第一次校验singleton是否为空
		if (singleton == null) {
			synchronized (RuleFactory.class) {
				// 第二次校验singleton是否为空
				if (singleton == null) {
					singleton = new RuleFactory();
				}
			}
		}
		return singleton;
	}

	private RulesDao rulesDao;
	private RuleFactory(RulesDao rulesDao) {
		this.rulesDao = rulesDao;
	}
	public static RuleFactory getInstance(RulesDao rulesDao) {
		// 第一次校验singleton是否为空
		if (singleton == null) {
			synchronized (RuleFactory.class) {
				// 第二次校验singleton是否为空
				if (singleton == null) {
					singleton = new RuleFactory(rulesDao);
				}
			}
		}
		return singleton;
	}

	public List<IRule> getRuleList() throws Exception {
		//调用普通的JAVA实现做对比
		List<IRule> rules = new ArrayList<>();
		NormalJavaRule normalJavaRule = new NormalJavaRule();
		rules.add(normalJavaRule);

		//直接读取Groovy文件生成IRule实现
		IRule groovyFile = GroovyFactory.getInstance()
				.getIRuleFromPackage("cn/pomit/skill/groovy/rule/file/GroovyFileRule.groovy");
		rules.add(groovyFile);

		//从Db的Groovy脚本中生成IRule实现
		Rules ruleGroovy = rulesDao.getByName("GroovyDbRule");
		if (ruleGroovy != null) {
			IRule groovyDb = GroovyFactory.getInstance().getIRuleFromCode(ruleGroovy.getRule());
			rules.add(groovyDb);
		}

		return rules;
	}
}

6.3 数据库访问相关实体

Rules:

package cn.pomit.skill.groovy.rule.db;

import java.util.Date;

public class Rules {
	private Integer id;
	private String rule;
	private String name;
	private Date create_time;
	private Date update_time;
	private Integer visible;

	public String getRule() {
		return rule;
	}

	public void setRule(String rule) {
		this.rule = rule;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public Integer getId() {
		return id;
	}

	public void setId(Integer id) {
		this.id = id;
	}

	public Integer getVisible() {
		return visible;
	}

	public void setVisible(Integer visible) {
		this.visible = visible;
	}

	public Date getUpdate_time() {
		return update_time;
	}

	public void setUpdate_time(Date update_time) {
		this.update_time = update_time;
	}

	public Date getCreate_time() {
		return create_time;
	}

	public void setCreate_time(Date create_time) {
		this.create_time = create_time;
	}
}

RulesDao:

package cn.pomit.skill.groovy.rule.db;


import java.util.List;

import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import org.apache.ibatis.annotations.Update;

@Mapper
public interface RulesDao {
    @Select("SELECT * FROM pomit_rule where id = #{id}")
    Rules getById(@Param("id") Integer id);
    
    @Select("SELECT * FROM pomit_rule where name = #{name}")
    Rules getByName(@Param("name") String name);

    @Insert("INSERT INTO pomit_rule(name,rule) VALUE(#{name},#{rule})")
    Integer setRule(@Param("name") String name,@Param("rule") String rule);

    @Select("SELECT * FROM pomit_rule order by create_time DESC")
    List<Rules> getRuleList();

    @Update("UPDATE pomit_rule SET visible=0 WHERE id = #{id}")
    Integer deleteRule(@Param("id") Integer id);

    @Update("UPDATE pomit_rule SET rule= #{rule} WHERE id = #{id}")
    Integer updateRule(@Param("id") Integer id,@Param("rule") String rule);

}

6.4 SpringBoot相关实体

ApiApplication:

package cn.pomit.skill.groovy;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ImportResource;

@SpringBootApplication
@ImportResource(locations={"classpath:spring-groovy.xml"})
public class ApiApplication {
	public static void main(String[] args) {
		SpringApplication.run(ApiApplication.class, args);
	}
}

6.5 测试web

WebRest:

package cn.pomit.skill.groovy.web;

import java.util.List;

import javax.annotation.Resource;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import cn.pomit.skill.groovy.rule.IRule;
import cn.pomit.skill.groovy.rule.RuleFactory;
import cn.pomit.skill.groovy.rule.db.RulesDao;

@RestController
@RequestMapping("/")
public class WebRest {
	@Autowired
	RulesDao rulesDao;
	
	@Resource(name = "springGroovyRule")
	IRule springGroovyRule;

	@RequestMapping(value = "/test")
	public String test() throws Exception {
		List<IRule> list = RuleFactory.getInstance(rulesDao).getRuleList();
		list.add(springGroovyRule);
		for (IRule item : list) {
			item.printInfo();
		}
		return "0000";
	}
}

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • Web基础配置篇(十六): Kubernetes集群的安装使用

    Kubernetes 简称为K8S,是用于自动部署,扩展和管理容器化应用程序的开源系统。Kubernetes的目标是让部署容器化的应用简单并且高效(powerf...

    品茗IT
  • Web基础配置篇(十): ActiveMQ与RabbitMQ的安装配置及使用

    消息中间件利用高效可靠的消息传递机制进行平台无关的数据交流,并基于数据通信来进行分布式系统的集成。通过提供消息传递和消息排队模型,它可以在分布式环境下扩展进程间...

    品茗IT
  • SpringCloud技术指南系列(六)服务注册发现之Zookeeper服务注册

    目前服务发现的解决方案有Eureka,Consul,Zookeeper等,这三个是SpringCloud官方支持的。

    品茗IT
  • Linux常用命令之cp、mv与rm

    cp passwd passwd-01:复制passwd到当前目录下,名称为passwd-01

    RambleHQ
  • 比特币存储与资产安全

    网贷谈嘉宾:比太钱包创始人文浩:今天和大家交流的内容是《比特币存储与资产安全》。目前,越来越多的人将比特币作为资产储藏,抵抗通胀膨胀。不论是企业还是个人,都越发...

    企鹅号小编
  • iOS逆向(1)-密码学(RSA)

    原文地址:https://juejin.im/post/5c7e72cd6fb9a049fc044519”

    iOSSir
  • Buffer pool 详解

    提示:公众号展示代码会自动折行,建议横屏阅读 ---- 1 综述 buffer pool 是 innodb的数据缓存,保存了 data page、index...

    腾讯数据库技术
  • 斯坦福AI几小时发现元素周期表,张首晟团队将设计替代图灵测试的新标准

    【新智元导读】斯坦福张首晟团队创造了一个人工智能程序Atom2Vec,只用几个小时就重新得出了元素周期表。这项研究更宏大的目标是设计出替代作为机器智能标准的图灵...

    新智元
  • 如何在厕所、垃圾桶或小树林捡一枚BCH?看完后我笑了...

    每个人都可以参与,只要你足够仔细和耐心。你可以藏宝物,也可以找宝物,而且往往很简单,比如这一个:

    区块链大本营
  • 来自群友的分享

    我是来自某大学本科,刚打完一个关于机器人的比赛,简单来说我在里面是负责识别一排矩形物体,返回最近的一个长方体并返回其相对于深度相机的三维坐标和角度。因为要使机器...

    点云PCL博主

扫码关注云+社区

领取腾讯云代金券