首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 网站开发 > Web前端 >

struts源码之8

2012-12-28 
struts源码之八创建完成ActionContext后,strtus2将当Dispatcher分配到当前线程。prepare.assignDispatcherT

struts源码之八

创建完成ActionContext后,strtus2将当Dispatcher分配到当前线程。

prepare.assignDispatcherToThread();

?

public void assignDispatcherToThread() {        Dispatcher.setInstance(dispatcher);    }

?

到底是怎么初始化分配的,其实也是放入ThreadLocal中,仔细看

/**     * Store the dispatcher instance for this thread.     *     * @param instance The instance     */    public static void setInstance(Dispatcher instance) {        Dispatcher.instance.set(instance);    }

?

/**     * Provide a thread local instance.     */    private static ThreadLocal<Dispatcher> instance = new ThreadLocal<Dispatcher>();

?

?

预处理完成后就判断是否有不需要处理的请求,如果有则 struts不处理,继续执行, 否则struts2过滤过来进行处理

if ( excludedPatterns != null && prepare.isUrlExcluded(request, excludedPatterns)) {chain.doFilter(request, response);
}

?然后就开始处理了,首先是包装requst

request = prepare.wrapRequest(request);

为什么要包装requst呢?因为是为了处理文件上传 multipart/form-data

  public HttpServletRequest wrapRequest(HttpServletRequest oldRequest) throws ServletException {        HttpServletRequest request = oldRequest;        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, servletContext);        } catch (IOException e) {            String message = "Could not wrap servlet request with MultipartRequestWrapper!";            throw new ServletException(message, e);        }        return request;    }

?

核心的处理是dispatcher.wrapRequst

