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}" οnchange="fileTypeCheck()"></x:upload>就可以使用标签了

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

 

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

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

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
依赖的文件: tomahawk-1.1.3.jar commons-fileupload-1.2.jar commons-io-1.3.1.jar Tomahawk.tld 把这个三个包放在/WEB_INF/lib目录下面。Jsf依赖的包也放在这个目录下面 Tomahawk.tld放在/WEB-INF目录下。Jsf标签也放在这个目录下面。 这个主要讲jsf上传文件,因此只罗列了上传文件用到的包和标签。 Web-xml文件如下: <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd"> <web-app> <context-param> <param-name>javax.faces.STATE_SAVING_METHOD</param-name> <param-value>client</param-value> </context-param> <!-- Context Listener creates and sets the application handler --> <!-- Faces Servlet --> <servlet> <servlet-name>Faces Servlet</servlet-name> <servlet-class>javax.faces.webapp.FacesServlet</servlet-class> <load-on-startup>1</load-on-startup> </servlet> <!-- Faces Servlet Mapping --> <servlet-mapping> <servlet-name>Faces Servlet</servlet-name> <url-pattern>*.jsf</url-pattern> </servlet-mapping> <filter> <filter-name>ExtensionsFilter</filter-name> <filter-class> org.apache.myfaces.component.html.util.ExtensionsFilter </filter-class> <init-param> <param-name>uploadMaxFileSize</param-name> <param-value>10m</param-value> </init-param> <init-param> <param-name>uploadThresholdSize</param-name> <param-value>100k</param-value> </init-param> </filter> <filter-mapping> <filter-name>ExtensionsFilter</filter-name> <!—要和<servlet-mapping>中的<servlet-name>一致--> <servlet-name>Faces Servlet</servlet-name> </filter-mapping> <welcome-file-list> <welcome-file>index.html</welcome-file> </welcome-file-list> </web-app> 上传文件的页面如下: <%@ include file="tags.jsp"%> <f:view> <h:form id="MyForm" enctype="multipart/form-data" > <h:messages globalOnly="true" styleClass="message"/> <h:panelGrid columns="3" border="0" cellspacing="5"> <h:outputLabel for="myFileId" value="File: "/> <x:inputFileUpload id="myFileId" value="#{myBean.myFile}" storage="file" required="true"/> <h:message for="myFileId"/> <h:outputLabel for="myParamId" value="Param: "/> <h:selectOneMenu id="myParamId" value="#{myBean.myParam}" required="true"> <f:selectItem itemLabel="" itemValue=""/> <f:selectItem itemLabel="MD5" itemValue="MD5"/> <f:selectItem itemLabel="SHA-1" itemValue="SHA-1"/> <f:selectItem itemLabel="SHA-256" itemValue="SHA-256"/> <f:selectItem itemLabel="SHA-384" itemValue="SHA-384"/> <f:selectItem itemLabel="SHA-512" itemValue="SHA-512"/> </h:selectOneMenu> <h:message for="myParamId"/> <h:outputText value=" "/> <h:commandButton value="Submit" action="#{myBean.processMyFile}"/> <h:outputText value=" "/> </h:panelGrid> </h:form> </f:view> 其中tags.jsp文件如下: <%@ page language="java" pageEncoding="GB18030"%> <%@ page contentType="text/html" %> <%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %> <%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %> <%@ taglib uri="http://java.sun.com/jstl/core" prefix="c" %> <%@ taglib uri="http://myfaces.apache.org/tomahawk" prefix="x"%> Faces-config.xml文件如下: <faces-config> <managed-bean> <managed-bean-name>myBean</managed-bean-name> <managed-bean-class> fileupload.MyBean </managed-bean-class> <managed-bean-scope>request</managed-bean-scope> </managed-bean> </faces-config> MyBean如下: package com.dhc; import java.io.BufferedInputStream; import java.io.FileOutputStream; import java.io.InputStream; import javax.faces.application.FacesMessage; import javax.faces.context.FacesContext; import org.apache.myfaces.custom.fileupload.UploadedFile; public class oaMailMainForm { private UploadedFile myFile; public UploadedFile getMyFile() { return myFile; } public void setMyFile(UploadedFile myFile) { this.myFile = myFile; } public String uploadedfile() { System.out.println("Entry"); try { InputStream in = new BufferedInputStream(myFile.getInputStream()); try { byte[] buffer = new byte[64 * 1024]; FileOutputStream fileOutputStream = new FileOutputStream( "C:\\My Files\\tst.jpg");// 这里可以把上传的文件写服务器目录,或者数据库中 while (in.read(buffer) > 0) { fileOutputStream.write(buffer); } } finally { in.close(); } System.out.println("End"); return "success"; } catch (Exception x) { System.out.print("Exception"); FacesMessage message = new FacesMessage( FacesMessage.SEVERITY_FATAL, x.getClass().getName(), x .getMessage()); FacesContext.getCurrentInstance().addMessage(null, message); return null; } } } 参考文献:http://www.blogjava.net/cooky/archive/2007/10/02/150176.html http://blog.csdn.net/meteorlWJ/archive/2008/01/09/2032505.aspx http://tml808.javaeye.com/blog/166853
由于JSF2.0标准实现没有提供文件上传组件,而实际应用中很多时候需要上传文件,为了方便开发,我做了一个基于JSF2.0的文件上传组件上传使用的是Apache 的commons-fileupload组件,我已经将commons-fileupload-1.2.1.jar和commons-io-1.3.2.jar打包成一个lfaces.jar文件,使用时无需导入这两个jar文件,我使用的是Facelets技术,使用时很简单,导入命名空间后就可以使用标签(<l:inputFile/>)了,这个标签和<h:inputText/>标签使用方法一样,具体请参考例子。补充说明:是以临时文件存放在服务器上的,上传后需要自行处理,响应之前(JSF处理完毕)将会删除该临时文件,要设置上传的参数,比如文件存放目录,上传大小等,请在源目录(src)下建一个名为uploadfile.properties的文件,内容如下: #设置用于存放用户上传的文件夹,可以是绝对路径,例:C:/upload,也可是相对路径,例:/upload, #文件上传后是以.tmp为后缀的临时文件存储在服务器上,请求处理完成后系统将自动删除该临时文件,需要自行保存文件到需求的目录 uploadFile.path=E:/ #设置上传文件总大小的上限 uploadFile.sizeMax=1024*1024*50 #设置上传文件大小的上限 uploadFile.fileSizeMax=1024*1024*10 #设置缓存大小,如果文件大于缓存大小时,则先把文件放到缓存中 uploadFile.sizeThreshold=1024*1024 #设置上传文件类型 uploadFile.extFilter=.jpg|.jpeg|.gif|.bmp|.png|.xls|.doc|.txt
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值