坑爹的UEditor與springMVC的結合

晦若晨曦發表於2017-12-14

富文字編輯器是網站中十分常用的一個元件,無論是網站後臺釋出資訊,前臺評論回覆發帖等操作,都離不開富文字編輯器的身影。

頂著百度的名頭,UEditor是一個功能十分強大的富文字編輯器。然而不得不說,這貨的文件寫的實在是太爛了。

在剛剛開始使用時,就遇到了讀取後臺配置檔案錯誤的問題,導致上傳圖片等功能不能使用。

##初見

在百度的UEditor官網可以下載到各個版本的編輯器,我選擇的是jsp+utf8的版本。

下載連結

然後你會欣慰的在頂部導航看到“文件”兩個大字。

我對燈發誓,已經仔細的看過了這個文件。

然而誰要你來教我怎麼部署jsp啊!!!

看來只能閉著眼睛摸索前進了,下載下來的檔案結構如圖所示

Paste_Image.png

總體還算清晰明瞭。後臺引用了jsp/lib下的包,然後我閱讀了controller.jsp……

噩夢開始

<%@ page language="java" contentType="text/html; charset=UTF-8"
	import="com.baidu.ueditor.ActionEnter"
    pageEncoding="UTF-8"%>
<%@ page trimDirectiveWhitespaces="true" %>
<%

    request.setCharacterEncoding( "utf-8" );
	response.setHeader("Content-Type" , "text/html");
	
	String rootPath = application.getRealPath( "/" );
	
	out.write( new ActionEnter( request, rootPath ).exec() );
	
%>
複製程式碼

這段程式碼其實還比較好理解。我將它翻譯到了Spring中如下所示:

@RequestMapping("editorConfig")
    public String editor (HttpServletRequest request,HttpServletResponse response) {
        try {
            request.setCharacterEncoding("utf-8");
            response.setHeader("Content-Type", "text/html");
            ServletContext application = request.getServletContext();
            String rootPath = application.getRealPath("/");
            String result = new ActionEnter(request, rootPath).exec();
            return result;
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return "";
    }
複製程式碼

恩,我去讀了它的原始碼,發現這個東西返回的就是一個字串,看我給的url,你猜它是個什麼字串?

然而事情哪有這麼簡單?

##填坑

根據文件(你終於有用了)在瀏覽器呼叫url

http://localhost:8080/user/editorConfig?action=config
複製程式碼

然後我得到了一串unicode碼,上網翻譯後是:“配置檔案載入失敗”

###第一步 標準解

首先看配置檔案在哪:

Paste_Image.png
然後想想怎麼拿到配置檔案呢?在初始化中,與檔案有關的東西只有一處:

String rootPath = application.getRealPath("/");
複製程式碼

再對比一下路徑: “/” “/resource/ueditor/jsp/config.json”

恩,貌似情況很明顯了,修改如下:

String rootPath = application.getRealPath("/resource/ueditor");
複製程式碼

興高采烈的重新部署專案,啟動伺服器,然後堅定地給我返回了一行unicode:

“配置檔案載入失敗”

第二步 追根溯源

失敗後繼續思考,既然載入失敗,肯定就是獲取不到檔案,由於/resource/ueditor目錄也明顯沒有指向config.json這個檔案,那麼這個坑爹的東西肯定在某個地方加上了什麼奇怪的路徑。

幸虧官方提供了原始碼,繼續讀原始碼,首先看啟動類ActionEnter的構造方法:

public ActionEnter ( HttpServletRequest request, String rootPath ) {
		
		this.request = request;
		this.rootPath = rootPath;
		this.actionType = request.getParameter( "action" );
		this.contextPath = request.getContextPath();
		this.configManager = ConfigManager.getInstance( this.rootPath, this.contextPath, request.getRequestURI() );
		
	}
複製程式碼

我看到了什麼?一個野生的ConfigManager!我賭五毛肯定是在這裡載入的配置檔案,於是繼續追下去看看,可以找到它的工廠方法和構造方法

/*
	 * 通過一個給定的路徑構建一個配置管理器, 該管理器要求地址路徑所在目錄下必須存在config.properties檔案
	 */
	private ConfigManager ( String rootPath, String contextPath, String uri ) throws FileNotFoundException, IOException {
		
		rootPath = rootPath.replace( "\\", "/" );
		
		this.rootPath = rootPath;
		this.contextPath = contextPath;
		
		if ( contextPath.length() > 0 ) {
			this.originalPath = this.rootPath + uri.substring( contextPath.length() );
		} else {
			this.originalPath = this.rootPath + uri;
		}
		
		this.initEnv();
		
	}
	
	/**
	 * 配置管理器構造工廠
	 * @param rootPath 伺服器根路徑
	 * @param contextPath 伺服器所在專案路徑
	 * @param uri 當前訪問的uri
	 * @return 配置管理器例項或者null
	 */
	public static ConfigManager getInstance ( String rootPath, String contextPath, String uri ) {
		
		try {
			return new ConfigManager(rootPath, contextPath, uri);
		} catch ( Exception e ) {
			return null;
		}
		
	}
複製程式碼

我肯定它的註釋有好多個版本沒有更新過了,但是並不影響我們理解它的意思。但是你為啥就不把這句話寫到文件裡面去呢?

罪魁禍首就在這裡:

this.originalPath = this.rootPath + uri.substring( contextPath.length() );
複製程式碼

它又在基礎路徑上新增了瀏覽器的Uri路徑!

鑑於spring的路徑不是那麼標準,於是這個路徑已經歪歪扭扭的歪到了這裡:

/my/tomcat/path/webapps/application/resource/ueditor/user/editorConfig
複製程式碼

找到了地方!我愉快的把config.json檔案複製了過去

興高采烈的重新部署專案,啟動伺服器,然後堅定地給我返回了一行unicode:

“配置檔案載入失敗”

第三步 終結

欲哭無淚的我只好繼續找下去

於是終於在ConfigManager中發現了這個方法:

private void initEnv () throws FileNotFoundException, IOException {
		
		File file = new File( this.originalPath );
		
		if ( !file.isAbsolute() ) {
			file = new File( file.getAbsolutePath() );
		}
		
		this.parentPath = file.getParent();
		
		String configContent = this.readFile( this.getConfigPath() );
		
		try{
			JSONObject jsonConfig = new JSONObject( configContent );
			this.jsonConfig = jsonConfig;
		} catch ( Exception e ) {
			this.jsonConfig = null;
		}
		
	}
複製程式碼

好噠,這個親又取了一層parent!!!

找到答案之後回想一下倒是也有道理。這個路徑本來指向controller.jsp檔案,又有config.json與此檔案在同一目錄下,取parent才是正確的開啟方式

再次將config.json複製了過去, 再次啟動專案,終於成功的顯示出了配置檔案的內容!!

相關文章