VelocityServlet的应用

在Velocity 1.4版本中,org.apache.velocity.servlet.VelocityServlet继承了HttpServlet,因此它继承了HttpSetvlet的对生命周期的管理,而且,只要我们在实现自己velocity servlet的时候,继承org.apache.velocity.servlet.VelocityServlet,然后继承它的一些重要的方法就可以完成实际的业务。

下载 velocity-1.4.zip 后将它的jar包导入工程即可。

详细配置

Windows Server 2003 SP2 + SQL Server 2000 + Eclipse 3.2 + MyEclipse 5.0 + Tomcat 5.5.9 + Hibernate 3.0 + Velocity 1.4

开发测试过程

我的工程的目录结构如下所示:

VelocityServlet
│ .classpath
│ .myhibernatedata
│ .mymetadata
│ .project

├─.myeclipse
├─src
│ │ hibernate.cfg.xml
│ │ velocity.properties
│ │
│ └─org
│      └─shirdrn
│          │ HibernateSessionFactory.java
│          │
│          └─velocity
│              ├─dao
│              │      PersonDao.java
│              │
│              ├─entity
│              │      Person.hbm.xml
│              │      Person.java
│              │
│              ├─service
│              │      PersonService.java
│              │
│              └─servlet
│                      ListPersonsServlet.java

└─WebRoot
    ├─log
    │      velocity.log
    │
    ├─META-INF
    │      MANIFEST.MF
    │
    ├─templates
    │      lists.vm
    │
    └─WEB-INF
        │ web.xml
        │
        ├─classes
        │ │ hibernate.cfg.xml
        │ │ velocity.properties
        │ │
        │ └─org
        │      └─shirdrn
        │          │ HibernateSessionFactory.class
        │          │
        │          └─velocity
        │              ├─dao
        │              │      PersonDao.class
        │              │
        │              ├─entity
        │              │      Person.class
        │              │      Person.hbm.xml
        │              │
        │              ├─service
        │              │      PersonService.class
        │              │
        │              └─servlet
        │                      ListPersonsServlet.class
        │
        └─lib
                antlr-2.7.5H3.jar
                asm-attrs.jar
                asm.jar
                cglib-2.1.jar
                commons-collections-2.1.1.jar
                commons-logging-1.0.4.jar
                dom4j-1.6.jar
                ehcache-1.1.jar
                hibernate3.jar
                jaas.jar
                jaxen-1.1-beta-4.jar
                jdbc2_0-stdext.jar
                jta.jar
                log4j-1.2.9.jar
                msbase.jar
                mssqlserver.jar
                msutil.jar
                xerces-2.6.2.jar
                xml-apis.jar

下面就详细介绍上面的核心代码。

Person实体对应的POJO,这对Velocity模板中使用Person的属性非常重要,其实是Person实体的setter和getter方法,如下所示:

package org.shirdrn.velocity.entity;

 

/**
* Person generated by MyEclipse - Hibernate Tools
*/

public class Person implements java.io.Serializable {


    // Fields   

     private String id;
     private String name;
     private String gender;
     private Integer age;
     private String addr;


    // Constructors

    /** default constructor */
    public Person() {
    }

/** minimal constructor */
    public Person(String id, String name) {
        this.id = id;
        this.name = name;
    }
   
    /** full constructor */
    public Person(String id, String name, String gender, Integer age, String addr) {
        this.id = id;
        this.name = name;
        this.gender = gender;
        this.age = age;
        this.addr = addr;
    }

  
    // Property accessors

    public String getId() {
        return this.id;
    }
   
    public void setId(String id) {
        this.id = id;
    }

    public String getName() {
        return this.name;
    }
   
    public void setName(String name) {
        this.name = name;
    }

    public String getGender() {
        return this.gender;
    }
   
    public void setGender(String gender) {
        this.gender = gender;
    }

    public Integer getAge() {
        return this.age;
    }
   
    public void setAge(Integer age) {
        this.age = age;
    }

    public String getAddr() {
        return this.addr;
    }
   
    public void setAddr(String addr) {
        this.addr = addr;
    }
}

编写了一个实现查询数据库表person中的数据的DAO,接口如下:

package org.shirdrn.velocity.dao;

import java.util.List;

public interface PersonDao {
public List queryPersons(String hql);
}

具体实现是在PersonService类中实现的,代码如下所示:

package org.shirdrn.velocity.service;

import java.util.List;

import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.Session;
import org.shirdrn.HibernateSessionFactory;
import org.shirdrn.velocity.dao.PersonDao;

