JSF自定义文件上传组件

 相信有很多使用JSF的人都和我一样比较青睐于SUN 的官方实现,但同时我们会遇到一些不方便,文件上传就是其中之一。当然我们可以选择其它实现如开源 myfaces甚至收费的实现richfaces。不过我们同样可以开发自己的组件,在这里我就以一个基于JSF1.2的文 件上传组件为例介绍jsf组件开发(其中我参考了jsf1.2和myfaces1.1的源代码,开源真是好啊)。

1、准备:

        先新建工程,如JSFX,并引入commons- fileupload.jar和commons-io.jar两个包(版本为1.2),源文件目录结构如下:

        

      

         jsf官方实现默认是不支持multipart/form -data类型的表单的,为了使jsf能够解析multipart/form-data表单的数据,我参考了myfaces1.1的方式,然 后按照commons-fileupload1.2重构了部分代码(myfaces1.1使用的是commons-fileupload1.1)

        myfaces之所以能处理multipart/form-data类型的 表单,关键就在于MultipartFilter和MultipartRequestWrapper这两个类,下面是我的代码:

MultipartFilter.java:

  1. package com.jsfx.filter;
  2. import java.io.IOException;
  3. import javax.servlet.Filter;
  4. import javax.servlet.FilterChain;
  5. import javax.servlet.FilterConfig;
  6. import javax.servlet.ServletException;
  7. import javax.servlet.ServletRequest;
  8. import javax.servlet.ServletResponse;
  9. import javax.servlet.http.HttpServletRequest;
  10. import javax.servlet.http.HttpServletResponse;
  11. import org.apache.commons.fileupload.servlet.ServletFileUpload;
  12. /**
  13.  * 用以解析multipart表单的过滤器
  14.  * 代码主要来自myFaces1.1的MultipartFilter类
  15.  * 主要区别是使用了commons-fileupload1.2处理文件上传
  16.  * */
  17. public class MultipartFilter implements Filter {
  18.     private int uploadMaxFileSize = 10 * 1024 * 1024// 默认文件最大大小为10 MB
  19.     private int uploadThresholdSize = 1 * 1024 * 1024// 默认临界值大小为1 MB(即超过1m的文件将使用缓存)
  20.     private String uploadRepositoryPath = null;//临时文件夹,默认为空,由虚拟机分配
  21.     public void init(FilterConfig filterConfig) {
  22.         uploadMaxFileSize = resolveSize(filterConfig
  23.                 .getInitParameter("uploadMaxFileSize"), uploadMaxFileSize);
  24.         uploadThresholdSize = resolveSize(filterConfig
  25.                 .getInitParameter("uploadThresholdSize"), uploadThresholdSize);
  26.         uploadRepositoryPath = filterConfig
  27.                 .getInitParameter("uploadRepositoryPath");
  28.     }
  29.     public void doFilter(ServletRequest request, ServletResponse response,
  30.             FilterChain chain) throws IOException, ServletException {
  31.         if (!(response instanceof HttpServletResponse)) {
  32.             chain.doFilter(request, response);
  33.             return;
  34.         }
  35.         HttpServletRequest httpRequest = (HttpServletRequest) request;
  36.         if (ServletFileUpload.isMultipartContent(httpRequest)) {//判断表单类型
  37.             chain.doFilter(new MultipartRequestWrapper(httpRequest,
  38.                     uploadMaxFileSize, uploadThresholdSize,
  39.                     uploadRepositoryPath), response);
  40.             //如果为multipart类型,对request进行包装,使jsf能解析表单数据
  41.         } else {
  42.             chain.doFilter(request, response);
  43.         }
  44.     }
  45.     public void destroy() {
  46.     }
  47.     private int resolveSize(String param, int defaultValue) {
  48.         int numberParam = defaultValue;
  49.         if (param != null) {
  50.             param = param.toLowerCase();
  51.             int factor = 1;
  52.             String number = param;
  53.             if (param.endsWith("g")) {
  54.                 factor = 1024 * 1024 * 1024;
  55.                 number = param.substring(0, param.length() - 1);
  56.             } else if (param.endsWith("m")) {
  57.                 factor = 1024 * 1024;
  58.                 number = param.substring(0, param.length() - 1);
  59.             } else if (param.endsWith("k")) {
  60.                 factor = 1024;
  61.                 number = param.substring(0, param.length() - 1);
  62.             }
  63.             numberParam = Integer.parseInt(number) * factor;
  64.         }
  65.         return numberParam;
  66.     }
  67. }

