# btg-autoroute-jfinal **Repository Path**: zcltd-btg/btg-autoroute-jfinal ## Basic Information - **Project Name**: btg-autoroute-jfinal - **Description**: jfinal自动路由 - **Primary Language**: Java - **License**: Apache-2.0 - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 4 - **Forks**: 0 - **Created**: 2018-04-21 - **Last Updated**: 2022-08-26 ## Categories & Tags **Categories**: webframework **Tags**: None ## README # btg-autoroute-jfinal #### 项目说明 > jfinal自动路由插件。 #### 项目特点 - 支持多种配置方式; - 支持设置同一个类是否能被多次路由; - 支持部分没有源码或不修改源码等特殊情况不使用默认路由规则的手工映射的支持; - 支持避免重复路由的算法机制; - 支持路由标记(如应用于否验证登录超时,是否检查签名验证等场景); - 支持无侵入的(基于正则,只转发不侵入)手工路由(只需配置一个handler),支持但不限于严格的resultful; - 手工路由优先级 > jfinal原生路由(使用时注意jfinal原生路由被手工路由规则覆盖,如/my/{param}会覆盖/my/method1); #### 源码结构 ``` annotation:路由所使用的注解 converter:className到controllerName的转换方式,可通过实现ControllerNameConverter自行扩展 SuffixControllerNameConverter类:去掉AutoRoutesAnnotation设置的ClsSuffixs(默认实现) formatter:controllerName到actionKey的转换方式,可通过实现ControllerNameFormatter自行扩展 AllToLowerControllerNameFormatter:controllerName全部转换为小写(默认实现) FirstToLowerControllerNameFormatter:controllerName首字母转换为小写,其余保持不变 handler:手工路由需要使用到的handler AutoRoutesAnnotation类:核心入口类,提供直接使用的api HttpRequestMethod类:http请求协议类型枚举 ``` #### 三方依赖 1. jfinal:https://gitee.com/jfinal/jfinal 2. servlet-api:jfinal的handler需要; 3. slf4j:插件日志框架使用(jdk log、log4j、connons log等自行选择,请自行脑补slf4j正确姿势); 4. btg-util:开源工具包,https://gitee.com/zcltd-btg/btg-util 5. junit:测试类使用(生产环境可不添加); #### 使用说明 ``` (可参见AutoRoutesAnnotation类注释) /** * jfinal支持注解的自动路由 *
* 关于注解: * 1、namespace作用范围:globleNamespace > packgeNamespace > classNamespace * 2、对于classNamespace:优先使用AutoRouteNamespace和AutoRouteUrl * 3、对于classNamespace:未配置AutoRouteNamespace和AutoRouteUrl时,优先使用AutoRoute * 4、对于classNamespace:全部未配置时,使用默认 * 5、若配置了自定义路由,自定义路由优先级最高; * 6、当指定了controllerClass可重复注册或AutoRouteRepeat为true时(配置优先级>注解优先级),同一个类可被多次路由;为false时, * 自动忽略后续的配置使用第一次路由配置; * * 路由规则: * 1、默认控制器固定为/; * 2、普通控制器最终路由为:globleNamespace+packgeNamespace+classNamespace; * 3、当未指定命名空间时,根据添加文件夹(或包名)为起始位置,使用子文件夹作为命名空间 * 4、当未指定访问路径时,类名转换为小写去掉action或controller作为访问路径 * * 手动路由: * 1、手动路由需在方法上添加注解ManuallyRoute,并指定url和http(可选,默认为空字符串)、method(可选,默认为全部); * 2、手工路由原理为通过handler将路由转发到真实jfinal路由,所以与标记无关; * 3、url可指定占位参数,最终会通过正则将占位参数转换为request的attribute; * 4、手动路由是方法级别的路由,跟前面的action路由无冲突,action路由规则仍然有效; * * 关于tag: * 1、tag标记目标为jfinal的路由;(重要) * 2、支持多个tag,支持注解和手工添加; * 3、支持根据url获取tag和验证url是否包含tag; * 4、路由时可使用AutoRoutesAnnotation.create(me)初始化实例,可在interceptor中使用AutoRoutesAnnotation.getInstance()获取实例; */ 1、使用全注解 @AutoRoute(namespace = "/mynamespace", url = "cust") public class MyController extends Controller { public void xxx() { } } 映射结果:/mynamespace/cust => MyController 2、使用子注解 @AutoRouteNamespace("/mynamespace") public class MyController extends Controller { public void xxx() { } } 映射结果:/mynamespace/my => MyController 或 @AutoRouteUrl("cust") public class MyController extends Controller { public void xxx() { } } 映射结果:/cust => MyController 或 @AutoRouteNamespace("/mynamespace") @AutoRouteUrl("cust") public class MyController extends Controller { public void xxx() { } } 映射结果:/mynamespace/cust => MyController 3、混合使用 @AutoRoute(namespace = "/p", url = "pcust") @AutoRouteNamespace("/s") public class MyController extends Controller { public void xxx() { } } 映射结果:/s/pcust => MyController 或 @AutoRoute(namespace = "/p", url = "pcust") @AutoRouteUrl("scust") public class MyController extends Controller { public void xxx() { } } 映射结果:/p/scust => MyController 或 @AutoRoute(namespace = "/p", url = "pcust") @AutoRouteNamespace("/s") @AutoRouteUrl("scust") public class MyController extends Controller { public void xxx() { } } 映射结果:/s/scust => MyController 4、是否可以被重复路由的annotation(默认为true) @AutoRouteRepeat public class MyController extends Controller { public void xxx() { } } 或 @AutoRouteRepeat(false) public class MyController extends Controller { public void xxx() { } } 5、手工路由 原理:通过对url的匹配和处理,将基于规则的路由转换为jfinal原始路由,所以对原始路由无侵入 注意:匹配处理使用了正则,需正确使用,避免url规则与正则规则冲突和错误匹配, 默认参数名占位匹配正则为\{[^\{\}]+\},url参数值匹配正则为[^/\\-\\?=&]+,若不满足要求可通过 setParamKeyRegStr()、setParamKeyReplaceRegStr()、setParamValueRegStr()自行更改设置 /** * @AutoRoute(url = "/ar") //将自动路由controllerKey指定为/ar,详见自动路由说明 * @ManuallyRoute(url = "/mr") //将手工路由controllerKey指定为/mr,对自动路由不影响,值影响手工路由,不指定时默认为自动路由一样 */ public class MyController extends Controller { /** * url:/my/param_value * 只能通过GET、POST访问(默认) */ @ManuallyRoute(url = "{param}") public void testA() { String param = getAttr("path.param");//值为param_value } /** * url:/my/test2/param_value * 可以通过POST请求方式访问 */ @ManuallyRoute(url = "/test2/{param}", method = HttpRequestMethod.POST) public void testB() { String param = getAttr("path.param");//值为param_value } } 6、tag标记 public class MyController extends Controller { @RouteTag("uncheckSessionTimeout") public void xxx() { } @RouteTag({"uncheckSessionTimeout","uncheckSign"}) public void yyy() { } } 7、jfinal配置 public void configRoute(Routes me) { AutoRoutesAnnotation ara = AutoRoutesAnnotation.create(me); //设置需要扫描的路径及包名及包名前缀 ara.setClassPath(XXX.class.getResource("/").getPath()); ara.setClassPathPre("/WEB-INF/classes"); //设置扫描的jar路径及jar包 ara.setJarPath(new File(XXX.class.getResource("/").getPath()).getParent() + File.separator + "lib" + File.separator); ara.addJar("controller-in-jar\\.jar"); //设置要映射package及namespace ara.addPackage("com.axinfu.sf.controller"); ara.addPackage("com.axinfu.sf.ws","/ws"); //设置默认控制器(将"/"映射到默认控制器) ara.setDefaultController(InitAction.class); //设置忽略的类 ara.addSkip(BaseController.class); //添加特殊自定义注解(当无源代码或不修改源代码等特殊情况下可用此方式) ara.addRoute("/custnamespace/cust1",Cust1Controller.class); ara.addRoute("/custnamespace/cust2",Cust2Controller.class); //手工设置Controller是否可以重复映射 ara.setControllerRepeat(UserAction.class, true); //手工设置Controller的method映射 ara.setManualRoute("/my/{param}", "/my/testA", new HttpRequestMethod[]{HttpRequestMethod.GET, HttpRequestMethod.POST}); //手工添加tag ara.addTag("/mycontroller/myaction","uncheckSessionTimeout"); ara.addTags("/mycontroller/myaction",new String[]{"uncheckSessionTimeout","uncheckSign"}); //启动路由 ara.route(); } 8、tag标记的手工指定和使用(jfinal interceptor) 一、自定义手工标记: { AutoRoutesAnnotation autoRoutesAnnotation = AutoRoutesAnnotation.getInstance(); autoRoutesAnnotation.addTag("/mycontroller/myaction","uncheckSessionTimeout"); autoRoutesAnnotation.addTags("/mycontroller/myaction",new String[]{"uncheckSessionTimeout","uncheckSign"}); } 或在autoroute插件处直接手工标记(使用前标记均有效) 二、对标记的使用(如session timeout检查场景) @Override public void intercept(Invocation inv) { Controller targetController = inv.getController(); String controllerKey = inv.getControllerKey(); controllerKey = controllerKey.endsWith("/") ? controllerKey : controllerKey + "/"; String url = controllerKey + inv.getMethodName(); if (AutoRoutesAnnotation.getInstance().containsTag(url, "uncheckSessionTimeout")) { inv.invoke(); return; } //其他session timeout验证逻辑 //如session过期则跳转到登录页面等 } ``` #### 版本更新记录 ``` 4.0.3: 1、修复tag处理bug; v4.0.2: 1、addJar()时使用原始正则,不做中间处理; v4.0.1: 1、转为独立maven依赖,去掉parent; v3.0.4: 1、btg-parent升级到v2.0.3,主要优化slf4j日志; v3.0.3: 1、btg-parent升级到v2.0.1; v3.0.2: 1、加入统计依赖管理; v3.0.1: 1、统一迁移至公司名下; v2.0.2: 1、对classPath的默认值进行了优化; v2.0.1: 1、转为maven项目; v1.2.0: 1、增加手工路由参数名称重复的验证; v1.1.10: 1、优化手工路由匹配规则,完全基于正则表达式,抛弃必须用/分隔的规则; 2、手工路由支持手工设置是否缓存,默认为true; v1.1.9: 1、增加对class级别的手工路由的支持(即支持多个Class中手工路由为同一个ControllerKey); 2、去除session timeout标记,更改为增强的tag标记; v1.1.8: 1、删除验证规则; v1.1.7: 1、修改验证规则:手工路由不能与原始路由相同改为日志警告; v1.1.6: 1、增加验证规则:手工路由不能与原始路由相同; v1.1.5: 1、修复手工路由缓存放入时的错误; v1.1.4: 1、更改path匹配后的参数名称url开头为path开头; v1.1.3: 1、路由协议拆分; 2、AutoRouteUrl多一个/; 3、标记手工路由为过期,强调支持但不推荐使用; v1.1.2: 1、增加部分没有源码或不修改源码等特殊情况的手工添加方法级别的路由; 2、为避免歧义,将原来getInstance(Route me)更换为create(Route me); 3、完善README.md; v1.1.1: 1、增加方法级别的路由; 2、支持严格的resultful风格路由; v1.0.7: 1、增加全局namespace,表示整个项目路由表(默认控制器除外)所使用的namespace,默认为不设置。 如:全局namespace为"/v1",原始路由为"/sys/user",最终实际路由为"/v1/sys/user"; 2、支持对packge单独设置namespace,表示指定packge下统一使用设置的namespace,无需再在Controller类中设置该namespace,默认不设置; 如:全局namespace为"/v1",packge的namespace为"/ws",原始路由为"/sys/user",最终实际路由为"/v1/ws/sys/user"; v1.0.6: 1、考虑到jar包以后维护可能会比较频繁,特统一版本号命名方式; v1.0.5: 1、修复多级package路由中的.号问题(将.转换成/); 2、增加控制器类名称转换扩展IControllerNameConverter(默认为去后缀实现并提供增加、删除后缀,内置controller、service、action三种后缀)和 二次格式化扩展IControllerNameFormatter(提供全部子母转小写实现和首字母转小写实现,默认为全部子母转小写),扩展方式为实现接口并编写 自己的实现,为AutoRoutesAnnotation注入自己的实现即可(调用set方法); v1.0.4: 1、增加对是否可以被重复路由的说明及使用配置方式; 2、增加标注session过期验证的支持及annotation; v1.0.3: 1、增加了Controller Class是否重复的设置和annotation; 2、修复了若干bug; v1.0.2: 1、增加了自定义路由 v1.0.1: 1、jfinal基于annotation的自动路由; ``` --- 豆圆