[EMAIL PROTECTED] writes:
> I've been reviewing how different people structure web-fired events in
>their servlets and how they use these events in their webapp architecture
>to
>handle the resulting view, integrating with JSP views, etc. What does
>everybody think? Anybody have any code to share so the rest of us can
>share
>in better event modelling? I think everyone could benefit from that. I
>did
>look in the archives (i say this since everyone seems to flame at the drop
>of a hat on this list) but didn't really find myself satisfied. So,
>anybody? anybody? bueller?
Personally, I've been developing pretty complex systems in the form of
servlets with external HTML template files, allowing me to have a very
clear separation between logic and rendering. The structure works
flawlessly for me, and it's the best solution I have encountered yet (and
I have worked with JSP solutions, HTML embedding in Java code, etc.).
Basically, I do all my HTML pages using a regular WYSISYG editor and save
them in a folder which the servlet can access. When dynamic data needs to
be inserted somewhere in the page, I simply type in a special tag
identifying the dynamic information. The concept is far from new, but I
needed a very fast and reliable way of using HTML templates with servlets,
something that doesn't come built-in... Being able to maintain my dynamic
Web pages using a regular HTML editor while developing the system core as
a servlet has become invaluable to me in all my Web projects.
Here's what one of my HTML templates would look like :
<HTML><BODY>
Your name is @-(username)-@, ok?
Oh and your password is probably @-(password)-@.
</BODY></HTML>
This way, the entire visual aspect of the system can be maintained by Web
designers, while the core logic is maintained by Java programmers who
don't like HTML ;-)
Btw, if you're wondering, I have chosen these tag delimiters ("@-(" and
")-@") because they can be inserted in any WYSIWIG application I know of
without bad consequences -- if I were to immitate HTML tags (<tag>), many
HTML editors would give me trouble when trying to insert one of my dynamic
tags inside an HTML tag, something I need to do quite often. The
character sequence also provides a way of finding tags very quickly, and
pretty much insuring that some HTML code or content cannot be mistaken for
a dynamic tag.
The key to speed here is the way each dynamic page is assembled when a
user sends a request. Before serving requests (at initialization time),
the servlet declares all tags used in its related HTML pages; each tag is
defined with an object (HTMLTag) whose behavior is customized to compute
an appropriate dynamic value. All HTMLTag objects are indexed in an
Hashtable, providing instant access by tag name when assembling.
Each dynamic page is loaded in memory by the servlet the first time each
page is requested. To hold the page, the servlet creates an HTMLTemplate
object, instanciated from a class I have designed (see code below). The
HTMLTemplate class is reponsible for reading HTML files from disk, making
sure that always the latest version of the files are in memory,
disassembling them into pre-processed templates, caching them in memory
for fast re-use, and assembling final HTML pages with real live data.
Something to keep in mind though is that this class is designed to be very
fast and efficient at assembly time (every time a dynamic page is returned
to a user). That's why the HTMLTemplate objects puts so much efforts in
disassembling the page the first time it reads it. But when a template is
cached, the only thing to do when a user makes a request is to call up the
assemble() method of a template, which assembles the dynamic page in a
flash. I have spent a number of hours testing and timing a wide range of
HTML page parsing techniques, and this disassembling-reassembling process
is the fastest and most efficient I have found yet.
The assembly process is fairly simple :
- create a StringBuffer at least as big as the original template (to avoid
unnecessary reallocation)
- loop over the parts array (parts[0]:html, parts[1]:tag, parts[2]:html,
parts[3]:tag, ...),
- if a part is HTML code (even), simply append it to the buffer
- if a part is a tag name (odd), get its HTMLTag object by name, call its
get() method and append the result to the buffer
- return the StringBuffer's String representation (toString())
There are probably a number of solutions for parsing HTML templates out
there, but I didn't do very extensive research on the subject. I prefer
to develop my own classes for this kind of thing, as it gives me more
control over every aspect of the process, and because it facilitates
portability.
I have just written a VERY simplified version of my HTMLTemplate class for
demonstration purposes (and to avoid copyright issues in my own company).
There might be some typos in there, I just typed this in my mail software,
so it's not been validated by a Java compiler. There are also some
"<insert code here>" and "... some code ... " statements here and there,
but pretty much anyone can fill-in the blanks if they want to.
Please don't hesitate to comment on this, or ask questions if it isn't
clear...
public class HTMLTemplate {
/* STATIC STUFF */
public static Hashtable tags;
public static Hashtable cache = new Hashtable();
public static synchronized void initialize() {
if (tags != null) {return;}
tags = new Hashtable();
registerTag(new HTMLTag("username") {public String get() {
return ... <insert code that returns a value here> ...;
}});
registerTag(new HTMLTag("password") {public String get() {
return ... <insert code that returns a value here> ...;
}});
}
public static void registerTag(HTMLTag tag) {
tags.put(tag.name,tag);
}
public static void registerTemplate(HTMLTemplate template) {
templates.put(template.filePath,template);
}
public static String html(String templatePath) {
HTMLTemplate template = templates.get(templatePath)==null?new
HTMLTemplate(file):templates.get(templatePath);
return template.assemble();
}
/* INSTANCE STUFF */
public String filePath;
public String[] parts;
public int initialTemplateSize;
public HTMLTemplate(File templatePath) {
if (tags == null) {HTMLTemplate .initialize();}
filePath = templatePath;
String content = read(new File(filePath));
parts = disassemble(content);
HTMLTemplate.registerTemplate(this);
}
public String read(File file) {
/* ... some code here that reads a file and returns the content as a
String ... */
initialTemplateSize = (int)file.length();
}
public String[] disassemble(String content) {
/*
... some code here that takes apart the content and returns a
String[]
array...
- array[0] : html code
- array[1] : first tag name
- array[2] : html code
- array[3] : second tag name
and so on...
*/
}
public String assemble() {
StringBuffer buf = new StringBuffer(initialTemplateSize);
boolean isTag = false;
for (int i = 0;i < parts.length;i++) {
if (isTag) {
HTMLTag tag = (HTMLTag)tags.get(parts[i]);
if (tag!=null) {buf.append(tag.get());}
} else {
buf.append(parts[i]);
}
isTag = !isTag;
}
}
public class HTMLTag {
public String name;
public HTMLTag(String name) {
this.name = name;
}
public String get() {
return "";
}
}
}
Sylvain Pedneault , technical supervisor
AQUOPS , 7400, boul. Saint-Laurent, bur. 528 Montr�al, QC H2R 2Y1
T�l�phone: (514) 948-1234 p.232 - T�l�copieur: (514) 948-1231
Courriel: [EMAIL PROTECTED] - Web:
www.aquops.qc.ca
___________________________________________________________________________
To unsubscribe, send email to [EMAIL PROTECTED] and include in the body
of the message "signoff SERVLET-INTEREST".
Archives: http://archives.java.sun.com/archives/servlet-interest.html
Resources: http://java.sun.com/products/servlet/external-resources.html
LISTSERV Help: http://www.lsoft.com/manuals/user/user.html