最详细的 SpringBoot 整合 UEditor 教程,解决多个 Bug

3,413 阅读32分钟
原文链接: blog.csdn.net

UEditor只提供JSP版本的后端入口代码。但提供了项目源码,因此可以根据业务需求修改源代码。

此处使用了SpringBoot框架,配备了Thymeleaf模板引擎,所以没有必要再添加jsp来兼容UEditor,可通过修改源码满足需要。下面是详细教程。

1.新建SpringBoot项目,添加web和thymeleaf包

pom文件如下:

  1. <?xml version="1.0" encoding= "UTF-8"?>  
  2. <project xmlns="http://maven.apache.org/POM/4.0.0"  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
  3.     xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" >  
  4.     <modelVersion>4.0.0</modelVersion >  
  5.   
  6.     <groupId>com.example</groupId >  
  7.     <artifactId>ueditor-test</artifactId >  
  8.     <version>0.0.1-SNAPSHOT</version >  
  9.     <packaging>jar</packaging>  
  10.   
  11.     <name>ueditor-test</name>  
  12.     <description>Demo project for Spring Boot</ description>  
  13.   
  14.     <parent>  
  15.         <groupId>org.springframework.boot</ groupId>  
  16.         <artifactId>spring-boot-starter-parent</ artifactId>  
  17.         <version>1.5.2.RELEASE</version >  
  18.   
  19.         <relativePath/> <!-- lookup parent from repository -->  
  20.     </parent>  
  21.   
  22.     <properties>  
  23.         <project.build.sourceEncoding>UTF-8</ project.build.sourceEncoding>  
  24.         <project.reporting.outputEncoding>UTF-8</ project.reporting.outputEncoding>  
  25.         <java.version>1.8</java.version >  
  26.         <!--修改thymeleaf版本-->  
  27.         <thymeleaf.version>3.0.3.RELEASE</ thymeleaf.version>  
  28.         <thymeleaf-layout-dialect.version>2.1.0</ thymeleaf-layout-dialect.version>  
  29.     </properties>  
  30.   
  31.     <dependencies>  
  32.         <dependency>  
  33.             <groupId>org.springframework.boot</ groupId>  
  34.             <artifactId>spring-boot-starter-thymeleaf </artifactId>  
  35.         </dependency>  
  36.         <dependency>  
  37.             <groupId>org.springframework.boot</ groupId>  
  38.             <artifactId>spring-boot-starter-web</ artifactId>  
  39.         </dependency>  
  40.   
  41.         <dependency>  
  42.             <groupId>org.springframework.boot</ groupId>  
  43.             <artifactId>spring-boot-starter-test </artifactId>  
  44.             <scope>test</ scope>  
  45.         </dependency>  
  46.     </dependencies>  
  47.   
  48.     <build>  
  49.         <plugins>  
  50.             <plugin>  
  51.                 <groupId>org.springframework.boot </groupId>  
  52.                 <artifactId>spring-boot-maven-plugin </artifactId>  
  53.             </plugin>  
  54.         </plugins>  
  55.     </build>  
  56.   
  57.   
  58. </project>  
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>

	<groupId>com.example</groupId>
	<artifactId>ueditor-test</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<packaging>jar</packaging>

	<name>ueditor-test</name>
	<description>Demo project for Spring Boot</description>

	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>1.5.2.RELEASE</version>

		<relativePath/> <!-- lookup parent from repository -->
	</parent>

	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
		<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
		<java.version>1.8</java.version>
		<!--修改thymeleaf版本-->
		<thymeleaf.version>3.0.3.RELEASE</thymeleaf.version>
		<thymeleaf-layout-dialect.version>2.1.0</thymeleaf-layout-dialect.version>
	</properties>

	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-thymeleaf</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>
	</dependencies>

	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>


</project>

2.从官网下载源代码并解压至项目,注意config.json我拷到了resources根路径下,如图:



3.添加UEditorController,跳转到index页面:

  1. package com.example;  
  2.   
  3. import org.springframework.stereotype.Controller;  
  4. import org.springframework.web.bind.annotation.RequestMapping;  
  5.   
  6. /** 
  7.  * Created by ldb on 2017/4/9. 
  8.  */  
  9. @Controller  
  10. public class UEditorController {  
  11.   
  12.   
  13.     @RequestMapping("/")  
  14.     private String showPage(){  
  15.         return "index";  
  16.     }  
  17.   
  18.      
  19. }  
package com.example;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

/**
 * Created by ldb on 2017/4/9.
 */
@Controller
public class UEditorController {


    @RequestMapping("/")
    private String showPage(){
        return "index";
    }

   
}

4.运行项目。访问路径localhost:8080,跳转到如下界面即是源码已拷贝成功