MultipartRequestWrapper.java

  1. package com.jsfx.filter;
  2. import java.io.File;
  3. import java.io.UnsupportedEncodingException;
  4. import java.util.Collections;
  5. import java.util.Enumeration;
  6. import java.util.HashMap;
  7. import java.util.Iterator;
  8. import java.util.List;
  9. import java.util.Map;
  10. import javax.faces.application.FacesMessage;
  11. import javax.faces.context.FacesContext;
  12. import javax.servlet.http.HttpServletRequest;
  13. import javax.servlet.http.HttpServletRequestWrapper;
  14. import org.apache.commons.fileupload.FileItem;
  15. import org.apache.commons.fileupload.FileUploadBase;
  16. import org.apache.commons.fileupload.FileUploadException;
  17. import org.apache.commons.fileupload.disk.DiskFileItemFactory;
  18. import org.apache.commons.fileupload.servlet.ServletFileUpload;
  19. /**
  20.  * Request的包装类,使jsf能解析表单数据 代码主要来自myFaces1.1的MultipartRequestWrapper类
  21.  * 主要区别是使用了commons-fileupload1.2处理文件上传
  22.  */
  23. @SuppressWarnings("unchecked")
  24. public class MultipartRequestWrapper extends HttpServletRequestWrapper {
  25.     public static final String UPLOADED_FILES_ATTRIBUTE = "org.apache.myfaces.uploadedFiles";
  26.     public static final String WWW_FORM_URLENCODED_TYPE = "application/x-www-form-urlencoded";
  27.     HttpServletRequest request = null;
  28.     HashMap parametersMap = null;// 参数表
  29.     ServletFileUpload fileUpload = null;
  30.     HashMap fileItems = null;// 上传文件表
  31.     int maxSize;// 表单最大大小
  32.     int thresholdSize;// 临界值大小
  33.     String repositoryPath;// 临时文件夹位置
  34.     public MultipartRequestWrapper(HttpServletRequest request, int maxSize,
  35.             int thresholdSize, String repositoryPath) {
  36.         super(request);
  37.         this.request = request;
  38.         this.maxSize = maxSize;
  39.         this.thresholdSize = thresholdSize;
  40.         this.repositoryPath = repositoryPath;
  41.     }
  42.     @Override
  43.     public Enumeration getParameterNames() {
  44.         if (parametersMap == null)
  45.             parseRequest();
  46.         return Collections.enumeration(parametersMap.keySet());
  47.     }
  48.     @Override
  49.     public String getParameter(String name) {
  50.         if (parametersMap == null)
  51.             parseRequest();
  52.         String[] values = (String[]) parametersMap.get(name);
  53.         if (values == null)
  54.             return null;
  55.         return values[0];
  56.     }
  57.     @Override
  58.     public String[] getParameterValues(String name) {
  59.         if (parametersMap == null)
  60.             parseRequest();
  61.         return (String[]) parametersMap.get(name);
  62.     }
  63.     @Override
  64.     public Map getParameterMap() {
  65.         if (parametersMap == null)
  66.             parseRequest();
  67.         return parametersMap;
  68.     }
  69.     /**
  70.      * 获取请求中的FileItem
  71.      */
  72.     public FileItem getFileItem(String fieldName) {
  73.         if (fileItems == null)
  74.             parseRequest();
  75.         return (FileItem) fileItems.get(fieldName);
  76.     }
  77.     /**
  78.      * 获取请求中的FileItem表
  79.      */
  80.     public Map getFileItems() {
  81.         if (fileItems == null)
  82.             parseRequest();
  83.         return fileItems;
  84.     }
  85.     @Override
  86.     public Object getAttribute(String string) {
  87.         if (string.equals(UPLOADED_FILES_ATTRIBUTE)) {
  88.             return getFileItems();
  89.         }
  90.         return super.getAttribute(string);
  91.     }
  92.     @Override
  93.     public String getContentType() {
  94.         return WWW_FORM_URLENCODED_TYPE;
  95.     }
  96.     /**
  97.      * 最关键的部分,解析表单数据
  98.      */
  99.     private void parseRequest() {
  100.         DiskFileItemFactory factory = new DiskFileItemFactory();
  101.         factory.setSizeThreshold(thresholdSize);// 设置临届大小
  102.         if (repositoryPath != null && repositoryPath.trim().length() > 0)
  103.             factory.setRepository(new File(repositoryPath));// 设置临时文件夹
  104.         fileUpload = new ServletFileUpload();
  105.         fileUpload.setFileItemFactory(factory);
  106.         fileUpload.setSizeMax(maxSize);// 设置表单最大大小
  107.         String charset = request.getCharacterEncoding();
  108.         fileUpload.setHeaderEncoding(charset);
  109.         List requestParameters = null;
  110.         try {
  111.             requestParameters = fileUpload.parseRequest(request);
  112.         } catch (FileUploadBase.SizeLimitExceededException e) {
  113.             e.printStackTrace();
  114.             FacesContext.getCurrentInstance().addMessage("",
  115.                     new FacesMessage(e.getMessage()));// 文件超过大小时提示用户
  116.             requestParameters = Collections.EMPTY_LIST;
  117.         } catch (FileUploadException fue) {
  118.             fue.printStackTrace();
  119.             FacesContext.getCurrentInstance().addMessage("",
  120.                     new FacesMessage(fue.getMessage()));
  121.             requestParameters = Collections.EMPTY_LIST;
  122.         }
  123.         parametersMap = new HashMap(requestParameters.size());// 建立参数表
  124.         fileItems = new HashMap();
  125.         for (Iterator iter = requestParameters.iterator(); iter.hasNext();) {
  126.             FileItem fileItem = (FileItem) iter.next();
  127.             if (fileItem.isFormField()) {// 普通参数处理
  128.                 String name = fileItem.getFieldName();
  129.                 String value = null;
  130.                 if (charset == null) {
  131.                     value = fileItem.getString();
  132.                 } else {
  133.                     try {
  134.                         value = new String(fileItem.get(), charset);
  135.                     } catch (UnsupportedEncodingException e) {
  136.                         value = fileItem.getString();
  137.                     }
  138.                 }
  139.                 addTextParameter(name, value);// 添加参数
  140.             } else {// 参数是一个文件
  141.                 if (fileItem.getName() != null) {
  142.                     fileItems.put(fileItem.getFieldName(), fileItem);// 添加Fileitem
  143.                 }
  144.             }
  145.         }
  146.         for (Iterator it = request.getParameterMap().entrySet().iterator(); it
  147.                 .hasNext();) {
  148.             Map.Entry entry = (Map.Entry) it.next();
  149.             Object value = entry.getValue();
  150.             if (value instanceof String[]) {
  151.                 String[] valuesArray = (String[]) entry.getValue();
  152.                 for (int i = 0; i < valuesArray.length; i++) {
  153.                     addTextParameter((String) entry.getKey(), valuesArray[i]);
  154.                 }
  155.             } else if (value instanceof String) {
  156.                 String strValue = (String) entry.getValue();
  157.                 addTextParameter((String) entry.getKey(), strValue);
  158.             } else if (value != null)
  159.                 throw new IllegalStateException("value of type : "
  160.                         + value.getClass() + " for key : " + entry.getKey()
  161.                         + " cannot be handled.");
  162.         }
  163.     }
  164.     private void addTextParameter(String name, String value) {
  165.         if (!parametersMap.containsKey(name)) {
  166.             String[] valuesArray = { value };
  167.             parametersMap.put(name, valuesArray);
  168.         } else {
  169.             String[] storedValues = (String[]) parametersMap.get(name);
  170.             int lengthSrc = storedValues.length;
  171.             String[] valuesArray = new String[lengthSrc + 1];
  172.             System.arraycopy(storedValues, 0, valuesArray, 0, lengthSrc);
  173.             valuesArray[lengthSrc] = value;
  174.             parametersMap.put(name, valuesArray);
  175.         }
  176.     }
  177. }

