在基于WebSphere JSF 1.2 Portlet Bridge的JSF Portlet中实现文件下载

7 篇文章 0 订阅
3 篇文章 0 订阅

本文讨论在基于WebSphere JSF 1.2 Portlet Bridge的JSF Portlet中实现文件下载。

JSR 286规范提供了一个基于resource serving的文件下载机制,但由于JSF 1.2 Portlet Bridge并没有提供相应的支持,所以必须在混合使用portlet和JSF来实现这个机制。

具体的实现包含三部分: 一个继承FacesPortlet并实现serveResource方法的portlet类, 一个显示下载链接的JSF页面, 以及一个提供文件内容的JSF managed bean。

portlet类

package demo;

import java.io.IOException;
import java.io.OutputStream;

import javax.el.ExpressionFactory;
import javax.el.ValueExpression;
import javax.faces.context.FacesContext;
import javax.faces.lifecycle.Lifecycle;
import javax.portlet.PortletException;
import javax.portlet.PortletSession;
import javax.portlet.ResourceRequest;
import javax.portlet.ResourceResponse;

import com.ibm.faces.portlet.FacesPortlet;
import com.ibm.faces.portlet.httpbridge.PortletRequestWrapper;
import com.ibm.faces.portlet.httpbridge.PortletResponseWrapper;
import com.ibm.faces.portlet.httpbridge.ResourceRequestWrapper;
import com.ibm.faces.portlet.httpbridge.ResourceResponseWrapper;

public class JSFPortlet extends FacesPortlet {

	@Override
	public void serveResource(ResourceRequest request, ResourceResponse response)
			throws PortletException, IOException {

		super.serveResource(request, response);

		TestBean testBean = (TestBean) getJSFManagedBean(
				request, response, TestBean.BEAN_NAME, TestBean.class);

		final OutputStream out = response.getPortletOutputStream();
		byte[] bytes = testBean.getCsv();
		response.setContentType("text/csv");
		response.setProperty("Content-Disposition",
				"attachment; filename=download.csv");
		response.setProperty("Content-length", String.valueOf(bytes.length));

		out.write(bytes);
		out.flush();
		out.close();
	}

	public Object getJSFManagedBean(ResourceRequest request,
			ResourceResponse response, String beanName, Class beanClass)
			throws PortletException {

		PortletSession portletSession = request.getPortletSession();

		Object jsfBean = (TestBean) portletSession.getAttribute(beanName);

		if (jsfBean == null) {
			PortletRequestWrapper requestWrapper = new ResourceRequestWrapper(
					request);
			requestWrapper.setPortletContext(getPortletContext());
			PortletResponseWrapper responseWrapper = new ResourceResponseWrapper(
					response);
			Lifecycle lifecycle = getLifecycle(requestWrapper);
			FacesContext context = getFacesContext(requestWrapper,
					responseWrapper, lifecycle);

			final ExpressionFactory expressionFactory = context
					.getApplication().getExpressionFactory();

			final ValueExpression valueExpression = expressionFactory
					.createValueExpression(context.getELContext(), 
							"#{" + beanName + "}", beanClass);
			jsfBean = (TestBean) valueExpression.getValue(context
					.getELContext());
		}

		return jsfBean;
	}
}

JSF页面

<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f"%>
<%@ taglib uri="http://java.sun.com/jsf/html" prefix="h"%>
<%@ taglib uri="http://java.sun.com/portlet_2_0" prefix="portlet"%>               
<%@taglib uri="http://www.ibm.com/xmlns/prod/websphere/portal/v6.1/portlet-client-model"   
       prefix="portlet-client-model" %>              
<%@ page language="java" contentType="text/html" pageEncoding="ISO-8859-1" session="false"%>
<portlet:defineObjects />
<portlet-client-model:init>
      <portlet-client-model:require module="ibm.portal.xml.*"/>
      <portlet-client-model:require module="ibm.portal.portlet.*"/>   
</portlet-client-model:init>  
 
       
<f:view>
  
  <portlet:resourceURL var="resourceUrl" >
	 <portlet:param name="action" value="csv" />
  </portlet:resourceURL>

  <a href="<%=resourceUrl%>">Download CSV</a>
  
</f:view>

JSF managed bean

package demo;

import java.util.Date;

public class TestBean {
	public static final String BEAN_NAME = "testBean";
	
	public byte[] getCsv() {
	    return new Date().toString().getBytes();
	  }
	
	public String getText() {
		return "Hello";
	}
}

开发中的一些发现:

- IBM JSF 1.2 Portlet Bridge没有提供portlet tag的对应Facelet taglib xml, 因此不能在基于Facelet的JSF页面中使用<portlet:resourceURL>。 这个问题已经在IBM JSF 2 Portlet Bridge中得到解决。

- <portlet:resourceURL> tag提供一个var属性, 可以用来定义一个变量来保存resource URL供页面上得其他代码使用。 JSR 286规范将该变量定义于JSP page scope中。 由于JSF无法访问JSP page scope, 因此页面上的JSF组件也无法使用该变量。

- 在传统的Servlet编程中,我们使用response.setHeader方法来设置HTTP response的头信息,包括Content-DispositionContent-length, 而在portlet中,我们使用ResourceResponse.setProperty方法。

-在portlet中可以通过两种方法来访问JSF managed beans, 如果要访问的JSF managed bean是一个session scope bean 且已存在于session只用, 那么可以使用portletSession.getAttribute(BEAN_NAME)来获取该bean, 否则的话, 就必须从FacesContext中使用JSF value expression表达式来创建和获取该bean。 由于IBM JSF 1.2 Portlet Bridge并没有提供一个直接的方法来获取FacesContext, 必须使用一些内部代码来实现该功能。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值