高级Java开发工程师手把手教你用AI人工智能帮你写JAVA代码实际案例二全网唯一
一、需求背景案例说明
笔者有个实际的生产项目,想自己自定义定时器到数据库表里面,不想配置到配置文件里面,很麻烦!这次想用AI帮我写代码!Java springboot 环境!
数据库设计为:
CREATE TABLE `timer_config` (
`id` int(0) NOT NULL AUTO_INCREMENT,
`timer_config` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '定时器配置:0 10 * * * ?',
`class_method_name` text CHARACTER SET utf8 COLLATE utf8_general_ci NULL COMMENT '执行类方法名称',
`remark` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '备注信息',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
-- ----------------------------
-- Records of md_timer_config
-- ----------------------------
INSERT INTO `timer_config` VALUES (1, '0 0 * * * ?', 'nasenServiceImpl.Task1', '方法1');
INSERT INTO `timer_config` VALUES (2, '0 5 * * * ?', 'nasenServiceImpl.Task2', '方法2');
大家按照我的训练人工智能的思路往下走,AI还是需要引导与指导的!笔者把思路方法写下来!
二、训练指导AI的方法步骤
训练AI口令步骤一
提问口令:
下面是mysql的一个定时器配置表!
CREATE TABLE `timer_config` (
`id` int(0) NOT NULL AUTO_INCREMENT,
`timer_config` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '定时器配置:0 10 * * * ?',
`class_method_name` text CHARACTER SET utf8 COLLATE utf8_general_ci NULL COMMENT '执行类方法名称',
`remark` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '备注信息',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
-- ----------------------------
-- Records of md_timer_config
-- ----------------------------
INSERT INTO `timer_config` VALUES (1, '0 0 * * * ?', 'nasenServiceImpl.Task1', '方法1');
INSERT INTO `timer_config` VALUES (2, '0 5 * * * ?', 'nasenServiceImpl.Task2', '方法2');
下面是java代码spingboot的定时器调度的例子:
@EnableScheduling
@Component
public class AutoConfigTaskschedule {
@Autowired
private nasenServiceImpl nasenServiceImpl;
@Scheduled(cron = "0 0 * * * ?")
public void task1() {
nasenServiceImpl.Task1();
}
@Scheduled(cron = "0 5 * * * ?")
public void task2() {
nasenServiceImpl.Task2();
}
}
你帮我修改代码,读取数据库的这个配置表,并动态的执行配置表里面的定时器任务!帮我把Java代码写出来
注意:你要提前给AI一个引导,这个引导是一个方向,比如你给他建表语句,跟你项目中已经写好的定时器的一个例子,AI可以读懂,给你项目大概方向的代码跟实现!
AI回复:
以下是修改后的 Java 代码,用于读取数据库中的定时器配置表,并动态执行配置表中的定时器任务:
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
@EnableScheduling
@Component
public class DynamicTaskScheduler {
@Autowired
private DataSource dataSource; // 注入数据源
@Scheduled(cron = "0 * * * *?") // 定期执行加载任务配置的操作
public void loadTasks() {
try (Connection connection = dataSource.getConnection()) {
String query = "SELECT timer_config, class_method_name FROM timer_config";
try (PreparedStatement statement = connection.prepareStatement(query);
ResultSet resultSet = statement.executeQuery()) {
while (resultSet.next()) {
String timerConfig = resultSet.getString("timer_config");
String classMethodName = resultSet.getString("class_method_name");
// 根据配置创建定时器任务
@Scheduled(cron = timerConfig)
public void performTask() {
nasenServiceImpl.getClass().getMethod(classMethodName).invoke(nasenServiceImpl);
}
}
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}
在上述代码中,通过 loadTasks
方法定期从数据库中加载任务配置。使用 DataSource
注入数据源,并执行查询操作获取定时器配置和对应的类方法名称。然后,根据配置动态创建定时器任务,并通过反射机制调用指定类的指定方法。
请确保已正确配置数据源,并根据实际情况进行调整和扩展。
这个代码还是有些错误的,所以我们要继续引导AI
这个代码经过测试是错误的,还得继续引导!
训练AI口令步骤二
提问口令:
@Autowired
private DataSource dataSource; // 注入数据源
@Scheduled(cron = "0 * * * *?") // 定期执行加载任务配置的操作
public void loadTasks() {
try (Connection connection = dataSource.getConnection()) {
String query = "SELECT timer_config, class_method_name FROM md_timer_config";
try (PreparedStatement statement = connection.prepareStatement(query);
ResultSet resultSet = statement.executeQuery()) {
while (resultSet.next()) {
String timerConfig = resultSet.getString("timer_config");
String classMethodName = resultSet.getString("class_method_name");
// 根据配置创建定时器任务
@Scheduled(cron = timerConfig)
public void performTask() {
clickHouseService.getClass().getMethod(classMethodName).invoke(clickHouseService);
}
}
}
} catch (SQLException e) {
e.printStackTrace();
}
}
你帮我修改代码,读取数据库的这个配置表,并动态的执行配置表里面的定时器任务!帮我把Java代码写出来,哪里不对也帮我改造一下
AI的回答如下:
在Spring Boot中动态创建定时任务并不像直接在类中声明@Scheduled
注解那么简单,因为注解是在编译时解析的,不能动态添加或更改。为此,我们需要利用Spring的任务调度器(TaskScheduler)结合数据访问来实现动态定时任务。
以下是一个基于ThreadPoolTaskScheduler
的实现示例:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.scheduling.TaskScheduler;
import org.springframework.scheduling.Trigger;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
import org.springframework.scheduling.support.CronTrigger;
import org.springframework.stereotype.Component;
import javax.sql.DataSource;
import java.lang.reflect.Method;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
@Component
public class DynamicTaskScheduler {
@Autowired
private DataSource dataSource;
@Autowired
private ApplicationContext applicationContext; // 用于获取Bean
private TaskScheduler taskScheduler = new ThreadPoolTaskScheduler();
@PostConstruct
public void init() {
taskScheduler.initialize(); // 初始化任务调度器
loadAndScheduleTasks();
}
private void loadAndScheduleTasks() {
try (Connection connection = dataSource.getConnection()) {
String query = "SELECT timer_config, class_method_name FROM md_timer_config";
try (PreparedStatement statement = connection.prepareStatement(query);
ResultSet resultSet = statement.executeQuery()) {
while (resultSet.next()) {
String timerConfig = resultSet.getString("timer_config");
String classMethodName = resultSet.getString("class_method_name");
scheduleTask(timerConfig, classMethodName);
}
}
} catch (SQLException e) {
e.printStackTrace();
}
}
private void scheduleTask(String timerConfig, String classMethodName) {
Class<?> serviceClass = getBeanClassByName(classMethodName.split("\\.")[0]);
String methodName = classMethodName.substring(classMethodName.indexOf(".") + 1);
Method method = findMethod(serviceClass, methodName);
if (method == null) {
throw new RuntimeException("无法找到方法: " + methodName);
}
Trigger trigger = new CronTrigger(timerConfig);
taskScheduler.schedule(() -> invokeMethod(method, applicationContext.getBean(serviceClass)), trigger);
}
private Class<?> getBeanClassByName(String beanName) {
return applicationContext.getBeansOfType(Object.class).keySet()
.stream()
.filter(key -> key.getName().equals(beanName))
.findFirst()
.map(key -> key.getType())
.orElseThrow(() -> new RuntimeException("无法找到名为" + beanName + "的Bean"));
}
private Method findMethod(Class<?> clazz, String methodName) {
try {
return clazz.getMethod(methodName);
} catch (NoSuchMethodException e) {
return null;
}
}
private void invokeMethod(Method method, Object target) {
try {
method.invoke(target);
} catch (IllegalAccessException | InvocationTargetException e) {
e.printStackTrace();
}
}
}
在这个例子中,我们首先初始化了一个ThreadPoolTaskScheduler
,然后从数据库中读取定时任务配置,并为每个配置创建一个新的定时任务,这些任务通过触发器(如CronTrigger)和任务执行体(即调用指定类的方法)来定义。
需要注意的是,getBeanClassByName
方法是基于假设数据库中的类名与Spring容器中的Bean名称一致,如果实际情况不同,可能需要调整这个方法以适应实际的Bean查找逻辑。同时,findMethod
方法是简单查找无参的公共方法,如果方法带有参数,还需要进一步完善该方法。
然后我们把代码复制到自己的项目跑跑改改,发现了有一个方法是错误的!
针对错误的方法,把提问的范围缩小!你要说出你自己具体的那个方法,什么问题,什么需求!
训练AI口令步骤三
上部分代码也粘贴给AI
上面代码中的getBeanClassByName方法报错,帮我重新写一个
注意:代码一定要附在上面,要不然AI读不懂!读不懂,他的回答就会千奇百怪!你要引导它给你最佳最准的答案!
AI回答如下:
在Spring中,获取Bean的类型通常不是基于Bean的名称而是基于类类型。如果你的class_method_name
字段格式是“ClassName.methodName”,那么我们可以尝试按类名直接获取Bean。不过,Spring容器中的Bean默认名称通常是首字母小写的类名。如果Bean的名称与类名不一致,你需要在配置文件中为Bean提供明确的名称。这里给出一个改进后的getBeanClassByName
方法,假设Spring Bean的名字和类名一致:
private Class<?> getBeanClassByName(String className) {
Map<String, Object> beans = applicationContext.getBeansWithAnnotation(Component.class);
for (Map.Entry<String, Object> entry : beans.entrySet()) {
if (entry.getValue().getClass().getSimpleName().equals(className)) {
return entry.getValue().getClass();
}
}
throw new RuntimeException("无法找到名为" + className + "的Bean");
}
然而,这种方法仍然存在一定的局限性,因为它是基于类的简单名匹配,并且依赖于所有的Spring Bean都有@Component
注解。在大型项目中,推荐使用更精确的方式来获取Bean,例如:
private Class<?> getBeanClassByName(String className) {
try {
return Class.forName(className);
} catch (ClassNotFoundException e) {
// 如果你想基于Spring容器中已注册的Bean名称来查找,则可以尝试以下方式
for (String beanName : applicationContext.getBeanDefinitionNames()) {
Class<?> beanType = applicationContext.getType(beanName);
if (beanType.getSimpleName().equals(className)) {
return beanType;
}
}
throw new RuntimeException("无法找到名为" + className + "的Bean");
}
}
请注意,尽管如此,这种方式仍不够健壮,因为在实际项目中类名和Bean名称可能存在差异。若要在Spring容器中准确地根据类名获取Bean,请确保你有足够的上下文信息来正确识别对应的Bean。如果Bean的名称和类名没有直接关系,可能需要在数据库中存储额外的信息,例如Bean的名称或者类的全限定名。
再把改造后的方法,放到自己项目里面测试一下跑通了!
最终整合AI跑通的代码如下:
package com.nasen.schedule;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.scheduling.TaskScheduler;
import org.springframework.scheduling.Trigger;
import org.springframework.scheduling.concurrent.ExecutorConfigurationSupport;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
import org.springframework.scheduling.support.CronTrigger;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import javax.sql.DataSource;
import java.lang.reflect.Method;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
@Component
public class DynamicTaskScheduler {
@Autowired
private DataSource dataSource;
@Autowired
private ApplicationContext applicationContext; // 用于获取Bean
private TaskScheduler taskScheduler = new ThreadPoolTaskScheduler();
@PostConstruct
public void init() {
((ExecutorConfigurationSupport) taskScheduler).initialize(); // 初始化任务调度器 loadAndScheduleTasks(); } private void loadAndScheduleTasks() { try (Connection connection = dataSource.getConnection()) {
String query = "SELECT timer_config, class_method_name FROM timer_config";
try (PreparedStatement statement = connection.prepareStatement(query);
ResultSet resultSet = statement.executeQuery()) {
while (resultSet.next()) {
String timerConfig = resultSet.getString("timer_config");
String classMethodName = resultSet.getString("class_method_name");
scheduleTask(timerConfig, classMethodName);
}
}
} catch (SQLException e) {
e.printStackTrace();
}
}
private void scheduleTask(String timerConfig, String classMethodName) {
Class<?> serviceClass = getBeanClassByName(classMethodName.split("\\.")[0]);
String methodName = classMethodName.substring(classMethodName.indexOf(".") + 1);
Method method = findMethod(serviceClass, methodName);
if (method == null) {
throw new RuntimeException("无法找到方法: " + methodName);
}
Trigger trigger = new CronTrigger(timerConfig);
taskScheduler.schedule(() -> invokeMethod(method, applicationContext.getBean(serviceClass)), trigger);
}
private Class<?> getBeanClassByName(String className) {
try {
return Class.forName(className);
} catch (ClassNotFoundException e) {
// 如果你想基于Spring容器中已注册的Bean名称来查找,则可以尝试以下方式
for (String beanName : applicationContext.getBeanDefinitionNames()) {
Class<?> beanType = applicationContext.getType(beanName);
if (beanType.getSimpleName().equals(className)) {
return beanType;
}
}
throw new RuntimeException("无法找到名为" + className + "的Bean");
}
}
private Method findMethod(Class<?> clazz, String methodName) {
try {
return clazz.getMethod(methodName);
} catch (NoSuchMethodException e) {
return null;
}
}
private void invokeMethod(Method method, Object target) {
try {
method.invoke(target);
} catch (Exception e) {
e.printStackTrace();
}
}
}
四、总结
引导思路方法很重要,你要给AI比较具体的例子,然后再缩小范围,然后再提出具体的需求,当然过程中还得自己去测代码,前提是你也得懂代码,你是一个引导者!
笔者这次用的2个AI平台互相引导,用到”豆包“与”通义千问“!
先问豆包AI,看他回答的怎么样,回答的不好,再问通义千问AI,看看是不是回答的更好!然后2者截取最好的,再引导,从这个实际例子中看,通义千问AI的训练水平更高,更聪明,更高说通义千问AI的训练程度更强!
豆包AI是字节跳动公司研发的一种人工智能工具,它基于云雀模型运行。这款工具融合了聊天机器人、写作助手和英语学习助手的功能,能应对各种任务,例如解答用户问题、进行对话、协助文本创作以及提供语言学习指导。豆包AI不仅可以从网页端访问,也能在iOS和Android平台上使用。
https://www.doubao.com/
通义千问是阿里云研发的超大规模语言模型,能够回答问题、创作文字,还能表达观点、撰写代码,功能强大且应用场景广泛。作为一个AI助手,通义千问能够帮助用户在工作、学习、生活中提高效率与质量,通过自然语言理解和生成技术,为用户提供精准、详尽和个性化的服务。您可以通过与通义千问互动,体验其多种功能和智能特性。
https://tongyi.aliyun.com/
2个AI 2个人工智能大师,看看他们谁强谁弱,我是让他们2个一起帮我工作!互相引导!互相帮助!
AI人工智能是什么
人工智能把它看成是一个巨大的无限的机器人或者是巨型的知识库,它能是模拟人类的神经大脑的一个创造的巨大的机器人,它可以通过自主学习与训练变得知识变得越来越丰富!我们普通人就帮它看成一个机器人即可!这个机器人可以协助你帮助你做一些工作、生活的事情,你要指导它、训练它让它为你所用!我们都看过施瓦辛格《未来战士》的天网,AI类似于天网的概念!你可能从脑子里想象你可以给他对话,他是你的管家!很多电影都有类似这些场景!笔者主要是从实际运用出发!就是生活中我们怎么运用到人工智能!
https://tongyi.aliyun.com/qianwen/
https://www.doubao.com/
五、笔者简介
国内某一线知名软件公司企业认证在职员工:任JAVA高级研发工程师,大数据领域专家,数据库领域专家兼任高级DBA!10年软件开发经验!现任国内某大型软件公司大数据研发工程师、MySQL数据库DBA,软件架构师。直接参与设计国家级亿级别大数据项目!并维护真实企业级生产数据库300余个!紧急处理数据库生产事故上百起,挽回数据丢失所造成的灾难损失不计其数!并为某国家级大数据系统的技术方案(国家知识产权局颁布)专利权的第一专利发明人!
文章评论