讓Eclipse的TomcatPlugin支持Tomcat 8.x

 使用tomcat插件啓動項目的優點:html

1.TomcatPlugin是一個免重啓的開發插件,原始的Servers方式啓動tomcat項目,修改xxx.ftl  或者 xxx.jsp 文件後須要重啓tomcat後內容才能獲得更新,而使用TomcatPlugin能夠避免這種重複重啓項目操做;java

2.多項目同時啓動時較方便。在開發環境中,可能要同時啓動多個項目,而每個平臺都有一個獨立的域名,使用Servers狀況下,若是隻使用一個8080端口啓動多個項目,會有衝突。可是使用TomcatPlugin,只須要配置一下hosts文件就能夠很方便的訪問各個項目。web

 

 

實現步驟:apache

1.下載eclipse tomcat 插件(略)windows

2.配置tomcattomcat

tomcat插件下載完成後 Window-->Preperences 中找到tomcat配置項app

 

 

 

3.配置server.xmldom

在conf/目錄下找到server.xml文件,並在 Engine 標籤中添加以下內容:eclipse

<Host name="www2.domain1.com" appBase="webapps" unpackWARs="true" autoDeploy="true">
  <Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs" prefix="localhost_access_log" suffix=".txt" pattern="%h %l %u %t "%r" %s %b" />
  <Context path="" reloadable="true" docBase="項目目錄1\src\main\webapp" workDir="項目目錄1\work" >
      <Loader className="org.apache.catalina.loader.DevLoader" reloadable="true" debug="1" useSystemClassLoaderAsParent="false" />
  </Context>
</Host>
<Host name="www2.domain2.com" appBase="webapps" unpackWARs="true" autoDeploy="true">
  <Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs" prefix="localhost_access_log" suffix=".txt" pattern="%h %l %u %t "%r" %s %b" />
  <Context path="" reloadable="true" docBase="項目目錄2\src\main\webapp" workDir="項目目錄2\work" >
      <Loader className="org.apache.catalina.loader.MyDevLoader" reloadable="true" debug="1" useSystemClassLoaderAsParent="false" />
  </Context>
</Host>

 

 

 

4.配置hosts文件webapp

在windows/system32/drivers/etc 目錄下找到hosts文件,添加以下內容:

#	127.0.0.1       localhost
#	::1             localhost
127.0.0.1  	www2.domain1.com    www2.domain2.com    www2.domain3.com

  

 

5.生成jar包

 

1.新建一個項目(或者使用原有的項目),建立一個包 名稱爲:org.apache.catalina.loader, 再建立一個類,名稱爲 MyDevLoader,拷貝下面java代碼部分

備註:你能夠隨意建立一個包名和類名,但須要與 <Loader className="org.apache.catalina.loader.MyDevLoader" reloadable="true" debug="1" useSystemClassLoaderAsParent="false" /> 中的className保持一至便可。

二、消除編譯報錯的地方。主要是tomcat 中的lib目錄下相關的jar包沒有引入進來。

三、從新打成JAR包,命名DevloaderTomcat8.jar。

四、將這個jar文件放入tomcat 中的lib目錄下。

 

