Velocity 的应用示例

类别:Java 点击:0 评论:0 推荐:

Velocity 的应用示例

 关键字:Java, JSP, Servlet, template, 模板, Apache, Jakarta, Velocity
读者要求:了解 Java Servlet 基本概念

 Velocity 是一个基于 Java 的通用模板工具,来自于 jakarta.apache.org 。

Velocity 的介绍请参考 Velocity -- Java Web 开发新技术。这里是它的一个应用示例。

这个例子参照了 PHP-Nuke 的结构, 即所有 HTTP 请求都以 http://www.some.com/xxx/Modules?name=xxx&arg1=xxx&bbb=xxx 的形式进行处理。例子中所有文件都是 .java 和 .html , 没有其他特殊的文件格式。除了 Modules.java 是 Java Servlet, 其余的 .java 文件都是普通的 Java Class.

所有 HTTP 请求都通过 Modules.java 处理。Modules.java 通过 Velocity 加载 Modules.htm。 Modules.htm 有页头,页脚,页左导航链接,页中内容几个部分。其中页头广告、页中内容是变化部分。页头广告由 Modules.java 处理,页中内容部分由 Modules.java dispatch 到子页面类处理。

1) Modules.java

    

import javax.servlet.*; import javax.servlet.http.*; import org.apache.velocity.*; import org.apache.velocity.context.*; import org.apache.velocity.exception.*; import org.apache.velocity.servlet.*; import commontools.*; public class Modules   extends VelocityServlet {   public Template handleRequest(HttpServletRequest request,                  HttpServletResponse response,                  Context context) {     //init     response.setContentType("text/html; charset=UTF-8");     response.setCharacterEncoding("utf-8");     //prepare function page     ProcessSubPage page = null;     ProcessSubPage mainPage = new HomeSubPage();     String requestFunctionName = (String) request.getParameter("name");     boolean logined = false;     String loginaccount = (String) request.getSession(true).getAttribute(       "loginaccount");     if (loginaccount != null) {       logined = true;     }     //default page is mainpage     page = mainPage;     if (requestFunctionName == null||requestFunctionName.equalsIgnoreCase("home")) {       page = mainPage;     }     //no login , can use these page     else if (requestFunctionName.equalsIgnoreCase("login")) {       page = new LoginProcessSubPage();     }     else if (requestFunctionName.equalsIgnoreCase("ChangePassword")) {       page = new ChangePasswordSubPage();     }     else if (requestFunctionName.equalsIgnoreCase("ForgetPassword")) {       page = new ForgetPassword();     }     else if (requestFunctionName.equalsIgnoreCase("about")) {       page = new AboutSubPage();     }     else if (requestFunctionName.equalsIgnoreCase("contact")) {       page = new ContactSubPage();     }     //for other page, need login first     else if (logined == false) {       page = new LoginProcessSubPage();     }     else if (requestFunctionName.equalsIgnoreCase("listProgram")) {       page = new ListTransactionProgramSubPage();     }     else if (requestFunctionName.equalsIgnoreCase(       "ViewProgramItem")) {       page = new ViewTransactionProgramItemSubPage();     }     else if (requestFunctionName.equalsIgnoreCase(       "UpdateProgramObjStatus")) {       page = new UpdateTransactionProgramObjStatusSubPage();     }     else if (requestFunctionName.equalsIgnoreCase(       "Search")) {       page = new SearchSubPage();     }     //check if this is administrator     else if (Utilities.isAdministratorLogined(request)) {       //Utilities.debugPrintln("isAdministratorLogined : true");       if (requestFunctionName.equalsIgnoreCase("usermanagement")) {         page = new UserManagementSubPage();       }       else if (requestFunctionName.equalsIgnoreCase(         "UploadFiles")) {         page = new UploadFilesSubPage();       }       else if (requestFunctionName.equalsIgnoreCase(         "DownloadFile")) {         page = new DownloadFileSubPage();       }       else if (requestFunctionName.equalsIgnoreCase(         "Report")) {         page = new ReportSubPage();       }     }     else {       //no right to access.       //Utilities.debugPrintln("isAdministratorLogined : false");       page = null;     }     //Utilities.debugPrintln("page : " + page.getClass().getName());     if(page != null){       context.put("function_page",             page.getHtml(this, request, response, context));     }else{       String msg = "Sorry, this module is for administrator only.
You are not administrator.
";       context.put("function_page",msg);     }          context.put("page_header",getPageHeaderHTML());     context.put("page_footer",getPageFooterHTML());     Template template = null;     try {       template = getTemplate("/templates/Modules.htm"); //good     }     catch (ResourceNotFoundException rnfe) {       Utilities.debugPrintln("ResourceNotFoundException 2");       rnfe.printStackTrace();     }     catch (ParseErrorException pee) {       Utilities.debugPrintln("ParseErrorException2 " + pee.getMessage());     }     catch (Exception e) {       Utilities.debugPrintln("Exception2 " + e.getMessage());     }     return template;   }   /**    * Loads the configuration information and returns that information as a Properties, e    * which will be used to initializ the Velocity runtime.    */   protected java.util.Properties loadConfiguration(ServletConfig config) throws     java.io.IOException, java.io.FileNotFoundException {     return Utilities.initServletEnvironment(this);   } }    

2) ProcessSubPage.java , 比较简单,只定义了一个函数接口 getHtml

       

import javax.servlet.http.*; import org.apache.velocity.context.*; import org.apache.velocity.servlet.*; import commontools.*; public abstract class ProcessSubPage implements java.io.Serializable {   public ProcessSubPage() {   }   public String getHtml(VelocityServlet servlet, HttpServletRequest request,              HttpServletResponse response,              Context context) {     Utilities.debugPrintln(       "you need to override this method in sub class of ProcessSubPage:"       + this.getClass().getName());     return "Sorry, this module not finish yet.";   } }        

他的 .java 文件基本上是 ProcessSubPage 的子类和一些工具类。 ProcessSubPage 的子类基本上都是一样的流程, 用类似
context.put("page_footer",getPageFooterHTML());
的写法置换 .html 中的可变部分即可。如果没有可变部分,完全是静态网页,比如 AboutSubPage, 就更简单。

3) AboutSubPage.java

       