最后在web.xml配置过滤器,sun的jsf实现就可以处理 multipart/form-data表单了。

web.xml:

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
  3.     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4.     xsi:schemaLocation="http://java.sun.com/xml/ns/javaee   http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
  5.     <context-param>
  6.         <param-name>javax.faces.CONFIG_FILES</param-name>
  7.         <param-value>/WEB-INF/faces-config.xml</param-value>
  8.     </context-param>
  9.     <servlet>
  10.         <servlet-name>Faces Servlet</servlet-name>
  11.         <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
  12.         <load-on-startup>0</load-on-startup>
  13.     </servlet>
  14.     <servlet-mapping>
  15.         <servlet-name>Faces Servlet</servlet-name>
  16.         <url-pattern>*.faces</url-pattern>
  17.     </servlet-mapping>
  18.     <description>=====配置过滤器=====</description>
  19.     <filter>
  20.         <filter-name>MultipartFilter</filter-name>
  21.         <filter-class>com.jsfx.filter.MultipartFilter</filter-class>
  22.     </filter>
  23.     <filter-mapping>
  24.         <filter-name>MultipartFilter</filter-name>
  25.         <servlet-name>Faces Servlet</servlet-name>
  26.     </filter-mapping>
  27.     <description>==================</description>
  28.     <welcome-file-list>
  29.         <welcome-file>index.jsp</welcome-file>
  30.     </welcome-file-list>
  31. </web-app>

 

