最近在做一个有趣的项目,做一个API生成小工具。可以对简单的API路径进行配置SQL自动生成API。
简单来讲:
URI对应sql/api/userselect * from user/api/user/addressselect * from address/api/order/listselect * from order也就是可以通过简单的sql配置,就自动生成对应的API,可以供前端调用。
初衷就是URI
使用者可以随意配置,不限制层级。 二级的/api/user
与三级/api/user/address
甚至更多层级都要支持。
最初我想到的是使用controller实现
@Controller
public class RestController {
@GetMapping(value = "/api/{path}")
public @ResponseBody SqlDTO getSqlApiData(@PathVariable String path) {
return null;
}
}
这种方法显示是可以实现单层级的API设计的。但是如果仅支持单层的api,总感觉不够优雅。如果API数量多了,也不方便管理。
最终我选用拦截器的方式来达到目标。
实现过程 cn/ycmit/sqlapi/conf/SqlApiConfig.javapackage cn.ycmit.sqlapi.conf;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class SqlApiConfig implements WebMvcConfigurer {
@Autowired
private SqlApiInterceptor sqlApiInterceptor;
public void addInterceptors(InterceptorRegistry registry) {
// 注册API拦截器
registry.addInterceptor(sqlApiInterceptor).addPathPatterns("/api/**");
}
}
cn/ycmit/sqlapi/conf/SqlApiInterceptor.java
package cn.ycmit.sqlapi.conf;
import cn.ycmit.sqlapi.util.IPUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.PrintWriter;
@Component
@Slf4j
public class SqlApiInterceptor implements HandlerInterceptor {
@Override
public void afterCompletion(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, Exception arg3)
throws Exception {
}
@Override
public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, ModelAndView arg3)
throws Exception {
}
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object arg2) throws Exception {
// 获取当前的ip信息
String originIp = IPUtil.getOriginIp(request);
log.debug(originIp);
String method = request.getMethod();
String servletPath = request.getServletPath();
// 获取url后面的路径
servletPath = servletPath.substring(5);
log.debug(servletPath);
response.setCharacterEncoding("UTF-8");
response.setContentType("application/json;charset=utf-8");
// 跨域设置
response.setHeader("Access-Control-Allow-Origin", "*");
response.setHeader("Access-Control-Allow-Credentials", "true");
// 这里很重要,要不然js header不能跨域携带 Authorization属性
response.setHeader("Access-Control-Allow-Headers", "Authorization");
response.setHeader("Access-Control-Allow-Methods", "POST,GET,PUT,OPTIONS,DELETE");
PrintWriter out = null;
try {
// js跨域的预检请求,不经过处理逻辑
if (method.equals("OPTIONS")) {
response.setStatus(HttpServletResponse.SC_OK);
return false;
}
out = response.getWriter();
String responseDto = "ip==>" + originIp + "---method==>" + method + "---servletPath==>" + servletPath;
log.debug(responseDto);
out.append(responseDto);
return false;
} catch (Exception e) {
e.printStackTrace();
response.sendError(500);
return false;
} finally {
if (out != null) {
out.close();
}
}
}
}
运行测试
双层级请求 超多层级的请求
至此我们成功的完成了这个任务。
比如:contoller中的路径如下:
@RequestMapping("/api/list")
public List apiList()
{
List list = new ArrayList();
list.add("简单");
list.add("高效");
list.add("稳定");
return list;
}
这个时候请求http://localhost:8080/api/list
这足矣说明拦截器的优化级比Contrller更高一些。
https://download.csdn.net/download/lxyoucan/85089858
参考https://www.baeldung.com/spring-controllers https://github.com/freakchick/DBApi