import org.apache.velocity.servlet.VelocityServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.velocity.context.Context; public class AboutSubPage extends ProcessSubPage {   public AboutSubPage() {   }   public String getHtml(VelocityServlet servlet, HttpServletRequest request,              HttpServletResponse response, Context context) {     //prepare data     //context.put("xxx","xxxx");                            Template template = null;     String fileName = "About.htm";     try {       template = servlet.getTemplate(fileName);       StringWriter sw = new StringWriter();       template.merge(context, sw);       return sw.toString();     }     catch (Exception ex) {       return "error get template " + fileName + " " + ex.getMessage();     }   } }        

其他 ProcessSubPage 的子类如上面基本类似,只不过会多了一些 context.put("xxx","xxxx") 的语句。

通过以上的例子,我们可以看到,使用 Velocity + Servlet , 所有的代码为: 1 个 java serverlet + m 个 java class + n 个 Html 文件。

这里是用了集中处理,然后分发(dispatch)的机制。不用担心用户在没有登陆的情况下访问某些页面。用户验证,页眉页脚包含都只写一次,易于编写、修改和维护。代码比较简洁,并且很容易加上自己的页面缓冲功能。可以随意将某个页面的 html 在内存中保存起来,缓存几分钟,实现页面缓冲功能。成功、出错页面也可以用同样的代码封装成函数,通过参数将 Message/Title 传入即可。

因为 Java 代码与 Html 代码完全在不同的文件中,美工与java代码人员可以很好的分工,每个人修改自己熟悉的文件,基本上不需要花时间做协调工作。而用 JSP, 美工与java代码人员共同修改维护 .jsp 文件,麻烦多多,噩梦多多。而且这里没有用 xml ,说实话,懂 xml/xls 之类的人只占懂 Java 程序员中的几分之一,人员不好找。

因为所有 java 代码人员写的都是标准 Java 程序,可以用任何 Java 编辑器,调试器,因此开发速度也会大大提高。美工写的是标准 Html 文件,没有 xml, 对于他们也很熟悉,速度也很快。并且,当需要网站改版的时候,只要美工把 html 文件重新修饰排版即可,完全不用改动一句 java 代码。

爽死了!!

4) 工具类 Utilities.java

       

import java.io.*; import java.sql.*; import java.text.*; import java.util.*; import java.util.Date; import javax.naming.*; import javax.servlet.*; import javax.servlet.http.*; import org.apache.velocity.*; import org.apache.velocity.app.*; import org.apache.velocity.context.Context; import org.apache.velocity.servlet.*; public class Utilities {   private static Properties m_servletConfig = null;   private Utilities() {   }   static {     initJavaMail();   }   public static void debugPrintln(Object o) {     String msg = "proj debug message at " + getNowTimeString() +       " ------------- ";     System.err.println(msg + o);   }   public static Properties initServletEnvironment(VelocityServlet v) {     // init only once     if (m_servletConfig != null) {       return m_servletConfig;     }     //debugPrintln("initServletEnvironment....");     try {       /*        * call the overridable method to allow the        * derived classes a shot at altering the configuration        * before initializing Runtime        */       Properties p = new Properties();       ServletConfig config = v.getServletConfig();       // Set the Velocity.FILE_RESOURCE_LOADED_PATH property       // to the root directory of the context.       String path = config.getServletContext().getRealPath("/");       //debugPrintln("real path of / is : " + path);       p.setProperty(Velocity.FILE_RESOURCE_LOADER_PATH, path);       // Set the Velocity.RUNTIME_LOG property to be the file       // velocity.log relative to the root directory       // of the context.       p.setProperty(Velocity.RUNTIME_LOG, path +              "velocity.log"); // Return the Properties object. //return p;       Velocity.init(p);       m_servletConfig = p;       return p;     }     catch (Exception e) {       debugPrintln(e.getMessage());       //throw new ServletException("Error initializing Velocity: " + e);     }     return null;     //this.getServletContext().getRealPath("/");   }   private static void initJavaMail() {   }   public static Connection getDatabaseConnection() {     Connection con = null;     try {       InitialContext initCtx = new InitialContext();       javax.naming.Context context = (javax.naming.Context) initCtx.         lookup("java:comp/env");       javax.sql.DataSource ds = (javax.sql.DataSource) context.lookup(         "jdbc/TestDB");       //Utilities.debugPrintln("ds = " + ds);       con = ds.getConnection();     }     catch (Exception e) {       Utilities.debugPrintln("Exception = " + e.getMessage());       return null;     }     //Utilities.debugPrintln("con = " + con);     return con;   }   public static java.sql.ResultSet excuteDbQuery(Connection con, String sql,     Object[] parameters) {     //Exception err = null;     //Utilities.debugPrintln("excuteDbQuery" + parameters[0] + " ,sql=" + sql);     try {       java.sql.PreparedStatement ps = con.prepareStatement(sql);       for (int i = 0; i < parameters.length; i++) {         processParameter(ps, i + 1, parameters[i]);       }       return ps.executeQuery();     }     catch (Exception e) {       //Utilities.debugPrintln(e.getMessage());       e.printStackTrace();     }     return null;   }   public static void excuteDbUpdate(String sql, Object[] parameters) {     Connection con = Utilities.getDatabaseConnection();     excuteDbUpdate(con, sql, parameters);     closeDbConnection(con);   }   public static void excuteDbUpdate(Connection con, String sql,                    Object[] parameters) {     Exception err = null;     try {       java.sql.PreparedStatement ps = con.prepareStatement(sql);       for (int i = 0; i < parameters.length; i++) {         processParameter(ps, i + 1, parameters[i]);       }       ps.execute();     }     catch (Exception e) {       err = e;       //Utilities.debugPrintln(err.getMessage());       e.printStackTrace();     }   }   private static void processParameter(java.sql.PreparedStatement ps,                      int index, Object parameter) {     try {       if (parameter instanceof String) {         ps.setString(index, (String) parameter);       }       else {         ps.setObject(index, parameter);       }     }     catch (Exception e) {       //Utilities.debugPrintln(e.getMessage());       e.printStackTrace();     }   }   public static void closeDbConnection(java.sql.Connection con) {     try {       con.close();     }     catch (Exception e) {       Utilities.debugPrintln(e.getMessage());     }   }   public static String getResultPage(     String title, String message, String jumpLink,     VelocityServlet servlet, HttpServletRequest request,     HttpServletResponse response, Context context) {     Template template = null;     context.put("MessageTitle", title);     context.put("ResultMessage", message);     context.put("JumpLink", jumpLink);     try {       template = servlet.getTemplate(         "/templates/Message.htm");       StringWriter sw = new StringWriter();       template.merge(context, sw);       return sw.toString();     }     catch (Exception ex) {       return "error get template Message.htm " + ex.getMessage();     }   }   public static String mergeTemplate(String fileName, VelocityServlet servlet,                     Context context) {     Template template = null;     try {       template = servlet.getTemplate(fileName);       StringWriter sw = new StringWriter();       template.merge(context, sw);       return sw.toString();     }     catch (Exception ex) {       return "error get template " + fileName + " " + ex.getMessage();     }   } }        

 

注意:基于排版的需要,代码中使用了中文全角空格。如果要复制代码,请在复制后进行文字替换。

 


作者Blog:http://blog.csdn.net/jacklondon/ 相关文章 我与 Joshua Bloch 的 email 讨论(emails between Joshua Bloch and me) C++ 中的 Singleton 实现 Velocity 的应用示例 Velocity -- Java Web 开发新技术 Java 的JDBC 数据库连接池实现方法

本文地址:http://com.8s8s.com/it/it16042.htm