@
Aliberter 解决方案为开启一个独立的 servlet,具体在 springboot 中注入方式如下:
```
@
Component@
ComponentScan("com.example.demo.*")
public class Beans {
@
Autowired private ApplicationContext context;
@
Bean public ServletRegistrationBean viewRedisServlet() {
ServletRegistrationBean<Servlet> servletServletRegistrationBean = new ServletRegistrationBean<>();
CustomerServlet servlet = new CustomerServlet();
servlet.setContext(context);
servletServletRegistrationBean.setServlet(servlet);
return servletServletRegistrationBean;
}
}
```
第二步编写 servlet 具体代码如下:
```
@
WebServletpublic class CustomerServlet extends HttpServlet {
Gson gson = new Gson();
private ApplicationContext context;
public ApplicationContext getContext() {
return context;
}
public void setContext(ApplicationContext context) {
this.context = context;
}
@
SneakyThrows @
Override protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 从请求头中获取一个标记,用于确认是需要进行处理的
String c = req.getHeader("is_c");
if (Boolean.valueOf(c)) {
String contextPath = req.getContextPath();
String servletPath = req.getServletPath();
// /{controller}/{action}/{apiVersion}/{userId}/{clientName}
String requestURI = req.getRequestURI();
String[] split = requestURI.split("/");
String controller = null;
String action = null;
String apiVersion = null;
String userId = null;
String clientName = null;
if (split.length == 6) {
controller = split[1];
action = split[2];
apiVersion = split[3];
userId = split[4];
clientName = split[5];
}
// 通过 spring 上下文去搜索 controller + actiron 对应的方法
ApplicationContext tuUse = this.context;
if (StringUtils.hasText(controller)) {
// 找到实例
Object bean = tuUse.getBean(controller);
// 找到执行方法
Method[] methods = bean.getClass().getDeclaredMethods();
Method toCall = null;
for (Method method : methods) {
boolean equals = method.getName().equals(action);
if (equals) {
toCall = method;
break;
}
}
// 获取方法参数类型, 你需要做转换
Class<?>[] types = toCall.getParameterTypes();
// 转换后进行参数使用调用方法
Object invoke = toCall.invoke(bean, apiVersion, userId, clientName);
resp.setContentType("application/json; charset=UTF-8");
resp.getWriter().write(gson.toJson(invoke));
}
System.out.println(contextPath);
}
}
}
```
上述代代码处理流程:
1. 判断是需要进行处理的
2. 将 url 中的 /{controller}/{action}/{apiVersion}/{userId}/{clientName}参数提取
3. 通过成员变量 context 在 spring 中根据名字获取 bean 实例,名字是 controller,通过 spring 中 Component 注解的 value 进行赋值
4. 在 bean 实例种搜索 action 对应的方法,这里要求方法名称和 action 强对应。
5. 将上一步得到的方法提取方法参数,将 url 参数进行类型转换。
6. 反射执行
7. response 返回
其他代码如下:
```
@
Datapublic class IndexResponse {
private int code;
private Object data;
}
```
```
@
Service(value = "home")
public class HomePageController {
public IndexResponse index(
String apiVersion,
String userId,
String clientName) {
IndexResponse response = new IndexResponse();
response.setCode(1);
response.setData(apiVersion + "-" +
userId + "-" +
clientName);
return response;
}
}
```
测试用例如下:
GET http://localhost:8080/home/index/6.0.0/0/Any.
HTTP/1.1 200
Content-Type: application/json;charset=UTF-8
Content-Length: 32
Date: Wed, 26 May 2021 05:14:26 GMT
Keep-Alive: timeout=60
Connection: keep-alive
{
"code": 1,
"data": "6.0.0-0-Any."
}