需求说明
一个简单而复杂的需求,背景是我司需要提供给供应商公司一个接口,这个接口按照供应商的条件接收他们传过来的数据,没见过吧!没办法!我们公司小!本来按照他们的传参直接写接口就行,但是呢,考虑到以后可能还会有这样的情况,就想把这接口弄成可以直接在页面配置,完了发布出来就可以被访问的。在网上找了半天,没有找到合适的我这场景的。后来才知道这种实现叫动态注册接口,然而换了关键词还是没有搜到,只好自己琢磨。
解决方案及实现
创建接口信息实体类
定义一个Java类,用于表示接口的相关信息,包括名称、请求方法、URL路径、参数列表等。
public class ApiInfo {
private String name;
private HttpMethod method;
private String path;
private List<String> headers;
/**
* 1 参数 2 对象
*/
private Integer paramType;
private List<ApiParameter> parameters;
// 省略构造方法和getter/setter
}
public class ApiParameter {
private String name;
private String type;
// 省略构造方法和getter/setter
}
设计数据库表结构
创建一个数据表,用于存储接口信息。
动态注册接口
可以通过编写代码来实现动态注册接口的逻辑。
@RestController
public class DynamicApiController {
private Map<String, ApiInfo> apiRegistry = new ConcurrentHashMap<>();
// 此处要有一个静态方法把数据库中的apiInfo存到apiRegistry 中
@Autowired
private ApiRepository apiRepository;
@PostMapping("/register-api")
public void registerApi(@RequestBody ApiInfo apiInfo) {
// 将接口信息保存到数据库
apiRepository.save(apiInfo);
// 注册接口到运行时的路由表中
apiRegistry.put(apiInfo.getPath(), apiInfo);
}
@RequestMapping("/{path}")
public Object handleApiRequest(@PathVariable String path, HttpServletRequest request) {
ApiInfo apiInfo = apiRegistry.get(path);
if (apiInfo != null && apiInfo.getMethod() == HttpMethod.resolve(request.getMethod())) {
// 处理请求逻辑,返回对应的数据或响应
// ...
}
// 处理未注册或不匹配的情况
// ...
}
}
上述代码中,DynamicApiController类负责处理动态注册的接口和处理请求。registerApi方法用于将接口信息保存到数据库,并将接口注册到内存中的路由表中。handleApiRequest方法则根据请求路径获取对应的接口信息,并进行处理。
数据处理
需要注意的是,HttpServletRequest 中的参数与对象处理方式是不同的,这就是ApiInfo 对象中paramType 属性的意义。
if (apiInfo.getParamType() == 1) {
for (ApiParamter pa : apiInfo.getParamters()) {
System.out.println(pa.getName() + "---" + request.getParameter(pa.getName()));
}
} else {
try {
ServletInputStream inputStream = request.getInputStream();
InputStreamReader reader = new InputStreamReader(inputStream, "utf-8");
BufferedReader bf = new BufferedReader(reader);
String line = null;
StringBuilder stb = new StringBuilder();
while ((line = bf.readLine()) != null) {
stb.append(line);
}
JSONObject jo = JSONObject.parseObject(stb.toString());
for (ApiParamter pa : apiInfo.getParamters()){
if (pa.getType() == "String") {
System.out.println(pa.getName()+"---"+jo.getString(pa.getName()));
}
if (pa.getType() == "Integer") {
System.out.println(pa.getName()+"---"+jo.getInteger(pa.getName()));
}
if ((pa.getType() == "List")) {
System.out.println(pa.getName()+"---"+jo.getJSONArray(pa.getName()));
}
}
System.out.println("-----------------------------");
System.out.println(jo);
} catch (Exception e) {
e.printStackTrace();
}
}
注意
需要注意的是,以上代码仅为演示目的,实际应用中可能需要更多的扩展和安全措施,如鉴权、参数校验等。此外,与数据库交互部分需要根据具体的数据库使用技术来编写。