5.此时发现上传图片功能不能用。下面接着看。修改pom,添加UEditor依赖的Jar包。pom文件如下: 

  1. <?xml version="1.0" encoding= "UTF-8"?>  
  2. <project xmlns="http://maven.apache.org/POM/4.0.0"  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
  3.     xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" >  
  4.     <modelVersion>4.0.0</modelVersion >  
  5.   
  6.     <groupId>com.example</groupId >  
  7.     <artifactId>ueditor</artifactId >  
  8.     <version>0.0.1-SNAPSHOT</version >  
  9.     <packaging>jar</packaging>  
  10.   
  11.     <name>ueditor</name>  
  12.     <description>Demo project for Spring Boot</ description>  
  13.   
  14.     <parent>  
  15.         <groupId>org.springframework.boot</ groupId>  
  16.         <artifactId>spring-boot-starter-parent</ artifactId>  
  17.         <version>1.5.2.RELEASE</version >  
  18.         <relativePath/> <!-- lookup parent from repository -->  
  19.     </parent>  
  20.   
  21.     <properties>  
  22.         <project.build.sourceEncoding>UTF-8</ project.build.sourceEncoding>  
  23.         <project.reporting.outputEncoding>UTF-8</ project.reporting.outputEncoding>  
  24.         <java.version>1.8</java.version >  
  25.         <thymeleaf.version>3.0.3.RELEASE</ thymeleaf.version>  
  26.         <thymeleaf-layout-dialect.version>2.1.0</ thymeleaf-layout-dialect.version>  
  27.     </properties>  
  28.   
  29.     <dependencies>  
  30.         <dependency>  
  31.             <groupId>org.springframework.boot</ groupId>  
  32.             <artifactId>spring-boot-starter-thymeleaf </artifactId>  
  33.         </dependency>  
  34.         <dependency>  
  35.             <groupId>org.springframework.boot</ groupId>  
  36.             <artifactId>spring-boot-starter-web</ artifactId>  
  37.         </dependency>  
  38.   
  39.         <dependency>  
  40.             <groupId>org.springframework.boot</ groupId>  
  41.             <artifactId>spring-boot-starter-test </artifactId>  
  42.             <scope>test</ scope>  
  43.         </dependency>  
  44.   
  45.         <!--UEditor依赖的jar包 -->  
  46.                 <dependency>  
  47.                     <groupId>org.json </groupId>  
  48.                     <artifactId>json </artifactId>  
  49.                 </dependency>  
  50.                 <dependency>  
  51.                     <groupId>commons-fileupload </groupId>  
  52.                     <artifactId>commons-fileupload </artifactId>  
  53.                     <version>1.3.2 </version>  
  54.                 </dependency>  
  55.                 <dependency>  
  56.                     <groupId>commons-codec </groupId>  
  57.                     <artifactId>commons-codec </artifactId>  
  58.                     <version>1.9 </version>  
  59.                 </dependency>  
  60.             </dependencies>  
  61.   
  62.             <build>  
  63.                 <plugins>  
  64.                     <plugin>  
  65.                         <groupId >org.springframework.boot</groupId>  
  66.                         <artifactId >spring-boot-maven-plugin</artifactId>  
  67.                     </plugin>  
  68.                 </plugins>  
  69.             </build>  
  70.   
  71.   
  72.         </project>  
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>

	<groupId>com.example</groupId>
	<artifactId>ueditor</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<packaging>jar</packaging>

	<name>ueditor</name>
	<description>Demo project for Spring Boot</description>

	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>1.5.2.RELEASE</version>
		<relativePath/> <!-- lookup parent from repository -->
	</parent>

	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
		<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
		<java.version>1.8</java.version>
		<thymeleaf.version>3.0.3.RELEASE</thymeleaf.version>
		<thymeleaf-layout-dialect.version>2.1.0</thymeleaf-layout-dialect.version>
	</properties>

	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-thymeleaf</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>

		<!--UEditor依赖的jar包 -->
                <dependency>
                    <groupId>org.json</groupId>
                    <artifactId>json</artifactId>
                </dependency>
                <dependency>
                    <groupId>commons-fileupload</groupId>
                    <artifactId>commons-fileupload</artifactId>
                    <version>1.3.2</version>
                </dependency>
                <dependency>
                    <groupId>commons-codec</groupId>
                    <artifactId>commons-codec</artifactId>
                    <version>1.9</version>
                </dependency>
            </dependencies>

            <build>
                <plugins>
                    <plugin>
                        <groupId>org.springframework.boot</groupId>
                        <artifactId>spring-boot-maven-plugin</artifactId>
                    </plugin>
                </plugins>
            </build>


        </project>