public class PersonService implements PersonDao {

public List queryPersons(String hql) {
   Session session = null;
   try{
    session = HibernateSessionFactory.getSession();
    Query query = session.createQuery(hql);
    return query.list();
   }
   catch(HibernateException e){
    e.printStackTrace();
   }
   finally{
    HibernateSessionFactory.closeSession();
   }
   return null;
}
}

应用Velocity最关键,最核心的Servlet的实现是在ListPersonsServlet类中,代码如下所示:

package org.shirdrn.velocity.servlet;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.List;
import java.util.Properties;

import javax.servlet.ServletConfig;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.velocity.Template;
import org.apache.velocity.app.Velocity;
import org.apache.velocity.context.Context;
import org.apache.velocity.exception.ParseErrorException;
import org.apache.velocity.exception.ResourceNotFoundException;
import org.apache.velocity.servlet.VelocityServlet;
import org.shirdrn.velocity.dao.PersonDao;
import org.shirdrn.velocity.service.PersonService;

public class ListPersonsServlet extends VelocityServlet {
  
protected Properties loadConfiguration(ServletConfig config)throws IOException, FileNotFoundException{    // 重写了VelocityServlet中的loadConfiguration方法
   String propsFileName = config.getInitParameter(INIT_PROPS_KEY);
   Properties props = new Properties();
   if(propsFileName != null){
    String realPath = getServletContext().getRealPath(propsFileName);
    if(realPath != null){
     propsFileName = realPath;
    }
    props.load(new FileInputStream(propsFileName));    // 加载属性配置文件
   }
//   将日志文件所在路径加入到Velocity上下文中
   String logFileName = props.getProperty(Velocity.RUNTIME_LOG);
   if(logFileName != null){
    String log = getServletContext().getRealPath(logFileName);
    if(log != null){
     props.setProperty(Velocity.RUNTIME_LOG,log);
    }
   }
   // 将Velocity模板加入到Velocity上下文(Context)中
   String path = props.getProperty(Velocity.FILE_RESOURCE_LOADER_PATH);
   if(path != null){
    String realPath = getServletContext().getRealPath(path);
    if(realPath != null){
     props.setProperty(Velocity.FILE_RESOURCE_LOADER_PATH, realPath);
    }
   }
   //System.out.println("props = "+props);
   //props = {file.resource.loader.path=D:/Tomcat 5.5/webapps/VelocityServlet/templates, runtime.log=D:/Tomcat 5.5/webapps/VelocityServlet/log/velocity.log}

   return props;
}

public Template handleRequest(HttpServletRequest request,HttpServletResponse response,Context ctx){
   PersonDao personDao = new PersonService();
   List personList = personDao.queryPersons("from Person");
   ctx.put("personList", personList);    // 将查询的数据列表放到Velocity上下文中
   Template template = null;
   try {
    template = getTemplate("lists.vm","UTF-8");    // 获取Velocity模板文件lists.vm
   } catch (ResourceNotFoundException e) {
    e.printStackTrace();
   } catch (ParseErrorException e) {
    e.printStackTrace();
   } catch (Exception e) {
    e.printStackTrace();
   }
   return template;
}
}

因为是VelocityServlet也是Servlet,所以要在web.xml中配置,如下所示:

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.4"
xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">

<servlet>
   <servlet-name>ListPersonsServlet</servlet-name>
   <servlet-class>org.shirdrn.velocity.servlet.ListPersonsServlet</servlet-class>
   <init-param>
    <param-name>org.apache.velocity.properties</param-name>
    <param-value>/WEB-INF/classes/velocity.properties</param-value>
   </init-param>
   <load-on-startup>1</load-on-startup>
</servlet>

<servlet-mapping>
   <servlet-name>ListPersonsServlet</servlet-name>
   <url-pattern>/ListPersonsServlet</url-pattern>
</servlet-mapping>

<welcome-file-list>
   <welcome-file>index.jsp</welcome-file>
</welcome-file-list>
</web-app>

上面web.xml文件中:

<init-param>
    <param-name>org.apache.velocity.properties</param-name>
    <param-value>/WEB-INF/classes/velocity.properties</param-value>
   </init-param>

配置了velocity.properties属性文件,该文件的内容如下所示:

default.contentType=text/html; charset=UTF-8
input.encoding=UTF-8
output.encoding=UTF-8
file.resource.loader.path = templates
runtime.log = log/velocity.log

前三行指定了输入输出的编码方式为UTF-8,这样设置以后,使用Velocity模板显示数据的时候,不会出现乱码问题。

