简单解决jfinal3.0环境下使用jfinal-shiro-2.0.0.jar,报NoSuchMethodError问题

写在前面:

    今天在Jfinal官方群上有朋友提到Jfinal3.0环境中使用jfinal-shiro-2.0.0.jar报java.lang.NoSuchMethodError。粗略看一下jfinal源码,Jfinal3.0对Routes这块做了调整,给朋友提了个方案,无奈他没实现,下班回来自己码5行代码解决了这个问题。

jfinal3.0的Routes调整:

    Jfinal 2.2 前 Jfinal使用Map<ControllerKey,Controller>存放信息,jfinal3.0后调整为List<Routes>,使用内部静态类Route代替了之前的Map,所以getEntrySet()方法也随之调整成了getRouteItemList(),知道这个调整,就好解决问题,就是把这个方法替换一下就可以收工了。

问题解决:

创建一个新的类ShiroPlugin3,将之前ShiroPlugin的代码copy一份即可,只要改动3行代码,如下(1、2、3):

public boolean start() {
    Set<String> excludedMethodName = buildExcludedMethodName();
    ConcurrentMap<String, AuthzHandler> authzMaps = new ConcurrentHashMap<String, AuthzHandler>();
    //逐个访问所有注册的Controller解析Controller及action上的所有Shiro注解。
    //并依据这些注解,actionKey提前构建好权限检查处理器。
	
    //for (Entry<String,Class<? extends Controller>>entry : routes.getEntrySet()) {
    // 1.使用getRouteItemList()替换以前的getEntrySet()
    for (Route route : routes.getRouteItemList()) {
		
        //Class<? extends Controller> controllerClass = entry.getValue();
        // 2.调整为route.getControllerClass()
        Class<? extends Controller> controllerClass = route.getControllerClass();
		
        //String controllerKey = entry.getKey();
	// 3.调整为route.getControllerKey()
	String controllerKey = route.getControllerKey();
		
	// 获取Controller的所有Shiro注解。
	List<Annotation> controllerAnnotations = getAuthzAnnotations(controllerClass);
	// 逐个遍历方法。
	Method[] methods = controllerClass.getMethods();
	for (Method method : methods) {
	    //排除掉Controller基类的所有方法,并且只关注没有参数的Action方法
	    if (!excludedMethodName.contains(method.getName()) && method.getParameterTypes().length == 0) {
		//若该方法上存在ClearShiro注解,对该action不访问控制检查。
		if(isClearShiroAnnotationPresent(method)){
		    continue;
		}
		//获取方法的所有Shiro注解。
		List<Annotation> methodAnnotations = getAuthzAnnotations(method);
		//依据Controller的注解和方法的注解来生成访问控制处理器。
		AuthzHandler authzHandler = createAuthzHandler(controllerAnnotations, methodAnnotations);
		//生成访问控制处理器成功。
		if (authzHandler != null) {
	            //构建ActionKey,参考ActionMapping中实现
		    String actionKey = createActionKey(controllerClass, method, controllerKey);
		    //添加映射
		    authzMaps.put(actionKey, authzHandler);
		}
	    }
        }
    }
    //注入到ShiroKit类中。ShiroKit类以单例模式运行。
    ShiroKit.init(authzMaps);
    /**
     * 设定登录,登录成功,未授权等url地址
     */
    ShiroKit.setLoginUrl(loginUrl);
    ShiroKit.setSuccessUrl(successUrl);
    ShiroKit.setUnauthorizedUrl(unauthorizedUrl);
    return true;
}

这里由于该类有几个private方法,所以采用简单粗暴的方法,直接copy jfinal-shiro的源码改了3行代码。

config方面改为:

me.add(new ShiroPlugin3(routes));

特别注意:ShiroPlugin3的包名一定要是com.jfinal.ext.plugin.shiro

中午提问题的朋友还在问为什么,这个是java的基础问题,可以到下图这个包下很多类都是非public的。

无标题.png

好啦,到这问题就解决了,虽然简答粗暴,但还是解决了,看了jfinal-shiro作者的项目已经2年没更新代码了,希望作者可以更新一下,虽然毕业半年来没用过jfinal,也没什么机会用(毕竟公司不用这个),但是jfinal还是挺好用的,jfinal-shiro也好像有不少人用。

PS: 下班等同事一起坐车等了一小时,撸码不太及时。·····

评论区

lantsui

2017-03-07 23:11

谢谢朋友对我的解答,非常感谢!

seventeenWen

2017-03-08 08:51

很及时,大写的NICE

JFinal

2017-03-08 11:01

最近好多人找我要这个,感谢分享,赞一个

板砖哥

2017-05-15 16:19

正打算用这个了,感谢!

IT路人

2018-01-09 16:07

还是报一样错啊,原因是这玩意:com.jfinal.config.Routes.getRouteItemList()