package org.apache.catalina.loader; import java.io.File; import java.io.FileFilter; import java.io.FileNotFoundException; import java.io.FileReader; import java.io.IOException; import java.io.LineNumberReader; import java.net.MalformedURLException; import java.net.URL; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.StringTokenizer; import javax.servlet.ServletContext; import javax.xml.parsers.ParserConfigurationException; import javax.xml.parsers.SAXParser; import javax.xml.parsers.SAXParserFactory; import org.apache.catalina.Context; import org.apache.catalina.Globals; import org.apache.catalina.LifecycleException; import org.apache.catalina.loader.DevLoader.WebClassPathEntryHandler; import org.xml.sax.Attributes; import org.xml.sax.SAXException; import org.xml.sax.helpers.DefaultHandler; /** * @author caoxiaobo 備註:修改DevLoader源碼後的,請生成jar包,而後放置tomcat中的lib目錄下; */
public class MyDevLoader extends WebappLoader { private static final String info = "org.apache.catalina.loader.MyDevLoader/1.0"; private String webClassPathFile = ".#webclasspath"; private String tomcatPluginFile = ".tomcatplugin"; WebappClassLoader loader = null; /** * @see org.apache.catalina.Lifecycle#start() * 若是您使用的是tomcat7,此處的方法名稱爲start(),若是是tomcat8,此處的方法名稱爲startInternal() */
    public void startInternal() throws LifecycleException { log("Starting MyDevLoader " + info); // setLoaderClass(DevWebappClassLoader.class.getName()); // 若是是tomcat7,此處調用 start()方法,若是是tomcat8,此處調用startInternal()方法 // super.start(); // tomcat7
        super.startInternal(); // tomcat8
        loader = (WebappClassLoader) super.getClassLoader(); if (loader instanceof WebappClassLoader == false) { logError("Unable to install WebappClassLoader !"); return; } List<String> webClassPathEntries = readWebClassPathEntries(); StringBuffer classpath = new StringBuffer(); for (Iterator<String> it = webClassPathEntries.iterator(); it.hasNext();) { String entry = (String) it.next(); File f = new File(entry); if (f.exists()) { if (f.isDirectory() && entry.endsWith("/") == false) f = new File(entry + "/"); try { URL url = f.toURI().toURL(); loader.addURL(url); // tomcat8 // loader.addRepository(url.toString()); // tomcat7
                    classpath.append(f.toString() + File.pathSeparatorChar); log("added " + url.toString()); } catch (MalformedURLException e) { logError(entry + " invalid (MalformedURL)"); } } else { logError(entry + " does not exist !"); } } /* * try { devCl.loadClass("at.kase.webfaces.WebApplication"); * devCl.loadClass("at.kase.taglib.BaseTag"); * devCl.loadClass("at.kase.taglib.xhtml.XHTMLTag"); * devCl.loadClass("at.kase.common.reflect.ClassHelper"); * devCl.loadClass("javax.servlet.jsp.jstl.core.Config"); * log("ALL OKAY !"); } catch(Exception e) { logError(e.toString()); } */ String cp = (String) getServletContext().getAttribute(Globals.CLASS_PATH_ATTR); StringTokenizer tokenizer = new StringTokenizer(cp, File.pathSeparatorChar + ""); while (tokenizer.hasMoreTokens()) { String token = tokenizer.nextToken(); // only on windows
            if (token.charAt(0) == '/' && token.charAt(2) == ':') token = token.substring(1); classpath.append(token + File.pathSeparatorChar); } // cp = classpath + cp;
 getServletContext().setAttribute(Globals.CLASS_PATH_ATTR, classpath.toString()); log("JSPCompiler Classpath = " + classpath); } private void log(String msg) { System.out.println("[MyDevLoader] " + msg); } private void logError(String msg) { System.err.println("[MyDevLoader] Error: " + msg); } private List<String> readWebClassPathEntries() { List<String> rc = null; File prjDir = getProjectRootDir(); if (prjDir == null) { return new ArrayList<String>(); } log("projectdir=" + prjDir.getAbsolutePath()); // try loading tomcat plugin file // DON"T LOAD TOMCAT PLUGIN FILE (DOESN't HAVE FULL PATHS ANYMORE)
        rc = loadTomcatPluginFile(prjDir); if (rc == null) { //rc = loadWebClassPathFile(prjDir);
 } if (rc == null) rc = new ArrayList<String>(); // should not happen !
        return rc; } private File getProjectRootDir() { File rootDir = getWebappDir(); FileFilter filter = new FileFilter() { public boolean accept(File file) { return (file.getName().equalsIgnoreCase(webClassPathFile) || file.getName().equalsIgnoreCase(tomcatPluginFile)); } }; while (rootDir != null) { File[] files = rootDir.listFiles(filter); if (files != null && files.length >= 1) { return files[0].getParentFile(); } rootDir = rootDir.getParentFile(); } return null; } private List<String> loadWebClassPathFile(File prjDir) { File cpFile = new File(prjDir, webClassPathFile); if (cpFile.exists()) { FileReader reader = null; try { List<String> rc = new ArrayList<String>(); reader = new FileReader(cpFile); LineNumberReader lr = new LineNumberReader(reader); String line = null; while ((line = lr.readLine()) != null) { // convert '\' to '/'
                    line = line.replace('\\', '/'); rc.add(line); } return rc; } catch (IOException ioEx) { ioEx.printStackTrace(); return null; } finally { try { if (reader != null) reader.close(); } catch (Exception ignored) { } } } else { return null; } } private List<String> loadTomcatPluginFile(File prjDir) { File cpFile = new File(prjDir, tomcatPluginFile); if (!cpFile.exists()) { return null; } SAXParserFactory saxParserFactory = SAXParserFactory.newInstance(); SAXParser saxParser = null; try { saxParser = saxParserFactory.newSAXParser(); // 仿照 Digester 類來實現xml解析
            WebClassPathEntryHandler dh = new WebClassPathEntryHandler(); saxParser.parse(cpFile, dh); String[] jars = dh.getBodyText().toString().split(";"); List<String> rc = new ArrayList<String>(); for (String path : jars) { if (isNotBlank(path)) { // 若是是編譯後../classes 文件夾路徑
                    if (!path.endsWith(".jar")) { if (path.endsWith("/classes")) { path = prjDir.getParentFile() + path; } } rc.add(path); } } return rc; } catch (ParserConfigurationException e) { // TODO Auto-generated catch block
 e.printStackTrace(); } catch (SAXException e) { // TODO Auto-generated catch block
 e.printStackTrace(); } catch (FileNotFoundException e) { // TODO Auto-generated catch block
 e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block
 e.printStackTrace(); } return null; } private ServletContext getServletContext() { // return ((Context) getContainer()).getServletContext(); // tomcat7
        return super.getContext().getServletContext(); // tomcat8
 } private File getWebappDir() { File webAppDir = new File(getServletContext().getRealPath("/")); return webAppDir; } private static boolean isNotBlank(String str) { return null != str && !"".equals(str) && !"".equals(str.trim()); } /** * 內部類,用來解析 .tomcatplugin 文件中的jar * * @author Administrator * */
    private class WebClassPathEntryHandler extends DefaultHandler { private String localTag; private StringBuilder bodyText = new StringBuilder(); @Override public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { if (qName.equals("webClassPathEntry")) { localTag = "webClassPathEntry"; } } @Override public void characters(char[] buffer, int start, int length) throws SAXException { if ("webClassPathEntry".equals(localTag)) { bodyText.append(buffer, start, length); bodyText.append(";"); } } public StringBuilder getBodyText() { return bodyText; } } }

 

