构建 API 接口及其相关组件通常是一项非常繁琐的任务,尤其是在处理复杂的数据模型和微服务等架构时。重复编码、设置配置以及构建单元测试的开销很快就会变得非常耗时。以下将介绍ChatGPT 等人工智能工具如何改变这种游戏规则。
在 API 接口开发中利用 AI 工具(CHAT GPT)
为了了解 ChatGPT 的功能,让我们深入了解一个实践示例。我们的任务是开发 REST API 来管理用户的个人身份信息 (PII)。此过程需要:
1、创建数据库(数据存储过程)
2、Repository层(数据库交互和数据访问对象的接口)
3、service层(业务逻辑层)
4、controller层(暴露接口)
数据库层
要构建存储过程,首先向 ChatGPT 提供表结构。之后,提供一个示例存储过程。 ChatGPT 就会使用这个存储过程模式并为指定的表构造一个新的存储过程。下面是提供的表结构:
CREATE TABLE `user_pii_data_repo` (
`id` bigint NOT NULL AUTO_INCREMENT,
`user_id` int DEFAULT NULL,
`loan_id` int DEFAULT NULL,
`ext_partner_name` varchar(30) NOT NULL,
`ext_partner_source` varchar(30) NOT NULL,
`phase` varchar(20) NOT NULL,
`session_uuid` varchar(36) DEFAULT NULL,
`first_name` varchar(300) DEFAULT NULL,
`last_name` varchar(300) DEFAULT NULL,
`address1` varchar(300) DEFAULT NULL,
`address2` varchar(300) DEFAULT NULL,
`city` varchar(300) DEFAULT NULL,
`state` char(2) DEFAULT NULL,
`zip` varchar(300) DEFAULT NULL,
`ssn` varchar(300) DEFAULT NULL,
`dob` date DEFAULT NULL,
`phone` varchar(300) DEFAULT NULL,
`payload_path` varchar(500) DEFAULT NULL,
PRIMARY KEY (`id`)
);
下面是生成的存储过程
CREATE PROCEDURE `p_get_user_pii_data`(IN v_user_id INT, IN v_loan_id INT)
BEGIN
SELECT
id, user_id, loan_id, ext_partner_name,
ext_partner_source, phase, session_uuid, first_name,
last_name, address1, address2, city,
state, zip, ssn, dob,
phone, payload_path
FROM
user_pii_data_repo
WHERE
user_id = v_user_id
AND
loan_id = v_loan_id;
END;
下图是访问gpt的对话记录,有CHATGPT账号的话,也可以访问这个链接(
https://chat.openai.com/share/ab4331b3-2822-46e6-9dc1-450aa2eb1431)
Repository层(数据库交互和数据访问对象的接口)
在构建存储层的过程中,我们为它提供了前面提到的存储过程和表定义。利用 ChatGPT 的功能,我们成功生成了:
1、JPA 实体。
2、一个完整的Repository层类,包含接口及其实现。
package com.demo.app.api.core.repository.user_pii;
import com.demo.app.api.core.model.user_pii.UserPiiData;
import java.util.List;
public interface UserPiiDataRepository {
List<UserPiiData> getUserPiiData(Integer userId, Integer loanId);
}
package com.demo.app.api.core.repository.user_pii;
import com.demo.app.api.core.model.user_pii.UserPiiData;
import com.demo.app.api.core.repository.EntityManagerThreadLocalHelper;
import com.demo.app.api.core.services.common.CryptoService;
import com.demo.app.api.utils.Utility;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Repository;
import javax.persistence.*;
import java.util.List;
@Repository
@Qualifier("userPiiDataRepository")
public class UserPiiDataRepositoryImpl implements UserPiiDataRepository {
private final Logger logger = LoggerFactory.getLogger(this.getClass());
@Autowired
EntityManagerThreadLocalHelper threadLocalHelper;
@Autowired
CryptoService cryptoService;
@Override
public List<UserPiiData> getUserPiiData(Integer userId, Integer loanId) {
List<UserPiiData> results = null;
try {
EntityManager entityManager = threadLocalHelper.getEntityManager();
StoredProcedureQuery query = entityManager.createStoredProcedureQuery(UserPiiDataDbConstants.PROC_UW_AP_GET_USER_PII_DATA, UserPiiData.class);
query.registerStoredProcedureParameter(UserPiiDataDbConstants.V_PARAM_USER_ID, Integer.class, ParameterMode.IN);
query.registerStoredProcedureParameter(UserPiiDataDbConstants.V_PARAM_LOAN_ID, Integer.class, ParameterMode.IN);
query.setParameter(UserPiiDataDbConstants.V_PARAM_USER_ID, userId);
query.setParameter(UserPiiDataDbConstants.V_PARAM_LOAN_ID, loanId);
query.execute();
results = query.getResultList();
for (UserPiiData userPiiData :
results) {
if (userPiiData != null) {
if (userPiiData.getFirstName() != null) {
String decryptedFirstName = this.cryptoService.decrypt(userPiiData.getFirstName());
userPiiData.setFirstName(decryptedFirstName);
}三
if (userPiiData.getDob() != null) {
String formattedDate = Utility.getFormattedDobMMDDYYYY(userPiiData.getDob());
userPiiData.setFormattedDob(formattedDate);
}
}
entityManager.detach(userPiiData);
}
threadLocalHelper.closeEntityManager();
} catch(Exception ex) {
logger.error("UserPiiDataRepositoryImpl::getUserPiiData - an error occurred while fetching user pii data", ex);
threadLocalHelper.closeEntityManager();
}
return results;
}
}
下图是访问gpt的对话记录,有CHATGPT账号的话,也可以访问这个链接(
https://chat.openai.com/share/ab4331b3-2822-46e6-9dc1-450aa2eb1431)
service层(业务逻辑层)
为了更深入的探索,我们为CHATGPT指定 JPA 实体和存储库接口等依赖项。 AI工具迅速生成了类。服务接口概述了一个明确的需求,用于根据用户和贷款 ID 获取用户 PII 数据。它的实现 UserPIIDataServiceImpl 利用 JPA 存储库来获取所需的数据,如果为 null,将返回一个空列表 — 这是避免NPE的很周到的做法。
package com.demo.app.api.core.services.user_pii;
import com.demo.app.api.core.model.user_pii.UserPiiData;
import java.util.List;
public interface UserPIIDataService {
List<UserPiiData> getUserPiiData(Integer userId, Integer loanId);
}
package com.demo.app.api.core.services.user_pii;
import com.demo.app.api.core.model.user_pii.UserPiiData;
import com.demo.app.api.core.repository.user_pii.UserPiiDataRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.Collections;
import java.util.List;
@Service
public class UserPIIDataServiceImpl implements UserPIIDataService {
@Autowired
UserPiiDataRepository userPiiDataRepository;
@Override
public List<UserPiiData> getUserPiiData(Integer userId, Integer loanId) {
List<UserPiiData> piiData = userPiiDataRepository.getUserPiiData(userId, loanId);
return piiData != null ? piiData : Collections.emptyList();
}
}
下图是访问gpt的对话记录,有CHATGPT账号的话,也可以访问这个链接(
https://chat.openai.com/share/ab4331b3-2822-46e6-9dc1-450aa2eb1431)
controller层
我们向 ChatGPT 提供了此示例以及服务接口和必要的实体对象。 作为回应,ChatGPT 生成了一个根据我们的要求定制的 RestController。下面是生成的类和代码:
package com.demo.app.api.controller.user_pii;
import com.demo.app.api.core.model.user_pii.UserPiiData;
import com.demo.app.api.core.services.user_pii.UserPIIDataService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiResponse;
import io.swagger.annotations.ApiResponses;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@CrossOrigin(origins = "*")
@RestController
@RequestMapping("/api/mis/v1/ap")
@Api(tags = "Controller for fetching User's PII data")
public class UserPIIDataController {
@Autowired
UserPIIDataService userPIIDataService;
@GetMapping(path = "/pii-data/user/{userId}/loan/{loanId}", produces = "application/json")
@ApiOperation("Fetch user's PII data by user ID and loan ID")
@ApiResponses(value = {
@ApiResponse(code = 200, message = "Successfully fetched user's PII data"),
@ApiResponse(code = 400, message = "Bad request"),
@ApiResponse(code = 404, message = "Not found"),
@ApiResponse(code = 500, message = "Internal server error")
})
public List<UserPiiData> getUserPiiDataByUserIdAndLoanId(
@PathVariable(name = "userId") Integer userId,
@PathVariable(name = "loanId") Integer loanId) {
return this.userPIIDataService.getUserPiiData(userId, loanId);
}
}
最后,为了确保一切按预期运行,我们使用 Postman 对 API 端点进行了验证。令人高兴的是,API 的行为完全符合预期,展示了自动生成代码的实际适用性和精度。 上面的示例可能看起来很简单,但我们还应用了这种方法来构建 API 接口,当处理大量表(例如 30 列)时,真正的优势就会显现出来。手动定义存储过程参数并构造具有多种属性的实体(每个属性都需要精确的列映射)可能是一个乏味且容易出错的过程。然而,利用 ChatGPT 或其他人工智能实用程序等工具可以消除这些重复性任务。因此,开发人员可以以更少的工作量生成更高效、文档齐全的代码。
总结
技术领域正在迅速发展。随着 ChatGPT 等人工智能工具的出现,开发人员现在在编码工作中拥有了强大的盟友。通过自动化 API 开发中更繁琐和重复的任务,这些工具不仅简化了流程,还大大提高了代码质量和准确性。本文分享的经验证明了这样一个事实:人工智能彻底改变软件开发的潜力不仅仅是猜测,而是我们开始接受的现实。随着我们不断前进,人与机器之间的这种协作无疑将重新定义软件工程的格局,为以前认为无法达到的新可能性和效率水平打开大门。
评论区