public HttpServletRequest wrapRequest(HttpServletRequest request, ServletContext servletContext) throws IOException {        // don't wrap more than once        if (request instanceof StrutsRequestWrapper) {            return request;        }        String content_type = request.getContentType();        if (content_type != null && content_type.contains("multipart/form-data")) {            MultiPartRequest mpr = null;            //check for alternate implementations of MultiPartRequest            Set<String> multiNames = getContainer().getInstanceNames(MultiPartRequest.class);            if (multiNames != null) {                for (String multiName : multiNames) {                    if (multiName.equals(multipartHandlerName)) {                        mpr = getContainer().getInstance(MultiPartRequest.class, multiName);                    }                }            }            if (mpr == null ) {                mpr = getContainer().getInstance(MultiPartRequest.class);            }            request = new MultiPartRequestWrapper(mpr, request, getSaveDir(servletContext));        } else {            request = new StrutsRequestWrapper(request);        }        return request;    }

?

?

首先是通过request获取getContentType

?String content_type = request.getContentType();

然后判断,如果请求中包含multipart/form-data

则创建一个MultiPartRequestWrapper,然后返回,否则创建一个通用的StrutsRequestWrapper

MultiPartRequestWrapper和StrutsRequestWrapper到底是什么关系?

通过源码可以看到,其实

MultiPartRequestWrapper本身继承自StrutsRequestWrapper,

它比StrutsRequestWrapper做了更多的事,就是文件上传的处理

?

public class MultiPartRequestWrapper extends StrutsRequestWrapper {    protected static final Logger LOG = LoggerFactory.getLogger(MultiPartRequestWrapper.class);    Collection<String> errors;    MultiPartRequest multi;    /**     * Process file downloads and log any errors.     *     * @param request Our HttpServletRequest object     * @param saveDir Target directory for any files that we save     * @param multiPartRequest Our MultiPartRequest object     */    public MultiPartRequestWrapper(MultiPartRequest multiPartRequest, HttpServletRequest request, String saveDir) {        super(request);                multi = multiPartRequest;        try {            multi.parse(request, saveDir);            for (Object o : multi.getErrors()) {                String error = (String) o;                addError(error);            }        } catch (IOException e) {            addError("Cannot parse request: "+e.toString());        }     }    /**     * Get an enumeration of the parameter names for uploaded files     *     * @return enumeration of parameter names for uploaded files     */    public Enumeration<String> getFileParameterNames() {        if (multi == null) {            return null;        }        return multi.getFileParameterNames();    }    /**     * Get an array of content encoding for the specified input field name or <tt>null</tt> if     * no content type was specified.     *     * @param name input field name     * @return an array of content encoding for the specified input field name     */    public String[] getContentTypes(String name) {        if (multi == null) {            return null;        }        return multi.getContentType(name);    }    /**     * Get a {@link java.io.File[]} for the given input field name.     *     * @param fieldName input field name     * @return a File[] object for files associated with the specified input field name     */    public File[] getFiles(String fieldName) {        if (multi == null) {            return null;        }        return multi.getFile(fieldName);    }    /**     * Get a String array of the file names for uploaded files     *     * @param fieldName Field to check for file names.     * @return a String[] of file names for uploaded files     */    public String[] getFileNames(String fieldName) {        if (multi == null) {            return null;        }        return multi.getFileNames(fieldName);    }    /**     * Get the filename(s) of the file(s) uploaded for the given input field name.     * Returns <tt>null</tt> if the file is not found.     *     * @param fieldName input field name     * @return the filename(s) of the file(s) uploaded for the given input field name or     *         <tt>null</tt> if name not found.     */    public String[] getFileSystemNames(String fieldName) {        if (multi == null) {            return null;        }        return multi.getFilesystemName(fieldName);    }    /**     * @see javax.servlet.http.HttpServletRequest#getParameter(String)     */    public String getParameter(String name) {        return ((multi == null) || (multi.getParameter(name) == null)) ? super.getParameter(name) : multi.getParameter(name);    }    /**     * @see javax.servlet.http.HttpServletRequest#getParameterMap()     */    public Map getParameterMap() {        Map<String, String[]> map = new HashMap<String, String[]>();        Enumeration enumeration = getParameterNames();        while (enumeration.hasMoreElements()) {            String name = (String) enumeration.nextElement();            map.put(name, this.getParameterValues(name));        }        return map;    }    /**     * @see javax.servlet.http.HttpServletRequest#getParameterNames()     */    public Enumeration getParameterNames() {        if (multi == null) {            return super.getParameterNames();        } else {            return mergeParams(multi.getParameterNames(), super.getParameterNames());        }    }    /**     * @see javax.servlet.http.HttpServletRequest#getParameterValues(String)     */    public String[] getParameterValues(String name) {        return ((multi == null) || (multi.getParameterValues(name) == null)) ? super.getParameterValues(name) : multi.getParameterValues(name);    }    /**     * Returns <tt>true</tt> if any errors occured when parsing the HTTP multipart request, <tt>false</tt> otherwise.     *     * @return <tt>true</tt> if any errors occured when parsing the HTTP multipart request, <tt>false</tt> otherwise.     */    public boolean hasErrors() {        return !((errors == null) || errors.isEmpty());    }    /**     * Returns a collection of any errors generated when parsing the multipart request.     *     * @return the error Collection.     */    public Collection<String> getErrors() {        return errors;    }    /**     * Adds an error message.     *     * @param anErrorMessage the error message to report.     */    protected void addError(String anErrorMessage) {        if (errors == null) {            errors = new ArrayList<String>();        }        errors.add(anErrorMessage);    }    /**     * Merges 2 enumeration of parameters as one.     *     * @param params1 the first enumeration.     * @param params2 the second enumeration.     * @return a single Enumeration of all elements from both Enumerations.     */    protected Enumeration mergeParams(Enumeration params1, Enumeration params2) {        Vector temp = new Vector();        while (params1.hasMoreElements()) {            temp.add(params1.nextElement());        }        while (params2.hasMoreElements()) {            temp.add(params2.nextElement());        }        return temp.elements();    }}

?

而StrutsRequestWrapper只有一个核心的方法就是getAttribute,

getAttribute的到底到哪里去取得值呢?

其实是到ValueStack中取值,我们所有的请求都被struts2添加到ValueStack中了。

 ValueStack stack = ctx.getValueStack();                        if (stack != null) {                            attribute = stack.findValue(s);                        }

?

回到MultiPartRequestWrapper中,

我们知道,当struts2处理文件上传时,支持多文件上传,而且只要在我们的 action中声明

File[] file,

String[] fileName即可,

原因是MultiPartRequest

是这个接口在搞鬼

?

public interface MultiPartRequest {    public void parse(HttpServletRequest request, String saveDir) throws IOException;        /**     * Returns an enumeration of the parameter names for uploaded files     *     * @return an enumeration of the parameter names for uploaded files     */    public Enumeration<String> getFileParameterNames();    /**     * Returns the content type(s) of the file(s) associated with the specified field name     * (as supplied by the client browser), or <tt>null</tt> if no files are associated with the     * given field name.     *     * @param fieldName input field name     * @return an array of content encoding for the specified input field name or <tt>null</tt> if     *         no content type was specified.     */    public String[] getContentType(String fieldName);    /**     * Returns a {@link java.io.File} object for the filename specified or <tt>null</tt> if no files     * are associated with the given field name.     *     * @param fieldName input field name     * @return a File[] object for files associated with the specified input field name     */    public File[] getFile(String fieldName);    /**     * Returns a String[] of file names for files associated with the specified input field name     *     * @param fieldName input field name     * @return a String[] of file names for files associated with the specified input field name     */    public String[] getFileNames(String fieldName);    /**     * Returns the file system name(s) of files associated with the given field name or     * <tt>null</tt> if no files are associated with the given field name.     *     * @param fieldName input field name     * @return the file system name(s) of files associated with the given field name     */    public String[] getFilesystemName(String fieldName);    /**     * Returns the specified request parameter.     *     * @param name the name of the parameter to get     * @return the parameter or <tt>null</tt> if it was not found.     */    public String getParameter(String name);    /**     * Returns an enumeration of String parameter names.     *     * @return an enumeration of String parameter names.     */    public Enumeration<String> getParameterNames();    /**     * Returns a list of all parameter values associated with a parameter name. If there is only     * one parameter value per name the resulting array will be of length 1.     *     * @param name the name of the parameter.     * @return an array of all values associated with the parameter name.     */    public String[] getParameterValues(String name);    /**     * Returns a list of error messages that may have occurred while processing the request.     * If there are no errors, an empty list is returned. If the underlying implementation     * (ie: pell, cos, jakarta, etc) cannot support providing these errors, an empty list is     * also returned. This list of errors is repoted back to the     * {@link MultiPartRequestWrapper}'s errors field.     *     * @return a list of Strings that represent various errors during parsing     */    public List getErrors();}

?

看了源码详细不用仔细说什么也能明白

?

这个类的实现类只有一个,那就是JakartaMultiPartRequest专门用来处理文件上传

我们看到它默认的属性

  protected Map<String,List<FileItem>> files = new HashMap<String,List<FileItem>>();    // maps parameter name -> List of param values    protected Map<String,List<String>> params = new HashMap<String,List<String>>();    // any errors while processing this request    protected List<String> errors = new ArrayList<String>();        protected long maxSize;

?

这就是我们的action中为什么实现文件上传是如此的容易,而且支持多文件上传。

当我们调用getFiles的时候,其实是调用JakartaMultiPartRequest中的getFile

?

 public File[] getFile(String fieldName) {        List<FileItem> items = files.get(fieldName);        if (items == null) {            return null;        }        List<File> fileList = new ArrayList<File>(items.size());        for (FileItem fileItem : items) {            File storeLocation = ((DiskFileItem) fileItem).getStoreLocation();            if(fileItem.isInMemory() && storeLocation!=null && !storeLocation.exists()) {                try {                    storeLocation.createNewFile();                } catch (IOException e) {                    if(LOG.isErrorEnabled()){                        LOG.error("Cannot write uploaded empty file to disk: " + storeLocation.getAbsolutePath(),e);                    }                }            }            fileList.add(storeLocation);        }        return fileList.toArray(new File[fileList.size()]);    }

?

这样把request就包装成strtus2的request了。可以处理普通请求和文件上传请求。

~~~~~~~~~~~~~~~~~

?

热点排行