1. 程式人生 > >intellij中啟動jetty出現的類載入問題

intellij中啟動jetty出現的類載入問題

背景

簡單來說,就是使用intellij啟動內嵌jetty的工程,爆出class not found exception,但是用eclipse啟動沒有問題,並且之前也是一直在eclipse中啟動,最近嚐鮮換成intellij才出現此問題。以下是具體配置

配置

開發環境

開發工具intellij
專案內嵌jetty+jFinal

問題
使用intellij啟動,失敗,工程以前都是在eclipse啟動,一點問題沒有,最近intellij大行其道才切換到intellij。

程式碼配置

public class MyJFinalConfig extends JFinalConfig
{
public static void main(String[] args) { JFinal.start("WebRoot", 8080, "/myproject", 5); } }

web.xml配置

 <filter>
        <filter-name>jfinal</filter-name>
        <filter-class>com.jfinal.core.JFinalFilter</filter-class>
        <init-param>
            <param
-name>configClass</param-name> <param-value>com.mypak.MyJFinalConfig</param-value> </init-param> </filter>

異常資訊class not found com.mypak.MyJFinalConfig

分析

追蹤出錯的原始碼

ps:程式碼大體上就是這樣,只是為了表達那個意思。

Object obj = Class.forName("com.mypak.MyJFinalConfig"
).forInstance; if(!obj instanceof JFinalFilter){ throw new Exception("出錯了") }

classloader在搗鬼

我們知道MyJFinalConfigJFinalFilter 子類,它的例項肯定是JFinalFilter 例項,但是實際執行結果來看,居然不是!
第一反應想到可能是ClassLoader在搗鼓,因為ClassLoader不同時,類的上下級關係無從談起,並且是jetty內嵌啟動,不同於以往的正常啟動,所以猜測可能跟classloader有關係。debug發現,MyJFinalConfig類載入器是sun.misc.Launcher$AppClassLoader,而JFinalFilter是jetty包中的WebAppClassLoader,果然classloader不一樣!原因找到了。

為何eclipse可以work,intellij就不行呢?

搜尋文章後發現,jetty的classloader會將WEB-INF/lib和 WEB-INF/classes底下的類,當作app的class,而不委託給父classloader。基於此,將intellij的outputpath設定為webRoot/WEB-INF/classes,讓WebAppClassLoader載入MyJFinalConfig這樣兩個類就都是WebAppClassLoader 了。

修正

設定outputpath,將webRoot下的資原始檔排除,否則classes資料夾下也有有頁面等資原始檔
D:\intellij_workspace\myproject\WebRoot\WEB-INF\classes。
這裡寫圖片描述

這裡寫圖片描述

後續

後來在看JFinal手冊時,發現同樣道理的一句話。此處的 Default out folder 必須要與 WebRoot\WEB-INF\classes 目錄完全一致才可以使用 JFinal 整合的 Jetty 來啟動專案
這裡寫圖片描述

並且,作者也說使用重啟方式,而不使用熱載入方式開發,因為重啟速度很快,如果熱載入還會出現classnotfoundexception。當然資原始檔,比如頁面、js修改後,不需要重啟。
這裡寫圖片描述