1、文章由来
最近在做Javaweb(ssh框架)项目开发,使用到百度编译器ueditor,在struts2框架中配置好了,利用百度编译器上传发现未找到上传数据,这个项目之前做的都是使用本文章的第一种方法,将访问controller.jsp的请求接口直接不经过struts2框架,但是由于现在这个项目要求安全性比较高,所以要实现当某一个用户未登录时,屏蔽ueditor的上传接口,所以就开始查找struts2框架中ueditor无法上传的原因。
2、原因
查找很多关于Struts2中无法使用ueditor的原因,发现百度上并没有太多的文章,当我想到以前看到的文章ssh框架利用ajax异步上传时候,如果使用原生ServletFileUpload来进行处理上传数据会发现request域为空,也就是说Struts2中获取的原生文件流被清空了,查找发现果然是,Struts2会对上传文件数据进行封装成MultiPartRequestWrapper对象,并清空request域中的文件流。这就导致ueditor上传时,无法获取到request域中的文件流。
3、解决方案
原因知道了,解决也就很简单了,共有两种方案。
3.1、方案1,将访问controller.jsp的请求不经过Struts2,直接使用原生Service进行请求。(访问jsp页面的本质还是请求Service,Tomcat自动将JSP页面封装成了原生Service)
3.1.1重写StrutsPrepareAndExecuteFilter方法
public class MyStrutsFilter extends StrutsPrepareAndExecuteFilter {
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) req;
String url = request.getRequestURI();
/*最好写成准确的请求 if (url.equals(url+"ueditor/jsp/controller.jsp")) {*/
if (url.contains("controller.jsp")) {
System.out.println("使用原生Service请求,不经过Struts");
chain.doFilter(req, res);
} else {
System.out.println("经过Struts");
super.doFilter(req, res, chain);
}
}
}
3.1.2、修改web.xml配置文件
将
<filter>
<filter-name>struts2</filter-name>
<filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
</filter>
修改成刚才重写的StrutsPrepareAndExecuteFilter类
<filter>
<filter-name>struts2</filter-name>
<filter-class>cn.itcast.filter.MyStrutsFilter</filter-class>
</filter>
3.1.3、问题解决,这样的话不经过Struts2,这就意味着当项目有需要登录的功能时,在未登录的情况下,这个端口依旧可以访问,这就带来了很大的安全隐患,在我写的前几个项目里面的解决方案是在重写的StrutsPrepareAndExecuteFilter类里面加入了利用原生Request和Response登录判断,但是在SSH框架中本身写的就有登录过滤类,再在原生请求中加入登录判断,加重了工作量,代码繁琐于是考虑能不能controller.jsp方法,并过去除对这个请求的数据封装,于是出现了第二个解决方案。
3.2、方案2,重写controller.jsp,利用Struts2实现
3.2.1创建UeditorController.java类,用于替换掉controller.jsp文件
public class UeditorController {
public void Controller() throws IOException {
HttpServletRequest request = ServletActionContext.getRequest();
HttpServletResponse response = ServletActionContext.getResponse();
request.setCharacterEncoding("utf-8");
HttpSession session = request.getSession();
String rootPath = session.getServletContext().getRealPath("/");
response.getOutputStream().write(new ActionEnter(request, rootPath).exec().getBytes(Charset.forName("utf-8")));
}
}
3.2.2、重写JakartaMultiPartRequest方法,用于请求UeditorController接口时,删除Struts2对文件流的清空,同时保留访问其他接口时对原生请求数据的封装
public class RequestParseWrapper extends JakartaMultiPartRequest {
public void parse(HttpServletRequest servletRequest, String saveDir) throws IOException {
String url = servletRequest.getRequestURI();
/*最好写成准确的请求 if (url.equals(url+"Controller")) {*/
if (!url.contains("Controller")) {
super.parse(servletRequest, saveDir);
}
}
}
在Struts2.xml中加入Action接口,配置UeditorController类,替换controller.jsp
<!--class变量中关联刚才写的UeditorController类 -->
<action name="UeditorController" class="com.baidu.ueditor.action.UeditorController" method="Controller"/>
在Struts2.xml中<struts>根节点下添加,应用重写的RequestParseWrapper类
<bean
type="org.apache.struts2.dispatcher.multipart.MultiPartRequest"
name="RequestParseWrapper"
class="com.baidu.ueditor.filter.RequestParseWrapper" scope="default"
optional="true" />
<!-- struts2是struts2.3.15.1之前的
<constant name="struts.multipart.handler " value="RequestParseWrapper"/>
-->
<!-- struts2是struts2.3.15.1以后的版本 -->
<constant name="struts.multipart.parser"
value="RequestParseWrapper" />
</struts>
3.2.3、删除导入的ueditor-1.1.2.jar包,直接使用百度编译器的源码,修改ConfigManager.java中的getConfigPath ()方法,使项目寻找config.json文件直接在项目根目录下
这个步骤可直接使用我修改好的源码替换掉ueditor-1.1.2.jar:https://download.csdn.net/download/qq_39905143/11441443
private String getConfigPath () {
//return this.parentPath + File.separator + ConfigManager.configFileName;
return rootPath+"WEB-INF/classes/"+ConfigManager.configFileName;
}
3.2.4、将config.json文件复制到项目的根目录下
3.2.5、修改ueditor.config.js文件,指定重写的Action
window.UEDITOR_CONFIG = {
//为编辑器实例添加一个路径,这个不能被注释
UEDITOR_HOME_URL: URL
// 服务器统一请求接口路径
, serverUrl: URL + "../UeditorController"
//工具栏上的所有的功能按钮和下拉框,可以在new编辑器的实例时选择自己需要的重新定义
, toolbars: [[
3.2.6、完成修改。
3.4、为了方便使用,我将这两个方案的SSH项目写了两个模板,打开可以直接使用,可以参考着模板项目来进行修改自己的项目,也可以在我整合的项目中直接做。
方案1模板ueditor+SSH项目:https://download.csdn.net/download/qq_39905143/11424702
方案2模板ueditor+SSH项目:https://download.csdn.net/download/qq_39905143/11424758
方案1完整MyStrutsFilter.java文件:
package cn.itcast.filter;
import java.io.IOException;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter;
public class MyStrutsFilter extends StrutsPrepareAndExecuteFilter {
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) req;
String url = request.getRequestURI();
/*最好写成准确的请求 if (url.equals(url+"ueditor/jsp/controller.jsp")) {*/
if (url.contains("controller.jsp")) {
System.out.println("使用原生Service请求,不经过Struts");
chain.doFilter(req, res);
} else {
System.out.println("经过Struts");
super.doFilter(req, res, chain);
}
}
}
方案1完整web.xml文件:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" version="2.5">
<display-name>UeditorModelSSH</display-name>
<context-param>
<param-name>log4jConfigLocation</param-name>
<param-value>classpath:log4j.properties</param-value>
</context-param>
<context-param>
<param-name>log4jRefreshInterval</param-name>
<param-value>60000</param-value>
</context-param>
<!-- 需要添加spring-web.jar包,否则用发生错误信息 -->
<listener>
<listener-class>org.springframework.web.util.Log4jConfigListener</listener-class>
</listener>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml</param-value>
</context-param>
<filter>
<filter-name>struts2</filter-name>
<filter-class>cn.itcast.filter.MyStrutsFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.htm</welcome-file>
<welcome-file>index.jsp</welcome-file>
<welcome-file>default.html</welcome-file>
<welcome-file>default.htm</welcome-file>
<welcome-file>default.jsp</welcome-file>
</welcome-file-list>
</web-app>
方案2完整UeditorController.java文件
package com.baidu.ueditor.action;
import java.io.IOException;
import java.nio.charset.Charset;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.apache.struts2.ServletActionContext;
import com.baidu.ueditor.ActionEnter;
public class UeditorController {
public void Controller() throws IOException {
HttpServletRequest request = ServletActionContext.getRequest();
HttpServletResponse response = ServletActionContext.getResponse();
request.setCharacterEncoding("utf-8");
HttpSession session = request.getSession();
String rootPath = session.getServletContext().getRealPath("/");
response.getOutputStream().write(new ActionEnter(request, rootPath).exec().getBytes(Charset.forName("utf-8")));
}
}
方案2完整RequestParseWrapper.java文件
package com.baidu.ueditor.parse;
import java.io.IOException;
import javax.servlet.http.HttpServletRequest;
import org.apache.struts2.dispatcher.multipart.JakartaMultiPartRequest;
public class RequestParseWrapper extends JakartaMultiPartRequest {
public void parse(HttpServletRequest servletRequest, String saveDir) throws IOException {
String url = servletRequest.getRequestURI();
/*最好写成准确的请求 if (url.equals(url+"Controller")) {*/
if (!url.contains("Controller")) {
super.parse(servletRequest, saveDir);
}
}
}
方案2完整struts.xml文件
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
"http://struts.apache.org/dtds/struts-2.3.dtd">
<struts>
<constant name="struts.objectFactory" value="spring"></constant>
<constant name="struts.devMode" value="false"></constant>
<!-- i18n:国际化. 解决post提交乱码 -->
<constant name="struts.i18n.encoding" value="UTF-8"></constant>
<!-- 百度编译器的配置端口 -->
<package name="Ueditor" namespace="/" extends="struts-default">
<!--class变量中关联第一个类 -->
<action name="UeditorController"
class="com.baidu.ueditor.action.UeditorController"
method="Controller">
</action>
</package>
<bean
type="org.apache.struts2.dispatcher.multipart.MultiPartRequest"
name="RequestParseWrapper"
class="com.baidu.ueditor.parse.RequestParseWrapper" scope="default"
optional="true" />
<!-- struts2是struts2.3.15.1之前的
<constant name="struts.multipart.handler " value="RequestParseWrapper"/>
-->
<!-- struts2是struts2.3.15.1以后的版本 -->
<constant name="struts.multipart.parser"
value="RequestParseWrapper" />
</struts>
方案2修改ueditor.config.js文件
//为编辑器实例添加一个路径,这个不能被注释
UEDITOR_HOME_URL: URL
// 服务器统一请求接口路径
, serverUrl: URL + "../UeditorController"