2、UploadedFile.java:作为标签的value存储上传文件相关属性的类。

  1. package com.jsfx.fileupload;
  2. import java.io.ByteArrayInputStream;
  3. import java.io.File;
  4. import java.io.IOException;
  5. import java.io.InputStream;
  6. import org.apache.commons.fileupload.FileItem;
  7. public class UploadedFile {
  8.     private String name;
  9.     private String contentType;
  10.     private FileItem fileItem;
  11.     public UploadedFile(FileItem fileItem) throws IOException {
  12.         this.name = fileItem.getName();
  13.         this.contentType = fileItem.getContentType();
  14.         this.fileItem = fileItem;
  15.     }
  16.     public void save(String file) {// 保存文件
  17.         try {
  18.             fileItem.write(new File(file));
  19.         } catch (Exception e) {
  20.             e.printStackTrace();
  21.         }
  22.     }
  23.     public byte[] getBytes() throws IOException {
  24.         byte[] bytes = new byte[(int) getSize()];
  25.         if (fileItem != null)
  26.             fileItem.getInputStream().read(bytes);
  27.         return bytes;
  28.     }
  29.     public InputStream getInputStream() throws IOException {
  30.         return fileItem != null ? fileItem.getInputStream()
  31.                 : new ByteArrayInputStream(new byte[0]);
  32.     }
  33.     public String getContentType() {
  34.         return contentType;
  35.     }
  36.     public String getName() {
  37.         return name;
  38.     }
  39.     public long getSize() {
  40.         return fileItem != null ? fileItem.getSize() : 0;
  41.     }
  42. }

UploadedFileConverter.java用来转化UploadedFile的类型

  1. package com.jsfx.fileupload;
  2. import javax.faces.component.UIComponent;
  3. import javax.faces.context.FacesContext;
  4. import javax.faces.convert.Converter;
  5. import javax.faces.convert.ConverterException;
  6. public class UploadedFileConverter implements Converter {
  7.     public Object getAsObject(FacesContext facescontext,
  8.             UIComponent uicomponent, String s) throws ConverterException {
  9.         return null;
  10.     }
  11.     public String getAsString(FacesContext facescontext,
  12.             UIComponent uicomponent, Object obj) throws ConverterException {
  13.         if (obj instanceof UploadedFile) {
  14.             return ((UploadedFile) obj).getName();
  15.         } else {
  16.             return null;
  17.         }
  18.     }
  19. }

3、实现标签描述库,这里使用的UploadTag类,下面将会提到

