Spring里面支持占位符的路由,比如
/api/v1/admin/prompts/{id}/assignments/{tenant_id}
当我在Controller里面使用
@ActionKey("/api/v1/admin/prompts/*/assignments/*")
或者
@ActionKey("/api/v1/admin/prompts/{id}/assignments/{tenant_id}")
然后访问 http://127.0.0.1:8080/api/v1/admin/prompts/1/assignments/11
以上两种方法都无法进入到对应的action,直接提示404,
只有
http://127.0.0.1:8080/api/v1/admin/prompts/*/assignments/*
和
http://127.0.0.1:8080/api/v1/admin/prompts/{id}/assignments/{tenant_id} 才能正常进入对应的action
请问各位应该怎么处理这样的路由?
当前处理的方式感觉比较丑陋,并且每一个类似的路由都需要手动添加
public void configRoute(Routes me) {
// 使用 jfinal 4.9.03 新增的路由扫描功能
me.scan("xx.xxx.");
me.add(new AdminRoutes());
}
public void configHandler(Handlers me) {
me.add(new PathVariableHandler());
}public class AdminRoutes extends Routes {
@Override
public void config() {
// 注册模板路由
PathVariableHandler.addRoute(
"/api/v1/admin/prompts/{id}/assign",
PromptsController.class,
"assign"
);
}
}public class PathVariableHandler extends Handler {
// 存储路由模板与正则表达式的映射关系
private static final Kv routeMap = Kv.create();
/**
* 注册模板路由
*
* @param template 路由模板,如 "/api/v1/admin/prompts/{id}/assignments/{tenant_id}"
* @param controller 目标Controller类
* @param methodName 目标方法名
*/
public static void addRoute(String template, Class<? extends Controller> controller, String methodName) {
// 转换模板为正则表达式
String regex = template.replaceAll("\\{([^}]+)}", "(?<$1>[^/]+)");
regex = "^" + regex.replace("/", "\\/") + "$";
Pattern pattern = Pattern.compile(regex);
// 提取参数名列表
List<String> paramNames = new ArrayList<>();
Matcher matcher = Pattern.compile("\\{([^}]+)}").matcher(template);
while (matcher.find()) {
paramNames.add(matcher.group(1));
}
// 存储路由配置
routeMap.set(template, new RouteConfig(pattern, paramNames, controller, methodName));
}
@Override
public void handle(String target, HttpServletRequest request, HttpServletResponse response, boolean[] isHandled) {
for (Object template : routeMap.keySet()) {
RouteConfig config = routeMap.getAs(template.toString());
Matcher matcher = config.pattern.matcher(target);
if (matcher.matches()) {
// 提取路径参数
Kv params = Kv.create();
for (String paramName : config.paramNames) {
params.set(paramName, matcher.group(paramName));
}
// 将参数存入Request属性
request.setAttribute("_pathVars", params);
// 构造ActionKey并转发请求
String actionKey = AnnotationUtil.getControllerPath(config.controller) + "/" + config.methodName;
String method = AnnotationUtil.getHttpMethod(config.controller, config.methodName);
if (method == null || method.equalsIgnoreCase(request.getMethod())) {
next.handle(actionKey, request, response, isHandled);
} else {
// HTTP 方法不匹配处理逻辑
isHandled[0] = true; // 重要!标记请求已处理
Kv error = Kv.create()
.set("code", 405)
.set("error", "Method Not Allowed")
.set("message", String.format(
"Request method '%s' not supported for %s. Required: %s",
request.getMethod(),
request.getRequestURI(),
method
));
response.setStatus(405);
response.setContentType("application/json");
try {
response.getWriter().write(JsonKit.toJson(error));
response.flushBuffer();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
return;
}
}
next.handle(target, request, response, isHandled);
}
// 路由配置内部类
private static class RouteConfig {
final Pattern pattern;
final List<String> paramNames;
final Class<? extends Controller> controller;
final String methodName;
RouteConfig(Pattern pattern, List<String> paramNames, Class<? extends Controller> controller, String methodName) {
this.pattern = pattern;
this.paramNames = paramNames;
this.controller = controller;
this.methodName = methodName;
}
}
}
扩展支持:
方案1:自定义ActionHandler,里面按需要的业务进行匹配url
https://jfinal.com/doc/2-7
configHandler 》 me.setActionHandler
(推荐)方案2:设置扩展 ActionMapping,按自己业务进行匹配url
https://jfinal.com/doc/2-2
configConstant 》me.setActionMapping 》继承ActionMapping 重写getAction 方法支持自己的业务。 具体的业务实现代码,可以问AI 上面字符串匹配与参数提取方式,会给出正则表达式实现