特別提醒:這個類是加載你當前項目根目錄下 .#webclasspath 或.tomcatplugin 文件的內容中的jar 文件的,有些項目沒有這個文件,則須要從其它項目中拷貝一份出來放入你的項目根目錄下。

 上面那個冗餘代碼比較多,下面這個示例爲了更方便理解Tomcat 類的加載過程,我把它優化了一下:

package org.apache.catalina.loader; import java.io.File; import java.io.FileFilter; import java.io.FileNotFoundException; import java.io.FileReader; import java.io.IOException; import java.io.LineNumberReader; import java.net.URL; import javax.xml.parsers.ParserConfigurationException; import javax.xml.parsers.SAXParser; import javax.xml.parsers.SAXParserFactory; import org.apache.catalina.LifecycleException; import org.xml.sax.Attributes; import org.xml.sax.SAXException; import org.xml.sax.helpers.DefaultHandler; public class DevLoader extends WebappLoader { /** * 經過 URLClassLoader 加載類/jar 文件 */
    private static WebappClassLoader loader = null; private String webClassPathFileName = ".#webclasspath"; private String tomcatPluginFileName = ".tomcatplugin"; @Override protected void startInternal() throws LifecycleException { super.startInternal(); // 仿照Digester獲取ClassLoader的寫法(Digester是用來解析xml文件的類)
        loader = (WebappClassLoader) super.getClassLoader(); // 獲取conf/context.xml中Context標籤配置的 docBase路徑
        String contextPath = this.getContext().getServletContext().getRealPath("/"); System.out.println(contextPath); File rootDir = new File(contextPath); // 獲取項目根路徑
        FileFilter filter = new FileFilter() { public boolean accept(File file) { return (file.getName().equalsIgnoreCase(webClassPathFileName) || file.getName().equalsIgnoreCase(tomcatPluginFileName)); } }; // 遞歸向上找父文件夾 
        while (rootDir != null) { File[] files = rootDir.listFiles(filter); if ((files != null) && (files.length >= 1)) { rootDir = files[0].getParentFile(); break; } else { rootDir = rootDir.getParentFile(); } } File webClassPathFile = new File(rootDir, webClassPathFileName); File tomcatPluginFile = new File(rootDir, tomcatPluginFileName); /** * 先加載 .#webclasspath 文件 */
        if (webClassPathFile.exists()) { loadJars$WebClasspath(webClassPathFile); return; } if (tomcatPluginFile.exists()) { loadJars$TomcatPlugin(tomcatPluginFile, rootDir); } } /** * 加載jar文件 這裏是解析.#webclasspath文件並加載jar文件 */
    private void loadJars$WebClasspath(File webClassPathFile) { FileReader reader = null; LineNumberReader lr = null; try { reader = new FileReader(webClassPathFile); lr = new LineNumberReader(reader); String path = null; while ((path = lr.readLine()) != null) { if (isNotBlank(path)) { path = path.replace('\\', '/'); File file = new File(path); URL url = file.toURI().toURL(); loader.addURL(url); System.out.println("[DevLoader]" + path); } } } catch (IOException ioEx) { ioEx.printStackTrace(); } catch (SecurityException e) { e.printStackTrace(); } catch (IllegalArgumentException e) { e.printStackTrace(); } finally { try { if (reader != null) reader.close(); if (lr != null) lr.close(); } catch (IOException e) { e.printStackTrace(); } } } /** * 加載jar文件 這裏是解析.tomcatplugin文件並加載jar文件 */
    private void loadJars$TomcatPlugin(File tomcatPluginFile, File rootDir) { SAXParserFactory saxParserFactory = SAXParserFactory.newInstance(); SAXParser saxParser = null; try { saxParser = saxParserFactory.newSAXParser(); // 仿照 Digester 類來實現xml解析
            WebClassPathEntryHandler dh = new WebClassPathEntryHandler(); saxParser.parse(tomcatPluginFile, dh); String[] jars = dh.getBodyText().toString().split(";"); for (String path : jars) { if (isNotBlank(path)) { // 若是是編譯後../classes 文件夾路徑
                    if (!path.endsWith(".jar")) { if (path.endsWith("/classes")) { path = rootDir.getParentFile() + path; } } File f = new File(path.trim()); URL url = f.toURI().toURL(); loader.addURL(url); System.out.println("[DevLoader]" + path); } } } catch (ParserConfigurationException e) { // TODO Auto-generated catch block
 e.printStackTrace(); } catch (SAXException e) { // TODO Auto-generated catch block
 e.printStackTrace(); } catch (FileNotFoundException e) { // TODO Auto-generated catch block
 e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block
 e.printStackTrace(); } } private static boolean isNotBlank(String str) { return null != str && !"".equals(str) && !"".equals(str.trim()); } /** * 內部類,用來解析 .tomcatplugin 文件中的jar */
    class WebClassPathEntryHandler extends DefaultHandler { private String localTag; private StringBuilder bodyText = new StringBuilder(); @Override public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { if (qName.equals("webClassPathEntry")) { localTag = "webClassPathEntry"; } } @Override public void characters(char[] buffer, int start, int length) throws SAXException { if ("webClassPathEntry".equals(localTag)) { bodyText.append(buffer, start, length); bodyText.append(";"); } } public StringBuilder getBodyText() { return bodyText; } } }

 

  

 

右鍵項目--> Properties --> Tomcat

 

至此咱們已經配置完結了!

點擊以下圖標開始啓動項目

 

 出現以下信息表示配置成功.

 

相關文章
相關標籤/搜索