`
韩悠悠
  • 浏览: 841866 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

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了。可以处理普通请求和文件上传请求。

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

 

分享到:
评论

相关推荐

    struts2.1.8 struts2源码 Eclipse关联这个可以

    在Eclipse中关联Struts2.1.8源码,可以帮助开发者更好地理解和调试代码。步骤包括: - 下载Struts2.1.8的源码包。 - 在Eclipse中,右键点击项目,选择"Build Path" -&gt; "Configure Build Path" -&gt; "Libraries" -&gt; ...

    struts框架的源码包

    struts源码包,解压后会有一个src文件夹,此文件夹下的就是struts的源码。

    孙卫琴struts源码.part1.rar

    孙卫琴 struts 源码 孙卫琴 struts 源码 孙卫琴 struts 源码

    struts源码struts源码struts源码

    通过深入研究Struts源码,我们可以了解到框架如何处理请求、执行业务逻辑以及如何将数据呈现给用户。这对于提升Java Web开发技能,理解MVC模式,以及进行性能优化都有着极大的帮助。同时,熟悉源码也有助于开发者更...

    struts2源码最新

    最新版的Struts2源码可以从GitHub的Apache官方仓库获取,这为我们提供了深入理解其内部工作原理和定制功能提供了可能。 Struts2的核心特性包括: 1. **Action与结果**:在Struts2中,业务逻辑处理主要由Action类...

    struts2 项目源码

    8. **OGNL(Object-Graph Navigation Language)**:Struts2使用OGNL作为默认表达式语言,用于在Action和视图之间传递数据。 9. **Struts2插件**:Struts2允许开发者通过插件扩展框架功能,例如国际化、上传下载等...

    struts2 源码分析

    Struts2 源码分析 Struts2 是一个基于MVC 模式的Web 应用程序框架,它的源码分析可以帮助我们更好地理解框架的内部机制和工作流程。下面是Struts2 源码分析的相关知识点: 1. Struts2 架构图 Struts2 的架构图...

    struts2 源码解读

    这篇博文“Struts2源码解读”深入剖析了Struts2的核心机制,帮助开发者更好地理解和利用这个框架。源码分析是提升编程技能和解决问题的关键,特别是对于复杂的框架如Struts2,理解其内部工作原理能够帮助我们优化...

    struts2框架源码

    深入理解Struts2的源码对于提升Java Web开发技能,尤其是在面试中讨论底层实现时,具有非常重要的价值。 首先,我们来看看Struts2的核心组件和设计理念: 1. **Action**:在Struts2中,Action类是业务逻辑处理的...

    struts2 源码

    8. **异常处理**: Struts2提供了一套完整的异常处理机制,包括全局异常映射和Action级别的异常处理。这使得开发者可以集中处理可能出现的错误,提高应用的健壮性。 9. **国际化(Internationalization, i18n)**: ...

    Struts2源码阅读

    通过阅读Struts2的源码,我们可以深入了解框架如何处理请求、如何调度Action以及如何应用拦截器来扩展功能。这有助于开发者更好地定制和优化他们的应用程序,提高代码质量和性能。在实际开发中,对源码的理解能帮助...

    struts2学习 源码

    本资料“struts2学习 源码”旨在帮助初学者理解Struts2的核心概念和工作原理,通过来自达内的详细代码实例来提供直观的学习体验。 Struts2框架的关键特性包括: 1. **动作(Action)**:在Struts2中,业务逻辑通常...

    struts-1.3.9 源码

    这里的"struts-1.3.9 源码"指的是Struts 1.x系列的第9次次要版本的源代码。Struts 1.3.9是在2008年发布的,它提供了许多增强和修复了之前版本中的问题,以提高框架的稳定性和安全性。 首先,我们来看看`LICENSE.txt...

    Struts2源码分析

    在深入理解Struts2的工作原理时,源码分析是必不可少的步骤。Struts2的核心设计理念和设计模式相比Struts1.x有了显著的变化,这使得它成为一个独立且成熟的框架。 首先,Struts2的架构基于WebWork的核心,这意味着...

    struts-1.2.9源码

    通过对Struts 1.2.9源码的深入学习,开发者可以了解Web应用的典型开发流程,掌握如何有效地组织和管理复杂的业务逻辑,以及如何优雅地处理用户交互。虽然Struts 1已逐渐被Struts 2和Spring MVC等更新框架替代,但它...

    STRUTS2源码解析

    STRUTS2源码解析STRUTS2源码解析STRUTS2源码解析STRUTS2源码解析STRUTS2源码解析STRUTS2源码解析STRUTS2源码解析STRUTS2源码解析STRUTS2源码解析STRUTS2源码解析STRUTS2源码解析STRUTS2源码解析STRUTS2源码解析...

    Struts 2的源码

    在深入理解Struts 2的源码之前,我们需要先了解其核心概念和组件。 1. **Action类与ActionMapping** Struts 2的核心是Action类,它是业务逻辑处理的中心。每个Action类对应一个用户请求,处理后返回一个Result。...

    struts2.0工程源码(完整的struts2.0学习工程源码)

    struts2.0工程源码(完整的struts2.0学习工程源码) 这是一个完整的工程源码,包括所用到的jar包和发布配置文件。 导入到eclipse里几个运行,struts2.0入门学习工程,适合struts2.0广大爱好者和初学者学习和交流。

    孙卫琴struts源码.part3.rar

    孙卫琴 struts 源码 孙卫琴 struts 源码 孙卫琴 struts 源码 103m

    struts2中的OGNL的源码

    通过深入学习OGNL的源码,开发者可以更好地定制和优化Struts2应用,提升性能,增强安全性,并能解决遇到的特定问题。这是一项值得投入时间和精力的任务,特别是对于那些希望在Web开发领域有深入理解的人来说。

Global site tag (gtag.js) - Google Analytics