項目實例改編:利用structs2的action 實時顯示圖片、pdf和其他內容的框架抽取。
重點:
- structs2的action的配置
- action的寫法和結果類型
- resulttype的寫法
- 網頁上實時顯示
1 structs2的action的配置
首先在package的標籤中加入自定義的結果類型<result-types>的名字displayResult,以及後面提到的自定義類DisplayFileResult,雖然不配置也不影響用戶體驗,但 structs默認的結果類型沒有直接適合的,例如使用stream會打印結果異常,如果不想異常,就在代碼中不要調用inputStream的close方法。
<package name="file" extends="structs-default">
......
<result-types>
<result-type name="displayResult"
class="ssc.net.cn.ecp.portal.bl.file.result.DisplayFileResult" />
</result-types>
......
</package>
在 <result-types>後配置圖片資源的action。見 <action name="showImageContent" > ,在成功結果類型的type屬性上加上displayResult
<package name="file" extends="structs-default">
......
<result-types>
<result-type name="displayResult"
class="ssc.net.cn.ecp.portal.bl.file.result.DisplayFileResult" />
</result-types>
<action name="showImageContent"
class="ssc.net.cn.ecp.portal.bl.file.action.ShowFileContent" method="showImage">
<result name="success" type="displayResult">
</result>
<result name="error" />
</action>
<action name="showPdfContent"
class="ssc.net.cn.ecp.portal.bl.file.action.ShowFileContent" method="showPdf">
<result name="success" type="displayResult">
</result>
<result name="error"/>
</action>
.
</package>
2 action的寫法和結果類型。
此處給出一個框架式的寫法,加入最少兩個方法getInputStream()和getContentType(),供DisplayFileResult類使用。
import org.apache.struts2.ServletActionContext;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionSupport;
public class ShowFileContent extends ActionSupport {
private InputStream inputStream;
public InputStream getInputStream() {
return inputStream;
}
public void setInputStream(InputStream inputStream) {
this.inputStream = inputStream;
}
private String contentType;
public String getContentType() {
return contentType;
}
public void setContentType(String contentType) {
this.contentType = contentType;
}
public String showImage() {
try {
HttpServletRequest request = (HttpServletRequest) ActionContext.getContext().get(ServletActionContext.HTTP_REQUEST);
String filePath = request.getParameter("filepath");
this.setInputStream(new java.io.FileInputSteam(filePath));
this.setContentType("image/png");
}
catch (IOException e) {
return ERROR
}
return SUCCESS;
}
public String showPdf() {
try {
HttpServletRequest request= (HttpServletRequest) ActionContext.getContext().get(ServletActionContext.HTTP_REQUEST);
String filePath = request.getParameter("filepath");
this.setInputStream(new java.io.FileInputSteam(filePath));
this.setContentType("application/pdf");
}
catch (IOException e){
return ERROR
}
return SUCCESS;
}
}
3 result type的寫法
調用response相關方法,把輸出流轉換爲資源方式。在這裏,我再老生長談一句話:一定要切記關閉流,如果不關閉流,在打開過多流後操作系統(Linux)會報類似“too many open files”之類的錯誤,導致無法訪問文件。
package ssc.net.cn.ecp.portal.bl.file.result;
import java.io.IOException;
import javax.servlet.http.HttpServletResponse;
import org.apache.struts2.ServletActionContext;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.Result;
public class DisplayFileResult implements Result {
private static final long serialVersionUID = 4897546905647587338L;
private HttpServletResponse response;
ShowFileContent action;
public void execute(ActionInvocation invocation) throws Exception {
init(invocation);
writeResponseOutputStream();
}
private void init(ActionInvocation invocation) {
action = (ShowFileContent) invocation.getAction();
response = ServletActionContext.getResponse();
response.setContentType(action.getContentType());
}
private void writeResponseOutputStream() {
java.io.InputStream is = action.getInputStream();
java.io.BufferedInputStream bi = null;
if (is == null) {
return;
}
try {
bi = new java.io.BufferedInputStream(is);
byte[] bytearray = new byte[1024];
int size = 0;
while ((size = bi.read(bytearray)) != -1) {
response.getOutputStream().write(bytearray, 0, size);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
response.flushBuffer();
} catch (IOException e) {
e.printStackTrace();
}
try {
bi.close();
} catch (IOException e) {
e.printStackTrace();
}
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
4 網頁上實時顯示。
給個顯示圖片的例子:實時顯示圖片,參數需要加入new date(), 瀏覽器就會認爲是一個新的圖片地址,而不會調用瀏覽器緩存顯示圖片。
<img src="showImageContent.action?filepath=mypic.gif‘&date="+String(new date()) />
給個pdf顯示的例子:
<iframe src="showPdfContent.action?filepath=mypic.gif‘&date="+String(new date()) />
後續改進:
通過重寫資源過濾器對資源進行壓縮和解壓縮。
( 作者注:交流環境靠大家,如果您覺得對您有幫助或您有改進建議,請給予寶貴的評論,以勉勵作者。)
效果如下: