直接贴Struts2的源码
按照执行流程
1.FilterDispacher类中:
/**
* Wrap and return the given request, if needed, so as to to transparently
* handle multipart data as a wrapped class around the given request.
*
* @param request Our ServletRequest object
* @param response Our ServerResponse object
* @return Wrapped HttpServletRequest object
* @throws ServletException on any error
*/
protected HttpServletRequest prepareDispatcherAndWrapRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException {
/*
* 不明白,dispatcher实例是何时给本地线程的
*
* 经debug后,发现最初的dispatcher实例是在FilterDispatcher中的init方法已经初始化了
*/
Dispatcher du = Dispatcher.getInstance();//每次的请求会是null:意味每次的本地线程都不同,因此会变成null
// Prepare and wrap the request if the cleanup filter hasn't already, cleanup filter should be
// configured first before struts2 dispatcher filter, hence when its cleanup filter's turn,
// static instance of Dispatcher should be null.
if (du == null) {
Dispatcher.setInstance(dispatcher);
// prepare the request no matter what - this ensures that the proper character encoding
// is used before invoking the mapper (see WW-9127)
/*
* 对于该prepare方法:struts2默认设置了request的setCharacterEncoding()方法,姑且先
* 不讨论设置成utf-8或者gbk会对获取客户端的参数有何种影响,我们首先肯定的是struts2对request
* 进行了编码设置,因此我会觉得在struts2作为web框架中增加编码设置变得非常多余
*/
dispatcher.prepare(request, response);
} else {
dispatcher = du;
}
try {
// Wrap request first, just in case it is multipart/form-data
// parameters might not be accessible through before encoding (ww-1278)
request = dispatcher.wrapRequest(request, getServletContext());
} catch (IOException e) {
String message = "Could not wrap servlet request with MultipartRequestWrapper!";
LOG.error(message, e);
throw new ServletException(message, e);
}
return request;
}
2.Dispatcher类中:
/**
* Prepare a request, including setting the encoding and locale.
*
* @param request The request
* @param response The response
*/
public void prepare(HttpServletRequest request, HttpServletResponse response) {
String encoding = null;
//默认编码
if (defaultEncoding != null) {
encoding = defaultEncoding;
}
Locale locale = null;
if (defaultLocale != null) {
locale = LocalizedTextUtil.localeFromString(defaultLocale, request.getLocale());
}
if (encoding != null) {
try {
//设置默认编码
request.setCharacterEncoding(encoding);
} catch (Exception e) {
LOG.error("Error setting character encoding to '" + encoding + "' - ignoring.", e);
}
}
if (locale != null) {
response.setLocale(locale);
}
if (paramsWorkaroundEnabled) {
request.getParameter("foo"); // simply read any parameter (existing or not) to "prime" the request
}
}
3.Dispatcher类中:
public HttpServletRequest wrapRequest(HttpServletRequest request, ServletContext servletContext) throws IOException {
// don't wrap more than once
/*
* 猜想疑惑:request的实例化使用sevlet容器进行初始化的,
* 但是为何这边要出现if判断其属于那种request下的实例,StrutsRequestWrapper或者MultiPartRequestWrapper下
* 那下面if如果要满足的话,前提必须进行了如下初始化
* 猜想:HttpSevrletRequest request=new StrutsRequestWrapper();
* 那问题便出来了,如何进行request初始化,还是容器吗?
* 每次请求都会初始化吗?他知道有StrutsRequestWrapper类吗?
* 如果前面猜想不成立的话:那么if永远也进步下去
*/
if (request instanceof StrutsRequestWrapper) {
return request;
}
//由于contentype的不同会使用不同的解析方式对request中的信息进行解析,
//故此进行判断
String content_type = request.getContentType();
if (content_type != null && content_type.indexOf("multipart/form-data") != -1) {
//主要涉及到Container和实现类ContainerImpl的设计思路,待日后研究
MultiPartRequest multi = getContainer().getInstance(MultiPartRequest.class);
//这里包含了上传文件的解析流程,仔细看还是可以看懂的,具体问题具体研究吧
request = new MultiPartRequestWrapper(multi, request, getSaveDir(servletContext));
} else {
//原来request在这里被struts2的request包裹类强奸了。尼玛。
request = new StrutsRequestWrapper(request);
}
return request;
}
如何更改struts2对于request的默认编码设置:<constant name="struts.i18n.encoding" value="utf-8/gbk" /> ps:默认情况下是utf-8
(struts2核心包下的default.properties中设置了默认编码值)
参考资料:http://blog.csdn.net/elimago/article/details/3601579
总结:
1.struts2默认对request进行了编码设置
2.Container和ContainerImpl实现类的设计准则待研究
3.对于上传文件的解析深入request = new MultiPartRequestWrapper(multi, request, getSaveDir(servletContext));待研究