6.照着源码里的controller.jsp.依样画葫芦,写入UEditorController类,映射路径为config。
  1. package com.example;  
  2.   
  3. import com.baidu.ueditor.ActionEnter;  
  4. import org.springframework.stereotype.Controller;  
  5. import org.springframework.web.bind.annotation.RequestMapping;  
  6.   
  7. import javax.servlet.http.HttpServletRequest;  
  8. import javax.servlet.http.HttpServletResponse;  
  9. import java.io.IOException;  
  10. import java.io.PrintWriter;  
  11.   
  12. /** 
  13.  * Created by ldb on 2017/4/9. 
  14.  */  
  15. @Controller  
  16. public class UEditorController {  
  17.   
  18.   
  19.     @RequestMapping("/")  
  20.     private String showPage(){  
  21.         return "index";  
  22.     }  
  23.   
  24.     @RequestMapping(value="/config")  
  25.     public void config(HttpServletRequest request, HttpServletResponse response) {  
  26.         response.setContentType("application/json");  
  27.         String rootPath = request.getSession().getServletContext().getRealPath("/");  
  28.         try {  
  29.             String exec = new ActionEnter(request, rootPath).exec();  
  30.             PrintWriter writer = response.getWriter();  
  31.             writer.write(exec);  
  32.             writer.flush();  
  33.             writer.close();  
  34.         } catch (IOException e) {  
  35.             e.printStackTrace();  
  36.         }  
  37.   
  38.     }  
  39. }  
package com.example;

import com.baidu.ueditor.ActionEnter;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;

/**
 * Created by ldb on 2017/4/9.
 */
@Controller
public class UEditorController {


    @RequestMapping("/")
    private String showPage(){
        return "index";
    }