第四行指定了模板文件所在的目录。

第五行指定了日志文件所在的目录。

我们实现的模板文件lists.vm的代码如下所示:

<html>
<head>
   <title>Velocity在Servlet中的应用</title>
</head>
<body bgcolor="#FFFFFF" border="1" borderColor="green" borderDarkColor="#FFFFFF" borderLightColor="#000000">
   <h1>Velocity应用的例子</h1>
   <table align="center" width="60%">
    <tr>
     <td>ID</td>
     <td>姓名</td>
     <td>性别</td>
     <td>年龄</td>
     <td>住址</td>
    </tr>
    #foreach($person in $personList)
    <tr>
     <td>$!person.id</td>
     <td>$!person.name</td>
     <td>$!person.gender</td>
     <td>$!person.age</td>
     <td>$!person.addr</td>
    </tr>
    #end
   </table>
</body>
</html>

上面使用$!person.addr可以使得:如果Person的某个字段为空,显示的时候用空格代替,如果使用$person.addr,则当addr字段为null的时候,页面显示的内容为$person.addr。

启动Tomcat Web Server,在浏览器地址栏中键链接:

http://localhost:8080/VelocityServlet/ListPersonsServlet

就可以看到从数据库中读取出来的Person的数据显示出来,如下所示:

Velocity应用的例子

ID姓名性别年龄住址
200804140001shirdrnmale25ChangChun
200804150001Poolinafemale24Changchun
200804150002Selibymale25Changchun
200804150006Koppafemale24Changchun
200804150008Justinmale24New York
200804150009Soloorfemale24London
200804150015Sujnnmale22Shanghai
200804160001SAgoop   
200804160002SAgoop   
200804160003SAgoop   
200804160004SAgoop   
200804160005SAgoop   
200804160006SAgoop   
200804160007SAgoop   
200804160008SAgoop   
200804160009SAgoop   
200804160010SAgoop   
200804160011SAgoop   
200804160012SAgoop   
200804160013SAgoop   
200804160014SAgoop   
200804160015SAgoop   
200804160016SAgoop   
200804160017SAgoop   
200804160018SAgoop   
200804160019异域王者20Beijing
200804160021异域王者20Beijing
200804160022风平浪静female22长春
200804160023风平浪静female22长春
200804160024异域王者20Beijing
200804170001异域王者female20Beijing
200804170030飞鱼20Beijing
200804170032飞鱼20Beijing
200804170033飞鱼20Beijing
200804170035飞鱼20Beijing

关于异常

如果发生下面的空指针异常:

java.lang.NullPointerException
at org.apache.velocity.runtime.resource.ResourceManagerImpl.getResource(ResourceManagerImpl.java:288)
at org.apache.velocity.runtime.RuntimeInstance.getTemplate(RuntimeInstance.java:1102)
at org.apache.velocity.runtime.RuntimeSingleton.getTemplate(RuntimeSingleton.java:324)
at org.apache.velocity.servlet.VelocityServlet.getTemplate(VelocityServlet.java:603)
at org.shirdrn.velocity.servlet.ListPersonsServlet.handleRequest(ListPersonsServlet.java:61)
at org.apache.velocity.servlet.VelocityServlet.doRequest(VelocityServlet.java:365)
at org.apache.velocity.servlet.VelocityServlet.doGet(VelocityServlet.java:318)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:689)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:802)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:252)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:173)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:213)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:178)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:126)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:105)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:107)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:148)
at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:856)
at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.processConnection(Http11Protocol.java:744)
at org.apache.tomcat.util.net.PoolTcpEndpoint.processSocket(PoolTcpEndpoint.java:527)
at org.apache.tomcat.util.net.LeaderFollowerWorkerThread.runIt(LeaderFollowerWorkerThread.java:80)
at org.apache.tomcat.util.threads.ThreadPool$ControlRunnable.run(ThreadPool.java:684)
at java.lang.Thread.run(Thread.java:595)

可能是由于使用Velocity的版本的问题,我在开始测试的时候,使用Velocity 1.5的jar包就发生上面的异常。而且在编写ListPersonsServlet文件的时候,总是提示VelocityServlet类已经过时,其实在Velocity 1.5的JavaDoc中可以看到只有是VelocityServlet类中的属性或者方法,都是过时的,所以版本问题要处理好。

心得总结

关于Velocty中出现中文乱码问题,可以在velocity.properties文件中加入下面的三行就可以解决:

default.contentType=text/html; charset=UTF-8
input.encoding=UTF-8
output.encoding=UTF-8

非常关键的三行。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值