WebWork标签非常出色,在有些应用中,可能不想使用其环境,但希望能够使用其标签思路。JSP模板的使用面更广,随简化WebWork方式,提供思路供大家参考。
1、开发标签基础类:
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.RandomAccessFile;
import java.io.Writer;
import java.util.Iterator;
import java.util.LinkedList;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.ServletRequest;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpServletResponseWrapper;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.tagext.BodyTagSupport;
public abstract class AbstractTag extends BodyTagSupport {
protected String templateName ;
private final static String templatePath = "/WEB-INF/tags/";
private static final long serialVersionUID = -1201668454354226175L;
public String getTemplateName() {
return templateName;
}
public void setTemplateName(String templateName) {
this.templateName = templateName;
}
protected String getBody() {
if (bodyContent == null) {
return "";
} else {
return bodyContent.getString().trim();
}
}
protected abstract void prepareData ();
public int doEndTag() throws JspException {
try {
prepareData ();
include(templatePath + this.getTemplateName(), pageContext.getOut(),
pageContext.getRequest(),
(HttpServletResponse)
pageContext.getResponse());
} catch (Exception e) {
// e.printStackTrace();
throw new JspException(e);
}
return EVAL_BODY_INCLUDE;
}
public int doStartTag() throws JspException {
try {
pageContext.getOut().write(getBody());
} catch (IOException e) {
throw new RuntimeException("IOError: " + e.getMessage(), e);
}
return EVAL_PAGE;
}
public static void include(String aResult, Writer writer,ServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
String resourcePath = aResult;
RequestDispatcher rd = request.getRequestDispatcher(resourcePath);
if (rd == null) {
throw new ServletException("Not a valid resource path:"
+ resourcePath);
}
// Include the resource
PageResponse pageResponse = new PageResponse(response);
// Include the resource
rd.include((HttpServletRequest) request, pageResponse);
// write the response back to the JspWriter, using the correct encoding.
String encoding = "GB2312";
if (encoding != null) {
// use the encoding specified in the property file
pageResponse.getContent().writeTo(writer, encoding);
} else {
// use the platform specific encoding
pageResponse.getContent().writeTo(writer, null);
}
}
static final class PageResponse extends HttpServletResponseWrapper {
protected PrintWriter pagePrintWriter;
protected ServletOutputStream outputStream;
private PageOutputStream pageOutputStream = null;
/**
* Create PageResponse wrapped around an existing HttpServletResponse.
*/
public PageResponse(HttpServletResponse response) {
super(response);
}
/**
* Return the content buffered inside the {@link PageOutputStream}.
*
* @return
* @throws IOException
*/
public FastByteArrayOutputStream getContent() throws IOException {
// if we are using a writer, we need to flush the
// data to the underlying outputstream.
// most containers do this - but it seems Jetty 4.0.5 doesn't
if (pagePrintWriter != null) {
pagePrintWriter.flush();
}
return ((PageOutputStream) getOutputStream()).getBuffer();
}
/**
* Return instance of {@link PageOutputStream} allowing all data written
* to stream to be stored in temporary buffer.
*/
public ServletOutputStream getOutputStream() throws IOException {
if (pageOutputStream == null) {
pageOutputStream = new PageOutputStream();
}
return pageOutputStream;
}
/**
* Return PrintWriter wrapper around PageOutputStream.
*/
public PrintWriter getWriter() throws IOException {
if (pagePrintWriter == null) {
pagePrintWriter = new PrintWriter(new
OutputStreamWriter(
getOutputStream(), getCharacterEncoding()));
}
return pagePrintWriter;
}
}
static final class PageOutputStream extends ServletOutputStream {
private FastByteArrayOutputStream buffer;
public PageOutputStream() {
buffer = new FastByteArrayOutputStream();
}
/**
* Return all data that has been written to this OutputStream.
*/
public FastByteArrayOutputStream getBuffer() throws IOException {
flush();
return buffer;
}
public void close() throws IOException {
buffer.close();
}
public void flush() throws IOException {
buffer.flush();
}
public void write(byte[] b, int o, int l) throws IOException {
buffer.write(b, o, l);
}
public void write(int i) throws IOException {
buffer.write(i);
}
public void write(byte[] b) throws IOException {
buffer.write(b);
}
}
static public class FastByteArrayOutputStream extends OutputStream {
// Static --------------------------------------------------------
private static final int DEFAULT_BLOCK_SIZE = 8192;
private LinkedList buffers;
// Attributes ----------------------------------------------------
// internal buffer
private byte[] buffer;
// is the stream closed?
private boolean closed;
private int blockSize;
private int index;
private int size;
// Constructors --------------------------------------------------
public FastByteArrayOutputStream() {
this(DEFAULT_BLOCK_SIZE);
}
public FastByteArrayOutputStream(int aSize) {
blockSize = aSize;
buffer = new byte[blockSize];
}
public int getSize() {
return size + index;
}
public void close() {
closed = true;
}
public byte[] toByteArray() {
byte[] data = new byte[getSize()];
// Check if we have a list of buffers
int pos = 0;
if (buffers != null) {
Iterator iter = buffers.iterator();
while (iter.hasNext()) {
byte[] bytes = (byte[]) iter.next();
System.arraycopy(bytes, 0, data, pos, blockSize);
pos += blockSize;
}
}
// write the internal buffer directly
System.arraycopy(buffer, 0, data, pos, index);
return data;
}
public String toString() {
return new String(toByteArray());
}
// OutputStream overrides ----------------------------------------
public void write(int datum) throws IOException {
if (closed) {
throw new IOException("Stream closed");
} else {
if (index == blockSize) {
addBuffer();
}
// store the byte
buffer[index++] = (byte) datum;
}
}
public void write(byte[] data, int offset, int length) throws IOException {
if (data == null) {
throw new NullPointerException();
} else if
((offset < 0) || ((offset + length) > data.length) || (length
< 0)) {
throw new IndexOutOfBoundsException();
} else if (closed) {
throw new IOException("Stream closed");
} else {
if ((index + length) > blockSize) {
int copyLength;
do {
if (index == blockSize) {
addBuffer();
}
copyLength = blockSize - index;
if (length < copyLength) {
copyLength = length;
}
System.arraycopy(data, offset, buffer, index, copyLength);
offset += copyLength;
index += copyLength;
length -= copyLength;
} while (length > 0);
} else {
// Copy in the subarray
System.arraycopy(data, offset, buffer, index, length);
index += length;
}
}
}
// Public
public void writeTo(OutputStream out) throws IOException {
// Check if we have a list of buffers
if (buffers != null) {
Iterator iter = buffers.iterator();
while (iter.hasNext()) {
byte[] bytes = (byte[]) iter.next();
out.write(bytes, 0, blockSize);
}
}
// write the internal buffer directly
out.write(buffer, 0, index);
}
public void writeTo(RandomAccessFile out) throws IOException {
// Check if we have a list of buffers
if (buffers != null) {
Iterator iter = buffers.iterator();
while (iter.hasNext()) {
byte[] bytes = (byte[]) iter.next();
out.write(bytes, 0, blockSize);
}
}
// write the internal buffer directly
out.write(buffer, 0, index);
}
public void writeTo(Writer out, String encoding) throws IOException {
// Check if we have a list of buffers
if (buffers != null) {
Iterator iter = buffers.iterator();
while (iter.hasNext()) {
byte[] bytes = (byte[]) iter.next();
if (encoding != null) {
out.write(new String(bytes, encoding));
} else {
out.write(new String(bytes));
}
}
}
// write the internal buffer directly
if (encoding != null) {
out.write(new String(buffer, 0, index, encoding));
} else {
out.write(new String(buffer, 0, index));
}
}
/**
* Create a new buffer and store the
* current one in linked list
*/
protected void addBuffer() {
if (buffers == null) {
buffers = new LinkedList();
}
buffers.addLast(buffer);
buffer = new byte[blockSize];
size += index;
index = 0;
}
}
}
2、定义一个具体的标签类
public class ListTag extends RiseAbstractTag {
private static final long serialVersionUID = 3385568988234498913L;
protected String templateName = "list.jsp";
private String id;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
protected void prepareData() {
this.setTemplateName(this.templateName);
pageContext.getRequest().setAttribute("id", this.id);
}
}
3、定义TLD文件
参考TLD文档
4、定义list.jsp模板
<%@ page contentType="text/html; charset=GBK" %>
<%
String id = (String)request.getAttribute("id");
%>
<table width="90%" border="0" cellpadding="0" cellspacing="2">
<tr>
<td>Id</td>
<td align="right"><%= id %></td>
</tr>
</table>
5、使用默认模板
<WWTag:list id="Hello World!"/>
6、使用自定义模板
a: 定义模板
<%@ page contentType="text/html; charset=GBK" %>
<%
String id = (String)request.getAttribute("id");
out.println("Id is : " + id);
%>
b: use it , 模板名:testList.jsp,放在/WEB-INF/tags目录下
<WWTag:list id="Hello World!" templateName="testList.jsp"/>