    @RequestMapping(value="/config")
    public void config(HttpServletRequest request, HttpServletResponse response) {
        response.setContentType("application/json");
        String rootPath = request.getSession().getServletContext().getRealPath("/");
        try {
            String exec = new ActionEnter(request, rootPath).exec();
            PrintWriter writer = response.getWriter();
            writer.write(exec);
            writer.flush();
            writer.close();
        } catch (IOException e) {
            e.printStackTrace();
        }

    }
}
7.一步一步debug,发现无法加载config.json文件。此时修改ConfigManage类的getConfigPath()方法。如下:

  1. package com.baidu.ueditor;  
  2.   
  3. import com.baidu.ueditor.define.ActionMap;  
  4. import org.json.JSONArray;  
  5. import org.json.JSONObject;  
  6.   
  7. import java.io.*;  
  8. import java.net.URISyntaxException;  
  9. import java.util.HashMap;  
  10. import java.util.Map;  
  11.   
  12. /** 
  13.  * 配置管理器 
  14.  * @author hancong03@baidu.com 
  15.  * 
  16.  */  
  17. public final class ConfigManager {  
  18.   
  19.     private final String rootPath;  
  20.     private final String originalPath;  
  21.     private final String contextPath;  
  22.     private static final String configFileName =  "config.json";  
  23.     private String parentPath = null;  
  24.     private JSONObject jsonConfig = null;  
  25.     // 涂鸦上传filename定义  
  26.     private final static String SCRAWL_FILE_NAME =  "scrawl";  
  27.     // 远程图片抓取filename定义  
  28.     private final static String REMOTE_FILE_NAME =  "remote";  
  29.       
  30.     /* 
  31.      * 通过一个给定的路径构建一个配置管理器, 该管理器要求地址路径所在目录下必须存在config.properties文件 
  32.      */  
  33.     private ConfigManager ( String rootPath, String contextPath, String uri ) throws FileNotFoundException, IOException {  
  34.           
  35.         rootPath = rootPath.replace( "\\", "/" );  
  36.           
  37.         this.rootPath = rootPath;  
  38.         this.contextPath = contextPath;  
  39.           
  40.         if ( contextPath.length() > 0 ) {  
  41.             this.originalPath = this.rootPath + uri.substring( contextPath.length() );  
  42.         } else {  
  43.             this.originalPath = this.rootPath + uri;  
  44.         }  
  45.           
  46.         this.initEnv();  
  47.           
  48.     }  
  49.       
  50.     /** 
  51.      * 配置管理器构造工厂 
  52.      * @param rootPath 服务器根路径 
  53.      * @param contextPath 服务器所在项目路径 
  54.      * @param uri 当前访问的uri 
  55.      * @return 配置管理器实例或者null 
  56.      */  
  57.     public static ConfigManager getInstance ( String rootPath, String contextPath, String uri ) {  
  58.           
  59.         try {  
  60.             return new ConfigManager(rootPath, contextPath, uri);  
  61.         } catch ( Exception e ) {  
  62.             return null;  
  63.         }  
  64.           
  65.     }  
  66.       
  67.     // 验证配置文件加载是否正确  
  68.     public boolean valid () {  
  69.         return this.jsonConfig != null;  
  70.     }  
  71.       
  72.     public JSONObject getAllConfig () {  
  73.           
  74.         return this.jsonConfig;  
  75.           
  76.     }  
  77.       
  78.     public Map<String, Object> getConfig ( int type ) {  
  79.           
  80.         Map<String, Object> conf = new HashMap<String, Object>();  
  81.         String savePath = null;  
  82.           
  83.         switch ( type ) {  
  84.           
  85.             case ActionMap.UPLOAD_FILE:  
  86.                 conf.put( "isBase64""false" );  
  87.                 conf.put( "maxSize"this.jsonConfig.getLong(  "fileMaxSize" ) );  
  88.                 conf.put( "allowFiles"this.getArray(  "fileAllowFiles" ) );  
  89.                 conf.put( "fieldName"this.jsonConfig.getString(  "fileFieldName" ) );  
  90.                 savePath = this.jsonConfig.getString( "filePathFormat" );  
  91.                 break;  
  92.                   
  93.             case ActionMap.UPLOAD_IMAGE:  
  94.                 conf.put( "isBase64""false" );  
  95.                 conf.put( "maxSize"this.jsonConfig.getLong(  "imageMaxSize" ) );  
  96.                 conf.put( "allowFiles"this.getArray(  "imageAllowFiles" ) );  
  97.                 conf.put( "fieldName"this.jsonConfig.getString(  "imageFieldName" ) );  
  98.                 savePath = this.jsonConfig.getString( "imagePathFormat" );  
  99.                 break;  
  100.                   
  101.             case ActionMap.UPLOAD_VIDEO:  
  102.                 conf.put( "maxSize"this.jsonConfig.getLong(  "videoMaxSize" ) );  
  103.                 conf.put( "allowFiles"this.getArray(  "videoAllowFiles" ) );  
  104.                 conf.put( "fieldName"this.jsonConfig.getString(  "videoFieldName" ) );  
  105.                 savePath = this.jsonConfig.getString( "videoPathFormat" );  
  106.                 break;  
  107.                   
  108.             case ActionMap.UPLOAD_SCRAWL:  
  109.                 conf.put( "filename", ConfigManager.SCRAWL_FILE_NAME );  
  110.                 conf.put( "maxSize"this.jsonConfig.getLong(  "scrawlMaxSize" ) );  
  111.                 conf.put( "fieldName"this.jsonConfig.getString(  "scrawlFieldName" ) );  
  112.                 conf.put( "isBase64""true" );  
  113.                 savePath = this.jsonConfig.getString( "scrawlPathFormat" );  
  114.                 break;  
  115.                   
  116.             case ActionMap.CATCH_IMAGE:  
  117.                 conf.put( "filename", ConfigManager.REMOTE_FILE_NAME );  
  118.                 conf.put( "filter"this.getArray(  "catcherLocalDomain" ) );  
  119.                 conf.put( "maxSize"this.jsonConfig.getLong(  "catcherMaxSize" ) );  
  120.                 conf.put( "allowFiles"this.getArray(  "catcherAllowFiles" ) );  
  121.                 conf.put( "fieldName"this.jsonConfig.getString(  "catcherFieldName" ) + "[]" );  
  122.                 savePath = this.jsonConfig.getString( "catcherPathFormat" );  
  123.                 break;  
  124.                   
  125.             case ActionMap.LIST_IMAGE:  
  126.                 conf.put( "allowFiles"this.getArray(  "imageManagerAllowFiles" ) );  
  127.                 conf.put( "dir"this.jsonConfig.getString(  "imageManagerListPath" ) );  
  128.                 conf.put( "count"this.jsonConfig.getInt(  "imageManagerListSize" ) );  
  129.                 break;  
  130.                   
  131.             case ActionMap.LIST_FILE:  
  132.                 conf.put( "allowFiles"this.getArray(  "fileManagerAllowFiles" ) );  
  133.                 conf.put( "dir"this.jsonConfig.getString(  "fileManagerListPath" ) );  
  134.                 conf.put( "count"this.jsonConfig.getInt(  "fileManagerListSize" ) );  
  135.                 break;  
  136.                   
  137.         }  
  138.           
  139.         conf.put( "savePath", savePath );  
  140.         conf.put( "rootPath"this.rootPath );  
  141.           
  142.         return conf;  
  143.           
  144.     }  
  145.       
  146.     private void initEnv () throws FileNotFoundException, IOException {  
  147.           
  148.         File file = new File( this.originalPath );  
  149.           
  150.         if ( !file.isAbsolute() ) {  
  151.             file = new File( file.getAbsolutePath() );  
  152.         }  
  153.           
  154.         this.parentPath = file.getParent();  
  155.           
  156.         String configContent = this.readFile( this.getConfigPath() );  
  157.           
  158.         try{  
  159.             JSONObject jsonConfig = new JSONObject( configContent );  
  160.             this.jsonConfig = jsonConfig;  
  161.         } catch ( Exception e ) {  
  162.             this.jsonConfig = null;  
  163.         }  
  164.           
  165.     }  
  166.   
  167.   
  168.     private String getConfigPath () {  
  169.         //return this.parentPath + File.separator + ConfigManager.configFileName;  
  170.         try {  
  171.             //获取classpath下的config.json路径  
  172.             return this.getClass().getClassLoader().getResource( "config.json").toURI().getPath();  
  173.         } catch (URISyntaxException e) {  
  174.             return null;  
  175.         }  
  176.     }  
  177.   
  178.     private String[] getArray ( String key ) {  
  179.           
  180.         JSONArray jsonArray = this.jsonConfig.getJSONArray( key );  
  181.         String[] result = new String[ jsonArray.length() ];  
  182.           
  183.         for ( int i = 0, len = jsonArray.length(); i < len; i++ ) {  
  184.             result[i] = jsonArray.getString( i );  
  185.         }  
  186.           
  187.         return result;  
  188.           
  189.     }  
  190.       
  191.     private String readFile ( String path ) throws IOException {  
  192.           
  193.         StringBuilder builder = new StringBuilder();  
  194.           
  195.         try {  
  196.               
  197.             InputStreamReader reader = new InputStreamReader( new FileInputStream( path ),  "UTF-8" );  
  198.             BufferedReader bfReader = new BufferedReader( reader );  
  199.               
  200.             String tmpContent = null;  
  201.               
  202.             while ( ( tmpContent = bfReader.readLine() ) != null ) {  
  203.                 builder.append( tmpContent );  
  204.             }  
  205.               
  206.             bfReader.close();  
  207.               
  208.         } catch ( UnsupportedEncodingException e ) {  
  209.             // 忽略  
  210.         }  
  211.           
  212.         return this.filter( builder.toString() );  
  213.           
  214.     }  
  215.       
  216.     // 过滤输入字符串, 剔除多行注释以及替换掉反斜杠  
  217.     private String filter ( String input ) {  
  218.           
  219.         return input.replaceAll( "/\\*[\\s\\S]*?\\*/""" );  
  220.           
  221.     }  
  222.       
  223. }  
