java.lang.NoSuchFieldException: resourceEntries struts2 原

1、關於項目中使用struts2 報java.lang.NoSuchFieldException: resourceEntries  的問題。

當我們使用tomcat 7.0.64 及以下的版本時是不會出問題的。當我們在使用tomcat 7.0.65時會報這個問題,網上看到很多解答都是說什麼tomcat 8之類的。

實際出現問題在tomcat 7.0.65 就開始了 。出現這個問題的根源是因爲。在64到65 的時候,org\apache\catalina\loader\WebappClassLoader.java 這個類進行了抽象,抽象出了org\apache\catalina\loader\WebappClassLoaderBase.java.

2、在我們用的struts2 的xwork 包內 \com\opensymphony\xwork2\util\LocalizedTextUtil.java內的清除tomcat 緩存的地方有問題。問題就初夏這個clearMap。java自帶的getDeclaredField 是取不到父類的屬性的。所以這裏會一直報錯。

最新版的這兩個方法:

private static void clearTomcatCache() {
        ClassLoader loader = getCurrentThreadContextClassLoader();
        // no need for compilation here.
        Class cl = loader.getClass();
        try {
            if ("org.apache.catalina.loader.WebappClassLoader".equals(cl.getName())) {
                clearMap(cl, loader, TOMCAT_RESOURCE_ENTRIES_FIELD);
            } else {
                if (LOG.isDebugEnabled()) {
                    LOG.debug("class loader " + cl.getName() + " is not tomcat loader.");
                }
            }
        } catch (NoSuchFieldException nsfe) {
            if ("org.apache.catalina.loader.WebappClassLoaderBase".equals(cl.getSuperclass().getName())) {
                if (LOG.isDebugEnabled()) {
                    LOG.debug("Base class #0 doesn't contain '#1' field, trying with parent!", nsfe, cl.getName(), TOMCAT_RESOURCE_ENTRIES_FIELD);
                }
                try {
                    clearMap(cl.getSuperclass(), loader, TOMCAT_RESOURCE_ENTRIES_FIELD);
                } catch (Exception e) {
                    if (LOG.isWarnEnabled()) {
                        LOG.warn("Couldn't clear tomcat cache using #0", e, cl.getSuperclass().getName());
                    }
                }
            }
        } catch (Exception e) {
            if (LOG.isWarnEnabled()) {
        	    LOG.warn("Couldn't clear tomcat cache", e, cl.getName());
            }
        }
    }
    private static void clearMap(Class cl, Object obj, String name)
            throws NoSuchFieldException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {

        Field field = cl.getDeclaredField(name);
        field.setAccessible(true);

        Object cache = field.get(obj);

        synchronized (cache) {
            Class ccl = cache.getClass();
            Method clearMethod = ccl.getMethod("clear");
            clearMethod.invoke(cache);
        }
    }

3、遇到這個問題的時候,我們往往在處理老項目,很多項目是因爲掃描除了漏洞而不得不使用新版本的tomcat。我們可以選擇升級struts2的版本,可是版本的升級會帶來很多意想不到的問題。擺在我們面前三條路①、用最新版本的struts2.②、拿出這個類,重新一下這兩個方法。③、更改一下這兩個方法,再放到jar包裏面。

參考:

apache commons  lang3包下的FieldUtils.getAllFields()可以獲取類和父類的所有(public、protected、default、private)屬性。

 

https://blog.csdn.net/wangjun5159/article/details/79289244

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章