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 上面字符串匹配与参数提取方式,会给出正则表达式实现