package com.baidu.ueditor;

import com.baidu.ueditor.define.ActionMap;
import org.json.JSONArray;
import org.json.JSONObject;

import java.io.*;
import java.net.URISyntaxException;
import java.util.HashMap;
import java.util.Map;

/**
 * 配置管理器
 * @author hancong03@baidu.com
 *
 */
public final class ConfigManager {

	private final String rootPath;
	private final String originalPath;
	private final String contextPath;
	private static final String configFileName = "config.json";
	private String parentPath = null;
	private JSONObject jsonConfig = null;
	// 涂鸦上传filename定义
	private final static String SCRAWL_FILE_NAME = "scrawl";
	// 远程图片抓取filename定义
	private final static String REMOTE_FILE_NAME = "remote";
	
	/*
	 * 通过一个给定的路径构建一个配置管理器, 该管理器要求地址路径所在目录下必须存在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;
		}
		
	}
	
	// 验证配置文件加载是否正确
	public boolean valid () {
		return this.jsonConfig != null;
	}
	
	public JSONObject getAllConfig () {
		
		return this.jsonConfig;
		
	}
	
	public Map<String, Object> getConfig ( int type ) {
		
		Map<String, Object> conf = new HashMap<String, Object>();
		String savePath = null;
		
		switch ( type ) {
		
			case ActionMap.UPLOAD_FILE:
				conf.put( "isBase64", "false" );
				conf.put( "maxSize", this.jsonConfig.getLong( "fileMaxSize" ) );
				conf.put( "allowFiles", this.getArray( "fileAllowFiles" ) );
				conf.put( "fieldName", this.jsonConfig.getString( "fileFieldName" ) );
				savePath = this.jsonConfig.getString( "filePathFormat" );
				break;
				
			case ActionMap.UPLOAD_IMAGE:
				conf.put( "isBase64", "false" );
				conf.put( "maxSize", this.jsonConfig.getLong( "imageMaxSize" ) );
				conf.put( "allowFiles", this.getArray( "imageAllowFiles" ) );
				conf.put( "fieldName", this.jsonConfig.getString( "imageFieldName" ) );
				savePath = this.jsonConfig.getString( "imagePathFormat" );
				break;
				
			case ActionMap.UPLOAD_VIDEO:
				conf.put( "maxSize", this.jsonConfig.getLong( "videoMaxSize" ) );
				conf.put( "allowFiles", this.getArray( "videoAllowFiles" ) );
				conf.put( "fieldName", this.jsonConfig.getString( "videoFieldName" ) );
				savePath = this.jsonConfig.getString( "videoPathFormat" );
				break;
				
			case ActionMap.UPLOAD_SCRAWL:
				conf.put( "filename", ConfigManager.SCRAWL_FILE_NAME );
				conf.put( "maxSize", this.jsonConfig.getLong( "scrawlMaxSize" ) );
				conf.put( "fieldName", this.jsonConfig.getString( "scrawlFieldName" ) );
				conf.put( "isBase64", "true" );
				savePath = this.jsonConfig.getString( "scrawlPathFormat" );
				break;
				
			case ActionMap.CATCH_IMAGE:
				conf.put( "filename", ConfigManager.REMOTE_FILE_NAME );
				conf.put( "filter", this.getArray( "catcherLocalDomain" ) );
				conf.put( "maxSize", this.jsonConfig.getLong( "catcherMaxSize" ) );
				conf.put( "allowFiles", this.getArray( "catcherAllowFiles" ) );
				conf.put( "fieldName", this.jsonConfig.getString( "catcherFieldName" ) + "[]" );
				savePath = this.jsonConfig.getString( "catcherPathFormat" );
				break;
				
			case ActionMap.LIST_IMAGE:
				conf.put( "allowFiles", this.getArray( "imageManagerAllowFiles" ) );
				conf.put( "dir", this.jsonConfig.getString( "imageManagerListPath" ) );
				conf.put( "count", this.jsonConfig.getInt( "imageManagerListSize" ) );
				break;
				
			case ActionMap.LIST_FILE:
				conf.put( "allowFiles", this.getArray( "fileManagerAllowFiles" ) );
				conf.put( "dir", this.jsonConfig.getString( "fileManagerListPath" ) );
				conf.put( "count", this.jsonConfig.getInt( "fileManagerListSize" ) );
				break;
				
		}
		
		conf.put( "savePath", savePath );
		conf.put( "rootPath", this.rootPath );
		
		return conf;
		
	}
	
	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;
		}
		
	}


	private String getConfigPath () {
		//return this.parentPath + File.separator + ConfigManager.configFileName;
		try {
			//获取classpath下的config.json路径
			return this.getClass().getClassLoader().getResource("config.json").toURI().getPath();
		} catch (URISyntaxException e) {
			return null;
		}
	}

	private String[] getArray ( String key ) {
		
		JSONArray jsonArray = this.jsonConfig.getJSONArray( key );
		String[] result = new String[ jsonArray.length() ];
		
		for ( int i = 0, len = jsonArray.length(); i < len; i++ ) {
			result[i] = jsonArray.getString( i );
		}
		
		return result;
		
	}
	
	private String readFile ( String path ) throws IOException {
		
		StringBuilder builder = new StringBuilder();
		
		try {
			
			InputStreamReader reader = new InputStreamReader( new FileInputStream( path ), "UTF-8" );
			BufferedReader bfReader = new BufferedReader( reader );
			
			String tmpContent = null;
			
			while ( ( tmpContent = bfReader.readLine() ) != null ) {
				builder.append( tmpContent );
			}
			
			bfReader.close();
			
		} catch ( UnsupportedEncodingException e ) {
			// 忽略
		}
		
		return this.filter( builder.toString() );
		
	}
	
	// 过滤输入字符串, 剔除多行注释以及替换掉反斜杠
	private String filter ( String input ) {
		
		return input.replaceAll( "/\\*[\\s\\S]*?\\*/", "" );
		
	}
	
}
this.getClass().getClassLoader().getResource("config.json").toURI().getPath(); 
此处需要先转为URI再getPath(),否则如果你的项目路径带空格或者带中文则无法读取到文件

