直接贴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));待研究