jsfx.tld(注意看它在上面项目中的位置

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <taglib version="2.1" xmlns="http://java.sun.com/xml/ns/javaee"
  3.     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4.     xsi:schemaLocation="http://java.sun.com/xml/ns/javaee web-jsptaglibrary_2_1.xsd">
  5.     <tlib-version>1.0</tlib-version>
  6.     <short-name>x</short-name>
  7.     <uri>http://jsfx.com/</uri>
  8.     <tag>
  9.         <name>upload</name>
  10.         <tag-class>com.jsfx.fileupload.UploadTag</tag-class>
  11.         <body-content>JSP</body-content>
  12.         <description>
  13.             为了简化开发只定义了几个必要和常用的属性如id,value,required,style,onchange等等
  14.         </description>
  15.         <attribute>
  16.             <name>id</name>
  17.             <rtexprvalue>true</rtexprvalue>
  18.         </attribute>
  19.         <attribute>
  20.             <name>value</name>
  21.             <rtexprvalue>false</rtexprvalue>
  22.             <deferred-value>
  23.                 <type>com.jsfx.fileupload.UploadedFile</type>
  24.             </deferred-value>
  25.         </attribute>
  26.         <attribute>
  27.             <name>converter</name>
  28.             <rtexprvalue>false</rtexprvalue>
  29.             <deferred-value>
  30.                 <type>com.jsfx.fileupload.UploadedFileConvert</type>
  31.             </deferred-value>
  32.         </attribute>
  33.         <attribute>
  34.             <name>required</name>
  35.             <rtexprvalue>false</rtexprvalue>
  36.             <deferred-value>
  37.                 <type>boolean</type>
  38.             </deferred-value>
  39.         </attribute>
  40.         <attribute>
  41.             <name>disabled</name>
  42.             <rtexprvalue>false</rtexprvalue>
  43.             <deferred-value>
  44.                 <type>boolean</type>
  45.             </deferred-value>
  46.         </attribute>
  47.         <attribute>
  48.             <name>readonly</name>
  49.             <rtexprvalue>false</rtexprvalue>
  50.             <deferred-value>
  51.                 <type>boolean</type>
  52.             </deferred-value>
  53.         </attribute>
  54.         <attribute>
  55.             <name>style</name>
  56.             <rtexprvalue>false</rtexprvalue>
  57.             <deferred-value>
  58.                 <type>java.lang.String</type>
  59.             </deferred-value>
  60.         </attribute>
  61.         <attribute>
  62.             <name>styleClass</name>
  63.             <rtexprvalue>false</rtexprvalue>
  64.             <deferred-value>
  65.                 <type>java.lang.String</type>
  66.             </deferred-value>
  67.         </attribute>
  68.         <attribute>
  69.             <name>onchange</name>
  70.             <required>false</required>
  71.             <deferred-value>
  72.                 <type>java.lang.String</type>
  73.             </deferred-value>
  74.         </attribute>
  75.     </tag>
  76. </taglib>

一个jsf自定义组件通常由

(1)标签属性处理类:主要作用是从页面标签接收值。继承至UIComponentELTag,这里与jsf1.1不同,由于使用了统一EL表 达式

(2)Component类:主要作用为在Server端保存及恢复组件状态。

(3)Renderer类: 主要功能是 在响应阶段将Java组件的属性转换为HTML代码,在接受请求阶段将HTML Request中传来的资料转换为Java组件的属性。

 

4、标签属性处理类:

UploadTag.java

  1. package com.jsfx.fileupload;
  2. import javax.faces.component.UIComponent;
  3. import javax.faces.context.FacesContext;
  4. import javax.faces.convert.Converter;
  5. import javax.faces.webapp.UIComponentELTag;
  6. import javax.servlet.jsp.JspException;
  7. public class UploadTag extends UIComponentELTag {
  8.     private javax.el.ValueExpression value;
  9.     private javax.el.ValueExpression converter;
  10.     private javax.el.ValueExpression styleClass;
  11.     private javax.el.ValueExpression disabled;
  12.     private javax.el.ValueExpression required;
  13.     private javax.el.ValueExpression style;
  14.     private javax.el.ValueExpression onchange;
  15.     @Override
  16.     public String getComponentType() {
  17.         return "HtmlUpload";//返回Component的类型,在faces-config.xml中找到相应的类
  18.     }
  19.     @Override
  20.     public String getRendererType() {
  21.         return "UploadRenderer";//返回Renderer的类型,在faces-config.xml中找到相应的类
  22.     }
  23.     public void setValue(javax.el.ValueExpression value) {
  24.         this.value = value;
  25.     }
  26.     public void setConverter(javax.el.ValueExpression converter) {
  27.         this.converter = converter;
  28.     }
  29.     public void setRequired(javax.el.ValueExpression required) {
  30.         this.required = required;
  31.     }
  32.     public void setDisabled(javax.el.ValueExpression disabled) {
  33.         this.disabled = disabled;
  34.     }
  35.     public void setStyle(javax.el.ValueExpression style) {
  36.         this.style = style;
  37.     }
  38.     public void setStyleClass(javax.el.ValueExpression styleClass) {
  39.         this.styleClass = styleClass;
  40.     }
  41.     public void setOnchange(javax.el.ValueExpression onchange) {
  42.         this.onchange = onchange;
  43.     }
  44.     @Override
  45.     protected void setProperties(UIComponent component) {
  46.         super.setProperties(component);
  47.         javax.faces.component.UIInput input = null;
  48.         try {
  49.             input = (javax.faces.component.UIInput) component;
  50.         } catch (ClassCastException cce) {
  51.             throw new IllegalStateException(
  52.                     "Component "
  53.                             + component.toString()
  54.                             + " not expected type.  Expected: javax.faces.component.UIInput.  Perhaps you're missing a tag?");
  55.         }
  56.         if (converter != null) {
  57.             if (!converter.isLiteralText()) {
  58.                 input.setValueExpression("converter", converter);
  59.             } else {
  60.                 Converter conv = FacesContext.getCurrentInstance()
  61.                         .getApplication().createConverter(
  62.                                 converter.getExpressionString());
  63.                 input.setConverter(conv);
  64.             }
  65.         }
  66.         if (value != null) {
  67.             input.setValueExpression("value", value);
  68.         }
  69.         if (required != null) {
  70.             input.setValueExpression("required", required);
  71.         }
  72.         if (disabled != null) {
  73.             input.setValueExpression("disabled", disabled);
  74.         }
  75.         if (style != null) {
  76.             input.setValueExpression("style", style);
  77.         }
  78.         if (styleClass != null) {
  79.             input.setValueExpression("styleClass", styleClass);
  80.         }
  81.         if (onchange != null) {
  82.             input.setValueExpression("onchange", onchange);
  83.         }
  84.     }
  85.     @Override
  86.     public int doStartTag() throws JspException {
  87.         try {
  88.             return super.doStartTag();
  89.         } catch (Exception e) {
  90.             Throwable root = e;
  91.             while (root.getCause() != null) {
  92.                 root = root.getCause();
  93.             }
  94.             throw new JspException(root);
  95.         }
  96.     }
  97.     @Override
  98.     public int doEndTag() throws JspException {
  99.         try {
  100.             return super.doEndTag();
  101.         } catch (Exception e) {
  102.             Throwable root = e;
  103.             while (root.getCause() != null) {
  104.                 root = root.getCause();
  105.             }
  106.             throw new JspException(root);
  107.         }
  108.     }
  109.     @Override
  110.     public void release() {
  111.         super.release();
  112.         this.value = null;
  113.         this.converter = null;
  114.         this.disabled = null;
  115.         this.style = null;
  116.         this.styleClass = null;
  117.         this.required = null;
  118.         this.onchange = null;
  119.     }
  120. }

5、Component类

HtmlUpload.java

  1. package com.jsfx.fileupload;
  2. import java.util.ArrayList;
  3. import java.util.List;
  4. import javax.el.ValueExpression;
  5. import javax.faces.component.UIInput;
  6. public class HtmlUpload extends UIInput {
  7.     private java.lang.Boolean disabled;
  8.     private java.lang.String style;
  9.     private java.lang.String styleClass;
  10.     private java.lang.String onchange;
  11.     public java.lang.String getOnchange() {
  12.         if (null != this.onchange) {
  13.             return this.onchange;
  14.         }
  15.         ValueExpression _ve = getValueExpression("onchange");
  16.         if (_ve != null) {
  17.             return (java.lang.String) _ve.getValue(getFacesContext()
  18.                     .getELContext());
  19.         } else {
  20.             return null;
  21.         }
  22.     }
  23.     public void setOnchange(java.lang.String onchange) {
  24.         this.onchange = onchange;
  25.         handleAttribute("onchange", onchange);
  26.     }
  27.     public boolean isDisabled() {
  28.         if (null != this.disabled) {
  29.             return this.disabled;
  30.         }
  31.         ValueExpression _ve = getValueExpression("disabled");
  32.         if (_ve != null) {
  33.             return (java.lang.Boolean) _ve.getValue(getFacesContext()
  34.                     .getELContext());
  35.         } else {
  36.             return false;
  37.         }
  38.     }
  39.     public void setDisabled(boolean disabled) {
  40.         this.disabled = disabled;
  41.     }
  42.     public java.lang.String getStyle() {
  43.         if (null != this.style) {
  44.             return this.style;
  45.         }
  46.         ValueExpression _ve = getValueExpression("style");
  47.         if (_ve != null) {
  48.             return (java.lang.String) _ve.getValue(getFacesContext()
  49.                     .getELContext());
  50.         } else {
  51.             return null;
  52.         }
  53.     }
  54.     public void setStyle(java.lang.String style) {
  55.         this.style = style;
  56.         handleAttribute("style", style);
  57.     }
  58.     public java.lang.String getStyleClass() {
  59.         if (null != this.styleClass) {
  60.             return this.styleClass;
  61.         }
  62.         ValueExpression _ve = getValueExpression("styleClass");
  63.         if (_ve != null) {
  64.             return (java.lang.String) _ve.getValue(getFacesContext()
  65.                     .getELContext());
  66.         } else {
  67.             return null;
  68.         }
  69.     }
  70.     public void setStyleClass(java.lang.String styleClass) {
  71.         this.styleClass = styleClass;
  72.     }
  73.     public HtmlUpload() {
  74.         super();
  75.         setRendererType("TestRenderer");
  76.     }
  77.     @SuppressWarnings("unchecked")
  78.     private void handleAttribute(String name, Object value) {
  79.         List<String> setAttributes = null;
  80.         setAttributes = (List<String>) this.getAttributes().get(
  81.                 "javax.faces.component.UIComponentBase.attributesThatAreSet");
  82.         if (setAttributes == null) {
  83.             setAttributes = new ArrayList<String>(6);
  84.             this
  85.                     .getAttributes()
  86.                     .put(
  87.                             "javax.faces.component.UIComponentBase.attributesThatAreSet",
  88.                             setAttributes);
  89.         }
  90.         if (value == null) {
  91.             setAttributes.remove(name);
  92.         } else if (!setAttributes.contains(name)) {
  93.             setAttributes.add(name);
  94.         }
  95.     }
  96. }

6、Renderer类

UploadRenderer.java

  1. package com.jsfx.fileupload;
  2. import java.io.IOException;
  3. import java.util.Map;
  4. import javax.faces.component.UIComponent;
  5. import javax.faces.context.ExternalContext;
  6. import javax.faces.context.FacesContext;
  7. import javax.faces.context.ResponseWriter;
  8. import javax.faces.convert.ConverterException;
  9. import javax.servlet.ServletRequest;
  10. import javax.servlet.http.HttpServletRequestWrapper;
  11. import org.apache.commons.fileupload.FileItem;
  12. import com.jsfx.filter.MultipartRequestWrapper;
  13. import com.sun.faces.renderkit.html_basic.HtmlBasicInputRenderer;
  14. public class UploadRenderer extends HtmlBasicInputRenderer {
  15.     
  16.     @Override
  17.     /**
  18.      * 生成<input: type=file/>的html标签
  19.      * */
  20.     protected void getEndTextToRender(FacesContext context,
  21.             UIComponent component, String currentValue) throws IOException {
  22.         String style = (String) component.getAttributes().get("style");
  23.         String styleClass = (String) component.getAttributes()
  24.                 .get("styleClass");
  25.         Boolean disabled = (Boolean) component.getAttributes().get("disabled");
  26.         String onchange = (String) component.getAttributes().get("onchange");
  27.         ResponseWriter writer = context.getResponseWriter();
  28.         assert (writer != null);
  29.         writer.startElement("input", component);
  30.         writeIdAttributeIfNecessary(context, writer, component);
  31.         writer.writeAttribute("type""file"null);
  32.         writer.writeAttribute("name", (component.getClientId(context)),
  33.                 "clientId");
  34.         if (currentValue != null) {
  35.             writer.writeAttribute("value", currentValue, "value");
  36.         }
  37.         if (null != styleClass) {
  38.             writer.writeAttribute("class", styleClass, "styleClass");
  39.         }
  40.         if (null != style) {
  41.             writer.writeAttribute("style", style, "style");
  42.         }
  43.         if (null != disabled) {
  44.             writer.writeAttribute("disabled", disabled, "disabled");
  45.         }
  46.         if (null != onchange) {
  47.             writer.writeAttribute("onchange", onchange, "onchange");
  48.         }
  49.         writer.endElement("input");
  50.     }
  51.     @Override
  52.     @SuppressWarnings("unchecked")
  53.     /**
  54.      * 这个方法将取出Request中的文件数据,并将提交的“value” uploadedFile实例化
  55.      * */
  56.     public void decode(FacesContext facesContext, UIComponent uiComponent) {
  57.         super.decode(facesContext, uiComponent);
  58.         Object request = facesContext.getExternalContext().getRequest();
  59.         if (!(request instanceof ServletRequest)) {
  60.             ExternalContext externalContext = facesContext.getExternalContext();
  61.             Map fileItems = (Map) externalContext.getRequestMap().get(
  62.                     MultipartRequestWrapper.UPLOADED_FILES_ATTRIBUTE);
  63.             FileItem fileItem = null;
  64.             if (fileItems != null) {
  65.                 String paramName = uiComponent.getClientId(facesContext);
  66.                 fileItem = (FileItem) fileItems.get(paramName);
  67.             }
  68.             if (fileItem != null) {
  69.                 try {
  70.                     UploadedFile upFile;
  71.                     upFile = new UploadedFile(fileItem);//实例化提交的value
  72.                     ((HtmlUpload) uiComponent).setSubmittedValue(upFile);
  73.                     ((HtmlUpload) uiComponent).setValid(true);
  74.                 } catch (IOException ioe) {
  75.                     ioe.printStackTrace();
  76.                 }
  77.             }
  78.             return;
  79.         }
  80.         if (facesContext.getExternalContext().getRequest() instanceof ServletRequest) {
  81.             ServletRequest multipartRequest = (ServletRequest) facesContext
  82.                     .getExternalContext().getRequest();
  83.             while (multipartRequest != null
  84.                     && !(multipartRequest instanceof MultipartRequestWrapper)) {
  85.                 if (multipartRequest instanceof HttpServletRequestWrapper) {
  86.                     multipartRequest = ((HttpServletRequestWrapper) multipartRequest)
  87.                             .getRequest();
  88.                 } else {
  89.                     multipartRequest = null;
  90.                 }
  91.             }
  92.             if (multipartRequest != null) {
  93.                 MultipartRequestWrapper mpReq = (MultipartRequestWrapper) multipartRequest;
  94.                 String paramName = uiComponent.getClientId(facesContext);
  95.                 FileItem fileItem = mpReq.getFileItem(paramName);
  96.                 if (fileItem != null) {
  97.                     try {
  98.                         UploadedFile upFile;
  99.                         upFile = new UploadedFile(fileItem);//实例化提交的value
  100.                         ((HtmlUpload) uiComponent).setSubmittedValue(upFile);
  101.                         ((HtmlUpload) uiComponent).setValid(true);
  102.                     } catch (IOException ioe) {
  103.                         ioe.printStackTrace();
  104.                     }
  105.                 }
  106.             }
  107.         }
  108.     }
  109.     @Override
  110.     public Object getConvertedValue(FacesContext context,
  111.             UIComponent component, Object submittedValue)
  112.             throws ConverterException {
  113.         if (submittedValue instanceof UploadedFile) {
  114.             UploadedFile file = (UploadedFile) submittedValue;
  115.             if (file.getName() != null && file.getName().length() > 0) {
  116.                 return file;
  117.             }
  118.         }
  119.         return null;
  120.     }
  121. }

7、整合

上面几个部分需要配置才能互相配合工作,这就需要UploadTag.java中的 getComponentType()、getRendererType()两个方法及配置文件。为了保证组件的独立性,我把faces-config.xml打包进了类的META-INF文件夹(见最上面项目的结构)。

faces-config.xml:

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <faces-config version="1.2" xmlns="http://java.sun.com/xml/ns/javaee"
  3.     xmlns:xi="http://www.w3.org/2001/XInclude"
  4.     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  5.     xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-facesconfig_1_2.xsd">
  6.     <component>
  7.         <component-type>HtmlUpload</component-type>
  8.         <component-class>
  9.             com.jsfx.fileupload.HtmlUpload
  10.         </component-class>
  11.     </component>
  12.     <render-kit>
  13.         <renderer>
  14.             <component-family>javax.faces.Input</component-family>
  15.             <renderer-type>UploadRenderer</renderer-type>
  16.             <renderer-class>
  17.                 com.jsfx.fileupload.UploadRenderer
  18.             </renderer-class>
  19.         </renderer>
  20.     </render-kit>
  21. </faces-config>

8、打包

只要按照上面的目录结构打包就可以保证组件的独立性了,只需要配置web.xml的过滤 器

然后在需要的页面引入标签:<%@ taglib uri="http://jsfx.com/" prefix="x"%>

就可以像这样<x:upload id="upload" value="#{user.picture}" onchange="fileTypeCheck()"></x:upload>就可以使用标签了

注意:最好用jdk5编译,用高版本的话可能会与jsf1.2有冲突。

 

本来有个使用样例的,在这里就不贴出来了,到这里可以下载,包括上面所有源代码。

http://download.csdn.net/source/637158

 

 

猜你喜欢

转载自blog.csdn.net/chch87/article/details/2949127