8.运行项目路径http://localhost:8080/config?action=config,如下图显示则表示可读取到config.json文件



9.此时点击上传图片显示 如下


提示未找到上传数据。继续一步步debug,发现在BinaryUploader类竟然无法获取到字节流


google得到原因是因为SpringMVC框架对含字节流的request进行了处理,此处传的是处理过的request,故获取不到字节流。此时采用SpringMVC框架的解析器multipartResolver。修改源码如下:

  1. package com.baidu.ueditor.upload;  
  2.   
  3. import com.baidu.ueditor.PathFormat;  
  4. import com.baidu.ueditor.define.AppInfo;  
  5. import com.baidu.ueditor.define.BaseState;  
  6. import com.baidu.ueditor.define.FileType;  
  7. import com.baidu.ueditor.define.State;  
  8. import org.apache.commons.fileupload.servlet.ServletFileUpload;  
  9. import org.springframework.web.multipart.MultipartFile;  
  10. import org.springframework.web.multipart.MultipartHttpServletRequest;  
  11.   
  12. import javax.servlet.http.HttpServletRequest;  
  13. import java.io.IOException;  
  14. import java.io.InputStream;  
  15. import java.util.Arrays;  
  16. import java.util.List;  
  17. import java.util.Map;  
  18.   
  19. public class BinaryUploader {  
  20.   
  21.     public static final State save(HttpServletRequest request,  
  22.             Map<String, Object> conf) {  
  23.         // FileItemStream fileStream = null;  
  24.         // boolean isAjaxUpload = request.getHeader( "X_Requested_With" ) != null;  
  25.   
  26.         if (!ServletFileUpload.isMultipartContent(request)) {  
  27.             return new BaseState(false, AppInfo.NOT_MULTIPART_CONTENT);  
  28.         }  
  29.   
  30.         // ServletFileUpload upload = new ServletFileUpload(  
  31.             //  new DiskFileItemFactory());  
  32.         //  
  33.         // if ( isAjaxUpload ) {  
  34.         //     upload.setHeaderEncoding( "UTF-8" );  
  35.         // }  
  36.   
  37.         try {  
  38.             // FileItemIterator iterator = upload.getItemIterator(request);  
  39.             //  
  40.             // while (iterator.hasNext()) {  
  41.             //  fileStream = iterator.next();  
  42.             //  
  43.             //  if (!fileStream.isFormField())  
  44.             //      break;  
  45.             //  fileStream = null;  
  46.             // }  
  47.             //  
  48.             // if (fileStream == null) {  
  49.             //  return new BaseState(false, AppInfo.NOTFOUND_UPLOAD_DATA);  
  50.             // }  
  51.             MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;  
  52.             MultipartFile multipartFile = multipartRequest.getFile(conf.get("fieldName").toString());  
  53.             if(multipartFile==null){  
  54.                 return new BaseState( false, AppInfo.NOTFOUND_UPLOAD_DATA);  
  55.             }  
  56.   
  57.             String savePath = (String) conf.get("savePath");  
  58.             //String originFileName = fileStream.getName();  
  59.             String originFileName = multipartFile.getOriginalFilename();  
  60.             String suffix = FileType.getSuffixByFilename(originFileName);  
  61.   
  62.             originFileName = originFileName.substring(0,  
  63.                     originFileName.length() - suffix.length());  
  64.             savePath = savePath + suffix;  
  65.   
  66.             long maxSize = ((Long) conf.get("maxSize")).longValue();  
  67.   
  68.             if (!validType(suffix, (String[]) conf.get("allowFiles"))) {  
  69.                 return new BaseState( false, AppInfo.NOT_ALLOW_FILE_TYPE);  
  70.             }  
  71.   
  72.             savePath = PathFormat.parse(savePath, originFileName);  
  73.   
  74.             String physicalPath = (String) conf.get("rootPath") + savePath;  
  75.   
  76.             //InputStream is = fileStream.openStream();  
  77.             InputStream is = multipartFile.getInputStream();  
  78.             State storageState = StorageManager.saveFileByInputStream(is,  
  79.                     physicalPath, maxSize);  
  80.             is.close();  
  81.   
  82.             if (storageState.isSuccess()) {  
  83.                 storageState.putInfo("url", PathFormat.format(savePath));  
  84.                 storageState.putInfo("type", suffix);  
  85.                 storageState.putInfo("original", originFileName + suffix);  
  86.             }  
  87.   
  88.             return storageState;  
  89.         // } catch (FileUploadException e) {  
  90.         //  return new BaseState(false, AppInfo.PARSE_REQUEST_ERROR);  
  91.         } catch (IOException e) {  
  92.         }  
  93.         return new BaseState(false, AppInfo.IO_ERROR);  
  94.     }  
  95.   
  96.     private static boolean validType(String type, String[] allowTypes) {  
  97.         List<String> list = Arrays.asList(allowTypes);  
  98.   
  99.         return list.contains(type);  
  100.     }  
  101. }  
