一、關於項目中使用struts2 報java.lang.NoSuchFieldException: resourceEntries 的問題。java
當咱們使用tomcat 7.0.64 及如下的版本時是不會出問題的。當咱們在使用tomcat 7.0.65時會報這個問題,網上看到不少解答都是說什麼tomcat 8之類的。apache
實際出現問題在tomcat 7.0.65 就開始了 。出現這個問題的根源是由於。在64到65 的時候,org\apache\catalina\loader\WebappClassLoader.java 這個類進行了抽象,抽象出了org\apache\catalina\loader\WebappClassLoaderBase.java.緩存
二、在咱們用的struts2 的xwork 包內 \com\opensymphony\xwork2\util\LocalizedTextUtil.java內的清除tomcat 緩存的地方有問題。問題就初夏這個clearMap。java自帶的getDeclaredField 是取不到父類的屬性的。因此這裏會一直報錯。tomcat
最新版的這兩個方法:app
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); } }
三、遇到這個問題的時候,咱們每每在處理老項目,不少項目是由於掃描除了漏洞而不得不使用新版本的tomcat。咱們能夠選擇升級struts2的版本,但是版本的升級會帶來不少意想不到的問題。擺在咱們面前三條路①、用最新版本的struts2.②、拿出這個類,從新一下這兩個方法。③、更改一下這兩個方法,再放到jar包裏面。.net
參考:debug
apache commons lang3包下的FieldUtils.getAllFields()能夠獲取類和父類的全部(public、protected、default、private)屬性。code
https://blog.csdn.net/wangjun5159/article/details/79289244blog