package com.baidu.ueditor.upload;

import com.baidu.ueditor.PathFormat;
import com.baidu.ueditor.define.AppInfo;
import com.baidu.ueditor.define.BaseState;
import com.baidu.ueditor.define.FileType;
import com.baidu.ueditor.define.State;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;

import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.io.InputStream;
import java.util.Arrays;
import java.util.List;
import java.util.Map;

public class BinaryUploader {

	public static final State save(HttpServletRequest request,
			Map<String, Object> conf) {
		// FileItemStream fileStream = null;
		// boolean isAjaxUpload = request.getHeader( "X_Requested_With" ) != null;

		if (!ServletFileUpload.isMultipartContent(request)) {
			return new BaseState(false, AppInfo.NOT_MULTIPART_CONTENT);
		}

        // ServletFileUpload upload = new ServletFileUpload(
			// 	new DiskFileItemFactory());
        //
        // if ( isAjaxUpload ) {
        //     upload.setHeaderEncoding( "UTF-8" );
        // }

		try {
			// FileItemIterator iterator = upload.getItemIterator(request);
            //
			// while (iterator.hasNext()) {
			// 	fileStream = iterator.next();
            //
			// 	if (!fileStream.isFormField())
			// 		break;
			// 	fileStream = null;
			// }
            //
			// if (fileStream == null) {
			// 	return new BaseState(false, AppInfo.NOTFOUND_UPLOAD_DATA);
			// }
			MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;
			MultipartFile multipartFile = multipartRequest.getFile(conf.get("fieldName").toString());
			if(multipartFile==null){
				return new BaseState(false, AppInfo.NOTFOUND_UPLOAD_DATA);
			}

			String savePath = (String) conf.get("savePath");
			//String originFileName = fileStream.getName();
			String originFileName = multipartFile.getOriginalFilename();
			String suffix = FileType.getSuffixByFilename(originFileName);

			originFileName = originFileName.substring(0,
					originFileName.length() - suffix.length());
			savePath = savePath + suffix;

			long maxSize = ((Long) conf.get("maxSize")).longValue();

			if (!validType(suffix, (String[]) conf.get("allowFiles"))) {
				return new BaseState(false, AppInfo.NOT_ALLOW_FILE_TYPE);
			}

			savePath = PathFormat.parse(savePath, originFileName);

			String physicalPath = (String) conf.get("rootPath") + savePath;

			//InputStream is = fileStream.openStream();
			InputStream is = multipartFile.getInputStream();
			State storageState = StorageManager.saveFileByInputStream(is,
					physicalPath, maxSize);
			is.close();

			if (storageState.isSuccess()) {
				storageState.putInfo("url", PathFormat.format(savePath));
				storageState.putInfo("type", suffix);
				storageState.putInfo("original", originFileName + suffix);
			}

			return storageState;
		// } catch (FileUploadException e) {
		// 	return new BaseState(false, AppInfo.PARSE_REQUEST_ERROR);
		} catch (IOException e) {
		}
		return new BaseState(false, AppInfo.IO_ERROR);
	}

	private static boolean validType(String type, String[] allowTypes) {
		List<String> list = Arrays.asList(allowTypes);

		return list.contains(type);
	}
}

此时进行上传图片,已经能够成功上传了。



10.可是图片究竟上传到哪里了呢?继续一步步debug发现,上传到如图路径



如图路径为tomcat缓存路径,只要重启下tomcat该文件就会被删除。我们需要将其存储到磁盘中。此时修改config.json文件。



红色箭头为修改处。我需要将文件存储到E:/image/**下,此处我多添加了basePath,是想把视频、音乐等静态资源都存储到E盘。由于添加了basePath,需要修改配置。通过debug来到ConfigManage


添加红色箭头代码,将basePath塞进配置文件里。之后继续来到上传文件类BinaryUploader,修改如下代码:



运行项目,点击添加图片。打开E盘的image目录,如图,成功上传到E盘对应路径


11.打开浏览器,发现页面无法加载图片。如下图:


打开浏览器调试器。如图


无法获取到图片。这是当然的,因为我们把图片存在E盘了,而spring并没有对E盘目录进行映射。此时我们加入路径映射。打开application.properties文件,添加如下代码

  1. web.upload-path=E:/  
  2. spring.mvc.static-path-pattern=/**  
  3. spring.resources.static-locations=classpath:/META-INF/resources/,classpath:/resources/,classpath:/static/,classpath:/public/,file:${web.upload-path}  
web.upload-path=E:/
spring.mvc.static-path-pattern=/**
spring.resources.static-locations=classpath:/META-INF/resources/,classpath:/resources/,classpath:/static/,classpath:/public/,file:${web.upload-path}

此时重新运行项目,点击上传图片,图片已经能够正常显示了。



12.至此,SpringBoot整合UEditor应该完了吧。别急,SpringBoot主张打包成Jar包运行,我们用Maven来打包运行试


java -jar 

打开项目地址,点击上传图片,发现竟然上传不了了??!!



这是怎么回事呢?为什么打成Jar包后就无法上传图片了呢。经过不断的debug和google。。发现了在Jar包里无法以ClassLoader.getResource().getPath()获得的路径读取文件,得用Class类的getResourceAsStream()来读取。具体博文如下:

http://hxraid.iteye.com/blog/483115?page=3#comments

13.那么我们就来修改源码,改成getResourceAsStream读取config.json文件吧。打开ConfigManager类,修改initEnv方法

  1. private void initEnv () throws FileNotFoundException, IOException {  
  2.           
  3.         File file = new File( this.originalPath );  
  4.           
  5.         if ( !file.isAbsolute() ) {  
  6.             file = new File( file.getAbsolutePath() );  
  7.         }  
  8.           
  9.         this.parentPath = file.getParent();  
  10.           
  11.         //String configContent = this.readFile( this.getConfigPath() );  
  12.         String configContent = this.filter(IOUtils.toString(this.getClass().getClassLoader().getResourceAsStream( "config.json")));  
  13.   
  14.         try{  
  15.             JSONObject jsonConfig = new JSONObject( configContent );  
  16.             this.jsonConfig = jsonConfig;  
  17.         } catch ( Exception e ) {  
  18.             this.jsonConfig = null;  
  19.         }  
  20.           
  21.     }  
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() );
		String configContent = this.filter(IOUtils.toString(this.getClass().getClassLoader().getResourceAsStream("config.json")));

		try{
			JSONObject jsonConfig = new JSONObject( configContent );
			this.jsonConfig = jsonConfig;
		} catch ( Exception e ) {
			this.jsonConfig = null;
		}
		
	}

14. ok了,再次打包,运行项目




成功了!!!


项目源码:https://github.com/llldddbbb/ueditor-test

本次教程到此结束。谢谢大家