﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>BlogJava-辰o(^o^)o的专栏[除非注释原创，其它文章基本来源于网络]-文章分类-J2ee</title><link>http://www.blogjava.net/jackybu/category/448.html</link><description>&lt;a href="http://www.fastonlineusers.com"&gt;&lt;b&gt;&lt;font color=red&gt;共有&lt;script src=http://fastonlineusers.com/online.php?d=jackybu.blogjava.net&gt;&lt;/script&gt;人在同时阅读此Blog&lt;/font&gt;&lt;/b&gt;&lt;/a&gt;</description><language>zh-cn</language><lastBuildDate>Fri, 02 Mar 2007 05:05:04 GMT</lastBuildDate><pubDate>Fri, 02 Mar 2007 05:05:04 GMT</pubDate><ttl>60</ttl><item><title>实例介绍Struts＋Spring＋Hibernate开发</title><link>http://www.blogjava.net/jackybu/articles/19546.html</link><dc:creator>辰</dc:creator><author>辰</author><pubDate>Sun, 13 Nov 2005 00:14:00 GMT</pubDate><guid>http://www.blogjava.net/jackybu/articles/19546.html</guid><wfw:comment>http://www.blogjava.net/jackybu/comments/19546.html</wfw:comment><comments>http://www.blogjava.net/jackybu/articles/19546.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jackybu/comments/commentRss/19546.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jackybu/services/trackbacks/19546.html</trackback:ping><description><![CDATA[

一 介绍

本文并不想介绍Struts，Spring，Hibernate的原理系统架构等，本文地目的是通过一个较复杂地实例介绍如何整合Struts，Spring，Hibernate，网上现有的例子虽然也能达到目的，但功能都比较单一，复杂的例子时会有意想不到的麻烦。本文对读者假设已经具备了以上框架的基础知识。以及那些已经了解Struts，Spring，Hibernate的基本概念，但是还没有亲身在较复杂的项目中体验Struts＋Spring＋Hibernate的开发人员。

1 Struts

    虽然不打算过多介绍Struts的原理，但是大概介绍一下还是有必要的。Struts本身就是 MVC 在这里负责将用户数据传人业务层，以及 将业务层处理的结果返回给用户，此系统属于较简单WEB应用，采用了OpenSessionInView模式处理LazyLoad问题，这样我们可以在用户视图中使用 get，set方法来方便地获取关联对象。为了处理庞大的Action和ActionForm问题，在此我门准备使用DynaActionForm (DynaValidatorForm)和DispatchAction以及 动态验证框架 来解决。及使用Tile来解决框架问题 。使用自定义标签处理分页和身份验证问题。

2 Spring

    Spring Framework最得以出名的是与Hibernate的无缝链接，虽然Spring 对Hibernate提供了90％以上的封装，使我们不必去关心Session 的建立，关闭，以及事务使我们能够专心的关注业务逻辑。但是一些特殊情况如 有时需要Query以及Criteria 对象，分页等，Spring不能给我们提供支持，总不能每次都在你的DAO上写个HibernateCallBackup()吧？Spring的作用不是把Hibernate再封装一层，而是让你接触不到Hibernate的API，而是帮助你管理好Session和Transaction。

在这里解决方法是：首先 写一个IBase 的接口，和一个BaseDao的实现。在实现中仿照HibernateTemplate，将其功能一一实现，同时考虑到Spring 未能支持的地方，我们不得已只好自己来管理Session，因此加入public Session openSession()，public Query getQuery(String sql)，public Criteria getCriteria(Class clazz)，以及分页的方法。 然后为每一个Entity 都建立继承于以上类的IEntity，与EntityDao。这里可以根据需求对Entity加入特殊的方法实现，如 在 StudentsDao.java 中加入类似用户身份验证等。以上就是数据访问层。接下来在Service层中通过对dao的引用完成业务逻辑方法。在下面的例子中我们分别为学生模块，教师模块，管理员模块构建Service层，StudentsServiceImpl，TeachersServiceImpl，AdminServiceImpl。

 

3 Hibernate

 有了Spring的封装，我们要对Hibernate做的就是正确实现对象关系的映射。由于此处处于系统的最底层，准确无误的实现对象之间的关联关系映射将起着至关重要的作用。

 总之，理解了Struts，Spring，Hibernate地原理以及之间的关系之后，剩下的工作就如同在以Spring为核心的Struts为表现的框架中堆积木。
下图可以更好的帮助我们理解Struts，Spring，Hibernate之间的关系。
pic1.JPG

二 案例简述：

设计思路主要源于 大学选修课，该系统可以方便处理学生在课程选报，学分查询，成绩查询，以及 成绩发布等。

系统以班级为核心，一门课程可以对应多个班级，一名教师也可以带不同的班级，学生可以选报不同课程所对应的班级，班级自身有目前人数，和最大人数，以及上课时间，上课地点的属性。

学生在选报班级之后，班级的人数会自动加一，直到等于最大人数时，其他学生将会有人数已满的错误提示。同理如果学生选择了同一课程的不同班级，也将收到错误提示。学生有密码，系别，学分，地址，电话等属性。

教师在系统中主要负责成绩发布，教师可以对其所带的班级的学生的成绩修改，系统会以成绩是否大于等于60来判断学生是否通过考试，如果通过会将该课程的学分累加到学生学分，同样如果教师二次修改了成绩，而且小于60，系统会在学生学分上扣掉该课程的分数。

课程在系统中具体体现为班级，自身带有学分属性。

系有编号，名称的属性，同时可以作为联系教师，课程，学生的桥梁。

 

功能模块

l       身份验证模块： 根据用户名，密码，用户类别 转发用户到不同的模块。

l       学生模块： 查看课程，查看班级，选报课程，查看己选课程，成绩查询。

l       教师模块： 录入成绩

l       管理员模块：对学生，教师，课程，班级，系 增，删，查，改。

 

三 具体实践

代码下载
http://www.blogjava.net/Files/limq/StudentManger.rar
1   对象关系映射：

首先，将库表映射为数据模型（SQL在源码中查看），转换后的数据模型如下图：
pic2.jpg

由此我们可以看出一下关联关系：

1 Students 和 Contact（联系方式）一对一关系。

2 Students 和 History（选课历史） 一对多关系

3 Students 和 Classes 多对多关系。

4 Classes 和 Classes_info 一对多关系。

5 Classes 和 Teachers 多对一关系。

6 Classes 和 Courses 多对一关系。

7 Course 和 Department（系） 多对一关系。

8 Teachers 和 Department 多对一关系。

9 Students 和 Department 多对一关系。

 

在Hibernate中将以上关系一一映射，如Students 和 History 一对多关系

Students.cfg.xm.：

 1 <set name="history"
 2                  table="history" 
 3                  cascade="all"
 4                  inverse="true"
 5                  lazy="true"  >
 6                 <key  column="student_id"/> 
 7             <one-to-many class="limq.hibernate.vo.History"
 8                                     />
 9             set>
10 

同样在History.cfg.xml中加入：
1  <many-to-one name="student"
2                   class="limq.hibernate.vo.Students"
3                   column="student_id"  >    
4      many-to-one>
5 

用过MyEclipse开发Hibernate的就知道，MyEclipse会帮助我们生成持久对象和抽象对象，我们要在 Students.java 中加入对History的引用

private Set history=new HashSet();

 

     public Set getHistory() {

        return history;

      }

 

    public void setHistory(Set history) {

        this.history = history;

}

同时，在AbstractHistory.java 中删除student_id 以及对应的get，set 方法，History.java 中加入

private Students student;

public Students getStudent() {

        return student;

    }

  

 public void setStudent(Students student) {

        this.student = student;

    }

具体内容请查看 源代码。

2 DAO 数据访问层

首先，编写IBaseDao与BaseDao，其中IBaseDao代码如下：

 1 package limq.hibernate.dao;
 2 
 3 import java.util.Collection;
 4 import java.util.List;
 5 import net.sf.hibernate.Criteria;
 6 import net.sf.hibernate.Query;
 7 import net.sf.hibernate.Session;
 8 import limq.exception.DaoException;
 9 
10 public interface IBaseDao {
11     
12     public Session openSession();
13     
14     public  int getTotalCount( String hql) throws Exception;
15     
16     public Query getQuery(String sql) throws Exception;
17     
18     public Criteria getCriteria(Class clazz) throws Exception;
19     
20     public int getTotalPage(int totalCount,int pageSize);
21     
22     public void create(Object entity);
23 
24     public void update(Object entity);
25 
26     public void delete(Object entity) throws DaoException;
27 
28     public void deleteAll(Class clazz) throws DaoException;
29 
30     public void deleteAll(Collection entities) throws DaoException;
31 
32     public Object loadByKey(Class clazz, String keyName, Object keyValue);
33 
34     public List find(String queryString) throws DaoException;
35 
36     public List find(String queryString, Object param) throws DaoException;
37 
38     public List find(String queryString, Object[] params) throws DaoException;
39 
40 }
41 

BaseDao继承org.springframework.orm.hibernate.support.HibernateDaoSupport

实现以上的 定义的方法

如：
 1 public void create(Object entity)  { 
 2         try { 
 3             getHibernateTemplate().save(entity); 
 4             
 5         } catch (Exception e) { 
 6             log.error("保存 " + entity.getClass().getName() + " 实例到数据库失败", e); 
 7            
 8         } 
 9     } 
10     /** 
11      * 获得session        
12      */ 
13     public Session openSession() {
14         return SessionFactoryUtils.getSession(getSessionFactory(), false);
15     }
16 
17     /** 
18      * 获得Query对象       
19      */ 
20     public Query getQuery(String sql) throws Exception{
21         Session session = this.openSession();
22         Query query = session.createQuery(sql); 
23     return query;
24     }
25     /** 
26      * 获得Criteria对象       
27      */
28     public Criteria getCriteria(Class clazz) throws Exception{
29         
30     Session session=this.openSession();
31     Criteria criteria = session.createCriteria(clazz);
32     return criteria;
33     }
34 

可以看到，这里即充分利用了Spring对Hibernate的支持，还弥补了Spring的不足。最后分别为每个持久对象建立Interface，以及DAO，使其分别继承IBaseDao与BaseDao。

如IDepartment，DepartmentDao

1 public interface IDepartment extends IBaseDao {}
2 
3 public class DepartmentDao extends BaseDao implements IBaseDao {}
4 

 

3 Service 层

 在这里需要认真思考每个业务逻辑所能用到的持久层对象和DAO，还要完成配置Spring框架， 首先我一起看看applications-service.xml

 
  1 xml version="1.0" encoding="UTF-8"?>
  2 DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" 
  3     "http://www.springframework.org/dtd/spring-beans.dtd">
  4 <beans>
  5   <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
  6     <property name="driverClassName">
  7       <value>com.mysql.jdbc.Drivervalue>
  8     property>
  9     <property name="url">
 10       <value>jdbc:mysql://localhost:3306/Studentvalue>
 11     property>
 12     <property name="username">
 13       <value>rootvalue>
 14     property>
 15     <property name="password">
 16       <value>value>
 17     property>
 18   bean>
 19   <bean id="sessionFactory" class="org.springframework.orm.hibernate.LocalSessionFactoryBean">
 20     <property name="dataSource">
 21       <ref local="dataSource"/>
 22     property>
 23     <property name="mappingResources">
 24       <list>
 25         <value>limq/hibernate/vo/Admins.hbm.xmlvalue>
 26         <value>limq/hibernate/vo/Classes.hbm.xmlvalue>
 27         <value>limq/hibernate/vo/Courses.hbm.xmlvalue>
 28         <value>limq/hibernate/vo/Students.hbm.xmlvalue>
 29         <value>limq/hibernate/vo/ClassesInfo.hbm.xmlvalue>
 30         <value>limq/hibernate/vo/Contact.hbm.xmlvalue>
 31         <value>limq/hibernate/vo/Department.hbm.xmlvalue>
 32         <value>limq/hibernate/vo/History.hbm.xmlvalue>
 33         <value>limq/hibernate/vo/Teachers.hbm.xmlvalue>
 34       list>
 35     property>
 36     <property name="hibernateProperties">
 37       <props>
 38         <prop key="hibernate.dialect">net.sf.hibernate.dialect.MySQLDialectprop>
 39         <prop key="hibernate.show_sql">trueprop>
 40       props>
 41     property>
 42   bean>
 43   <bean id="myTransactionManager" class="org.springframework.orm.hibernate.HibernateTransactionManager">
 44     <property name="sessionFactory">
 45       <ref local="sessionFactory"/>
 46     property>
 47   bean>
 48   
 49   <bean id="hibernateInterceptor" class="org.springframework.orm.hibernate.HibernateInterceptor">
 50     <property name="sessionFactory">
 51       <ref bean="sessionFactory"/>
 52     property>
 53   bean>
 54   <bean id="studentDaoTarget" class="limq.hibernate.dao.StudentsDao">
 55     <property name="sessionFactory">
 56       <ref bean="sessionFactory"/>
 57     property>
 58   bean>
 59   <bean id="teacherDaoTarget" class="limq.hibernate.dao.TeachersDao">
 60     <property name="sessionFactory">
 61       <ref bean="sessionFactory"/>
 62     property>
 63   bean>
 64   <bean id="courseDaoTarget" class="limq.hibernate.dao.CoursesDao">
 65     <property name="sessionFactory">
 66       <ref bean="sessionFactory"/>
 67     property>
 68   bean>
 69   <bean id="classDaoTarget" class="limq.hibernate.dao.ClassesDao">
 70     <property name="sessionFactory">
 71       <ref bean="sessionFactory"/>
 72     property>
 73   bean>
 74   <bean id="departmentDaoTarget" class="limq.hibernate.dao.DepartmentDao">
 75     <property name="sessionFactory">
 76       <ref bean="sessionFactory"/>
 77     property>
 78   bean>
 79   <bean id="adminDaoTarget" class="limq.hibernate.dao.AdminDao">
 80     <property name="sessionFactory">
 81       <ref bean="sessionFactory"/>
 82     property>
 83   bean>
 84   <bean id="studentDao" class="org.springframework.aop.framework.ProxyFactoryBean">
 85     <property name="proxyInterfaces">
 86       <value>limq.hibernate.dao.IStudentsvalue>
 87     property>
 88     <property name="interceptorNames">
 89       <list>
 90         <value>hibernateInterceptorvalue>
 91         <value>studentDaoTargetvalue>
 92       list>
 93     property>
 94   bean>
 95   <bean id="teacherDao" class="org.springframework.aop.framework.ProxyFactoryBean">
 96     <property name="proxyInterfaces">
 97       <value>limq.hibernate.dao.ITeachersvalue>
 98     property>
 99     <property name="interceptorNames">
100       <list>
101         <value>hibernateInterceptorvalue>
102         <value>teacherDaoTargetvalue>
103       list>
104     property>
105   bean>
106   <bean id="courseDao" class="org.springframework.aop.framework.ProxyFactoryBean">
107     <property name="proxyInterfaces">
108       <value>limq.hibernate.dao.ICoursesvalue>
109     property>
110     <property name="interceptorNames">
111       <list>
112         <value>hibernateInterceptorvalue>
113         <value>courseDaoTargetvalue>
114       list>
115     property>
116   bean>
117   <bean id="classDao" class="org.springframework.aop.framework.ProxyFactoryBean">
118     <property name="proxyInterfaces">
119       <value>limq.hibernate.dao.IClassesvalue>
120     property>
121     <property name="interceptorNames">
122       <list>
123         <value>hibernateInterceptorvalue>
124         <value>classDaoTargetvalue>
125       list>
126     property>
127   bean>
128   <bean id="departmentDao" class="org.springframework.aop.framework.ProxyFactoryBean">
129     <property name="proxyInterfaces">
130       <value>limq.hibernate.dao.IDepartmentvalue>
131     property>
132     <property name="interceptorNames">
133       <list>
134         <value>hibernateInterceptorvalue>
135         <value>departmentDaoTargetvalue>
136       list>
137     property>
138   bean>
139   <bean id="adminDao" class="org.springframework.aop.framework.ProxyFactoryBean">
140     <property name="proxyInterfaces">
141       <value>limq.hibernate.dao.IAdminvalue>
142     property>
143     <property name="interceptorNames">
144       <list>
145         <value>hibernateInterceptorvalue>
146         <value>adminDaoTargetvalue>
147       list>
148     property>
149   bean>
150   
151   <bean id="studentManagerTarget" class="limq.spring.service.StudentsServiceImpl">
152     <property name="studentsDao">
153       <ref bean="studentDao"/>
154     property>
155     <property name="coursesDao">
156       <ref bean="courseDao"/>
157     property>
158     <property name="classesDao">
159       <ref bean="classDao"/>
160     property>
161     <property name="departmentsdao">
162       <ref bean="departmentDao"/>
163     property>
164   bean>
165   <bean id="teacherManagerTarget" class="limq.spring.service.TeachersServiceImpl">
166     <property name="teachersDao">
167       <ref bean="teacherDao"/>
168     property>
169     <property name="coursesDao">
170       <ref bean="courseDao"/>
171     property>
172     <property name="classesDao">
173       <ref bean="classDao"/>
174     property>
175     <property name="studentsDao">
176       <ref bean="studentDao"/>
177     property>
178   bean>
179   <bean id="adminManagerTarget" class="limq.spring.service.AdminServiceImpl">
180     <property name="adminDao">
181       <ref bean="adminDao"/>
182     property>
183     <property name="teachersDao">
184       <ref bean="teacherDao"/>
185     property>
186     <property name="coursesDao">
187       <ref bean="courseDao"/>
188     property>
189     <property name="classesDao">
190       <ref bean="classDao"/>
191     property>
192     <property name="studentsDao">
193       <ref bean="studentDao"/>
194     property>
195     <property name="departmentsdao">
196       <ref bean="departmentDao"/>
197     property>
198   bean>
199   
200   <bean id="studentManager" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
201     <property name="transactionManager">
202       <ref bean="myTransactionManager"/>
203     property>
204     <property name="target">
205       <ref bean="studentManagerTarget"/>
206     property>
207     <property name="transactionAttributes">
208       <props>
209         <prop key="get*">PROPAGATION_SUPPORTSprop>
210         <prop key="*">PROPAGATION_REQUIREDprop>
211       props>
212     property>
213   bean>
214   <bean id="teacherManager" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
215     <property name="transactionManager">
216       <ref bean="myTransactionManager"/>
217     property>
218     <property name="target">
219       <ref bean="teacherManagerTarget"/>
220     property>
221     <property name="transactionAttributes">
222       <props>
223         <prop key="get*">PROPAGATION_SUPPORTSprop>
224         <prop key="*">PROPAGATION_REQUIREDprop>
225       props>
226     property>
227   bean>
228   <bean id="adminManager" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
229     <property name="transactionManager">
230       <ref bean="myTransactionManager"/>
231     property>
232     <property name="target">
233       <ref bean="adminManagerTarget"/>
234     property>
235     <property name="transactionAttributes">
236       <props>
237         <prop key="get*">PROPAGATION_SUPPORTSprop>
238         <prop key="*">PROPAGATION_REQUIREDprop>
239       props>
240     property>
241   bean>
242 beans>
243 

以StudentsServiceImpl以为例，下图演示了如何利用Spring的Ioc与Hibernate的结合。

可以看到分别将studentDao,classDao,coursesDao,departmentDao,注入studentManager.
pic4.JPG
  1 IStudentsService.java
  2 public interface IStudentsService {
  3 
  4     public  boolean validate(String username,String pasword);  
  5     public Classes[] getClassesFromCourse(Courses courses);
  6     public  Department getDepFromID(Integer id);
  7     public   Courses getCourseFromID(Integer id);
  8     public   Classes getClassFromID(Integer id);
  9     public  Students getStudetFromName(String name);
 10     public  boolean ifEnrolSameCourse(Classes clazz,Students stu);
 11     public  void selectClasses(Students stu, Classes clazz,Date date);
 12     public  boolean ifMoreThanCap(Classes clazz);
 13     public void updateSudent(Students stu,Contact contact);
 14     public HashMap getCourse(PageInfo pageinfo) throws Exception;
 15     public HashMap getStudentHistory(PageInfo pageinfo,String stu_name) throws Exception;
 16  
 17 }
 18 
 19 实现StudentsServiceImpl.java
 20 public class StudentsServiceImpl implements IStudentsService {
 21 
 22     private Logger log = Logger.getLogger(this.getClass());
 23 
 24     private IStudents studentsDao;
 25 
 26     private ICourses coursesDao;
 27 
 28     private IClasses classesDao;
 29 
 30     private IDepartment departmentsdao;
 31 
 32     /**
 33      * 验证用户名密码
 34      * 
 35      * @param username
 36      *            用户名
 37      * @param password
 38      *            密码
 39      */
 40 
 41     public boolean validate(String username, String password) {
 42 
 43         String password2 = studentsDao.getPasswordFromUsername(username);
 44         if (password.equals(password2))
 45             return true;
 46         else
 47             return false;
 48 
 49     }
 50 
 51     /**
 52      * 查找所有课程
 53      *  
 54      */
 55     public Courses[] getAllCourses() {
 56 
 57         List list = null;
 58         try {
 59 
 60             list = coursesDao.find("select c from Courses as c ");
 61         } catch (Exception e) {
 62         }
 63 
 64         return (Courses[]) list.toArray(new Courses[0]);
 65     }
 66 
 67     /**
 68      *  分页显示所有课程
 69      * 
 70      * @param pageinfo
 71      */
 72     public HashMap getCourse(PageInfo pageinfo) throws Exception {
 73 
 74         HashMap hp = new HashMap();
 75         String hsql = "select c from Courses as c order by c.id";
 76         Query query = coursesDao.getQuery(hsql);
 77         int totalCount = pageinfo.getTatalCount();
 78         int totalPage = pageinfo.getTotalpage();
 79         int start = pageinfo.getStart();
 80         totalCount = totalCount == -1 ? coursesDao.getTotalCount(hsql)
 81                 : totalCount;
 82         totalPage = totalPage == -1 ? coursesDao.getTotalPage(totalCount,
 83                 pageinfo.getPageSize()) : totalPage;
 84         query.setFirstResult(start);
 85         query.setMaxResults(pageinfo.getPageSize());
 86         List list = query.list();
 87         hp.put("courses", (Courses[]) list.toArray(new Courses[0]));
 88         hp.put("totalCount", new Integer(totalCount));
 89         hp.put("totalPage", new Integer(totalPage));
 90         return hp;
 91     }
 92     /**
 93      *  分页显示所有选课历史
 94      * @param pageinfo 
 95      * @param stu_name
 96      */
 97     public HashMap getStudentHistory(PageInfo pageinfo, String stu_name)
 98             throws Exception {
 99         HashMap hp = new HashMap();
100         Students stu = this.getStudetFromName(stu_name);
101         Integer stu_id = stu.getId();
102         Criteria criteria = coursesDao.getCriteria(History.class);
103         criteria.createCriteria("student").add(Expression.eq("name", stu_name));
104         int totalCount = pageinfo.getTatalCount();
105         int totalPage = pageinfo.getTotalpage();
106         int start = pageinfo.getStart();
107         totalCount = totalCount == -1 ? criteria.list().size() : totalCount;
108         totalPage = totalPage == -1 ? studentsDao.getTotalPage(totalCount,
109         pageinfo.getPageSize()) : totalPage;
110         criteria.setFirstResult(start);
111         criteria.setMaxResults(pageinfo.getPageSize());
112         criteria.addOrder(Order.asc("id"));
113         List list = criteria.list();
114         hp.put("history", (History[]) list.toArray(new History[0]));
115         hp.put("totalCount", new Integer(totalCount));
116         hp.put("totalPage", new Integer(totalPage));
117         return hp;
118     }
119     /**
120      * 根据课程查找班级
121      * @param course
122      *            课程实体
123      * @return 返回该课程下所有班级
124      */
125     public Classes[] getClassesFromCourse(Courses course) {
126         return coursesDao.getClassesFromCourse(course);
127     }
128 
129     /**
130      * 根据主键查找系
131      * @param id
132      *            主键ID
133      */
134     public Department getDepFromID(Integer id) {
135         return (Department) departmentsdao
136                 .loadByKey(Department.class, "id", id);
137     }
138 
139     /**
140      * 根据主键查找课程
141      * @param id
142      *            主键ID
143      */
144     public Courses getCourseFromID(Integer id) {
145         return (Courses) coursesDao.loadByKey(Courses.class, "id", id);
146     }
147     /**
148      * 根据主键查找班级
149      * @param id
150      *            主键ID
151      */
152     public Classes getClassFromID(Integer id) {
153         return (Classes) classesDao.loadByKey(Classes.class, "id", id);
154     }
155 
156     /**
157      * 根据姓名查找学生
158      * @param name
159      */
160     public Students getStudetFromName(String name) {
161         return (Students) studentsDao.loadByKey(Students.class, "name", name);
162     }
163 
164     /**
165      * 检查学生是否选报了同一课程的班级
166      * @param clazz
167      *            所选报的班级
168      * @param stu
169      *            学生实体
170      * @return true 该生选报同一课程的班级
171      * @return false 没有报过该课程的班级，可以选报
172      *  
173      */
174     public boolean ifEnrolSameCourse(Classes clazz, Students stu) {
175 
176         Courses cour = clazz.getCourse();
177 
178         Classes[] classes = (Classes[]) stu.getClasses()
179                 .toArray(new Classes[0]);
180         for (int i = 0; i < classes.length; i++) {
181 
182             Courses c1 = classes[i].getCourse();
183 
184             if (c1.getId().equals(cour.getId()))
185                 return true;
186         }
187         return false;
188     }
189 
190     /**
191      * 检查课程的目前人数 
192      * @param clazz
193      *            检查班级人数是否已满
194      * @param clazz
195      *            班级实体
196      * @return true 班级人数已满
197      * @return false 班级人数未满
198      *  
199      */
200     public boolean ifMoreThanCap(Classes clazz) {
201         Integer capacity = clazz.getCapacity();
202         Integer maxcapacity = clazz.getMaxcapacity();
203         if (capacity.intValue() < maxcapacity.intValue()) {
204             clazz.setCapacity(Integer.valueOf(capacity.intValue() + 1));
205             //classesDao.update(clazz);
206             return false;
207         } else
208             return true;
209 
210     }
211 
212     /**
213      * 数据库插入选择班级的记录
214      * @param stu
215      *            学生
216      * @param clazz
217      *            所选择的班级
218      */
219     public void selectClasses(Students stu, Classes clazz, Date date)
220  {
221         stu.getClasses().add(clazz);
222         clazz.getStudents().add(stu);          
223         History his = new History();
224         his.setEnrolTime(date);
225         his.setStudent(stu);
226         his.setClasses(clazz);
227         his.setScore(clazz.getCourse().getScore());
228         his.setMarking(new Double(0));
229         try{
230         String cour_name=new String(clazz.getCourse().getName().getBytes("GBK"));       
231         his.setCourseName(cour_name);
232         }catch( java.io.UnsupportedEncodingException e){e.getStackTrace();}       
233         stu.getHistory().add(his);
234     }
235 
236     public void updateSudent(Students stu,Contact contact){
237         
238        studentsDao.update(stu);
239        studentsDao.update(contact);
240     
241     }
242     public IStudents getStudentsDao() {
243         return studentsDao;
244     }
245     public void setStudentsDao(IStudents studentsDao) {
246         this.studentsDao = studentsDao;
247     }
248     public IClasses getClassesDao() {
249         return classesDao;
250     }
251     public void setClassesDao(IClasses classesDao) {
252         this.classesDao = classesDao;
253     }
254     public ICourses getCoursesDao() {
255         return coursesDao;
256     }
257     public void setCoursesDao(ICourses coursesDao) {
258         this.coursesDao = coursesDao;
259     }
260     public IDepartment getDepartmentsdao() {
261         return departmentsdao;
262     }
263     public void setDepartmentsdao(IDepartment departmentdao) {
264         this.departmentsdao = departmentdao;
265     }
266 }
267 
268 

4 UI层

这里我们选择Struts，首先配置 web.xml

 1 xml version="1.0" encoding="UTF-8"?>
 2 <web-app xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.4" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee   http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
 3   <context-param>
 4     <param-name>contextConfigLocationparam-name>
 5     <param-value>/WEB-INF/classes/applications-service.xmlparam-value>
 6   context-param>
 7   <context-param>
 8     <param-name>log4jConfigLocationparam-name>
 9     <param-value>/WEB-INF/log4j.propertiesparam-value>
10   context-param>
11   <filter>
12     <filter-name>hibernateFilterfilter-name>
13     <filter-class>org.springframework.orm.hibernate.support.OpenSessionInViewFilterfilter-class>
14   filter>
15   <filter-mapping>
16     <filter-name>hibernateFilterfilter-name>
17     <url-pattern>/*url-pattern>
18   filter-mapping>
19   <filter>
20     <filter-name>Set Character Encodingfilter-name>
21     <filter-class>limq.struts.SetCharacterEncodingFilterfilter-class>
22   filter>
23   <filter-mapping>
24     <filter-name>Set Character Encodingfilter-name>
25     <url-pattern>/*url-pattern>
26   filter-mapping>
27   <servlet>
28     <servlet-name>SpringContextServletservlet-name>
29     <servlet-class>org.springframework.web.context.ContextLoaderServletservlet-class>
30     <load-on-startup>1load-on-startup>
31   servlet>
32   <servlet>
33     <servlet-name>actionservlet-name>
34     <servlet-class>org.apache.struts.action.ActionServletservlet-class>
35     <init-param>
36       <param-name>configparam-name>
37       <param-value>/WEB-INF/struts-config.xmlparam-value>
38     init-param>
39     <init-param>
40       <param-name>debugparam-name>
41       <param-value>3param-value>
42     init-param>
43     <init-param>
44       <param-name>detailparam-name>
45       <param-value>3param-value>
46     init-param>
47     <load-on-startup>0load-on-startup>
48   servlet>
49   <servlet-mapping>
50     <servlet-name>actionservlet-name>
51     <url-pattern>*.dourl-pattern>
52   servlet-mapping>
53 web-app>
54 
55 

其中注意这几句,
1 <filter>
2     <filter-name>hibernateFilterfilter-name>
3 <filter-class>org.springframework.orm.hibernate.support.OpenSessionInViewFilterfilter-class>
4   filter>
5 <filter-mapping>
6     <filter-name>hibernateFilterfilter-name>
7     <url-pattern>/*url-pattern>
8 filter-mapping>
9 

由于我们使用了lazy = "true"，如果想在UI层使用实体对象关联来获得其他对象时就会有这样的提示：

org.hibernate.LazyInitializationException: failed to lazily initialize a collection

Spring 中引入了 OpenSessionInView模式可以处理以上问题，即在web.xml中加入以上代码。

 

 

接下来建立抽象BaseAction，和 BaseDispatchAction，其中后者与前者相似目的为减少Action的数量
 1 abstract class BaseAction extends Action {
 2 
 3     private IStudentsService studentsService;
 4     private ITeachersService teachersSerivce;
 5     private IAdminService adminService;
 6     public void setServlet(ActionServlet actionServlet) {
 7         super.setServlet(actionServlet);
 8         ServletContext servletContext = actionServlet.getServletContext();
 9         WebApplicationContext wac = WebApplicationContextUtils
10                 .getRequiredWebApplicationContext(servletContext);
11 
12         this.studentsService = (IStudentsService) wac.getBean("studentManager");
13         this.adminService = (IAdminService) wac.getBean("adminManager");
14         this.teachersSerivce = (ITeachersService) wac.getBean("teacherManager");
15     }
16     public IStudentsService getStudentsService() {
17         return studentsService;
18     }
19     public ITeachersService getTeachersSerivce() {
20         return teachersSerivce;
21     }
22     public void setTeachersSerivce(ITeachersService teachersSerivce) {
23         this.teachersSerivce = teachersSerivce;
24     }
25     public IAdminService getAdminService() {
26         return adminService;
27     }
28     public void setAdminService(IAdminService adminService) {
29         this.adminService = adminService;
30     }
31 }
32 

BaseDispatchAction与之类似，请查看源码。其他Action都从这两个类继承。

以下就以查看课程下的班级为例演示Struts与Spring的使用：

 1 CoursesAction.java
 2     /** 
 3      * 查看课程下的班级 
 4      */ 
 5     public ActionForward viewClassFromCourse(ActionMapping mapping,
 6             ActionForm form, HttpServletRequest request,
 7             HttpServletResponse response) throws Exception {
 8         Integer cour_id = Integer.valueOf((request.getParameter("cour_id")));
 9         Courses cour = super.getStudentsService().getCourseFromID(cour_id);
10         Classes[] clazz =(Classes[])cour.getClasses().toArray(new Classes[0]);
11         request.setAttribute("clazz", clazz);
12         return mapping.findForward("success");
13 }
14 

这里从上一个页面获得课程编号 cour_id, 然后通过StudentsServiceImpl中的
1 public Courses getCourseFromID(Integer id) {
2         return (Courses) coursesDao.loadByKey(Courses.class, "id", id);
3 }
4 

方法查到Courses实例，利用Courses和Classes的关联关系得到Classes[],在将其放入

Request. 通过mapping.findForward("success")，转发到

select_course_Content.jsp


CustomRequestProcessor.java 介绍
 1 public class CustomRequestProcessor extends RequestProcessor {
 2     protected boolean processPreprocess(HttpServletRequest request,
 3             HttpServletResponse response) {
 4         boolean continueProcessing = true;
 5         HttpSession session = request.getSession();
 6         String uri =request.getRequestURI();
 7         if ( session == null || session.getAttribute("userName") == null ) {
 8             continueProcessing = false;  
 9         if(uri.endsWith("login.do")) return true;    
10         try{
11             response.sendRedirect("/StudentManger/login.jsp" );
12           }catch( Exception ex ){
13             log.error( "Problem sending redirect from processPreprocess()" );
14           }
15         }
16         return continueProcessing;
17     }
18 }
19 

为了验证用户操作权限，这里扩展了Struts 的RequestProcessor来判断Session如果Session和userName都不空则程序继续，否则重定向到login.jsp。要想扩展RequestProcessor类，需在Struts的配置文件中加入
1 <controller 
2 contentType="text/html;charset=UTF-8"
3 locale="true" 
4 nocache="true" 
5 processorClass="limq.struts.CustomRequestProcessor"/>
6 

呵呵，当然在正规使用时仅仅这样验证是不够的。欢迎你把自己修改方法告诉我。

 

4分页处理：

下面重点讨论一下Hibernate的分页处理方式。

Hibernate 中处理查询主要有 Query ，Criteria，分别以 HSQL或编程方式实现，

本例对这两种方法都有相关处理。由于在Spring中无法直接使用Query和Criteria对象

所以只有先从Spring那里借一个Session，等使用完了在还给Sping处理。读者应该还记得在BaseDao中有这样的语句方便我们获取Session及其他对象：

 
 1     public Query getQuery(String sql) throws Exception{
 2         Session session = this.openSession();
 3         Query query = session.createQuery(sql); 
 4     return query;
 5     }
 6    
 7     public Criteria getCriteria(Class clazz) throws Exception{
 8         
 9     Session session=this.openSession();
10     Criteria criteria = session.createCriteria(clazz);
11     return criteria;
12     }
13 

Service层以查询所有课程与学生选课记录为例处理Query与Criteria：
 1  StudentsServiceImpl.java
 2     public HashMap getCourse(PageInfo pageinfo) throws Exception {
 3 
 4         HashMap hp = new HashMap();
 5         String hsql = "select c from Courses as c order by c.id";
 6         Query query = coursesDao.getQuery(hsql);
 7         int totalCount = pageinfo.getTatalCount();
 8         int totalPage = pageinfo.getTotalpage();
 9         int start = pageinfo.getStart();
10         totalCount = totalCount == -1 ? coursesDao.getTotalCount(hsql)
11                 : totalCount;
12         totalPage = totalPage == -1 ? coursesDao.getTotalPage(totalCount,
13                 pageinfo.getPageSize()) : totalPage;
14         query.setFirstResult(start);
15         query.setMaxResults(pageinfo.getPageSize());
16         List list = query.list();
17         hp.put("courses", (Courses[]) list.toArray(new Courses[0]));
18         hp.put("totalCount", new Integer(totalCount));
19         hp.put("totalPage", new Integer(totalPage));
20         return hp;
21     }
22    
23     public HashMap getStudentHistory(PageInfo pageinfo, String stu_name)
24             throws Exception {
25         HashMap hp = new HashMap();
26         Students stu = this.getStudetFromName(stu_name);
27         Integer stu_id = stu.getId();
28         Criteria criteria = coursesDao.getCriteria(History.class);
29         criteria.createCriteria("student").add(Expression.eq("name", stu_name));
30         int totalCount = pageinfo.getTatalCount();
31         int totalPage = pageinfo.getTotalpage();
32         int start = pageinfo.getStart();
33         totalCount = totalCount == -1 ? criteria.list().size() : totalCount;
34         totalPage = totalPage == -1 ? studentsDao.getTotalPage(totalCount,
35         pageinfo.getPageSize()) : totalPage;
36         criteria.setFirstResult(start);
37         criteria.setMaxResults(pageinfo.getPageSize());
38         criteria.addOrder(Order.asc("id"));
39         List list = criteria.list();
40         hp.put("history", (History[]) list.toArray(new History[0]));
41         hp.put("totalCount", new Integer(totalCount));
42         hp.put("totalPage", new Integer(totalPage));
43         return hp;
44     }
45 PageIngfo.java
46 public class PageInfo  {
47     
48     int pageNo=0;
49     int totalpage=-1;
50     int tatalCount=-1;
51     int pageSize=0;
52 int start=0;
53 
54 

可以看到getCourse和getStudentHistory有很多相似之处，Hibernate为Query和Criteria提供了针对不同数据库的解决分页方法， Quey需要我们写HSQL， Criteria不但可以应付带有条件的查询，还不用我们自己写HSQL，PageInfo是含有分页信息的普通java类。

再看看Struts是如何调用getStudentHistory 的，

 1 PageAction.java
 2 public class PageAction  extends BaseDispatchAction{
 3     public ActionForward execute(ActionMapping mapping,
 4              ActionForm form,
 5              HttpServletRequest request,
 6              HttpServletResponse response)
 7 throws Exception {
 8         String pageNo=request.getParameter("pageNo");
 9         String totalcount=request.getParameter("totalcount");
10         String totalpage=request.getParameter("totalpage");
11         int pagesize=2;//每页的大小
12         PageInfo page =new PageInfo();
13         page.setPageSize(pagesize);
14         HashMap hp=null;
15         History[] historys = null;
16         String stu_name=null;
17         HttpSession session = request.getSession();
18         stu_name = (String) session.getAttribute("userName"); 
19         if(pageNo == null || totalcount == null || totalpage==null){
20         //第一次发送请求
21             page.setPageNo(1);           
22             hp=super.getStudentsService().getStudentHistory(page,stu_name);
23             page.setTatalCount(((Integer)hp.get("totalCount")).intValue());
24             page.setTotalpage(((Integer)hp.get("totalPage")).intValue());      
25         }else{
26             page.setPageNo(Integer.parseInt(pageNo));
27             page.setTatalCount(Integer.parseInt(totalcount));
28             page.setTotalpage(Integer.parseInt(totalpage));
29            hp=super.getStudentsService().getStudentHistory(page,stu_name);
30            
31         }
32      historys =(History[]) hp.get("history");
33      request.setAttribute("history",historys);
34      request.setAttribute("pageinfo",page);    
35         return mapping.findForward("success");
36     }
37 }
38 


在stu_his_Content.jsp中避免代码重复使用了自定义标志来处理分页

 1 <%@ page contentType="text/html;charset=UTF-8" language="java"  %> 
 2 <%@ taglib uri="/WEB-INF/struts-bean.tld" prefix="bean" %>
 3 <%@ taglib uri="/WEB-INF/struts-html.tld" prefix="html" %>
 4 <%@ taglib uri="/WEB-INF/struts-logic.tld" prefix="logic" %>
 5 <%@ page import="limq.hibernate.vo.*"%>
 6 <%@ taglib uri="/WEB-INF/MyTag.tld" prefix="mytag"%>
 7 <%@ page import="limq.common.*"%>
 8 <html:html locale="true"> 
 9   <body>
10   <%
11   PageInfo pageinfo =(PageInfo) request.getAttribute("pageinfo");
12   History[] historys = (History[])request.getAttribute("history");
13   %>
14 <table width="550" border="1" cellspacing="0" align="center" cellpadding="0">
15   <tr>
16     <td><bean:message key="class.id"/>td>
17     <td><bean:message key="course.name"/>td>
18     <td><bean:message key="enrol.time"/>td>
19     <td><bean:message key="score"/>td>
20     <td><bean:message key="marking"/>td>
21   tr>
22   <%
23   for(int i=0;i<historys.length;i++){
24   History  his=historys[i];
25   %>
26   <tr>
27     <td><%=his.getClasses().getId()%>td>
28     <td><%=his.getCourseName()%>td>
29     <td><%=his.getEnrolTime()%>td>
30     <td><%=his.getScore()%>td>
31     <td><%=his.getMarking()%>td>
32   tr>
33   <%
34   }
35   %>
36 table>
37 <mytag:page pageinfo="<%=pageinfo%>" action="getHistory.do"/>
38 body>
39 html:html>
40 


标志处理类如下：
 1 PageTag.java
 2 
 3 public class PageTag extends SimpleTagSupport {
 4 
 5     private PageInfo pageinfo = null;
 6 private String action = null;
 7 
 8     public String getAction() {
 9         return action;}
10     public void setAction(String action) {
11         this.action = action;
12     }
13     public PageInfo getPageinfo() {
14         return pageinfo;
15     }
16     public void setPageinfo(PageInfo pageinfo) {
17         this.pageinfo = pageinfo;
18     }
19 
20     public void doTag() throws JspException, IOException {
21         JspWriter out = getJspContext().getOut();
22 
23         int totalpage = pageinfo.getTotalpage();
24         int totalcount = pageinfo.getTatalCount();
25         int pageNo = pageinfo.getPageNo();
26         int addPageNo = pageNo + 1;
27         int minPageNo = pageNo - 1;
28 
29         out.println("< SPAN>"400\" align=\"center\"  cellPadding=\"0\" cellSpacing=\"0\"> ");
30         out.print("");
31         out.println("共" + totalcount + "条，" + totalpage + "页，当前"
32                 + pageNo + "页
");
66 
67     }
68 
69 }
70 


5 中文乱码问题：

1 数据库：MYSQL 4.1 （或以上版本）4.1直接支持Unicode，以下版本支持的不好。

2 驱动： MySQL JDBC Driver的3.0.16（或以上版本）

3 在数据库中做如下设定

pic5.JPG

4 在建立表时同样加上ENGINE=MyISAM DEFAULT CHARSET=gbk
1CREATE TABLE `students` (
2  `id` int(20) NOT NULL default '0',
3  `name` varchar(20) NOT NULL default '',
4  `department_id` int(11) default NULL,
5  `password` varchar(20) default NULL,
6  `score` double(15,3) default NULL,
7  PRIMARY KEY  (`id`)
8) ENGINE=MyISAM DEFAULT CHARSET=gbk
9

5 配置hibernate.cfg.xml
1 <property name="connection.url">jdbc:mysql://localhost:3306/Studentproperty>
2 <property name="dialect">net.sf.hibernate.dialect.MySQLDialectproperty>
3 <property name="connection.password">property>
4 <property name="connection.driver_class">com.mysql.jdbc.Driverproperty>
5 

robbin： MySQL JDBC Driver的3.0.16也是一个分水岭，3.0.16版本会取数据库本身的编码，然后按照该编码转换，这种方式和Oracle的JDBC Driver是一样的。例如你的数据库是GBK编码的话，JDBC Driver就会把数据库里面的取出来的字符串按照GBK往unicode转换，送给JVM。因此正确的设置数据库本身的编码就尤为重要。

MySQL JDBC Driver3.0.16以下的版本则不然，它不会那么智能的根据数据库编码来确定如何转换，它总是默认使用ISO8859-1，因此你必须使用 characterEncoding=GBK来强制他把数据库中取出来的字符串按照GBK来往unicode转换。
因此，使用什么数据库版本，不管是3.x，还是4.0.x还是4.1.x，其实对我们来说不重要，重要的有二：

1) 正确的设定数据库编码，MySQL4.0以下版本的字符集总是默认ISO8859-1，MySQL4.1在安装的时候会让你选择。如果你准备使用UTF- 8，那么在创建数据库的时候就要指定好UTF-8(创建好以后也可以改，4.1以上版本还可以单独指定表的字符集)
2) 使用3.0.16以上版本的JDBC Driver，那么你就不需要再写什么characterEncoding=UTF-8

 

6 开发工具介绍

MyEclipse 3.8

首先添加用户库，如下图将Struts,Spring,Hibernate 的库添加到用户库中

pic6.JPG

如果出现环境问题可能你的Struts包有问题，请到http://struts.apache.org/download.cgi下载struts-1.2.7-lib.zip 。

具体使用参考http://www.laliluna.de/struts-hibernate-integration-tutorial-en.html

总结

本文至此已将Struts+Sprng+Hibernate的大致思路以及本人所遇到的难点，重点介绍完了。

其中管理员我只完成了对学生的部分，其他功能大同小异，有兴趣的读者不妨动手试试。最后建议初学者不要直接使用Spring对Hibernate的封装，而是从Hibernate学起，先要学会自己管理Session，Transaction，然后在用Spring，这样理解会更深刻。同时如果你有好的建议，或问题请联系我

QQ 39315890

Email: mill_lmq@yahoo.com.cn

参考：

Spring Framework之最佳实践：

http://www.gpowersoft.com/tech/Spring/

Hibernate+Spring 对DAO的处理实列

http://www.javaeye.com/viewtopic.php?t=7923&start=0&postdays=0&postorder=asc&highlight=

Hibernate实现分页查询的原理分析

http://forum.javaeye.com/viewtopic.php?t=261&start=0&postdays=0&postorder=asc&highlight=

Spring的DAO设计实践

http://www.hibernate.org.cn/viewtopic.php?t=8224&start=0&postdays=0&postorder=asc&highlight=

用 OpenSessionInViewInterceptor 的思路解决Hibernate Lazy问题

http://www.javaeye.com/viewtopic.php?t=14631&start=0&postdays=0&postorder=asc&highlight=

上一篇    下一篇    （kukoo的分类目录[Java]中共10篇）  
相关文章
• Eclipse快速上手Hibernate--8.关联映射(多对多)   05.11.11  from joes
• Eclipse快速上手Hibernate--7.关联映射(一对多)(2)   05.11.11  from joes
• Eclipse快速上手Hibernate--6.关联映射(一对一)(1)   05.11.11  from joes
• Eclipse快速上手Hibernate--5.组件映射   05.11.11  from joes
• Eclipse快速上手Hibernate--4.继承映射(3)   05.11.11  from joes<img src ="http://www.blogjava.net/jackybu/aggbug/19546.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jackybu/" target="_blank">辰</a> 2005-11-13 08:14 <a href="http://www.blogjava.net/jackybu/articles/19546.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>JSP中的全文检索&lt;from:blog.csdn.net/leshui&gt;</title><link>http://www.blogjava.net/jackybu/articles/2512.html</link><dc:creator>辰</dc:creator><author>辰</author><pubDate>Mon, 28 Mar 2005 02:02:00 GMT</pubDate><guid>http://www.blogjava.net/jackybu/articles/2512.html</guid><wfw:comment>http://www.blogjava.net/jackybu/comments/2512.html</wfw:comment><comments>http://www.blogjava.net/jackybu/articles/2512.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jackybu/comments/commentRss/2512.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jackybu/services/trackbacks/2512.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 全文检索一直都是web方面的关键技术，如何在浩如烟海的信息中找到自己想要的信息是人们最关心的。鼎鼎大名的GOOGLE就是一个很成功的例子，网络上的人们大部分都用GOOGLE来查找自己需要的内容。全文检索主要有两个技术指标：快速和精确。前一段时间做了一个新闻系统，老板要加上全文检索的功能，想了很久才用一个不太高明的方法实现了。现在分享一下，希望是抛砖引玉吧，如果大家有更好的办法请跟在后边：）先介...&nbsp;&nbsp;<a href='http://www.blogjava.net/jackybu/articles/2512.html'>阅读全文</a><img src ="http://www.blogjava.net/jackybu/aggbug/2512.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jackybu/" target="_blank">辰</a> 2005-03-28 10:02 <a href="http://www.blogjava.net/jackybu/articles/2512.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>JAVA中的时间操作</title><link>http://www.blogjava.net/jackybu/articles/2511.html</link><dc:creator>辰</dc:creator><author>辰</author><pubDate>Mon, 28 Mar 2005 01:58:00 GMT</pubDate><guid>http://www.blogjava.net/jackybu/articles/2511.html</guid><wfw:comment>http://www.blogjava.net/jackybu/comments/2511.html</wfw:comment><comments>http://www.blogjava.net/jackybu/articles/2511.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jackybu/comments/commentRss/2511.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jackybu/services/trackbacks/2511.html</trackback:ping><description><![CDATA[<P class=MsoNormal style="TEXT-INDENT: 24pt; mso-char-indent-count: 2.0; mso-char-indent-size: 12.0pt"><SPAN style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体">经常看见<SPAN lang=EN-US>jsp版里有人问时间操作的问题，这些问题一般包括：取当前时间，把一个指定的字符串时间转化成时间类型，求两个时间之间的天数，求一段时间以前的时间，求一段时间以后的时间，在这里就把这些问题汇总一下。<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /><o:p></o:p></SPAN></SPAN></P>
<P class=MsoNormal style="TEXT-INDENT: 24pt; mso-char-indent-count: 2.0; mso-char-indent-size: 12.0pt"><SPAN lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体">&lt;%@<SPAN style="mso-spacerun: yes">&nbsp; </SPAN>page<SPAN style="mso-spacerun: yes">&nbsp; </SPAN>contentType="text/html;charset=gb2312"%&gt;<o:p></o:p></SPAN></P>
<P class=MsoNormal style="TEXT-INDENT: 24pt; mso-char-indent-count: 2.0; mso-char-indent-size: 12.0pt"><SPAN lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体">&lt;%@ page import="java.text.*"%&gt;<o:p></o:p></SPAN></P>
<P class=MsoNormal style="TEXT-INDENT: 24pt; mso-char-indent-count: 2.0; mso-char-indent-size: 12.0pt"><SPAN lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体">&lt;%@ page import="java.util.*"%&gt;<o:p></o:p></SPAN></P>
<P class=MsoNormal style="TEXT-INDENT: 24pt; mso-char-indent-count: 2.0; mso-char-indent-size: 12.0pt"><SPAN lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体">&lt;%<o:p></o:p></SPAN></P>
<P class=MsoNormal style="TEXT-INDENT: 24pt; mso-char-indent-count: 2.0; mso-char-indent-size: 12.0pt"><SPAN lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体">//字符串转化成时间类型（字符串可以是任意类型，只要和SimpleDateFormat中的格式一致即可）<o:p></o:p></SPAN></P>
<P class=MsoNormal style="TEXT-INDENT: 24pt; mso-char-indent-count: 2.0; mso-char-indent-size: 12.0pt"><SPAN lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体">java.text.SimpleDateFormat sdf = new java.text.SimpleDateFormat("M/dd/yyyy hh:mm:ss a",java.util.Locale.US);<o:p></o:p></SPAN></P>
<P class=MsoNormal style="TEXT-INDENT: 24pt; mso-char-indent-count: 2.0; mso-char-indent-size: 12.0pt"><SPAN lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体">java.util.Date d = sdf.parse("5/13/2003 10:31:37 AM");<SPAN style="mso-spacerun: yes">&nbsp; </SPAN><o:p></o:p></SPAN></P>
<P class=MsoNormal style="TEXT-INDENT: 24pt; mso-char-indent-count: 2.0; mso-char-indent-size: 12.0pt"><SPAN lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体">out.println(d);<o:p></o:p></SPAN></P>
<P class=MsoNormal style="TEXT-INDENT: 24pt; mso-char-indent-count: 2.0; mso-char-indent-size: 12.0pt"><SPAN lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体">out.println("&lt;br&gt;");<o:p></o:p></SPAN></P>
<P class=MsoNormal style="TEXT-INDENT: 24pt; mso-char-indent-count: 2.0; mso-char-indent-size: 12.0pt"><SPAN lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体">SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");<o:p></o:p></SPAN></P>
<P class=MsoNormal style="TEXT-INDENT: 24pt; mso-char-indent-count: 2.0; mso-char-indent-size: 12.0pt"><SPAN lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体">String mDateTime1=formatter.format(d);<o:p></o:p></SPAN></P>
<P class=MsoNormal style="TEXT-INDENT: 24pt; mso-char-indent-count: 2.0; mso-char-indent-size: 12.0pt"><SPAN lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体">out.println(mDateTime1);<o:p></o:p></SPAN></P>
<P class=MsoNormal style="TEXT-INDENT: 24pt; mso-char-indent-count: 2.0; mso-char-indent-size: 12.0pt"><SPAN lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体">out.println("&lt;br&gt;");<o:p></o:p></SPAN></P>
<P class=MsoNormal style="TEXT-INDENT: 24pt; mso-char-indent-count: 2.0; mso-char-indent-size: 12.0pt"><SPAN lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体">out.println(d.getTime());<o:p></o:p></SPAN></P>
<P class=MsoNormal style="TEXT-INDENT: 24pt; mso-char-indent-count: 2.0; mso-char-indent-size: 12.0pt"><SPAN lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体">out.println("&lt;br&gt;");<o:p></o:p></SPAN></P>
<P class=MsoNormal style="TEXT-INDENT: 24pt; mso-char-indent-count: 2.0; mso-char-indent-size: 12.0pt"><SPAN lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体"><SPAN style="mso-spacerun: yes">&nbsp;&nbsp; </SPAN>//当前时间<o:p></o:p></SPAN></P>
<P class=MsoNormal style="TEXT-INDENT: 24pt; mso-char-indent-count: 2.0; mso-char-indent-size: 12.0pt"><SPAN lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体"><SPAN style="mso-spacerun: yes">&nbsp;&nbsp; </SPAN>Calendar cal<SPAN style="mso-spacerun: yes">&nbsp; </SPAN>= Calendar.getInstance();<o:p></o:p></SPAN></P>
<P class=MsoNormal style="TEXT-INDENT: 24pt; mso-char-indent-count: 2.0; mso-char-indent-size: 12.0pt"><SPAN lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体"><SPAN style="mso-spacerun: yes">&nbsp;</SPAN>//<SPAN style="mso-spacerun: yes">&nbsp; </SPAN>SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd<SPAN style="mso-spacerun: yes">&nbsp; </SPAN>HH:mm:ss");<o:p></o:p></SPAN></P>
<P class=MsoNormal style="TEXT-INDENT: 24pt; mso-char-indent-count: 2.0; mso-char-indent-size: 12.0pt"><SPAN lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体">SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd<SPAN style="mso-spacerun: yes">&nbsp; </SPAN>HH:mm:ss G E D F w W a E F");<o:p></o:p></SPAN></P>
<P class=MsoNormal style="TEXT-INDENT: 24pt; mso-char-indent-count: 2.0; mso-char-indent-size: 12.0pt"><SPAN lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体"><SPAN style="mso-spacerun: yes">&nbsp;&nbsp; </SPAN>String mDateTime=formatter.format(cal.getTime());<o:p></o:p></SPAN></P>
<P class=MsoNormal style="TEXT-INDENT: 24pt; mso-char-indent-count: 2.0; mso-char-indent-size: 12.0pt"><SPAN lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体"><SPAN style="mso-spacerun: yes">&nbsp;&nbsp; </SPAN>out.println(mDateTime);<o:p></o:p></SPAN></P>
<P class=MsoNormal style="TEXT-INDENT: 24pt; mso-char-indent-count: 2.0; mso-char-indent-size: 12.0pt"><SPAN lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体"><SPAN style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp; </SPAN>out.println("&lt;br&gt;");<o:p></o:p></SPAN></P>
<P class=MsoNormal style="TEXT-INDENT: 24pt; mso-char-indent-count: 2.0; mso-char-indent-size: 12.0pt"><SPAN lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体"><SPAN style="mso-spacerun: yes">&nbsp;&nbsp; </SPAN>//1年前日期<o:p></o:p></SPAN></P>
<P class=MsoNormal style="TEXT-INDENT: 24pt; mso-char-indent-count: 2.0; mso-char-indent-size: 12.0pt"><SPAN lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体"><SPAN style="mso-spacerun: yes">&nbsp;&nbsp; </SPAN>java.util.Date myDate=new java.util.Date();<SPAN style="mso-spacerun: yes">&nbsp; </SPAN><o:p></o:p></SPAN></P>
<P class=MsoNormal style="TEXT-INDENT: 24pt; mso-char-indent-count: 2.0; mso-char-indent-size: 12.0pt"><SPAN lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体"><SPAN style="mso-spacerun: yes">&nbsp;&nbsp; </SPAN>long myTime=(myDate.getTime()/1000)-60*60*24*365;<o:p></o:p></SPAN></P>
<P class=MsoNormal style="TEXT-INDENT: 24pt; mso-char-indent-count: 2.0; mso-char-indent-size: 12.0pt"><SPAN lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体"><SPAN style="mso-spacerun: yes">&nbsp;&nbsp; </SPAN>myDate.setTime(myTime*1000);<o:p></o:p></SPAN></P>
<P class=MsoNormal style="TEXT-INDENT: 24pt; mso-char-indent-count: 2.0; mso-char-indent-size: 12.0pt"><SPAN lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体"><SPAN style="mso-spacerun: yes">&nbsp;&nbsp; </SPAN>String mDate=formatter.format(myDate);<o:p></o:p></SPAN></P>
<P class=MsoNormal style="TEXT-INDENT: 24pt; mso-char-indent-count: 2.0; mso-char-indent-size: 12.0pt"><SPAN lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体"><SPAN style="mso-spacerun: yes">&nbsp;&nbsp; </SPAN>out.println(mDate);<o:p></o:p></SPAN></P>
<P class=MsoNormal style="TEXT-INDENT: 24pt; mso-char-indent-count: 2.0; mso-char-indent-size: 12.0pt"><SPAN lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体"><SPAN style="mso-spacerun: yes">&nbsp;&nbsp; </SPAN>out.println("&lt;br&gt;");<o:p></o:p></SPAN></P>
<P class=MsoNormal style="TEXT-INDENT: 24pt; mso-char-indent-count: 2.0; mso-char-indent-size: 12.0pt"><SPAN lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体"><SPAN style="mso-spacerun: yes">&nbsp;&nbsp; </SPAN>//明天日期<o:p></o:p></SPAN></P>
<P class=MsoNormal style="TEXT-INDENT: 24pt; mso-char-indent-count: 2.0; mso-char-indent-size: 12.0pt"><SPAN lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体"><SPAN style="mso-spacerun: yes">&nbsp;&nbsp; </SPAN>myDate=new java.util.Date(); <o:p></o:p></SPAN></P>
<P class=MsoNormal style="TEXT-INDENT: 24pt; mso-char-indent-count: 2.0; mso-char-indent-size: 12.0pt"><SPAN lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体"><SPAN style="mso-spacerun: yes">&nbsp;&nbsp; </SPAN>myTime=(myDate.getTime()/1000)+60*60*24;<o:p></o:p></SPAN></P>
<P class=MsoNormal style="TEXT-INDENT: 24pt; mso-char-indent-count: 2.0; mso-char-indent-size: 12.0pt"><SPAN lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体"><SPAN style="mso-spacerun: yes">&nbsp;&nbsp; </SPAN>myDate.setTime(myTime*1000);<o:p></o:p></SPAN></P>
<P class=MsoNormal style="TEXT-INDENT: 24pt; mso-char-indent-count: 2.0; mso-char-indent-size: 12.0pt"><SPAN lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体"><SPAN style="mso-spacerun: yes">&nbsp;&nbsp; </SPAN>mDate=formatter.format(myDate);<o:p></o:p></SPAN></P>
<P class=MsoNormal style="TEXT-INDENT: 24pt; mso-char-indent-count: 2.0; mso-char-indent-size: 12.0pt"><SPAN lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体"><SPAN style="mso-spacerun: yes">&nbsp;&nbsp; </SPAN>out.println(mDate);<o:p></o:p></SPAN></P>
<P class=MsoNormal style="TEXT-INDENT: 24pt; mso-char-indent-count: 2.0; mso-char-indent-size: 12.0pt"><SPAN lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体"><SPAN style="mso-spacerun: yes">&nbsp;&nbsp; </SPAN>out.println("&lt;br&gt;");<o:p></o:p></SPAN></P>
<P class=MsoNormal style="TEXT-INDENT: 24pt; mso-char-indent-count: 2.0; mso-char-indent-size: 12.0pt"><SPAN lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体"><SPAN style="mso-spacerun: yes">&nbsp; </SPAN>//两个时间之间的天数<o:p></o:p></SPAN></P>
<P class=MsoNormal style="TEXT-INDENT: 24pt; mso-char-indent-count: 2.0; mso-char-indent-size: 12.0pt"><SPAN lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体"><SPAN style="mso-spacerun: yes">&nbsp;&nbsp; </SPAN>SimpleDateFormat myFormatter = new SimpleDateFormat("yyyy-MM-dd");<o:p></o:p></SPAN></P>
<P class=MsoNormal style="TEXT-INDENT: 24pt; mso-char-indent-count: 2.0; mso-char-indent-size: 12.0pt"><SPAN lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体"><SPAN style="mso-spacerun: yes">&nbsp;&nbsp; </SPAN>java.util.Date date= myFormatter.parse("2003-05-1"); <o:p></o:p></SPAN></P>
<P class=MsoNormal style="TEXT-INDENT: 24pt; mso-char-indent-count: 2.0; mso-char-indent-size: 12.0pt"><SPAN lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体"><SPAN style="mso-spacerun: yes">&nbsp;&nbsp; </SPAN>java.util.Date mydate= myFormatter.parse("1899-12-30");<o:p></o:p></SPAN></P>
<P class=MsoNormal style="TEXT-INDENT: 24pt; mso-char-indent-count: 2.0; mso-char-indent-size: 12.0pt"><SPAN lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体"><SPAN style="mso-spacerun: yes">&nbsp;&nbsp; </SPAN>long<SPAN style="mso-spacerun: yes">&nbsp; </SPAN>day=(date.getTime()-mydate.getTime())/(24*60*60*1000);<o:p></o:p></SPAN></P>
<P class=MsoNormal style="TEXT-INDENT: 24pt; mso-char-indent-count: 2.0; mso-char-indent-size: 12.0pt"><SPAN lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体"><SPAN style="mso-spacerun: yes">&nbsp;&nbsp; </SPAN>out.println(day);<o:p></o:p></SPAN></P>
<P class=MsoNormal style="TEXT-INDENT: 24pt; mso-char-indent-count: 2.0; mso-char-indent-size: 12.0pt"><SPAN lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体"><SPAN style="mso-spacerun: yes">&nbsp;&nbsp; </SPAN>out.println("&lt;br&gt;");<o:p></o:p></SPAN></P>
<P class=MsoNormal style="TEXT-INDENT: 24pt; mso-char-indent-count: 2.0; mso-char-indent-size: 12.0pt"><SPAN lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体"><SPAN style="mso-spacerun: yes">&nbsp;</SPAN><o:p></o:p></SPAN></P>
<P class=MsoNormal style="TEXT-INDENT: 24pt; mso-char-indent-count: 2.0; mso-char-indent-size: 12.0pt"><SPAN lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体">//加半小时<o:p></o:p></SPAN></P>
<P class=MsoNormal style="TEXT-INDENT: 24pt; mso-char-indent-count: 2.0; mso-char-indent-size: 12.0pt"><SPAN lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体">SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");<o:p></o:p></SPAN></P>
<P class=MsoNormal style="TEXT-INDENT: 24pt; mso-char-indent-count: 2.0; mso-char-indent-size: 12.0pt"><SPAN lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体">java.util.Date date1 = format.parse("2002-02-28 23:16:00");<o:p></o:p></SPAN></P>
<P class=MsoNormal style="TEXT-INDENT: 24pt; mso-char-indent-count: 2.0; mso-char-indent-size: 12.0pt"><SPAN lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体">long Time=(date1.getTime()/1000)+60*30;<o:p></o:p></SPAN></P>
<P class=MsoNormal style="TEXT-INDENT: 24pt; mso-char-indent-count: 2.0; mso-char-indent-size: 12.0pt"><SPAN lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体">date1.setTime(Time*1000);<o:p></o:p></SPAN></P>
<P class=MsoNormal style="TEXT-INDENT: 24pt; mso-char-indent-count: 2.0; mso-char-indent-size: 12.0pt"><SPAN lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体">String mydate1=formatter.format(date1);<o:p></o:p></SPAN></P>
<P class=MsoNormal style="TEXT-INDENT: 24pt; mso-char-indent-count: 2.0; mso-char-indent-size: 12.0pt"><SPAN lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体">out.println(mydate1);<o:p></o:p></SPAN></P>
<P class=MsoNormal style="TEXT-INDENT: 24pt; mso-char-indent-count: 2.0; mso-char-indent-size: 12.0pt"><SPAN lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体">out.println("&lt;br&gt;");<o:p></o:p></SPAN></P>
<P class=MsoNormal style="TEXT-INDENT: 24pt; mso-char-indent-count: 2.0; mso-char-indent-size: 12.0pt"><SPAN lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体">&nbsp;<o:p></o:p></SPAN></P>
<P class=MsoNormal style="TEXT-INDENT: 24pt; mso-char-indent-count: 2.0; mso-char-indent-size: 12.0pt"><SPAN lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体"><SPAN style="mso-spacerun: yes">&nbsp; </SPAN><o:p></o:p></SPAN></P>
<P class=MsoNormal style="TEXT-INDENT: 24pt; mso-char-indent-count: 2.0; mso-char-indent-size: 12.0pt"><SPAN lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体">//年月周求日期<o:p></o:p></SPAN></P>
<P class=MsoNormal style="TEXT-INDENT: 24pt; mso-char-indent-count: 2.0; mso-char-indent-size: 12.0pt"><SPAN lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体">SimpleDateFormat formatter2 = new SimpleDateFormat("yyyy-MM F E");<o:p></o:p></SPAN></P>
<P class=MsoNormal style="TEXT-INDENT: 24pt; mso-char-indent-count: 2.0; mso-char-indent-size: 12.0pt"><SPAN lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体">java.util.Date date2= formatter2.parse("2003-05 5 星期五"); <o:p></o:p></SPAN></P>
<P class=MsoNormal style="TEXT-INDENT: 24pt; mso-char-indent-count: 2.0; mso-char-indent-size: 12.0pt"><SPAN lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体">SimpleDateFormat formatter3 = new SimpleDateFormat("yyyy-MM-dd");<o:p></o:p></SPAN></P>
<P class=MsoNormal style="TEXT-INDENT: 24pt; mso-char-indent-count: 2.0; mso-char-indent-size: 12.0pt"><SPAN lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体">String mydate2=formatter3.format(date2);<o:p></o:p></SPAN></P>
<P class=MsoNormal style="TEXT-INDENT: 24pt; mso-char-indent-count: 2.0; mso-char-indent-size: 12.0pt"><SPAN lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体">out.println(mydate2);<o:p></o:p></SPAN></P>
<P class=MsoNormal style="TEXT-INDENT: 24pt; mso-char-indent-count: 2.0; mso-char-indent-size: 12.0pt"><SPAN lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体">out.println("&lt;br&gt;");<o:p></o:p></SPAN></P>
<P class=MsoNormal style="TEXT-INDENT: 24pt; mso-char-indent-count: 2.0; mso-char-indent-size: 12.0pt"><SPAN lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体">//求是星期几<o:p></o:p></SPAN></P>
<P class=MsoNormal style="TEXT-INDENT: 24pt; mso-char-indent-count: 2.0; mso-char-indent-size: 12.0pt"><SPAN lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体">mydate= myFormatter.parse("2001-1-1");<o:p></o:p></SPAN></P>
<P class=MsoNormal style="TEXT-INDENT: 24pt; mso-char-indent-count: 2.0; mso-char-indent-size: 12.0pt"><SPAN lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体">SimpleDateFormat formatter4 = new SimpleDateFormat("E");<o:p></o:p></SPAN></P>
<P class=MsoNormal style="TEXT-INDENT: 24pt; mso-char-indent-count: 2.0; mso-char-indent-size: 12.0pt"><SPAN lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体">String mydate3=formatter4.format(mydate);<o:p></o:p></SPAN></P>
<P class=MsoNormal style="TEXT-INDENT: 24pt; mso-char-indent-count: 2.0; mso-char-indent-size: 12.0pt"><SPAN lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体">out.println(mydate3);<o:p></o:p></SPAN></P>
<P class=MsoNormal style="TEXT-INDENT: 24pt; mso-char-indent-count: 2.0; mso-char-indent-size: 12.0pt"><SPAN lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体">out.println("&lt;br&gt;");<o:p></o:p></SPAN></P>
<P class=MsoNormal style="TEXT-INDENT: 24pt; mso-char-indent-count: 2.0; mso-char-indent-size: 12.0pt"><SPAN lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体">%&gt;<o:p></o:p></SPAN></P><img src ="http://www.blogjava.net/jackybu/aggbug/2511.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jackybu/" target="_blank">辰</a> 2005-03-28 09:58 <a href="http://www.blogjava.net/jackybu/articles/2511.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Ant应用(1)</title><link>http://www.blogjava.net/jackybu/articles/2407.html</link><dc:creator>辰</dc:creator><author>辰</author><pubDate>Thu, 24 Mar 2005 06:10:00 GMT</pubDate><guid>http://www.blogjava.net/jackybu/articles/2407.html</guid><wfw:comment>http://www.blogjava.net/jackybu/comments/2407.html</wfw:comment><comments>http://www.blogjava.net/jackybu/articles/2407.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jackybu/comments/commentRss/2407.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jackybu/services/trackbacks/2407.html</trackback:ping><description><![CDATA[<TABLE cellSpacing=1 cellPadding=1 width=750 align=center border=0>
<TBODY>
<TR>
<TD width=750>
<TABLE cellSpacing=1 cellPadding=1 width="98%" border=0>
<TBODY>
<TR>
<TD><SPAN class=date>张利海 于 2004年11月13日 23:16 发表</SPAN> </TD></TR>
<TR>
<TD>关键词 : java log4j ant Hibernate apache</TD></TR>
<TR>
<TD>
<P><FONT size=2>这是我写的ANT的培训内容，还不是很全，只有基本的内容：<BR>1 Ant是什么？ <BR>Apache Ant 是一个基于 Java的生成工具。<BR>生成工具在软件开发中用来将源代码和其他输入文件转换为可执行文件的形式（也有可能转换为可安装的产品映像形式）。随着应用程序的生成过程变得更加复杂，确保在每次生成期间都使用精确相同的生成步骤，同时实现尽可能多的自动化，以便及时产生一致的生成版本<BR>2 下载、安装Ant <BR>安装Ant<BR>下载.zip文件，解压缩到c:ant1.3(后面引用为%ANT_HOME%)<BR><BR>2.1 在你运行Ant之前需要做一些配置工作。<BR>? 将bin目录加入PATH环境变量。 <BR>? 设定ANT_HOME环境变量，指向你安装Ant的目录。在一些OS上，Ant的脚本可以猜测ANT_HOME（Unix和Windos NT/2000）－但最好不要依赖这一特性。 <BR>? 可选地，设定JAVA_HOME环境变量（参考下面的高级小节），该变量应该指向你安装JDK的目录。<BR>注意：不要将Ant的ant.jar文件放到JDK/JRE的lib/ext目录下。Ant是个应用程序，而lib/ext目录是为JDK扩展使用的（如JCE，JSSE扩展）。而且通过扩展装入的类会有安全方面的限制。<BR>2.2 运行Ant <BR><BR>运行Ant非常简单，当你正确地安装Ant后，只要输入ant就可以了。<BR><BR>? 没有指定任何参数时，Ant会在当前目录下查询build.xml文件。如果找到了就用该文件作为buildfile。如果你用 -find 选项。Ant就会在上级目录中寻找buildfile，直至到达文件系统的根。要想让Ant使用其他的buildfile，可以用参数 -buildfile file，这里file指定了你想使用的buildfile。<BR><BR>? 可以指定执行一个或多个target。当省略target时，Ant使用标签&lt;project&gt;的default属性所指定的target。<BR><BR><BR>命令行选项总结：<BR>ant [options] [target [target2 [target3] ...]]<BR>Options:<BR>-help print this message<BR>-projecthelp print project help information<BR>-version print the version information and exit<BR>-quiet be extra quiet<BR>-verbose be extra verbose<BR>-debug print debugging information<BR>-emacs produce logging information without adornments<BR>-logfile file use given file for log output<BR>-logger classname the class that is to perform logging<BR>-listener classname add an instance of class as a project listener<BR>-buildfile file use specified buildfile<BR>-find file search for buildfile towards the root of the filesystem and use the first one found<BR>-Dproperty=value set property to value <BR>例子<BR>ant<BR>使用当前目录下的build.xml运行Ant，执行缺省的target。<BR>ant -buildfile test.xml<BR>使用当前目录下的test.xml运行Ant，执行缺省的target。<BR>ant -buildfile test.xml dist<BR>使用当前目录下的test.xml运行Ant，执行一个叫做dist的target。<BR>ant -buildfile test.xml -Dbuild=build/classes dist<BR>使用当前目录下的test.xml运行Ant，执行一个叫做dist的target，并设定build属性的值为build/classes。<BR><BR>3 编写build.xml <BR><BR>Ant的buildfile是用XML写的。每个buildfile含有一个project。<BR><BR>buildfile中每个task元素可以有一个id属性，可以用这个id值引用指定的任务。这个值必须是唯一的。（详情请参考下面的Task小节）<BR><BR>3.1 Projects<BR><BR>project有下面的属性：<BR>Attribute Description Required<BR>name 项目名称. No<BR>default 当没有指定target时使用的缺省target Yes<BR>basedir 用于计算所有其他路径的基路径。该属性可以被basedir property覆盖。当覆盖时，该属性被忽略。如果属性和basedir property都没有设定，就使用buildfile文件的父目录。 No<BR>项目的描述以一个顶级的&lt;description&gt;元素的形式出现（参看description小节）。<BR><BR>一个项目可以定义一个或多个target。一个target是一系列你想要执行的。执行Ant时，你可以选择执行那个target。当没有给定target时，使用project的default属性所确定的target。<BR><BR>3.2 Targets<BR><BR>一个target可以依赖于其他的target。例如，你可能会有一个target用于编译程序，一个target用于生成可执行文件。你在生成可执行文件之前必须先编译通过，所以生成可执行文件的target依赖于编译target。Ant会处理这种依赖关系。<BR><BR>然而，应当注意到，Ant的depends属性只指定了target应该被执行的顺序－如果被依赖的target无法运行，这种depends对于指定了依赖关系的target就没有影响。<BR><BR>Ant会依照depends属性中target出现的顺序（从左到右）依次执行每个target。然而，要记住的是只要某个target依赖于一个target，后者就会被先执行。<BR>&lt;target name="A"/&gt;<BR>&lt;target name="B" depends="A"/&gt;<BR>&lt;target name="C" depends="B"/&gt;<BR>&lt;target name="D" depends="C,B,A"/&gt;<BR>假定我们要执行target D。从它的依赖属性来看，你可能认为先执行C，然后B，最后A被执行。错了，C依赖于B，B依赖于A，所以先执行A，然后B，然后C，最后D被执行。<BR><BR>一个target只能被执行一次，即时有多个target依赖于它（看上面的例子）。<BR><BR>如果（或如果不）某些属性被设定，才执行某个target。这样，允许根据系统的状态（java version, OS, 命令行属性定义等等）来更好地控制build的过程。要想让一个target这样做，你就应该在target元素中，加入if（或unless）属性，带上target因该有所判断的属性。例如：<BR>&lt;target name="build-module-A" if="module-A-present"/&gt;<BR>&lt;target name="build-own-fake-module-A" unless="module-A-present"/&gt;<BR>如果没有if或unless属性，target总会被执行。<BR><BR>可选的description属性可用来提供关于target的一行描述，这些描述可由-projecthelp命令行选项输出。<BR><BR>将你的tstamp task在一个所谓的初始化target是很好的做法，其他的target依赖这个初始化target。要确保初始化target是出现在其他target依赖表中的第一个target。在本手册中大多数的初始化target的名字是"init"。<BR><BR>target有下面的属性：<BR>Attribute Description Required<BR>name target的名字 Yes<BR>depends 用逗号分隔的target的名字列表，也就是依赖表。 No<BR>if 执行target所需要设定的属性名。 No<BR>unless 执行target需要清除设定的属性名。 No<BR>description 关于target功能的简短描述。 No<BR><BR>3.3 Tasks<BR><BR>一个task是一段可执行的代码。<BR><BR>一个task可以有多个属性（如果你愿意的话，可以将其称之为变量）。属性只可能包含对property的引用。这些引用会在task执行前被解析。<BR><BR>下面是Task的一般构造形式：<BR>&lt;name attribute1="value1" attribute2="value2" ... /&gt;<BR>这里name是task的名字，attributeN是属性名，valueN是属性值。<BR><BR>有一套内置的（built-in）task，以及一些可选task，但你也可以编写自己的task。<BR><BR>所有的task都有一个task名字属性。Ant用属性值来产生日志信息。<BR><BR>可以给task赋一个id属性：<BR>&lt;taskname id="taskID" ... /&gt;<BR>这里taskname是task的名字，而taskID是这个task的唯一标识符。通过这个标识符，你可以在脚本中引用相应的task。例如，在脚本中你可以这样：<BR>&lt;script ... &gt;<BR>task1.setFoo("bar");<BR>&lt;/script&gt;<BR>设定某个task实例的foo属性。在另一个task中（用java编写），你可以利用下面的语句存取相应的实例。<BR>project.getReference("task1").<BR>注意1：如果task1还没有运行，就不会被生效（例如：不设定属性），如果你在随后配置它，你所作的一切都会被覆盖。<BR><BR>注意2：未来的Ant版本可能不会兼容这里所提的属性，因为很有可能根本没有task实例，只有proxies。<BR><BR>3.4 Properties<BR><BR>一个project可以有很多的properties。可以在buildfile中用property task来设定，或在Ant之外设定。一个property有一个名字和一个值。property可用于task的属性值。这是通过将属性名放在"${"和"}"之间并放在属性值的位置来实现的。例如如果有一个property builddir的值是"build"，这个property就可用于属性值：${builddir}/classes。这个值就可被解析为build/classes。<BR><BR>内置属性<BR><BR>如果你使用了&lt;property&gt; task 定义了所有的系统属性，Ant允许你使用这些属性。例如，${os.name}对应操作系统的名字。<BR><BR>要想得到系统属性的列表可参考the Javadoc of System.getProperties。<BR><BR>除了Java的系统属性，Ant还定义了一些自己的内置属性： <BR>basedir project基目录的绝对路径 (与&lt;project&gt;的basedir属性一样)。<BR>ant.file buildfile的绝对路径。<BR>ant.version Ant的版本。<BR>ant.project.name 当前执行的project的名字；由&lt;project&gt;的name属性设定.<BR>ant.java.version Ant检测到的JVM的版本； 目前的值有"1.1", "1.2", "1.3" and "1.4".<BR><BR>例子<BR>&lt;project name="MyProject" default="dist" basedir="."&gt; <BR><BR>&lt;!-- set global properties for this build --&gt;<BR>&lt;property name="src" value="."/&gt;<BR>&lt;property name="build" value="build"/&gt;<BR>&lt;property name="dist" value="dist"/&gt; <BR><BR>&lt;target name="init"&gt;<BR>&lt;!-- Create the time stamp --&gt;<BR>&lt;tstamp/&gt;<BR>&lt;!-- Create the build directory structure used by compile --&gt;<BR>&lt;mkdir dir="${build}"/&gt;<BR>&lt;/target&gt;<BR><BR>&lt;target name="compile" depends="init"&gt;<BR>&lt;!-- Compile the java code from ${src} into ${build} --&gt;<BR>&lt;javac srcdir="${src}" destdir="${build}"/&gt;<BR>&lt;/target&gt;<BR><BR>&lt;target name="dist" depends="compile"&gt;<BR>&lt;!-- Create the distribution directory --&gt;<BR>&lt;mkdir dir="${dist}/lib"/&gt;<BR>&lt;!-- Put everything in ${build} into the MyProject-${DSTAMP}.jar file --&gt;<BR>&lt;jar jarfile="${dist}/lib/MyProject-${DSTAMP}.jar" basedir="${build}"/&gt;<BR>&lt;/target&gt;<BR><BR>&lt;target name="clean"&gt;<BR>&lt;!-- Delete the ${build} and ${dist} directory trees --&gt;<BR>&lt;delete dir="${build}"/&gt;<BR>&lt;delete dir="${dist}"/&gt;<BR>&lt;/target&gt;<BR><BR>&lt;/project&gt;<BR><BR>3.5 Path-like Structures<BR>你可以用":"和";"作为分隔符，指定类似PATH和CLASSPATH的引用。Ant会把分隔符转换为当前系统所用的分隔符。<BR><BR>当需要指定类似路径的值时，可以使用嵌套元素。一般的形式是<BR>&lt;classpath&gt;<BR>&lt;pathelement path="${classpath}"/&gt;<BR>&lt;pathelement location="lib/helper.jar"/&gt;<BR>&lt;/classpath&gt;<BR>location属性指定了相对于project基目录的一个文件和目录，而path属性接受逗号或分号分隔的一个位置列表。path属性一般用作预定义的路径－－其他情况下，应该用多个location属性。<BR><BR>为简洁起见，classpath标签支持自己的path和location属性。所以：<BR>&lt;classpath&gt;<BR>&lt;pathelement path="${classpath}"/&gt;<BR>&lt;/classpath&gt;<BR>可以被简写作：<BR>&lt;classpath path="${classpath}"/&gt;<BR>也可通过&lt;fileset&gt;元素指定路径。构成一个fileset的多个文件加入path-like structure的顺序是未定的。<BR>&lt;classpath&gt;<BR>&lt;pathelement path="${classpath}"/&gt;<BR>&lt;fileset dir="lib"&gt;<BR>&lt;include name="**/*.jar"/&gt;<BR>&lt;/fileset&gt;<BR>&lt;pathelement location="classes"/&gt;<BR>&lt;/classpath&gt;<BR>上面的例子构造了一个路径值包括：${classpath}的路径，跟着lib目录下的所有jar文件，接着是classes目录。<BR><BR>如果你想在多个task中使用相同的path-like structure，你可以用&lt;path&gt;元素定义他们（与target同级），然后通过id属性引用－－参考Referencs例子。<BR><BR>path-like structure可能包括对另一个path-like structurede的引用（通过嵌套&lt;path&gt;元素）：<BR>&lt;path id="base.path"&gt;<BR>&lt;pathelement path="${classpath}"/&gt;<BR>&lt;fileset dir="lib"&gt;<BR>&lt;include name="**/*.jar"/&gt;<BR>&lt;/fileset&gt;<BR>&lt;pathelement location="classes"/&gt;<BR>&lt;/path&gt;<BR>&lt;path id="tests.path"&gt;<BR>&lt;path refid="base.path"/&gt;<BR>&lt;pathelement location="testclasses"/&gt;<BR>&lt;/path&gt;<BR>前面所提的关于&lt;classpath&gt;的简洁写法对于&lt;path&gt;也是有效的，如：<BR>&lt;path id="tests.path"&gt;<BR>&lt;path refid="base.path"/&gt;<BR>&lt;pathelement location="testclasses"/&gt;<BR>&lt;/path&gt;<BR>可写成：<BR>&lt;path id="base.path" path="${classpath}"/&gt;<BR>命令行变量<BR><BR>有些task可接受参数，并将其传递给另一个进程。为了能在变量中包含空格字符，可使用嵌套的arg元素。<BR>Attribute Description Required<BR>value 一个命令行变量；可包含空格字符。 只能用一个<BR>line 空格分隔的命令行变量列表。 <BR>file 作为命令行变量的文件名；会被文件的绝对名替代。 <BR>path 一个作为单个命令行变量的path-like的字符串；或作为分隔符，Ant会将其转变为特定平台的分隔符。 <BR><BR>例子<BR>&lt;arg value="-l -a"/&gt;<BR>是一个含有空格的单个的命令行变量。<BR>&lt;arg line="-l -a"/&gt;<BR>是两个空格分隔的命令行变量。<BR>&lt;arg path="/dir;/dir2:dir3"/&gt;<BR>是一个命令行变量，其值在DOS系统上为dir;dir2;dir3；在Unix系统上为/dir:/dir2:/dir3 。<BR><BR>References<BR><BR>buildfile元素的id属性可用来引用这些元素。如果你需要一遍遍的复制相同的XML代码块，这一属性就很有用－－如多次使用&lt;classpath&gt;结构。<BR><BR>下面的例子：<BR>&lt;project ... &gt;<BR>&lt;target ... &gt; <BR>&lt;rmic ...&gt; <BR>&lt;classpath&gt; <BR>&lt;pathelement location="lib/"/&gt; <BR>&lt;pathelement path="${java.class.path}/"/&gt; <BR>&lt;pathelement path="${additional.path}"/&gt; <BR>&lt;/classpath&gt; <BR>&lt;/rmic&gt; <BR>&lt;/target&gt;<BR>&lt;target ... &gt;<BR>&lt;javac ...&gt;<BR>&lt;classpath&gt;<BR>&lt;pathelement location="lib/"/&gt;<BR>&lt;pathelement path="${java.class.path}/"/&gt;<BR>&lt;pathelement path="${additional.path}"/&gt;<BR>&lt;/classpath&gt;<BR>&lt;/javac&gt;<BR>&lt;/target&gt;<BR>&lt;/project&gt;<BR>可以写成如下形式：<BR>&lt;project ... &gt; <BR>&lt;path id="project.class.path"&gt; <BR>&lt;pathelement location="lib/"/&gt;<BR>&lt;pathelement path="${java.class.path}/"/&gt; <BR>&lt;pathelement path="${additional.path}"/&gt; <BR>&lt;/path&gt;<BR>&lt;target ... &gt;<BR>&lt;rmic ...&gt;<BR>&lt;classpath refid="project.class.path"/&gt;<BR>&lt;/rmic&gt;<BR>&lt;/target&gt;<BR>&lt;target ... &gt; <BR>&lt;javac ...&gt;<BR>&lt;classpath refid="project.class.path"/&gt;<BR>&lt;/javac&gt;<BR>&lt;/target&gt;<BR>&lt;/project&gt;<BR>所有使用PatternSets, FileSets 或 path-like structures嵌套元素的task也接受这种类型的引用。</FONT><BR></P></TD></TR></TBODY></TABLE></TD></TR>
<TR>
<TD>
<SCRIPT language=JavaScript>
	var url = location.href;
	document.write("原文出处:"+url);
</SCRIPT>
原文出处:http://www.zhanglihai.com/article/2004-11-13/LH6G03L12G08G6G32G041903WBGND25G.xtp <BR>
<SCRIPT type=text/javascript><!--
google_ad_client = "pub-9146239964040731";
google_ad_width = 728;
google_ad_height = 90;
google_ad_format = "728x90_as";
google_ad_channel ="";
google_ad_type = "text";
google_color_border = "000000";
google_color_bg = "F0F0F0";
google_color_link = "0000FF";
google_color_url = "008000";
google_color_text = "000000";
//--></SCRIPT>

<SCRIPT src="http://pagead2.googlesyndication.com/pagead/show_ads.js" type=text/javascript>
</SCRIPT>
</TD></TR></TBODY></TABLE><img src ="http://www.blogjava.net/jackybu/aggbug/2407.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jackybu/" target="_blank">辰</a> 2005-03-24 14:10 <a href="http://www.blogjava.net/jackybu/articles/2407.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>对于moxie的"WebWork教程"补充 - [类型转化] </title><link>http://www.blogjava.net/jackybu/articles/1754.html</link><dc:creator>辰</dc:creator><author>辰</author><pubDate>Sat, 05 Mar 2005 14:20:00 GMT</pubDate><guid>http://www.blogjava.net/jackybu/articles/1754.html</guid><wfw:comment>http://www.blogjava.net/jackybu/comments/1754.html</wfw:comment><comments>http://www.blogjava.net/jackybu/articles/1754.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jackybu/comments/commentRss/1754.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jackybu/services/trackbacks/1754.html</trackback:ping><description><![CDATA[<SPAN class=postbody>moxie的WebWork教程 ( <A href="http://forum.javaeye.com/viewtopic.php?t=5964" target=_blank>http://forum.javaeye.com/viewtopic.php?t=5964</A> ) 非常详细，但是好像还缺少了webwork其他一些很有特色的东西，我在这里补充一些上来，首先是类型转化： <BR><BR>我们知道由于HTTP协议只能传递String，如果后台的Java模型使用了其他类型的属性，必须得做一些转化工作，而这些转化代码通常却是繁琐而又无聊，WebWork提供了Type Conversion功能，能够让我们从这些代码中解脱出来。 <BR><BR>看一个例子， <BR><BR>一个Person对象，有一个出生日期的属性： <BR></SPAN>
<TABLE cellSpacing=1 cellPadding=3 width="90%" align=center border=0>
<TBODY>
<TR>
<TD><SPAN class=genmed><B>java代码:&nbsp;</B></SPAN></TD></TR>
<TR>
<TD class=code>
<DIV style="FONT-FAMILY: 'Courier New', Courier, monospace"><BR><BR><SPAN style="FONT-WEIGHT: bold; COLOR: #990066" ?>public</SPAN> <SPAN style="FONT-WEIGHT: bold; COLOR: #990066" ?>class</SPAN> Person <SPAN style="COLOR: #000000">{</SPAN> <BR>&nbsp; &nbsp; <SPAN style="FONT-WEIGHT: bold; COLOR: #990066" ?>private</SPAN> <SPAN style="COLOR: #aaaadd" ?>Date</SPAN> dateOfBirth; <BR><SPAN style="COLOR: #000000">}</SPAN> <BR></DIV><BR></TD></TR></TBODY></TABLE><SPAN class=postbody><BR><BR>一个Action对Person做操作： <BR></SPAN>
<TABLE cellSpacing=1 cellPadding=3 width="90%" align=center border=0>
<TBODY>
<TR>
<TD><SPAN class=genmed><B>java代码:&nbsp;</B></SPAN></TD></TR>
<TR>
<TD class=code>
<DIV style="FONT-FAMILY: 'Courier New', Courier, monospace"><BR><BR><SPAN style="FONT-WEIGHT: bold; COLOR: #990066" ?>public</SPAN> <SPAN style="FONT-WEIGHT: bold; COLOR: #990066" ?>class</SPAN> CreatePerson <SPAN style="FONT-WEIGHT: bold; COLOR: #990066" ?>implements</SPAN> <SPAN style="COLOR: #aaaadd" ?>Action</SPAN> <SPAN style="COLOR: #000000">{</SPAN> <BR>&nbsp; &nbsp; <SPAN style="FONT-WEIGHT: bold; COLOR: #990066" ?>private</SPAN> Person person; <BR>&nbsp; &nbsp; <BR>&nbsp; &nbsp; <SPAN style="FONT-WEIGHT: bold; COLOR: #990066" ?>public</SPAN> <SPAN style="COLOR: #aaaadd" ?>String</SPAN> execute<SPAN style="COLOR: #000000">(</SPAN><SPAN style="COLOR: #000000">)</SPAN> <SPAN style="FONT-WEIGHT: bold; COLOR: #990066" ?>throws</SPAN> <SPAN style="COLOR: #aaaadd" ?>Exception</SPAN> <SPAN style="COLOR: #000000">{</SPAN> <BR>&nbsp; &nbsp; &nbsp; &nbsp; <SPAN style="COLOR: #6666ff">//Do some work</SPAN> <BR>&nbsp; &nbsp; &nbsp; &nbsp; <SPAN style="COLOR: #6666ff">//...</SPAN> <BR>&nbsp; &nbsp; &nbsp; &nbsp; <SPAN style="FONT-WEIGHT: bold; COLOR: #990066" ?>return</SPAN> SUCCESS; <BR>&nbsp; &nbsp; <SPAN style="COLOR: #000000">}</SPAN> <BR><BR><SPAN style="COLOR: #000000">}</SPAN> <BR></DIV><BR></TD></TR></TBODY></TABLE><SPAN class=postbody><BR><BR>我们通常在页面上会限制这个日期的格式（比如yyyy-MM-dd），通过写一个WebWork的转化器，我们就可以把在页面上：&lt;input type="text" name="person.dateOfBirth" value="1949-10-01"/&gt; 这样的值直接变成了相应的Date对象。 <BR><BR>转换器需要扩展ognl.DefaultTypeConverter (在webwork2.1.6以后，我们可以扩展WebWorkTypeConverter这个对象，更新的代码可以参考这个： <A href="http://cvs.javaeye.com:8008/quake/getfile/jert/src/java/com/javaeye/core/webwork/converter/DateConverter.java?v=1.2" target=_blank>http://cvs.javaeye.com:8008/quake/getfile/jert/src/java/com/javaeye/core/webwork/converter/DateConverter.java?v=1.2</A> ) <BR></SPAN>
<TABLE cellSpacing=1 cellPadding=3 width="90%" align=center border=0>
<TBODY>
<TR>
<TD><SPAN class=genmed><B>java代码:&nbsp;</B></SPAN></TD></TR>
<TR>
<TD class=code>
<DIV style="FONT-FAMILY: 'Courier New', Courier, monospace"><BR><BR><SPAN style="FONT-WEIGHT: bold; COLOR: #990066" ?>public</SPAN> <SPAN style="FONT-WEIGHT: bold; COLOR: #990066" ?>class</SPAN> DateConverter <SPAN style="FONT-WEIGHT: bold; COLOR: #990066" ?>extends</SPAN> DefaultTypeConverter <SPAN style="COLOR: #000000">{</SPAN> <BR>&nbsp; &nbsp; <SPAN style="FONT-WEIGHT: bold; COLOR: #990066" ?>private</SPAN> <SPAN style="FONT-WEIGHT: bold; COLOR: #990066" ?>static</SPAN> <SPAN style="FONT-WEIGHT: bold; COLOR: #990066" ?>final</SPAN> <SPAN style="COLOR: #aaaadd" ?>SimpleDateFormat</SPAN> sdf = <SPAN style="FONT-WEIGHT: bold; COLOR: #990066" ?>new</SPAN> <SPAN style="COLOR: #aaaadd" ?>SimpleDateFormat</SPAN><SPAN style="COLOR: #000000">(</SPAN>"yyyy-MM-dd"<SPAN style="COLOR: #000000">)</SPAN>; <BR><BR>&nbsp; &nbsp; <SPAN style="FONT-WEIGHT: bold; COLOR: #990066" ?>public</SPAN> <SPAN style="COLOR: #aaaadd" ?>Object</SPAN> convertValue<SPAN style="COLOR: #000000">(</SPAN><SPAN style="COLOR: #aaaadd" ?>Map</SPAN> ognlContext, <SPAN style="COLOR: #aaaadd" ?>Object</SPAN> value, <SPAN style="FONT-WEIGHT: bold; COLOR: #990066" ?>Class</SPAN> toType<SPAN style="COLOR: #000000">)</SPAN> <SPAN style="COLOR: #000000">{</SPAN> <BR>&nbsp; &nbsp; &nbsp; &nbsp; <SPAN style="COLOR: #aaaadd" ?>Object</SPAN> result = <SPAN style="FONT-WEIGHT: bold; COLOR: #990066" ?>null</SPAN>; <BR>&nbsp; &nbsp; &nbsp; &nbsp; <SPAN style="FONT-WEIGHT: bold; COLOR: #990066" ?>if</SPAN> <SPAN style="COLOR: #000000">(</SPAN>toType == <SPAN style="COLOR: #aaaadd" ?>Date</SPAN>.<SPAN style="COLOR: #000000">class</SPAN><SPAN style="COLOR: #000000">)</SPAN> <SPAN style="COLOR: #000000">{</SPAN> <BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; result = doConvertToDate<SPAN style="COLOR: #000000">(</SPAN>value<SPAN style="COLOR: #000000">)</SPAN>; <BR>&nbsp; &nbsp; &nbsp; &nbsp; <SPAN style="COLOR: #000000">}</SPAN> <SPAN style="FONT-WEIGHT: bold; COLOR: #990066" ?>else</SPAN> <SPAN style="FONT-WEIGHT: bold; COLOR: #990066" ?>if</SPAN> <SPAN style="COLOR: #000000">(</SPAN>toType == <SPAN style="COLOR: #aaaadd" ?>String</SPAN>.<SPAN style="COLOR: #000000">class</SPAN><SPAN style="COLOR: #000000">)</SPAN> <SPAN style="COLOR: #000000">{</SPAN> <BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; result = doConvertToString<SPAN style="COLOR: #000000">(</SPAN>value<SPAN style="COLOR: #000000">)</SPAN>; <BR>&nbsp; &nbsp; &nbsp; &nbsp; <SPAN style="COLOR: #000000">}</SPAN> <BR>&nbsp; &nbsp; &nbsp; &nbsp; <SPAN style="FONT-WEIGHT: bold; COLOR: #990066" ?>return</SPAN> result; <BR>&nbsp; &nbsp; <SPAN style="COLOR: #000000">}</SPAN> <BR><BR>&nbsp; &nbsp; <SPAN style="FONT-WEIGHT: bold; COLOR: #990066" ?>private</SPAN> <SPAN style="COLOR: #aaaadd" ?>Date</SPAN> doConvertToDate<SPAN style="COLOR: #000000">(</SPAN><SPAN style="COLOR: #aaaadd" ?>Object</SPAN> value<SPAN style="COLOR: #000000">)</SPAN> <SPAN style="COLOR: #000000">{</SPAN> <BR>&nbsp; &nbsp; &nbsp; &nbsp; <SPAN style="COLOR: #aaaadd" ?>Date</SPAN> result = <SPAN style="FONT-WEIGHT: bold; COLOR: #990066" ?>null</SPAN>; <BR><BR>&nbsp; &nbsp; &nbsp; &nbsp; <SPAN style="FONT-WEIGHT: bold; COLOR: #990066" ?>if</SPAN> <SPAN style="COLOR: #000000">(</SPAN>value instanceof <SPAN style="COLOR: #aaaadd" ?>String</SPAN><SPAN style="COLOR: #000000">)</SPAN> <SPAN style="COLOR: #000000">{</SPAN> <BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <SPAN style="FONT-WEIGHT: bold; COLOR: #990066" ?>try</SPAN> <SPAN style="COLOR: #000000">{</SPAN> <BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; result = sdf.<SPAN style="COLOR: #000000">parse</SPAN><SPAN style="COLOR: #000000">(</SPAN><SPAN style="COLOR: #000000">(</SPAN><SPAN style="COLOR: #aaaadd" ?>String</SPAN><SPAN style="COLOR: #000000">)</SPAN> value<SPAN style="COLOR: #000000">)</SPAN>; <BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <SPAN style="COLOR: #000000">}</SPAN> <SPAN style="FONT-WEIGHT: bold; COLOR: #990066" ?>catch</SPAN> <SPAN style="COLOR: #000000">(</SPAN><SPAN style="COLOR: #aaaadd" ?>ParseException</SPAN> e<SPAN style="COLOR: #000000">)</SPAN> <SPAN style="COLOR: #000000">{</SPAN> <BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; throw <SPAN style="FONT-WEIGHT: bold; COLOR: #990066" ?>new</SPAN> XworkException<SPAN style="COLOR: #000000">(</SPAN>"Could not parse date", e<SPAN style="COLOR: #000000">)</SPAN>; <BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <SPAN style="COLOR: #000000">}</SPAN> <BR>&nbsp; &nbsp; &nbsp; &nbsp; <SPAN style="COLOR: #000000">}</SPAN> <SPAN style="FONT-WEIGHT: bold; COLOR: #990066" ?>else</SPAN> <SPAN style="FONT-WEIGHT: bold; COLOR: #990066" ?>if</SPAN> <SPAN style="COLOR: #000000">(</SPAN>value instanceof <SPAN style="COLOR: #aaaadd" ?>Object</SPAN><SPAN style="COLOR: #000000">[</SPAN><SPAN style="COLOR: #000000">]</SPAN><SPAN style="COLOR: #000000">)</SPAN> <SPAN style="COLOR: #000000">{</SPAN> <BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <SPAN style="COLOR: #6666ff">// let's try to convert the first element only</SPAN> <BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <SPAN style="COLOR: #aaaadd" ?>Object</SPAN><SPAN style="COLOR: #000000">[</SPAN><SPAN style="COLOR: #000000">]</SPAN> array = <SPAN style="COLOR: #000000">(</SPAN><SPAN style="COLOR: #aaaadd" ?>Object</SPAN><SPAN style="COLOR: #000000">[</SPAN><SPAN style="COLOR: #000000">]</SPAN><SPAN style="COLOR: #000000">)</SPAN> value; <BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <SPAN style="FONT-WEIGHT: bold; COLOR: #990066" ?>if</SPAN> <SPAN style="COLOR: #000000">(</SPAN><SPAN style="COLOR: #000000">(</SPAN>array != <SPAN style="FONT-WEIGHT: bold; COLOR: #990066" ?>null</SPAN><SPAN style="COLOR: #000000">)</SPAN> &amp;&amp; <SPAN style="COLOR: #000000">(</SPAN>array.<SPAN style="COLOR: #000000">length</SPAN> &gt;= <SPAN style="COLOR: #000000" ?>1</SPAN><SPAN style="COLOR: #000000">)</SPAN><SPAN style="COLOR: #000000">)</SPAN> <SPAN style="COLOR: #000000">{</SPAN> <BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; value = array<SPAN style="COLOR: #000000">[</SPAN><SPAN style="COLOR: #000000" ?>0</SPAN><SPAN style="COLOR: #000000">]</SPAN>; <BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; result = doConvertToDate<SPAN style="COLOR: #000000">(</SPAN>value<SPAN style="COLOR: #000000">)</SPAN>; <BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <SPAN style="COLOR: #000000">}</SPAN> <BR>&nbsp; &nbsp; &nbsp; &nbsp; <SPAN style="COLOR: #000000">}</SPAN> <SPAN style="FONT-WEIGHT: bold; COLOR: #990066" ?>else</SPAN> <SPAN style="FONT-WEIGHT: bold; COLOR: #990066" ?>if</SPAN> <SPAN style="COLOR: #000000">(</SPAN><SPAN style="COLOR: #aaaadd" ?>Date</SPAN>.<SPAN style="COLOR: #000000">class</SPAN>.<SPAN style="COLOR: #000000">isAssignableFrom</SPAN><SPAN style="COLOR: #000000">(</SPAN>value.<SPAN style="COLOR: #000000">getClass</SPAN><SPAN style="COLOR: #000000">(</SPAN><SPAN style="COLOR: #000000">)</SPAN><SPAN style="COLOR: #000000">)</SPAN><SPAN style="COLOR: #000000">)</SPAN> <SPAN style="COLOR: #000000">{</SPAN> <BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; result = <SPAN style="COLOR: #000000">(</SPAN><SPAN style="COLOR: #aaaadd" ?>Date</SPAN><SPAN style="COLOR: #000000">)</SPAN> value; <BR>&nbsp; &nbsp; &nbsp; &nbsp; <SPAN style="COLOR: #000000">}</SPAN> <BR>&nbsp; &nbsp; &nbsp; &nbsp; <SPAN style="FONT-WEIGHT: bold; COLOR: #990066" ?>return</SPAN> result; <BR>&nbsp; &nbsp; <SPAN style="COLOR: #000000">}</SPAN> <BR><BR>&nbsp; &nbsp; <SPAN style="FONT-WEIGHT: bold; COLOR: #990066" ?>private</SPAN> <SPAN style="COLOR: #aaaadd" ?>String</SPAN> doConvertToString<SPAN style="COLOR: #000000">(</SPAN><SPAN style="COLOR: #aaaadd" ?>Object</SPAN> value<SPAN style="COLOR: #000000">)</SPAN> <SPAN style="COLOR: #000000">{</SPAN> <BR>&nbsp; &nbsp; &nbsp; &nbsp; <SPAN style="COLOR: #aaaadd" ?>String</SPAN> result = <SPAN style="FONT-WEIGHT: bold; COLOR: #990066" ?>null</SPAN>; <BR>&nbsp; &nbsp; &nbsp; &nbsp; <SPAN style="FONT-WEIGHT: bold; COLOR: #990066" ?>if</SPAN> <SPAN style="COLOR: #000000">(</SPAN>value instanceof <SPAN style="COLOR: #aaaadd" ?>Date</SPAN><SPAN style="COLOR: #000000">)</SPAN> <SPAN style="COLOR: #000000">{</SPAN> <BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; result = sdf.<SPAN style="COLOR: #000000">format</SPAN><SPAN style="COLOR: #000000">(</SPAN>value<SPAN style="COLOR: #000000">)</SPAN>; <BR>&nbsp; &nbsp; &nbsp; &nbsp; <SPAN style="COLOR: #000000">}</SPAN> <BR>&nbsp; &nbsp; &nbsp; &nbsp; <SPAN style="FONT-WEIGHT: bold; COLOR: #990066" ?>return</SPAN> result; <BR>&nbsp; &nbsp; <SPAN style="COLOR: #000000">}</SPAN> <BR><SPAN style="COLOR: #000000">}</SPAN> <BR></DIV><BR></TD></TR></TBODY></TABLE><SPAN class=postbody><BR><BR>那么WebWork是如何知道要使用这个转化器对Person的dateOfBirth做转化呢？我们有2种方法： <BR>1. Class-specific conversion rules <BR>写一个className-conversion.properties，这上面的例子里，我们就在Person.java所在的package下面，写一个Person-conversion.properties <BR>在这个文件里面指定： <BR>dateOfBirth=com.javaeye.core.webwork.converter.DateConverter <BR><BR>2. Application-wide conversion rules <BR>在classpath root下面写一个xwork-conversion.properties: <BR>java.util.Date=com.javaeye.core.webwork.converter.DateConverter <BR><BR>这样一旦写好了一个转换器以后，就能够很方便地被重用了，在这篇wiki里面，有更加详细的介绍： <A href="http://wiki.opensymphony.com/display/XW/Type+Conversion" target=_blank>http://wiki.opensymphony.com/display/XW/Type+Conversion</A> <BR><BR>再举一个实际的例子： <BR>在jert里面，我们希望可以给用户选择多语言，那么我们在页面上提供了一个下拉列表，选项有zh_CN和en_US，通过一个LocaleConverter，我们就可以直接把String转化成Locale对象： <BR><BR><A href="http://cvs.javaeye.com:8008/quake/getfile/jert/src/java/com/javaeye/core/webwork/converter/LocaleConverter.java?v=1.1" target=_blank>http://cvs.javaeye.com:8008/quake/getfile/jert/src/java/com/javaeye/core/webwork/converter/LocaleConverter.java?v=1.1</A> <BR><BR>结论：灵活使用转换器可以减少我们那些繁琐无聊的类型转化代码。</SPAN><img src ="http://www.blogjava.net/jackybu/aggbug/1754.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jackybu/" target="_blank">辰</a> 2005-03-05 22:20 <a href="http://www.blogjava.net/jackybu/articles/1754.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>J2EE学习经验和流程</title><link>http://www.blogjava.net/jackybu/articles/1740.html</link><dc:creator>辰</dc:creator><author>辰</author><pubDate>Sat, 05 Mar 2005 10:42:00 GMT</pubDate><guid>http://www.blogjava.net/jackybu/articles/1740.html</guid><wfw:comment>http://www.blogjava.net/jackybu/comments/1740.html</wfw:comment><comments>http://www.blogjava.net/jackybu/articles/1740.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jackybu/comments/commentRss/1740.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jackybu/services/trackbacks/1740.html</trackback:ping><description><![CDATA[J2ee学习流程<BR><BR>在这里我谈谈我在学习j2ee流程，并谈到在此过程中领会的经验和教训。以便后来者少走<BR>弯路。<BR>Java发展到现在，按应用来分主要分为三大块：J2SE,J2ME和J2EE。这三块相互补充，应用<BR>范围不同。<BR>J2SE就是Java2的标准版，主要用于桌面应用软件的编程；<BR>J2ME主要应用于嵌入是系统开发，如手机和PDA的编程；<BR>J2EE是Java2的企业版，主要用于分布式的网络程序的开发，如电子商务网站和ERP系统。<BR><BR><BR>先学习j2se<BR>要学习j2ee就要先学习j2se，刚开始学习j2se先建议不要使用IDE，然后渐渐的过渡到使用<BR>IDE开发，毕竟用它方便嘛。学习j2se推荐三本书，《java2核心技术一二卷》，《java编<BR>程思想》，《java模式》。其中《java编程思想》要研读，精读。这一段时间是基本功学<BR>习，时间会很长，也可能很短，这要看学习者自身水平而定。<BR><BR>不要被IDE纠缠<BR>在学习java和j2ee过程中，你会遇到五花八门的IDE，不要被他们迷惑，学JAVA的时候，要<BR>学语言本身的东西，不要太在意IDE的附加功能，JAVA编程在不同IDE之间的转换是很容易<BR>的，过于的在意IDE的功能反而容易耽误对语言本身的理解。目前流行的IDE有jbuilder，<BR>eclipse和eclipse的加强版WSAD。用好其中一个就可以了，推荐从eclipse入手j2ee。因为<BR>Jbuilder更适合于写j2se程序。<BR><BR>选择和学习服务器使用配置<BR>当你有了j2se和IDE的经验时，可以开始j2ee的学习了，web服务器：tomcat，勿庸置疑，<BR>tomcat为学习web服务首选。而应用服务器目前主要有三个：jboss、weblogic、webspher<BR>e。有很多项目开始采用jboss，并且有大量的公司开始做websphere或weblogic向jboss应<BR>用服务器的移植（节省成本），这里要说的是，学习tomcat和jboss我认为是首选，也是最<BR>容易上手的。学习服务器使用配置最好去询问有经验的人（有条件的话），因为他们或许<BR>一句话就能解决问题，你自己上网摸索可能要一两天（我就干过这种傻事），我们应该把<BR>主要时间放在学习原理和理论上，一项特定技术的使用永远代替不了一个人的知识和学问<BR>。<BR><BR>学习web知识<BR>如果你是在做电子商务网站等时，你可能要充当几个角色，这是你还要学习：<BR>html，可能要用到dreamwave等IDE。<BR>Javascript，学会简单的数据校验，数据联动显示等等<BR><BR>J2eeAPI学习<BR>学习j2eeAPI和学习服务器应该是一个迭代的过程。<BR>先学习jsp和servlet编程，这方面的书很多，我建立看oreilly公司的两本《jsp设计》和<BR>《java servlet编程》，oreilly出的书总是那本优秀，不得不佩服。<BR>学习jdbc数据库编程，j2ee项目大多都是MIS系统，访问数据库是核心。这本应属于j2se学<BR>习中，这里拿出来强调一下。<BR>学习jndi api，它和学习ejb可以结合起来。<BR>学习ejb api，推荐书《精通ejb》<BR>经过上面的这些的学习，大概可以对付一般的应用了。<BR>有人说跟着sun公司的《j2ee tutorial》一路学下来，当然也可以。<BR><BR>学习ejb设计模式和看代码（最重要）<BR>设计模式是练内功，其重要性可以这么说吧，如果你不会用设计模式的话，你将写出一堆<BR>使用了ejb的垃圾，有慢又是一堆bug，其结果不如不用ejb实现（ejb不等于j2ee）<BR>无论学习什么语言，都应该看大量代码，你看的代码量不到一定数量，是学不好j2ee的<BR><BR>目前有很多开源的工程可以作为教材：<BR>jive论坛<BR>petstore sun公司<BR>dune sun公司<BR>等等，研读一个，并把它用到自己的工程中来。<BR><BR>J2ee其他学习<BR>当你渐渐对j2ee了解到一定深度时，你要开始关注当前领域中的一些技术变化，J2ee是一<BR>块百家争鸣的领域，大家都在这里提出自己的解决方案，例如struts，hibernate，ofbiz<BR>等等，学习这些东西要你的项目和目标而定，预先补充一下未尝不可，但不用涉及太深，<BR>毕竟学习原理和理论是最最重要的事。<BR><BR>目前常见j2eeAPI<BR> JavaServer Pages(JSP)技术1.2 <BR> Java Servlet技术2.3 <BR> JDBC API 2.0 <BR> Java XML处理API(JAXP)1.1 <BR> Enterprise JavaBeans技术2.0 <BR> Java消息服务(JMS)1.0 <BR> Java命名目录接口(JNDI)1.2 <BR> Java事务API(JTA) 1.0 <BR> JavaMail API 1.2 <BR> JavaBeans激活架构(JAF)1.0 <BR> J2EE连接器体系结构(JCA)1.0 <BR> Java认证和授权服务(JAAS)1.0 <BR>&nbsp;&nbsp; 学习上面的某些API要以你的项目而定，了解所有他们总之是有好处的<BR>&nbsp;&nbsp; 上面印证了大家说的一句话，java语言本身不难学，但是技术太多，所以学java很费劲<BR>。回想一下，基本上每个初学者，在刚学习java的时候可能都会问别人这么一句话，你怎<BR>么知道的哪个方法(api)在哪个包里的？呵呵，无他，唯手熟尔。<BR><img src ="http://www.blogjava.net/jackybu/aggbug/1740.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jackybu/" target="_blank">辰</a> 2005-03-05 18:42 <a href="http://www.blogjava.net/jackybu/articles/1740.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>我眼中的Spring </title><link>http://www.blogjava.net/jackybu/articles/1739.html</link><dc:creator>辰</dc:creator><author>辰</author><pubDate>Sat, 05 Mar 2005 10:40:00 GMT</pubDate><guid>http://www.blogjava.net/jackybu/articles/1739.html</guid><wfw:comment>http://www.blogjava.net/jackybu/comments/1739.html</wfw:comment><comments>http://www.blogjava.net/jackybu/articles/1739.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jackybu/comments/commentRss/1739.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jackybu/services/trackbacks/1739.html</trackback:ping><description><![CDATA[<P>用Spring有一段时间了，最近在部门内部做个Spring的培训，一个很自然的问题出现大脑<BR>之中，Spring好在哪？<BR>我可以摆出许多广告，但那不是我的感觉。于是，我向自己发问，要求一个属于自己的答<BR>案<BR>Dependency Injection<BR>原来，它叫IoC。Martin Flower发话了，是个框架都有IoC，这不足以新生容器反转的“如<BR>何定位插件的具体实现”，于是，它有了个新名字，Dependency Injection。<BR>其实，它就是一种将调用者与被调用者分离的思想，Uncle Bob管它叫DIP（Dependency I<BR>nversion Principle），并把它归入OO设计原则。<BR>同Spring相比，它更早进入我的大脑。一切都是那么朦胧，直至Spring出现。<BR>慢慢的，我知道了它还分为Interface Injection（type 1），Setter Injection（type <BR>2），Constructor Injection（type 3）。Martin Flower那篇为它更名的大作让我心目关<BR>于它的一切趋于完整。<BR>在Spring中，它是一切的基础。Spring的种种优势随之而来。<BR>于我而言，它为我带来更多的是思维方式的转变，恐怕以后我再也无法写出那种一大块的<BR>全功能程序了。<BR>动态配置<BR>这里提及的动态配置包括两个部分：系统的生成和系统的修改。<BR>基于Spring的应用是依赖配置文件组织起来的，这意味着我们所编写的程序，更多的是在<BR>完成具体的功能，而各个功能之间的串连，就要靠配置文件了。<BR>随之而来的一个好处就是，我们可以在不重新编译代码的情况下，改变系统行为。<BR>或许不修改代码可以成为另一个理由，但在我看来，修改Java代码和修改配置文件没有什<BR>么本质区别，只要能把配置文件视为另一种语言，不是吗？<BR>有位同事问我，Spring的配置文件的正确性是否只有运行时才能发现，道理上讲是这样的<BR>。每次修改配置文件，然后跑起来确定其正确性，这确实是一件费力不讨好的事。如果你<BR>是Eclipse的用户，你就幸福多了，已经有人开发了Spring的插件协助你完成这个工作。<BR><BR>易测的结构<BR>曾经有一次在现场，我改一个简单的小bug，简单到加在一起改的代码不超过五行。但从我<BR>定位到错误到完全把bug修正，用了两个多小时，这使得两个同伴最后只能对我怒目而视。<BR><BR>这其中固然有我自己糊涂的原因，代码不可测也是很重要的一个原因。每次修改了一句话<BR>，就要部署到应用服务器上，运行起来看结果。相信每个有在应用服务器上部署应用经验<BR>的人都知道那是多么漫长的过程。<BR>如果以前对我说，对于一个好的应用来说，可测试性也非常重要，我摆出一副非常不屑的<BR>态度，惨痛的教训彻底的教育了我。<BR>Dependency Injection让整个应用结构清楚了许多，我们可以针对每个具体的模块进行单<BR>元测试，而不必像过去一样，只有把整个应用部署到应用服务器上运行起来之后，才能测<BR>试。<BR>局部的稳定带来的是更多的信心，当系统一点点整合在一起，信心就越来越足。<BR>不存在的接口压力<BR>项目组中的一个同事对我说，用Spring跟没用一样。原因是我们的代码并没有继承Spring<BR>中的类，也没有实现Spring中的接口。<BR>这恰好就是Spring的优势之一，这使得我们的应用不必困在Spring上。依赖于特定的API就<BR>意味着要在一棵树上吊死。我们原来系统中很难测试的另一个原因就是在代码中遍布Http<BR>ServletResponse，这使得我们的代码只有放在Web容器中才能跑起来。<BR>Rod Johnson在评价一个Web框架的优劣时，将是否依赖于Servlet API作为一个及其重要的<BR>标准。<BR>依赖于特定API就意味着要依赖于特定的容器或是框架，就像Servlet一定要跑在Web Cont<BR>ainer里，EJB一定要有AppServer一样。<BR>没有了接口的压力，使得我们应用可以完全脱离Spring运行。在系统开发期间，我不断强<BR>调即便没有Spring，我们的应用依然可以自行组装来运行，给我这种底气的理由就是Spri<BR>ng没有侵略性的接口。另一个原因是当时我并没有对把整个系统放到Spring上有十足的把<BR>握。^_^<BR>消除Singleton<BR>Singleton是二十三个经典的设计模式之一，不幸的是，到了J2EE的世界，由于classload<BR>er的原因，它几乎成了一个经典的反模式。曾经在自己的代码中大量运用Singleton，部署<BR>中遇到的问题加上太多的重复代码，给我留下了一段不堪回首的经历。<BR>Spring的出现漂亮的解决这个问题，我只要在配置文件中配置一个bean，它缺省行为就是<BR>Singleton，我不必再为反模式抓空心思，不必再为了Singleton编码。<BR>择其善者而从之<BR>不同于很多技术，Spring并不是一个“要么全部，要么没有”的东西，它是一个分层的结<BR>构。我们可以从中选取我们感兴趣的部分，而不必理会其它的部分。我用得最多的部分就<BR>是Spring的Core部分，也就是基于bean的配置框架，对于其上的MVC、ORM、DAO等等，我并<BR>不了解，但这丝毫不影响我的运用。<BR>开阔视野<BR>Spring本身包含很多的东西，从Dependency Injection之类思想性的东西，到现在颇为流<BR>行的AOP、ORM之类实现技术。在Spring的路线图中，JMX、JMS、JCA等等已经都纳入了Spr<BR>ing未来的发展计划中。于我而言，沉浸于Spring的世界里，一段时间内不愁没东西可学。<BR><BR>Spring起源于Rod Johnson的《Expert One-on-One J2EE Design and Development》，所<BR>以，这本书成了Spring最好的辅导材料。书中的许多观点的提出完全是基于Rod本人的实际<BR>经验，比起不少假大空的理论或是广告来得实际得多。Spring邮件列表中有人这样评价，<BR>这本书值得“cover-to-cover”的读。如果你和曾经的我一样，迷失于J2EE纷繁复杂的世<BR>界中，这是一剂让你清醒过来的良药。<BR>这就是我眼中的Spring，这些理由比之许多Spring的广告显得单薄许多，因为我对Spring<BR>的了解实在有限，但这足以让我相信在Spring上花费时间是值得的。 <BR></P><img src ="http://www.blogjava.net/jackybu/aggbug/1739.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jackybu/" target="_blank">辰</a> 2005-03-05 18:40 <a href="http://www.blogjava.net/jackybu/articles/1739.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>类似QQ的同名用户登录问题的解决 </title><link>http://www.blogjava.net/jackybu/articles/1720.html</link><dc:creator>辰</dc:creator><author>辰</author><pubDate>Sat, 05 Mar 2005 06:57:00 GMT</pubDate><guid>http://www.blogjava.net/jackybu/articles/1720.html</guid><wfw:comment>http://www.blogjava.net/jackybu/comments/1720.html</wfw:comment><comments>http://www.blogjava.net/jackybu/articles/1720.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jackybu/comments/commentRss/1720.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jackybu/services/trackbacks/1720.html</trackback:ping><description><![CDATA[<P><FONT size=4>发现对于登录问题的解决都说用session监听,但是没有人写出示例代码,今天写了一个,希望对大家有所帮助.<BR>解决同名用户登录的问题,类似QQ,即同名用户第二次登录,第一次登录的用户就掉线.<BR>SessionListener.java监听session的类,部署于/App/WEB-INF/classes/com/test下(其中App为你的应用程序目录)<BR>package com.test;<BR>import javax.servlet.http.*;<BR>import java.util.*;</FONT></P>
<P><FONT size=4>public class SessionListener implements HttpSessionListener{<BR>&nbsp;&nbsp;&nbsp; private static HashMap hUserName = new HashMap();//保存sessionID和username的映射<BR>&nbsp;&nbsp;&nbsp; /**以下是实现HttpSessionListener中的方法**/<BR>&nbsp;&nbsp;&nbsp; public void sessionCreated(HttpSessionEvent se){<BR>&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp;&nbsp; <BR>&nbsp;&nbsp;&nbsp; public void sessionDestroyed(HttpSessionEvent se){<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; hUserName.remove( se.getSession().getId() );<BR>&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp;&nbsp; /*<BR>&nbsp;&nbsp;&nbsp;&nbsp; * isAlreadyEnter-用于判断用户是否已经登录以及相应的处理方法<BR>&nbsp;&nbsp;&nbsp;&nbsp; * @param sUserName String-登录的用户名称<BR>&nbsp;&nbsp;&nbsp;&nbsp; * @return boolean-该用户是否已经登录过的标志<BR>&nbsp;&nbsp;&nbsp;&nbsp; */<BR>&nbsp;&nbsp;&nbsp; public static boolean isAlreadyEnter(HttpSession session,String sUserName){<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; boolean flag = false;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(hUserName.containsValue(sUserName)){//如果该用户已经登录过，则使上次登录的用户掉线(依据使用户名是否在hUserName中)<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; flag = true;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //遍历原来的hUserName，删除原用户名对应的sessionID(即删除原来的sessionID和username)<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Iterator iter = hUserName.entrySet().iterator();<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; while (iter.hasNext()) {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Map.Entry entry = (Map.Entry)iter.next();<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Object key = entry.getKey();<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Object val = entry.getValue();<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if( ( (String)val ).equals(sUserName) ){<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; hUserName.remove(key);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; hUserName.put( session.getId(),sUserName );//添加现在的sessionID和username<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println("hUserName = " + hUserName);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else{//如果该用户没登录过，直接添加现在的sessionID和username<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; flag = false;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; hUserName.put( session.getId(),sUserName );<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println("hUserName = " + hUserName);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return flag;<BR>&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp;&nbsp; /*<BR>&nbsp;&nbsp;&nbsp;&nbsp; * isOnline-用于判断用户是否在线<BR>&nbsp;&nbsp;&nbsp;&nbsp; * @param session HttpSession-登录的用户名称<BR>&nbsp;&nbsp;&nbsp;&nbsp; * @return boolean-该用户是否在线的标志<BR>&nbsp;&nbsp;&nbsp;&nbsp; */<BR>&nbsp;&nbsp;&nbsp; public static boolean isOnline(HttpSession session){<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; boolean flag = true;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if( hUserName.containsKey( session.getId() ) ){<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; flag = true;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else{<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; flag = false;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return flag;<BR>&nbsp;&nbsp;&nbsp; }<BR>}</FONT></P>
<P><FONT size=4>web.xml部署于/App/WEB-INF下<BR>&lt;?xml version="1.0" encoding="ISO-8859-1"?&gt;</FONT></P>
<P><FONT size=4>&lt;!DOCTYPE web-app<BR>PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"<BR>"</FONT><A href="http://java.sun.com/j2ee/dtds/web-app_2.3.dtd"><FONT size=4>http://java.sun.com/j2ee/dtds/web-app_2.3.dtd</FONT></A><FONT size=4>"&gt;</FONT></P>
<P><FONT size=4>&lt;web-app&gt;</FONT></P>
<P><FONT size=4>&lt;listener&gt;<BR>&lt;listener-class&gt;<BR>com.inspirer.dbmp.SessionListener<BR>&lt;/listener-class&gt;<BR>&lt;/listener&gt;</FONT></P>
<P><FONT size=4>&lt;/web-app&gt;<BR>应用部分<BR>1.在你的登录验证时,调用SessionListener.isAlreadyEnter(session,"admin")<BR>既可以判断该用户名的用户是否登录过,又可以使上次登录的用户掉线<BR>2.其他页面调用SessionListener.isOnline(session),可以判断该用户是否在线.<BR></FONT></P><img src ="http://www.blogjava.net/jackybu/aggbug/1720.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jackybu/" target="_blank">辰</a> 2005-03-05 14:57 <a href="http://www.blogjava.net/jackybu/articles/1720.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>TOMCAT完全攻略 </title><link>http://www.blogjava.net/jackybu/articles/1719.html</link><dc:creator>辰</dc:creator><author>辰</author><pubDate>Sat, 05 Mar 2005 06:53:00 GMT</pubDate><guid>http://www.blogjava.net/jackybu/articles/1719.html</guid><wfw:comment>http://www.blogjava.net/jackybu/comments/1719.html</wfw:comment><comments>http://www.blogjava.net/jackybu/articles/1719.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jackybu/comments/commentRss/1719.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jackybu/services/trackbacks/1719.html</trackback:ping><description><![CDATA[<DIV>
<BLOCKQUOTE>随着java的流行，其在web上的应用也越来越广，tomcat作为一个开源的servlet容器，应用前景越来越广，本文将向你讲述tomcat的一些知识。</BLOCKQUOTE>
<P><A id=1 name=1><SPAN class=atitle2>一：简介</SPAN></A><BR>tomcat是jakarta项目中的一个重要的子项目，其被JavaWorld杂志的编辑选为2001年度最具创新的java产品(Most Innovative Java Product)，同时它又是sun公司官方推荐的servlet和jsp容器(具体可以见http://java.sun.com/products/jsp/tomcat/)，因此其越来越多的受到软件公司和开发人员的喜爱。servlet和jsp的最新规范都可以在tomcat的新版本中得到实现。</P>
<P><A id=2 name=2><SPAN class=atitle2>二：安装及配置</SPAN></A><BR>tomcat最新版本为4.0.1，这个版本用了一个新的servlet容器Catalina，完整的实现了servlet2.3和jsp1.2规范。注意安装之前你的系统必须安装了jdk1.2以上版本。</P>
<P><SPAN class=atitle3>(一)：安装</SPAN><BR>1：windows平台<BR>从tomcat网站下载<A href="http://jakarta.apache.org/builds/jakarta-tomcat-4.0/release/v4.0.1/bin/jakarta-tomcat-4.0.1.exe" target=_blank>jakarta-tomcat-4.0.1.exe</A>，按照一般的windows程序安装步骤即可安装好tomcat,安装时它会自动寻找你的jdk和jre的位置。</P>
<P>2：linux平台<BR>下载<A href="http://jakarta.apache.org/builds/jakarta-tomcat-4.0/release/v4.0.1/bin/jakarta-tomcat-4.0.1.tar.gz" target=_blank>jakarta-tomcat-4.0.1.tar.gz</A>，将其解压到一个目录。</P>
<P><SPAN class=atitle3>(二)：配置</SPAN><BR>运行tomcat需要设置JAVA_HOME变量</P>
<TABLE cellSpacing=0 cellPadding=5 width="100%" bgColor=#cccccc border=1>
<TBODY>
<TR>
<TD><PRE><CODE>set JAVA_HOME=c:/jdk (win98，在msdos方式下使用，或者放入autoexec.bat中) export JAVA_HOME=/usr/local/jdk (linux下使用，放到/etc/bashrc或者/etc/profile中) </CODE> </PRE></TD></TR></TBODY></TABLE><BR><BR>
<P><SPAN class=atitle3>(三)：运行</SPAN><BR>设置完毕后就可以运行tomcat服务器了，进入tomcat的bin目录，win98下用startup启动tomcat，linux下用startup.sh，相应的关闭tomcat的命令为shutdown和shutdown.sh。</P>
<P>启动后可以在浏览器中输入http://localhost:8080/测试，由于tomcat本身具有web服务器的功能，因此我们不必安装apache，当然其也可以与apache集成到一起，下面会介绍。</P>
<P>下面你可以测试其自带的jsp和servlet示例。</P>
<P><A id=3 name=3><SPAN class=atitle2>三：应用</SPAN></A></P>
<P><SPAN class=atitle3>(一):目录结构</SPAN><BR>tomcat的目录结构如下：</P>
<TABLE cellSpacing=0 cellPadding=5 width="100%" bgColor=#cccccc border=1>
<TBODY>
<TR>
<TD>目录名</TD>
<TD>简介</TD></TR>
<TR>
<TD>bin</TD>
<TD>存放启动和关闭tomcat脚本</TD></TR>
<TR>
<TD>conf</TD>
<TD>包含不同的配置文件,server.xml(Tomcat的主要配置文件)和web.xml</TD></TR>
<TR>
<TD>work</TD>
<TD>存放jsp编译后产生的class文件</TD></TR>
<TR>
<TD>webapp</TD>
<TD>存放应用程序示例，以后你要部署的应用程序也要放到此目录</TD></TR>
<TR>
<TD>logs</TD>
<TD>存放日志文件</TD></TR>
<TR>
<TD>lib/japser/common</TD>
<TD>这三个目录主要存放tomcat所需的jar文件</TD></TR></TBODY></TABLE><BR><BR>
<P><SPAN class=atitle3>(二)：server.xml配置简介</SPAN><BR>下面我们将讲述这个文件中的基本配置信息，更具体的配置信息见tomcat的文档</P>
<TABLE cellSpacing=0 cellPadding=0 width="80%" bgColor=#cccccc border=1>
<TBODY>
<TR>
<TD width="27%">元素名</TD>
<TD width="21%">属性</TD>
<TD width="52%">解释</TD></TR>
<TR>
<TD width="27%" rowSpan=2>server</TD>
<TD width="21%">port</TD>
<TD width="52%">指定一个端口，这个端口负责监听关闭tomcat的请求</TD></TR>
<TR>
<TD width="21%">shutdown</TD>
<TD width="52%">指定向端口发送的命令字符串</TD></TR>
<TR>
<TD width="27%">service</TD>
<TD width="21%">name</TD>
<TD width="52%">指定service的名字</TD></TR>
<TR>
<TD width="27%" rowSpan=7>Connector<BR>(表示客户端和service之间的连接)</TD>
<TD width="21%">port</TD>
<TD width="52%">指定服务器端要创建的端口号，并在这个断口监听来自客户端的请求</TD></TR>
<TR>
<TD width="21%">minProcessors</TD>
<TD width="52%">服务器启动时创建的处理请求的线程数</TD></TR>
<TR>
<TD width="21%">maxProcessors</TD>
<TD width="52%">最大可以创建的处理请求的线程数</TD></TR>
<TR>
<TD width="21%">enableLookups</TD>
<TD width="52%">如果为true，则可以通过调用request.getRemoteHost()进行DNS查询来得到远程客户端的实际主机名，若为false则不进行DNS查询，而是返回其ip地址</TD></TR>
<TR>
<TD width="21%">redirectPort</TD>
<TD width="52%">指定服务器正在处理http请求时收到了一个SSL传输请求后重定向的端口号</TD></TR>
<TR>
<TD width="21%">acceptCount</TD>
<TD width="52%">指定当所有可以使用的处理请求的线程数都被使用时，可以放到处理队列中的请求数，超过这个数的请求将不予处理</TD></TR>
<TR>
<TD width="21%">connectionTimeout</TD>
<TD width="52%">指定超时的时间数(以毫秒为单位)</TD></TR>
<TR>
<TD width="27%">Engine<BR>(表示指定service中的请求处理机，接收和处理来自Connector的请求)</TD>
<TD width="21%">defaultHost</TD>
<TD width="52%">指定缺省的处理请求的主机名，它至少与其中的一个host元素的name属性值是一样的</TD></TR>
<TR>
<TD width="27%" rowSpan=3>Context<BR>(表示一个web应用程序，通常为WAR文件，关于WAR的具体信息见servlet规范)</TD>
<TD width="21%">docBase</TD>
<TD width="52%">应用程序的路径或者是WAR文件存放的路径</TD></TR>
<TR>
<TD width="21%">path</TD>
<TD width="52%">表示此web应用程序的url的前缀，这样请求的url为http://localhost:8080/path/****</TD></TR>
<TR>
<TD width="21%">reloadable</TD>
<TD width="52%">这个属性非常重要，如果为true，则tomcat会自动检测应用程序的/WEB-INF/lib 和/WEB-INF/classes目录的变化，自动装载新的应用程序，我们可以在不重起tomcat的情况下改变应用程序</TD></TR>
<TR>
<TD width="27%" rowSpan=3>
<P>host<BR>(表示一个虚拟主机)</P></TD>
<TD width="21%">name</TD>
<TD width="52%">指定主机名</TD></TR>
<TR>
<TD width="21%">appBase</TD>
<TD width="52%">应用程序基本目录，即存放应用程序的目录</TD></TR>
<TR>
<TD width="21%">unpackWARs</TD>
<TD width="52%">如果为true，则tomcat会自动将WAR文件解压，否则不解压，直接从WAR文件中运行应用程序</TD></TR>
<TR>
<TD rowSpan=4>
<P>Logger<BR>(表示日志，调试和错误信息)</P></TD>
<TD width="21%">className</TD>
<TD width="52%">指定logger使用的类名，此类必须实现org.apache.catalina.Logger 接口</TD></TR>
<TR>
<TD width="21%">prefix</TD>
<TD width="52%">指定log文件的前缀</TD></TR>
<TR>
<TD width="21%">suffix</TD>
<TD width="52%">指定log文件的后缀</TD></TR>
<TR>
<TD width="21%">timestamp</TD>
<TD width="52%">如果为true，则log文件名中要加入时间，如下例:localhost_log.2001-10-04.txt</TD></TR>
<TR>
<TD width="27%">
<P>Realm<BR>(表示存放用户名，密码及role的数据库)</P></TD>
<TD width="21%">className</TD>
<TD width="52%">指定Realm使用的类名，此类必须实现org.apache.catalina.Realm接口</TD></TR>
<TR>
<TD rowSpan=3>
<P>Valve<BR>(功能与Logger差不多，其prefix和suffix属性解释和Logger 中的一样)</P></TD>
<TD width="21%">className</TD>
<TD width="52%">
<P>指定Valve使用的类名，如用org.apache.catalina.valves.AccessLogValve类可以记录应用程序的访问信息</P></TD></TR>
<TR>
<TD width="21%">directory</TD>
<TD width="52%">指定log文件存放的位置</TD></TR>
<TR>
<TD width="21%">pattern</TD>
<TD width="52%">有两个值，common方式记录远程主机名或ip地址，用户名，日期，第一行请求的字符串，HTTP响应代码，发送的字节数。combined方式比common方式记录的值更多</TD></TR></TBODY></TABLE>
<P>注意：1：经过我测试，我设置Context 的path="",reloadable=true，然后放一个WAR文件到webapps目录，结果tomcat不能检测出此文件(重起tomcat可以)，而把此文件解压，则tomcat会自动检测出这个新的应用程序。如果不能自动检测WAR文件，我们可以利用下面管理中讲的方法来部署应用程序。</P>
<P>2：默认的server.xml中，Realm元素只设置了一个className属性，但此文件中也包含几个通过JDBC连接到数据库进行验证的示例(被注释掉了)，通过Realm元素我们可以实现容器安全管理(Container Managed Security)。</P>
<P>3：还有一些元素我们没有介绍，如Parameter，loader，你可以通过tomcat的文档获取这些元素的信息。</P>
<P><SPAN class=atitle3>(三)：管理</SPAN></P>
<P><B>1：配置</B><BR>在进行具体的管理之前，我们先给tomcat添加一个用户，使这个用户有权限来进行管理。</P>
<P>打开conf目录下的tomcat-users.xml文件，在相应的位置添加下面一行：</P>
<TABLE cellSpacing=0 cellPadding=5 width="100%" bgColor=#cccccc border=1>
<TBODY>
<TR>
<TD><PRE><CODE>&lt;user name="zf" password="zf" roles="standard,manager"/&gt;  </CODE> </PRE></TD></TR></TBODY></TABLE><BR><BR>
<P>注意：这一行的最后部分一定是/&gt;,tomcat的文档掉了/符号，如果没有/符号的话，tomcat重起时将无法访问应用程序。通过logs/catalina.out文件你可以看到这个错误的详细信息。</P>
<P>然后重起tomcat，在浏览器中输入http://localhost:8080/manager/，会弹出对话框，输入上面的用户名和密码即可。</P>
<P><B>2：应用程序列表</B><BR>在浏览器中输入http://localhost:8080/manager/list，浏览器将会显示如下的信息：</P>
<TABLE cellSpacing=0 cellPadding=5 width="100%" bgColor=#cccccc border=1>
<TBODY>
<TR>
<TD><PRE><CODE>OK - Listed applications for virtual host localhost /ex:running:1 /examples:running:1 /webdav:running:0 /tomcat-docs:running:0 /manager:running:0 /:running:0</CODE> </PRE></TD></TR></TBODY></TABLE><BR><BR>
<P>面的信息分别为应用程序的路径，当前状态(running 或者stopped)，与这个程序相连的session数。</P>
<P><B>3：重新装载应用程序</B><BR>在浏览器中输入 http://localhost:8080/manager/reload?path=/examples，浏览器显示如下：</P>
<TABLE cellSpacing=0 cellPadding=5 width="100%" bgColor=#cccccc border=1>
<TBODY>
<TR>
<TD><PRE><CODE>OK - Reloaded application at context path /examples   </CODE> </PRE></TD></TR></TBODY></TABLE><BR><BR>
<P>表示example应用程序装载成功，如果我们将server.xml的Context元素的reloadable属性设为true(见上面表格)，则没必要利用这种方式重新装载应用程序，因为tomcat会自动装载。</P>
<P><B>4：显示session信息</B><BR>在浏览器中输入http://localhost:8080/manager/sessions?path=/examples，浏览器显示如下：</P>
<TABLE cellSpacing=0 cellPadding=5 width="100%" bgColor=#cccccc border=1>
<TBODY>
<TR>
<TD><PRE><CODE>OK - Session information for application at context path </CODE></PRE><PRE><CODE>/examples Default maximum session inactive interval 30 minutes   </CODE> </PRE></TD></TR></TBODY></TABLE><BR><BR>
<P><B>5：启动和关闭应用程序</B><BR>在浏览器中输入http://localhost:8080/manager/start?path=/examples和http://localhost:8080/manager/stop?path=/examples分别启动和关闭examples应用程序。</P>
<P><B>6：部署及撤销部署</B><BR>WAR有两种组织方式，一种是按一定的目录结构组织文件，一种是一个后缀为WAR的压缩包，因此它的部署方式也有两种：<BR>(1)：在浏览器中输入：<FONT face=新宋体><CODE>http://localhost:8080/manager/install?path=/examples&amp;war=file:/c:examples</CODE><BR></FONT>就会将按目录结构组织的WAR部署</P>
<P>(2)：如果输入:<FONT face=新宋体><CODE>http://localhost:8080/manager/install?path=/examples&amp;war=jar:file:/c:examples.war!/</CODE><BR></FONT>就会将按压缩包组织的WAR部署，注意此url后半部分一定要有!/号。</P>
<P>部署后就可以用 http://localhost:8080/examples访问了。</P>
<P>在浏览器中输入：<FONT face=新宋体><CODE>http://localhost:8080/manager/remove?path=/examples</CODE><BR></FONT>就会撤销刚才部署的应用程序。</P>
<P><SPAN class=atitle3>(四)：与apache集成</SPAN><BR>虽然tomcat也可以作web服务器,但其处理静态html的速度比不上apache,且其作为web服务器的功能远不如apache,因此我们想把apache和tomcat集成起来。</P>
<P>我们以linux系统为例介绍.</P>
<P>从apache网站下载<A href="http://www.apache.org/dist/httpd/apache_1.3.22.tar.gz" target=_blank>apache1.3.22源代码版本</A>，然后使用如下命令配置安装apache：</P>
<TABLE cellSpacing=0 cellPadding=5 width="100%" bgColor=#cccccc border=1>
<TBODY>
<TR>
<TD><PRE><CODE>mkdir /usr/local/apache tar zxvf apache.1.32.tar.gz cd apache.1.32 ./configure --prefix=/usr/local/apache --enable-module=so  make make install </CODE> </PRE></TD></TR></TBODY></TABLE><BR><BR>
<P>注意configure命令指定目标安装目录，并且加入DSO(Dynamic Shared Object)支持，注意一定不要忘了这一个选项。</P>
<P>然后下载<A href="http://jakarta.apache.org/builds/jakarta-tomcat-4.0/release/v4.0.1/bin/linux/i386/webapp-module-1.0-tc40-linux-glibc2.2.tar.gz" target=_blank>webapp模块</A>，将解压后mod_webapp.so文件放入apache的libexec目录，编辑apache的conf目录下的httpd.conf，在这个文件的最后加入下面三行：</P>
<TABLE cellSpacing=0 cellPadding=5 width="100%" bgColor=#cccccc border=1>
<TBODY>
<TR>
<TD><PRE><CODE>LoadModule webapp_module libexec/mod_webapp.so WebAppConnection warpConnection warp localhost:8008 WebAppDeploy examples warpConnection /examples/  </CODE> </PRE></TD></TR></TBODY></TABLE><BR><BR>
<P>第一行是加入webapp模块，如果编译apache时不增加DSO支持，则无法使用LoadModule指令，第二行指定tomcat与apache的连接，第三行指定部署那个应用，这两个指令使用格式如下：</P>
<TABLE cellSpacing=0 cellPadding=5 width="100%" bgColor=#cccccc border=1>
<TBODY>
<TR>
<TD><PRE><CODE>WebAppConnection [connection name] [provider] [host:port] WebAppDeploy [application name] [connection name] [url path]   </CODE> </PRE></TD></TR></TBODY></TABLE><BR><BR>
<P>其中connection name指定连接名，provider只能是warp，port端口与你的tomcat的配置文件server.xml最后几行指定的要保持一致。文件如下：</P>
<TABLE cellSpacing=0 cellPadding=5 width="100%" bgColor=#cccccc border=1>
<TBODY>
<TR>
<TD><PRE><CODE>&lt;Service name="Tomcat-Apache"&gt;  </CODE></PRE><PRE><CODE>&lt;Connector className="org.apache.catalina.connector.warp.WarpConnector" </CODE></PRE><PRE><CODE>port="8008" minProcessors="5" maxProcessors="75" enableLookups="true" acceptCount="10" debug="0"/&gt; </CODE></PRE><PRE><CODE>****** </CODE></PRE><PRE><CODE>&lt;/Service&gt;  </CODE> </PRE></TD></TR></TBODY></TABLE><BR><BR>
<P>application name与你在tomcat中部署的应用名一致，url path指定访问这个应用的url。例如上面的例子可以通过http://localhost/examples/来访问tomcat中的examples应用。</P>
<P><SPAN class=atitle3>(五)：中文问题</SPAN><BR>一般jsp的乱码问题可以通过在jsp中加入&lt;%@ page contentType="text/html;charset=GB2312" %&gt;来解决，至于servlet的乱码在可以使用servlet2.3中提供的HttpServeletRequest.setCharacterEncoding函数。更详细的中文问题请见<A href="http://www-900.ibm.com/developerWorks/cn/java/jsp_dbcsz/index.shtml" target=_blank>JSP/Servlet 中的汉字编码问题</A>。</P>
<P><A id=4 name=4><SPAN class=atitle2>四：综述</SPAN></A><BR>tomcat作为一个servlet(jsp也被编译为servlet执行)容器，其应用前景是非常好的，如果与<A href="http://www.jboss.org/" target=_blank>jboss</A>结合起来，则可以实现sun的j2ee规范(用jboss作ejb服务器)。jboss的官方网站也提供集成了tomcat3.2*的jboss以供下载。另外一个开源的应用服务器(<A href="http://www.enhydra.org/" target=_blank>enhydra</A>) 也是基于tomcat的，其提供了更友好的管理界面，部署应用程序也更简单，功能也更强大。</P>
<DIV></DIV></DIV><img src ="http://www.blogjava.net/jackybu/aggbug/1719.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jackybu/" target="_blank">辰</a> 2005-03-05 14:53 <a href="http://www.blogjava.net/jackybu/articles/1719.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Spring学习笔记</title><link>http://www.blogjava.net/jackybu/articles/1716.html</link><dc:creator>辰</dc:creator><author>辰</author><pubDate>Sat, 05 Mar 2005 06:20:00 GMT</pubDate><guid>http://www.blogjava.net/jackybu/articles/1716.html</guid><wfw:comment>http://www.blogjava.net/jackybu/comments/1716.html</wfw:comment><comments>http://www.blogjava.net/jackybu/articles/1716.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jackybu/comments/commentRss/1716.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jackybu/services/trackbacks/1716.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: ******************************************************* 作者：陈刚，程序员，广西省桂林人，广西师范大学数学系97届毕业。blog：http://blog.csdn.net/glchengangEmail：glchengang@yeah.net&nbsp; ************************************...&nbsp;&nbsp;<a href='http://www.blogjava.net/jackybu/articles/1716.html'>阅读全文</a><img src ="http://www.blogjava.net/jackybu/aggbug/1716.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jackybu/" target="_blank">辰</a> 2005-03-05 14:20 <a href="http://www.blogjava.net/jackybu/articles/1716.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>使用JSP + JAVABEAN + XML 开发的一个例子 </title><link>http://www.blogjava.net/jackybu/articles/1578.html</link><dc:creator>辰</dc:creator><author>辰</author><pubDate>Mon, 28 Feb 2005 13:39:00 GMT</pubDate><guid>http://www.blogjava.net/jackybu/articles/1578.html</guid><wfw:comment>http://www.blogjava.net/jackybu/comments/1578.html</wfw:comment><comments>http://www.blogjava.net/jackybu/articles/1578.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jackybu/comments/commentRss/1578.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jackybu/services/trackbacks/1578.html</trackback:ping><description><![CDATA[<P>本例子是参考了一些网站上有关JSP 对 XML 的操作的相关文档，又结合了一些个人的体会。例子涉及的内容是，开发的一个企业内部定餐系统后台管理端的部分代码，功能主要集中在对于餐馆基本信息的管理。</P>
<P>该例子本身开发的起因是我在原公司和同事们一个玩笑的一部分。特此也表达对那些一起共事的朋友们的想念。</P>
<P>例子本身是在TOMCAT4.01 平台下运行的B/S结构的程式。有关TOMCAT 的配置，这里不做说明。只讲解一下相关文件及文件夹的目录结构。</P>
<P>目录结构说明：<BR>/tomcat/webapps/canyin/&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; -----主目录<BR>/tomcat/webapps/canyin/jsp/&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; -----JSP 文件目录<BR>/tomcat/webapps/canyin/jsp/admin/&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; -----实现后台管理的JSP 文件的存放目录<BR>/tomcat/webapps/canyin/WEB-INF/classes/canyin/&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ------javabean 文件的存放目录<BR>/tomcat/webapps/canyin/data/&nbsp;&nbsp; -----xml 文件存放目录<BR>/tomcat/webapps/ROOT/&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; -----tomcat 启动文件存放文件夹，只存放了index.html 文件</P>
<P>文件简单说明：<BR>/tomcat/webapps/canyin/data/users.xml&nbsp;&nbsp;&nbsp; -----记录用户信息<BR>/tomcat/webapps/canyin/data/restaurants.xml&nbsp; -----记录餐馆的基础信息</P>
<P><BR>/tomcat/webapps/ROOT/index.html&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; -----首页，页面出现输入框，要求用户输入用户名，密码</P>
<P><BR>/tomcat/webapps/canyin/jsp/loginjudge.jsp&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; -----用户身份判断页面，根据用户名称和密码决定页面是转入后台管理端，还是前台客户端。本例子中，用户身份一旦确认为有管理权限，可以进入后台管理端，就直接跳到餐馆基本信息管理页面，简化说明的流程。<BR>/tomcat/webapps/canyin/jsp/admin/admin_rest.jsp&nbsp;&nbsp;&nbsp; -----餐馆基本信息管理页面，管理餐馆的名称，电话，地址等信息</P>
<P>/tomcat/webapps/canyin/WEB-INF/classes/canyin/checkSessionBean.class&nbsp; ----- 后台管理端检测标志用户身份的session 的值，如果不是管理员的话，跳回登陆页面。&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <BR>/tomcat/webapps/canyin/WEB-INF/classes/canyin/connXmlBean.class&nbsp; -----连接xml 文件<BR>/tomcat/webapps/canyin/WEB-INF/classes/canyin/writeXmlBean.class&nbsp; -----写入xml文件</P>
<P>文件详细介绍及附带代码说明。</P>
<P>/tomcat/webapps/canyin/data/users.xml&nbsp;&nbsp;&nbsp; </P>
<P>代码：<BR>&nbsp; &lt;?xml version="1.0" encoding="UTF-8" ?&gt; </P>
<P>- &lt;users&gt;<BR>&nbsp; &lt;user name="joard" password="joard" roles="admin" /&gt; <BR>&nbsp; &lt;user name="joard01" password="joard01" roles="user" /&gt; <BR>&nbsp; &lt;user name="joard02" password="joard02" roles="user" /&gt; <BR>&nbsp; &lt;/users&gt;<BR>&nbsp;<BR>说明：字段含义是用户名，密码以及用户的身份<BR>&nbsp;<BR>/tomcat/webapps/canyin/data/restaurants.xml&nbsp; </P>
<P>代码：<BR>&nbsp; &lt;?xml version="1.0" encoding="UTF-8" ?&gt; <BR>- &lt;restaurants num="10"&gt;<BR>- &lt;restaurant id="1"&gt;<BR>&nbsp; &lt;name&gt;上海亭快餐店&lt;/name&gt; <BR>&nbsp; &lt;phone&gt;021-76546726&lt;/phone&gt; <BR>&nbsp; &lt;address&gt;百老汇广场B座&lt;/address&gt; <BR>&nbsp; &lt;/restaurant&gt;<BR>- &lt;restaurant id="8"&gt;<BR>&nbsp; &lt;name&gt;香格里拉大饭店&lt;/name&gt; <BR>&nbsp; &lt;phone&gt;021-2312134&lt;/phone&gt; <BR>&nbsp; &lt;address&gt;南京路1023号&lt;/address&gt; <BR>&nbsp; &lt;/restaurant&gt;<BR>&nbsp; &lt;/restaurants&gt;<BR>说明：&lt;num&gt;属性是记录在restaurants.xml 文件中总共有过多少条记录，每新增一条，无论以后删除是否，该值都会增加1，就好象数据库中习惯使用的自动增加1的id 项。用来给新增的 &lt;restaurant&gt;的属性&lt;id&gt;赋一个唯一的值。其它的字段意思比较明显。<BR>/tomcat/webapps/ROOT/index.html&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; （单纯的HTML代码）</P>
<P>代码：<BR>&lt;html&gt;<BR>&lt;head&gt;<BR>&lt;title&gt;oddWorld 餐饮系统&lt;/title&gt;<BR>&lt;meta http-equiv="Content-Type" content="text/html; charset=gb2312"&gt;<BR>&lt;/head&gt;</P>
<P>&lt;body onload="javascript:dataform.username.focus()"&gt;<BR>&lt;div align="center"&gt;<BR>&nbsp; &lt;table width="100%" border="0" cellspacing="0" cellpadding="0" height="22"&gt;<BR>&nbsp;&nbsp;&nbsp; &lt;tr&gt; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;td width="1"&gt;&lt;img src="images/top_r1.GIF" width="62" height="22"&gt;&lt;/td&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;td width=150 align="center"&gt; 餐饮系统登录 &lt;/td&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;td&gt;&lt;img src="images/top_r2.GIF" width="294" height="22"&gt;&lt;/td&gt;<BR>&nbsp;&nbsp;&nbsp; &lt;/tr&gt;<BR>&nbsp; &lt;/table&gt;<BR>&nbsp; &lt;br&gt;<BR>&nbsp; &lt;br&gt;<BR>&nbsp; &lt;table width="300" border="0" cellspacing="1" cellpadding="0" &gt;<BR>&nbsp;&nbsp;&nbsp; &lt;tr&gt; <BR>&nbsp;&nbsp;&nbsp; &lt;td height="200" valign="top" align="center"&gt; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;p align="center"&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;table width="100%" border="0" cellspacing="1" cellpadding="5" bgcolor=#999999 class=a9px&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;tr&gt; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;td bgcolor="#efefef"&gt;餐饮系统登录&lt;/td&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/tr&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;tr&gt; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;td bgcolor="#FFFFFF" valign="top" align="center"&gt; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;table width="100%" border="0" cellspacing="0" cellpadding="0"&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;form name=dataform method=post action=''canyin/jsp/loginjudge.jsp''&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;tr&gt; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;td width="100"&gt;&lt;b&gt;登录名：&lt;/b&gt;&lt;/td&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;td&gt; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;input maxlength=16 <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; name="username" class=stedit value="joard"&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/td&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/tr&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;tr&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;td width="100"&gt;&lt;b&gt;密码：&lt;/b&gt;&lt;/td&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;td&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;input&nbsp; class=stedit&nbsp; maxlength=16 <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; name="userpass" type=password value="oddworld"&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/td&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/tr&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/form&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/table&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;br&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;table border=0 cellpadding=0 cellspacing=0&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;tbody&gt; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;tr&gt; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;td&gt; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;input&nbsp; class=stbtm&nbsp; name=update onClick="javascript:if (checkform()==false);" type=button value="登&nbsp;&nbsp;&nbsp; 录"&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/td&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;td&gt; &lt;/td&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;td&gt; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;input class=stbtm name=Submit onClick="javascript:window.location.href=''index.asp?myjoke=1'';" type=button value="修改密码"&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/td&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;td&gt; &lt;/td&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/tr&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/tbody&gt; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/table&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;br&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/td&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/tr&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/table&gt;<BR>&nbsp;&nbsp;&nbsp; &lt;/td&gt;<BR>&nbsp; &lt;/tr&gt;<BR>&lt;/table&gt;<BR>&lt;/div&gt;<BR>&lt;/body&gt;<BR>&lt;/html&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp; &lt;SCRIPT language=javascript&gt;<BR>&lt;!--<BR>function checkform()<BR>{ <BR>&nbsp;var Checkblank = /^(\s*|(\　)|(\.))*$/;<BR>&nbsp;if (Checkblank.test(dataform.username.value))&nbsp;&nbsp;&nbsp; <BR>{<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; alert("登录名不能为空!");<BR>&nbsp;&nbsp; return false; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (Checkblank.test(dataform.userpass.value))&nbsp;&nbsp;&nbsp; <BR>{<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; alert("密码不能为空!");<BR>&nbsp;&nbsp; return false; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } </P>
<P><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; window.dataform.submit();</P>
<P>&nbsp;&nbsp; }<BR>--&gt;</P>
<P>&lt;/SCRIPT&gt;</P>
<P>说明：把用户名称和用户密码提交到/tomcat/webapps/canyin/jsp/loginjudge.jsp&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </P>
<P>/tomcat/webapps/canyin/WEB-INF/classes/canyin/checkSessionBean.class&nbsp; （代码是相应的java 文件）</P>
<P>package canyin;</P>
<P>import javax.servlet.http.HttpSession;<BR>import javax.servlet.http.HttpServletRequest;</P>
<P>public class checkSessionBean {<BR>&nbsp;<BR>&nbsp;private boolean bolCheckPass=false;<BR>&nbsp;private HttpServletRequest request = null;<BR>&nbsp;<BR>&nbsp;public boolean checkSessionBean(HttpServletRequest request,String strSessionName,String strCheckValue){<BR>&nbsp;&nbsp; public boolean checkSessionBean(HttpServletRequest request){<BR>&nbsp; HttpSession session = request.getSession(false);<BR>&nbsp; return(bolCheckPass);<BR>&nbsp; <BR>&nbsp; if (strSessionName==null || strCheckValue==null){<BR>&nbsp;&nbsp; return(bolCheckPass);<BR>&nbsp; }else{<BR>&nbsp;&nbsp; if (session!=null &amp;&amp; session.getValue(strSessionName)!=null){<BR>&nbsp;&nbsp;&nbsp; bolCheckPass=session.getValue(strSessionName).equals(strCheckValue);<BR>&nbsp;&nbsp; }<BR>&nbsp;&nbsp; <BR>&nbsp;&nbsp;&nbsp;&nbsp; return(bolCheckPass);<BR>&nbsp; }<BR>&nbsp;}<BR>}</P>
<P>说明：检验参数传入的session 名称的数值和参数传入的字段的数值是否相等。</P>
<P>/tomcat/webapps/canyin/WEB-INF/classes/canyin/connXmlBean.class&nbsp; </P>
<P>代码：<BR>package canyin;</P>
<P>import javax.xml.parsers.*;<BR>import javax.xml.transform.*;<BR>import javax.xml.transform.dom.DOMSource;<BR>import javax.xml.transform.stream.StreamResult;<BR>import org.w3c.dom.*;</P>
<P>public class connXmlBean {<BR>&nbsp;<BR>&nbsp;private DocumentBuilderFactory factory=null;<BR>&nbsp;private DocumentBuilder builder=null;<BR>&nbsp;private Document doc=null;<BR>&nbsp;<BR>&nbsp;public connXmlBean(){}<BR>&nbsp; <BR>&nbsp;public String connXml(String xmlFileName){<BR>&nbsp; <BR>&nbsp; String strExc="";<BR>&nbsp; <BR>&nbsp; try{<BR>&nbsp;&nbsp; factory = DocumentBuilderFactory.newInstance();<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; builder=factory.newDocumentBuilder();<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; doc=builder.parse(xmlFileName);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; doc.normalize(); <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }catch(Exception e){<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; strExc=e.toString();<BR>&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp;&nbsp; <BR>&nbsp;&nbsp;&nbsp; return(strExc);<BR>&nbsp;}<BR>&nbsp;<BR>&nbsp;public Document getXmlDoc(){<BR>&nbsp;&nbsp;&nbsp; return(doc);<BR>&nbsp;}<BR>}</P>
<P>说明：打开一个指定xml 文件</P>
<P>/tomcat/webapps/canyin/WEB-INF/classes/canyin/writeXmlBean.class&nbsp; </P>
<P>代码：<BR>package canyin;</P>
<P>import javax.xml.parsers.*;<BR>import javax.xml.transform.*;<BR>import javax.xml.transform.dom.DOMSource;<BR>import javax.xml.transform.stream.StreamResult;<BR>import java.io.File;<BR>import org.w3c.dom.*;</P>
<P>public class writeXmlBean {<BR>&nbsp;<BR>&nbsp;public writeXmlBean(){}<BR>&nbsp; <BR>&nbsp;public String writeXml(Document doc,String xmlFileName){<BR>&nbsp; <BR>&nbsp; String strExc="";<BR>&nbsp; <BR>&nbsp; try{<BR>&nbsp;&nbsp; TransformerFactory tfactory = TransformerFactory.newInstance(); <BR>&nbsp;&nbsp; Transformer transformer = tfactory.newTransformer(); </P>
<P>&nbsp;&nbsp; DOMSource source = new DOMSource(doc); </P>
<P>&nbsp;&nbsp; StreamResult result = new StreamResult(new File(xmlFileName)); </P>
<P>&nbsp;&nbsp; transformer.transform(source,result);&nbsp; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }catch(Exception e){<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; strExc=e.toString();<BR>&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp;&nbsp; <BR>&nbsp;&nbsp;&nbsp; return(strExc);<BR>&nbsp;}<BR>&nbsp;<BR>}</P>
<P>说明：写入dom 的内容到一个指定的xml 文件。</P>
<P>/tomcat/webapps/canyin/jsp/loginjudge.jsp&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </P>
<P>代码：<BR>&lt;%--&nbsp; oddWorld 餐饮管理系统(简体中文版) 2002年12月1日<BR>&nbsp;copy right by joard ast&nbsp; <BR>&nbsp;<BR>&nbsp;loginjudge.jsp 功能：用户身份校验，根据 /data/user.xml 文件内标示的用户不同的身份<BR>&nbsp;决定转入后台管理页面，还是客户点菜页面。<BR>&nbsp;--%&gt;</P>
<P>&lt;%@ page contentType="text/html;charset=gb2312" %&gt;<BR>&lt;%@ page language="java" import="javax.xml.parsers.*" %&gt;<BR>&lt;%@ page import="org.w3c.dom.*" %&gt;<BR>&lt;%@ page import="canyin.*" %&gt; </P>
<P>&lt;jsp:useBean id="xmlBean" class="canyin.connXmlBean" scope="page" /&gt;</P>
<P>&lt;%<BR>session.setMaxInactiveInterval(1800);</P>
<P><BR>Document doc;<BR>NodeList users;<BR>String strExc="";<BR>String strUsername,strPassword;</P>
<P>strUsername=(String)request.getParameter("username");<BR>strPassword=(String)request.getParameter("userpass");</P>
<P>//校验数据是否为空<BR>if (strUsername=="" || strPassword=="" ){<BR>&nbsp;out.println("&lt;script language=''javascript''&gt;");<BR>&nbsp;out.println("alert(''用户名或密码有空值!'');");<BR>&nbsp;out.println("window.location.href=''/index.html'';");<BR>&nbsp;out.println("&lt;/script&gt;");<BR>&nbsp;return;<BR>}</P>
<P>xmlBean.connXml("webapps/canyin/data/users.xml");<BR>doc=xmlBean.getXmlDoc();</P>
<P>try{<BR>&nbsp;users =doc.getElementsByTagName("user");<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <BR>&nbsp;&nbsp;&nbsp;&nbsp; for (int i=0;i&lt;users.getLength();i++){<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Element user=(Element) users.item(i);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <BR>&nbsp; String strAtrNameValue=user.getAttributeNode("name").getNodeValue();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <BR>&nbsp;String strAtrPassWordValue=user.getAttributeNode("password").getNodeValue();<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; String strAtrRoleValue=user.getAttributeNode("roles").getNodeValue(); <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (strAtrNameValue.equals(strUsername) &amp;&amp; strAtrPassWordValue.equals(strPassword)){<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (strAtrRoleValue.equals("admin")){<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; out.println("&lt;script language=''javascript''&gt;");<BR>&nbsp;&nbsp;&nbsp; out.println("alert(''欢迎管理员登陆系统!'');");<BR>&nbsp;&nbsp;&nbsp; out.println("&lt;/script&gt;");<BR>&nbsp;&nbsp;&nbsp; <BR>&nbsp;&nbsp;&nbsp; //设置标示用户身份的 session（sesUserRole） ，管理员身份为 admin<BR>&nbsp;&nbsp;&nbsp; session.setAttribute("sesUserRole","admin");<BR>&nbsp;&nbsp;&nbsp; <BR>&nbsp;&nbsp;&nbsp; //跳转到管理页面<BR>&nbsp;&nbsp;&nbsp; response.sendRedirect("admin/admin_rest.jsp");<BR>&nbsp;&nbsp;&nbsp; return;<BR>&nbsp;&nbsp;&nbsp; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }else{<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //设置标示用户身份的 session（sesUserRole） ，管理员身份为 user<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; session.setAttribute("sesUserRole","user");<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //跳转到普通用户页面<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; response.sendRedirect("index.jsp");&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</P>
<P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }else{<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; out.println("&lt;script language=''javascript''&gt;");<BR>&nbsp;&nbsp; out.println("alert(''用户名或密码错误!'');");<BR>&nbsp;&nbsp; out.println("history.go(-1);");<BR>&nbsp;&nbsp; out.println("&lt;/script&gt;");<BR>&nbsp;&nbsp; return;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</P>
<P>&nbsp;}<BR>}catch(Exception e){<BR>&nbsp;&nbsp;&nbsp;&nbsp; strExc=e.toString();<BR>}<BR>%&gt;<BR>说明：.......</P>
<P>/tomcat/webapps/canyin/jsp/admin/admin_rest.jsp&nbsp;&nbsp;&nbsp; </P>
<P>代码：<BR>&lt;%--&nbsp; oddWorld 餐饮管理系统(简体中文版) 2002年12月1日<BR>&nbsp;copy right by joard ast&nbsp; <BR>&nbsp;<BR>&nbsp;admin_rest.jsp 功能：后台管理页面，餐馆管理页面。<BR>&nbsp;--%&gt;</P>
<P>&lt;%@ page contentType="text/html;charset=gb2312" %&gt;<BR>&lt;%@ page language="java" import="javax.xml.parsers.*" %&gt;<BR>&lt;%@ page import="javax.xml.transform.*" %&gt;<BR>&lt;%@ page import="org.w3c.dom.*" %&gt;<BR>&lt;%@ page import="canyin.*" %&gt; </P>
<P>&lt;%@ include file="../../include/sys_dialog.jsp" %&gt;</P>
<P>&lt;jsp:useBean id="checkSessionBean" class="canyin.checkSessionBean" scope="page" /&gt;<BR>&lt;jsp:useBean id="xmlBean" class="canyin.connXmlBean" scope="page" /&gt;<BR>&lt;jsp:useBean id="writeXmlBean" class="canyin.writeXmlBean" scope="page" /&gt;</P>
<P>&lt;%//校验可户身份，判断是不是管理员<BR>if(!checkSessionBean.checkSessionBean(request,"sesUserRole","admin")){<BR>&nbsp;out.print(showDialog("您没有管理的权限!","/index.html"));<BR>&nbsp;return;<BR>}</P>
<P>//从餐馆资料文件 rest.xml 中得到相关数据<BR>Document doc;<BR>NodeList restaurants;</P>
<P>String strAct;<BR>int intId=0;<BR>String strOperation="show";</P>
<P>//接受外部传入的参数<BR>strAct=(String)request.getParameter("act");</P>
<P>xmlBean.connXml("webapps/canyin/data/restaurants.xml");<BR>doc=xmlBean.getXmlDoc();<BR>restaurants =doc.getElementsByTagName("restaurant");</P>
<P>//根据外部传入的参数来决定对 restaurant.xml 文件的操作<BR>if (strAct!=null){<BR>&nbsp;if(strAct.equals("addnewDo")){<BR>&nbsp; <BR>&nbsp; String strName;<BR>&nbsp; String strPhone;<BR>&nbsp; String strAddress;<BR>&nbsp; Text textseg;<BR>&nbsp; <BR>&nbsp; strName=(String)request.getParameter("name").trim();<BR>&nbsp; strPhone=(String)request.getParameter("phone").trim();<BR>&nbsp; strAddress=(String)request.getParameter("address").trim();<BR>&nbsp; <BR>&nbsp; //数据校验<BR>&nbsp; if(strName==null){<BR>&nbsp;&nbsp; out.print(showDialog("餐馆名称不能为空!"));<BR>&nbsp;&nbsp; return;<BR>&nbsp; }<BR>&nbsp; if(strPhone==null){<BR>&nbsp;&nbsp; out.print(showDialog("餐馆电话不能为空!"));<BR>&nbsp;&nbsp; return;<BR>&nbsp; }<BR>&nbsp; /*if(strAddress==null){<BR>&nbsp;&nbsp; out.print(showDialog("餐馆地址不能为空!"));<BR>&nbsp;&nbsp; return;<BR>&nbsp; }*/<BR>&nbsp; <BR>&nbsp; //校验数据的唯一性<BR>&nbsp; for(int i=0;i&lt;restaurants.getLength();i++){<BR>&nbsp;&nbsp; Element restaurant=(Element) restaurants.item(i);<BR>&nbsp;&nbsp; if(((String)restaurant.getElementsByTagName("name").item(0).getFirstChild().getNodeValue()).equals(strName)){<BR>&nbsp;&nbsp;&nbsp; out.print(showDialog("餐馆名称重复!"));<BR>&nbsp;&nbsp;&nbsp; return; <BR>&nbsp;&nbsp; }else{<BR>&nbsp;&nbsp;&nbsp; if(((String)restaurant.getElementsByTagName("name").item(0).getFirstChild().getNodeValue()).equals(strPhone)){<BR>&nbsp;&nbsp;&nbsp;&nbsp; out.print(showDialog("餐馆电话重复!"));<BR>&nbsp;&nbsp;&nbsp;&nbsp; return;<BR>&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp; }<BR>&nbsp;&nbsp; <BR>&nbsp; }<BR>&nbsp; <BR>&nbsp; <BR>&nbsp;&nbsp;&nbsp; <BR>&nbsp; //得到已有的记录数，给新增的餐馆记录设定唯一的递增的id 属性<BR>&nbsp; int intNum=0;<BR>&nbsp; Element restNum=(Element)doc.getElementsByTagName("restaurants").item(0);<BR>&nbsp; intNum=Integer.parseInt(restNum.getAttributeNode("num").getNodeValue()); </P>
<P>&nbsp; intNum+=1;<BR>&nbsp; <BR>&nbsp; //为restaurants的属性num 的数值加1<BR>&nbsp; restNum.getAttributeNode("num").setNodeValue(String.valueOf(intNum));</P>
<P>&nbsp; //新增节点&nbsp;&nbsp;&nbsp; <BR>&nbsp; Element newRestaurant=doc.createElement("restaurant");<BR>&nbsp; <BR>&nbsp; Attr newArrId=doc.createAttribute("id");<BR>&nbsp; //Attribute newArrId = new Attribute("id",String.valueOf(intNum));&nbsp; <BR>&nbsp; textseg=doc.createTextNode(String.valueOf(intNum));<BR>&nbsp; newArrId.setValue(String.valueOf(intNum));<BR>&nbsp; newRestaurant.setAttributeNode(newArrId);<BR>&nbsp; <BR>&nbsp; Element newName=doc.createElement("name");<BR>&nbsp; textseg=doc.createTextNode(strName);<BR>&nbsp; newName.appendChild(textseg);<BR>&nbsp; newRestaurant.appendChild(newName);<BR>&nbsp; <BR>&nbsp; Element newPhone=doc.createElement("phone");<BR>&nbsp; textseg=doc.createTextNode(strPhone);<BR>&nbsp; newPhone.appendChild(textseg);<BR>&nbsp; newRestaurant.appendChild(newPhone);<BR>&nbsp; <BR>&nbsp; Element newAddress=doc.createElement("address");<BR>&nbsp; textseg=doc.createTextNode(strAddress);<BR>&nbsp; newAddress.appendChild(textseg);<BR>&nbsp; newRestaurant.appendChild(newAddress);<BR>&nbsp; <BR>&nbsp; doc.getDocumentElement().appendChild(newRestaurant);</P>
<P>&nbsp; //调用bean 写入相应的xml文件<BR>&nbsp; writeXmlBean.writeXml(doc,"webapps/canyin/data/restaurants.xml");</P>
<P>&nbsp; response.sendRedirect(request.getRequestURI());&nbsp; <BR>&nbsp; return;<BR>&nbsp;}<BR>&nbsp;if(strAct.equals("modiDo")){<BR>&nbsp; String strName;<BR>&nbsp; String strPhone;<BR>&nbsp; String strAddress;<BR>&nbsp; Text textseg;<BR>&nbsp; int modiId;<BR>&nbsp; //记录要修改的记录是item(i)的哪一项<BR>&nbsp; int intI=0;<BR>&nbsp; <BR>&nbsp; strName=(String)request.getParameter("name").trim();<BR>&nbsp; strPhone=(String)request.getParameter("phone").trim();<BR>&nbsp; strAddress=(String)request.getParameter("address").trim();<BR>&nbsp; modiId=Integer.parseInt(request.getParameter("recordId").trim());<BR>&nbsp; <BR>&nbsp; //数据校验<BR>&nbsp; if(strName==null){<BR>&nbsp;&nbsp; out.print(showDialog("餐馆名称不能为空!"));<BR>&nbsp;&nbsp; return;<BR>&nbsp; }<BR>&nbsp; if(strPhone==null){<BR>&nbsp;&nbsp; out.print(showDialog("餐馆电话不能为空!"));<BR>&nbsp;&nbsp; return;<BR>&nbsp; }<BR>&nbsp; if(modiId==0){<BR>&nbsp;&nbsp; out.print(showDialog("你要修改餐馆的记录不存在!"));<BR>&nbsp;&nbsp; return;<BR>&nbsp; }<BR>&nbsp; /*if(strAddress==null){<BR>&nbsp;&nbsp; out.print(showDialog("餐馆地址不能为空!"));<BR>&nbsp;&nbsp; return;<BR>&nbsp; }*/<BR>&nbsp; <BR>&nbsp; //标志显示记录存在<BR>&nbsp; boolean recordExist=false;<BR>&nbsp; <BR>&nbsp; //校验数据的唯一性<BR>&nbsp; for(int i=0;i&lt;restaurants.getLength();i++){<BR>&nbsp;&nbsp; Element restaurant=(Element) restaurants.item(i);<BR>&nbsp;&nbsp; <BR>&nbsp;&nbsp; if(Integer.parseInt(restaurant.getAttributeNode("id").getNodeValue())==modiId){<BR>&nbsp;&nbsp;&nbsp; recordExist=true;<BR>&nbsp;&nbsp;&nbsp; intI=i;</P>
<P>&nbsp;&nbsp; }<BR>&nbsp;&nbsp; <BR>&nbsp;&nbsp; if(((String)restaurant.getElementsByTagName("name").item(0).getFirstChild().getNodeValue()).equals(strName) &amp;&amp; Integer.parseInt(restaurant.getAttributeNode("id").getNodeValue())!=modiId ){<BR>&nbsp;&nbsp;&nbsp; out.print(showDialog("餐馆名称重复!"));<BR>&nbsp;&nbsp;&nbsp; return; <BR>&nbsp;&nbsp; }else{<BR>&nbsp;&nbsp;&nbsp; if(((String)restaurant.getElementsByTagName("name").item(0).getFirstChild().getNodeValue()).equals(strPhone) &amp;&amp; Integer.parseInt(restaurant.getAttributeNode("id").getNodeValue())!=modiId ){<BR>&nbsp;&nbsp;&nbsp;&nbsp; out.print(showDialog("餐馆电话重复!"));<BR>&nbsp;&nbsp;&nbsp;&nbsp; return;<BR>&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp; }<BR>&nbsp;&nbsp; <BR>&nbsp; }<BR>&nbsp; </P>
<P> <BR>&nbsp; if(!recordExist){<BR>&nbsp;&nbsp; out.print(showDialog("你要修改餐馆的记录不存在!"));<BR>&nbsp;&nbsp; return;<BR>&nbsp; }else{<BR>&nbsp;&nbsp; //进行记录更改的操作<BR>&nbsp;&nbsp; try{<BR>&nbsp;&nbsp;&nbsp; Element modiRestaurant=(Element) restaurants.item(intI);<BR>&nbsp;&nbsp;&nbsp; modiRestaurant.getElementsByTagName("name").item(0).getFirstChild().setNodeValue(strName);<BR>&nbsp;&nbsp;&nbsp; modiRestaurant.getElementsByTagName("phone").item(0).getFirstChild().setNodeValue(strPhone);<BR>&nbsp;&nbsp;&nbsp; modiRestaurant.getElementsByTagName("address").item(0).getFirstChild().setNodeValue(strAddress);<BR>&nbsp;&nbsp;&nbsp; <BR>&nbsp;&nbsp;&nbsp; //调用bean 写入相应的xml文件<BR>&nbsp;&nbsp;&nbsp; writeXmlBean.writeXml(doc,"webapps/canyin/data/restaurants.xml");<BR>&nbsp; <BR>&nbsp;&nbsp;&nbsp; response.sendRedirect(request.getRequestURI());&nbsp; <BR>&nbsp;&nbsp;&nbsp; return; <BR>&nbsp;&nbsp;&nbsp; <BR>&nbsp;&nbsp; }catch(Exception e){}<BR>&nbsp; }<BR>&nbsp;}<BR>&nbsp;//进行删除操作<BR>&nbsp;if(strAct.equals("del")){<BR>&nbsp; int delId;<BR>&nbsp; //记录要修改的记录是item(i)的哪一项<BR>&nbsp; int intI=0;</P>
<P>&nbsp; delId=Integer.parseInt(request.getParameter("recordId").trim());</P>
<P>&nbsp; if(delId==0){<BR>&nbsp;&nbsp; out.print(showDialog("你要修改餐馆的记录不存在!"));<BR>&nbsp;&nbsp; return;<BR>&nbsp; }<BR>&nbsp; <BR>&nbsp; file://标志显示记录存在<BR>&nbsp; boolean recordExist=false;</P>
<P>&nbsp; //校验数据的唯一性<BR>&nbsp; for(int i=0;i&lt;restaurants.getLength();i++){<BR>&nbsp;&nbsp; Element restaurant=(Element) restaurants.item(i);<BR>&nbsp;&nbsp; <BR>&nbsp;&nbsp; if(Integer.parseInt(restaurant.getAttributeNode("id").getNodeValue())==delId){<BR>&nbsp;&nbsp;&nbsp; recordExist=true;<BR>&nbsp;&nbsp;&nbsp; intI=i;</P>
<P>&nbsp;&nbsp; }<BR>&nbsp; }<BR>&nbsp; <BR>&nbsp; if(!recordExist){<BR>&nbsp;&nbsp; out.print(showDialog("你要删除餐馆的记录不存在!"));<BR>&nbsp;&nbsp; return;<BR>&nbsp; }else{<BR>&nbsp;&nbsp; //进行记录删除的操作<BR>&nbsp;&nbsp; try{<BR>&nbsp;&nbsp;&nbsp; Node delNode=(Node)restaurants.item(intI);<BR>&nbsp;&nbsp;&nbsp; <BR>&nbsp;&nbsp;&nbsp; doc.getElementsByTagName("restaurants").item(0).removeChild(delNode);</P>
<P>&nbsp;&nbsp;&nbsp; //调用bean 写入相应的xml文件<BR>&nbsp;&nbsp;&nbsp; writeXmlBean.writeXml(doc,"webapps/canyin/data/restaurants.xml");</P>
<P>&nbsp;&nbsp;&nbsp; response.sendRedirect(request.getRequestURI());&nbsp; <BR>&nbsp;&nbsp;&nbsp; return; <BR>&nbsp;&nbsp;&nbsp; <BR>&nbsp;&nbsp; }catch(Exception e){}<BR>&nbsp; }</P>
<P>&nbsp;}<BR>}</P>
<P>//由外部传入参数决定页面相应的处理状态<BR>if (strAct==null){<BR>&nbsp;strOperation="show";<BR>}else{<BR>&nbsp;if (strAct.equals("modi")){<BR>&nbsp; strOperation="modi";<BR>&nbsp; intId=Integer.parseInt(request.getParameter("recordId"));<BR>&nbsp;}else{<BR>&nbsp; if(strAct.equals("addnew")){<BR>&nbsp;&nbsp; strOperation="addnew";<BR>&nbsp; }else{<BR>&nbsp;&nbsp; strOperation="show";<BR>&nbsp; }<BR>&nbsp;}<BR>}</P>
<P><BR>//如果为空记录，则变更页面状态为“新增”<BR>if (restaurants.getLength()==0){<BR>&nbsp;strOperation="addnew";<BR>}<BR>%&gt;</P>
<P>&lt;html&gt;<BR>&lt;head&gt;<BR>&lt;title&gt;oddWorld 餐饮系统&lt;/title&gt;<BR>&lt;meta http-equiv="Content-Type" content="text/html; charset=gb2312"&gt;<BR>&lt;meta http-equiv="expires" content="0"&gt;<BR>&lt;link rel="stylesheet" href="../../include/itsp.css" type="text/css"&gt;<BR>&lt;/head&gt;</P>
<P>&lt;body &gt;<BR>&lt;div align="center"&gt;<BR>&nbsp; &lt;table width="100%" border="0" cellspacing="0" cellpadding="0" height="22"&gt;<BR>&nbsp;&nbsp;&nbsp; &lt;tr&gt; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;td width="1"&gt;&lt;img src="../../images/top_r1.GIF" width="62" height="22"&gt;&lt;/td&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;td width=150 align="center"&gt; 餐饮系统管理--餐馆管理&lt;/td&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;td&gt;&lt;img src="../../images/top_r2.GIF" width="294" height="22"&gt;&lt;/td&gt;<BR>&nbsp;&nbsp; &lt;td width=100 align="center"&gt;&lt;a href="/index.html"&gt;[ 退出系统 ]&lt;/a&gt;&lt;/td&gt;<BR>&nbsp;&nbsp;&nbsp; &lt;/tr&gt;<BR>&nbsp; &lt;/table&gt;<BR>&nbsp; &lt;br&gt;<BR>&nbsp; &lt;br&gt;<BR>&nbsp; &lt;table bgcolor="#999999" align=center border=0 cellpadding=1 cellspacing=1 <BR>width="90%"&gt;<BR>&nbsp;&nbsp;&nbsp; &lt;tbody&gt; <BR>&nbsp;&nbsp;&nbsp; &lt;tr bgcolor="#efefef" align="center" valign="middle"&gt; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;td class=ttTable height=30 width="20"&gt; &lt;/td&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;td class=ttTable height=30 width="0"&gt;餐馆名称&lt;/td&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;td class=ttTable height=30 width="0"&gt;餐馆电话&lt;/td&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;td class=ttTable height=30 width="0"&gt; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;div align="center"&gt;餐馆地址&lt;/div&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/td&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;td class=ttTable height=30 width="30"&gt; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;div align="center"&gt;修改&lt;/div&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/td&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;td class=ttTable height=30 width="30"&gt; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;div align="center"&gt;删除&lt;/div&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/td&gt;<BR>&nbsp;&nbsp;&nbsp; &lt;/tr&gt;<BR>&lt;%<BR>&nbsp;for(int i=0;i&lt;restaurants.getLength();i++)<BR>&nbsp;{<BR>&nbsp; Element restaurant=(Element) restaurants.item(i);<BR>&nbsp; <BR>&nbsp; if (strOperation=="modi" &amp;&amp; Integer.parseInt(restaurant.getAttributeNode("id").getNodeValue())==intId){<BR>%&gt;<BR>&nbsp;&nbsp;&nbsp; &lt;%//显示修改的格式%&gt;<BR>&nbsp;&nbsp;&nbsp; &lt;tr align="center" bgcolor="#ffffff" valign="middle"&gt; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;form name=dataform action="&lt;%=request.getRequestURI()%&gt;?act=modiDo" method="post"&nbsp; onSubmit=''return checkform(this);'' &gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;td class=tdsmall height=25 width="20"&gt; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;input type="hidden" name="recordId" value="&lt;%=restaurant.getAttributeNode("id").getNodeValue()%&gt;"&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;%=(i+1)%&gt;&lt;/td&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;td class=tdsmall height=25&gt; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;input name="name" class=stedit<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; style="HEIGHT: 22px; WIDTH: 150px" value="&lt;%if(restaurant.getElementsByTagName("name").item(0).hasChildNodes()){<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; out.print(restaurant.getElementsByTagName("name").item(0).getFirstChild().getNodeValue());<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }%&gt;<BR>" maxlength="40" &gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/td&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;td class=tdsmall height=25&gt; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;input name="phone" class=stedit<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; style="HEIGHT: 22px; WIDTH: 100px" value="&lt;%if(restaurant.getElementsByTagName("phone").item(0).hasChildNodes()){<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; out.print(restaurant.getElementsByTagName("phone").item(0).getFirstChild().getNodeValue());<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }%&gt;" maxlength="20" &gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/td&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;td class=tdsmall height=25&gt; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;input name="address" class=stedit<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; style="HEIGHT: 22px; WIDTH: 200px" value="&lt;%<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(restaurant.getElementsByTagName("address").item(0).hasChildNodes()){<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; out.print(restaurant.getElementsByTagName("address").item(0).getFirstChild().getNodeValue());<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }%&gt;" maxlength="100" &gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/td&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;td class=tdsmall height=25 width="25"&gt;&lt;a href="javascript:if (checkform()==false);"&gt;&lt;img border=0 <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; height=15 src="../../images/editok.gif" width=15&gt;&lt;/a&gt;&lt;/td&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;td class=tdsmall height=25 width="25"&gt; &lt;/td&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/form&gt;<BR>&nbsp;&nbsp;&nbsp; &lt;/tr&gt;<BR>&nbsp;&nbsp;&nbsp; &lt;% }else{ <BR>&nbsp;&nbsp;&nbsp; //显示正常的格式 %&gt;<BR>&nbsp;&nbsp;&nbsp; &lt;tr align="center" bgcolor="#ffffff" valign="middle"&gt; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;td class=tdsmall height=25 width="20"&gt;&lt;%=(i+1)%&gt;&lt;/td&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;td class=tdsmall height=25 width="0"&gt;&lt;%if(restaurant.getElementsByTagName("name").item(0).hasChildNodes()){<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; out.print(restaurant.getElementsByTagName("name").item(0).getFirstChild().getNodeValue());<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }%&gt;<BR>&lt;/td&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;td class=tdsmall height=25 width="0"&gt;&lt;%if(restaurant.getElementsByTagName("phone").item(0).hasChildNodes()){<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; out.print(restaurant.getElementsByTagName("phone").item(0).getFirstChild().getNodeValue());<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }%&gt;&lt;/td&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;td class=tdsmall height=25 width="0"&gt; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;%<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(restaurant.getElementsByTagName("address").item(0).hasChildNodes()){<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; out.print(restaurant.getElementsByTagName("address").item(0).getFirstChild().getNodeValue());<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }%&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/td&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;td class=tdsmall height=25 width="30"&gt;&lt;a href="&lt;%=request.getRequestURI()%&gt;?act=modi&amp;recordId=&lt;%=restaurant.getAttributeNode("id").getNodeValue()%&gt;"&gt;&lt;img border=0 <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; height=15 src="../../images/edit.gif" width=15&gt;&lt;/a&gt;&lt;/td&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;td class=tdsmall height=25 width="30"&gt;&lt;img border=0 <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; height=15 <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; onClick="javascript:if(confirm(''您是否确定删除本记录，删除后将导至记录无法使用？'')){window.location.href=''&lt;%=request.getRequestURI()%&gt;?act=del&amp;recordId=&lt;%=restaurant.getAttributeNode("id").getNodeValue()%&gt;'';}" <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; src="../../images/delete.gif" style="CURSOR: hand" width=15&gt; &lt;/td&gt;<BR>&nbsp;&nbsp;&nbsp; &lt;/tr&gt;<BR>&nbsp;&nbsp;&nbsp; &lt;% } <BR>}%&gt;<BR>&nbsp;&nbsp;&nbsp; &lt;% if (strOperation=="addnew"){<BR>&nbsp;&nbsp;&nbsp; //显示新增的格式%&gt;<BR>&nbsp;&nbsp;&nbsp; &lt;tr align="center" bgcolor="#ffffff" valign="middle"&gt; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;form name=dataform2 action="&lt;%=request.getRequestURI()%&gt;?act=addnewDo" method="post"&nbsp; onSubmit=''return checkform2(this);'' &gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;td class=tdsmall height=25 width="20"&gt;&lt;/td&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;td class=tdsmall height=25&gt; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;input name="name" class=stedit<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; style="HEIGHT: 22px; WIDTH: 150px" value="" maxlength="40" &gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/td&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;td class=tdsmall height=25&gt; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;input name="phone" class=stedit<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; style="HEIGHT: 22px; WIDTH: 100px" value="" maxlength="20" &gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/td&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;td class=tdsmall height=25&gt; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;input name="address" class=stedit<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; style="HEIGHT: 22px; WIDTH: 200px" value="" maxlength="100" &gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/td&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;td class=tdsmall height=25 width="25"&gt;&lt;a href="javascript:if (checkform2()==false);"&gt;&lt;img border=0 <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; height=15 src="../../images/editok.gif" width=15&gt;&lt;/a&gt;&lt;/td&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;td class=tdsmall height=25 width="25"&gt; &lt;/td&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/form&gt;<BR>&nbsp;&nbsp;&nbsp; &lt;/tr&gt;<BR>&nbsp;&nbsp;&nbsp; &lt;% } %&gt;<BR>&nbsp;&nbsp;&nbsp; &lt;/tbody&gt; <BR>&nbsp; &lt;/table&gt;<BR>&nbsp; &lt;br&gt;<BR>&nbsp; &lt;table align=center border=0 cellpadding=0 cellspacing=2 width="95%"&gt;<BR>&nbsp;&nbsp;&nbsp; &lt;tbody&gt; <BR>&nbsp;&nbsp;&nbsp; &lt;tr valign=center&gt; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;td align=middle&gt; &lt;br&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;table border=0 cellpadding=0 cellspacing=0&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;tr&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;td&gt; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;% if (strOperation=="addnew"){<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; %&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;input class=stbtm name=update onClick="javascript:if (checkform2()==false);" type=button value="更新记录"&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;% }else{<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(strOperation=="modi"){<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; %&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;input class=stbtm name=update onClick="javascript:if (checkform()==false);" type=button value="更新记录"&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;% <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }else{<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; %&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;input class=stbtm type="button" name="Button" value="新 增" onClick="javascript:window.location.href=''&lt;%=request.getRequestURI()%&gt;?act=addnew'';"&gt;&lt;% <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } %&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/td&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;td&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;input class=stbtm type="button" name="Button" value="返 回" onClick="javascript:window.location.href=''index.jsp'';"&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/td&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/tr&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/table&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/td&gt;<BR>&nbsp;&nbsp;&nbsp; &lt;/tr&gt;<BR>&nbsp; &lt;/table&gt;<BR>&nbsp; &lt;p&gt; &lt;/p&gt;<BR>&lt;/div&gt;<BR>&lt;/body&gt;<BR>&lt;/html&gt;<BR>&lt;SCRIPT LANGUAGE=javascript&gt;<BR>&lt;!--<BR>function checkform2()<BR>{<BR>&nbsp;var Checkblank = /^(\s*|(\　)|(\.))*$/;<BR>&nbsp; <BR>&nbsp; if (Checkblank.test(dataform2.name.value))<BR>&nbsp;{<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; alert("餐馆名称不能为空！");<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; dataform2.name.focus();<BR>&nbsp;&nbsp; return false; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } <BR>&nbsp;<BR>&nbsp; if (Checkblank.test(dataform2.phone.value))&nbsp;&nbsp;&nbsp; <BR>&nbsp;{<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; alert("餐馆电话不能为空！");<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; dataform2.phone.focus();<BR>&nbsp;&nbsp; return false; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; window.dataform2.submit();<BR>&nbsp; }<BR>&nbsp; <BR>&nbsp; function checkform()<BR>{&nbsp; <BR>&nbsp;var Checkblank = /^(\s*|(\　)|(\.))*$/;<BR>&nbsp;if (Checkblank.test(dataform.name.value))<BR>&nbsp;{<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; alert("餐馆名称不能为空！");<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; dataform.name.focus();<BR>&nbsp;&nbsp; return false; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (Checkblank.test(dataform.phone.value))<BR>&nbsp;{<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; alert("餐馆电话不能为空！");<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; dataform.phone.focus();<BR>&nbsp;&nbsp; return false; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </P>
<P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; window.dataform.submit();<BR>&nbsp; }<BR>--&gt;<BR>&lt;/SCRIPT&gt;<BR>说明：本文件的书写有很多地方并不简练，因为在程式的开发过程中，过分简练的程序往往会带来后期维护的困难。</P>
<P>开发心得：</P>
<P>doc.getElementsByTagName("restaurants").item(int i)的返回值是node 型，如果不是要调用它的属性值，没有必要强制转型为 Element型。可以直接操作。本系统因为开发的参考资料的错误，所以全都采用了强制转型。可以在以后的开发中考虑使用node 直接进行操作。</P>
<P>trim() 和 Interger.parseInt() 函数都不可以接受null 型的数值</P>
<P>在tomcat 下左右的文件都是目录从TOMCAT 算起，具体情况请参见\webapps\canyin\jsp\userjudge.jsp 里关于xml 路径的写法。</P><img src ="http://www.blogjava.net/jackybu/aggbug/1578.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jackybu/" target="_blank">辰</a> 2005-02-28 21:39 <a href="http://www.blogjava.net/jackybu/articles/1578.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>利用 Jsp+Taglib+JavaBean 快速构建 动态数据库查询模板 </title><link>http://www.blogjava.net/jackybu/articles/1577.html</link><dc:creator>辰</dc:creator><author>辰</author><pubDate>Mon, 28 Feb 2005 13:37:00 GMT</pubDate><guid>http://www.blogjava.net/jackybu/articles/1577.html</guid><wfw:comment>http://www.blogjava.net/jackybu/comments/1577.html</wfw:comment><comments>http://www.blogjava.net/jackybu/articles/1577.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jackybu/comments/commentRss/1577.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jackybu/services/trackbacks/1577.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 本文主要介绍如何快速利用 jsp+taglib+javaBean 构建动态数据库查询模板的全过程,已经如和使用,扩展该模板的方法.&nbsp;&nbsp;&nbsp; 本模板所要实现的功能是: 通过非常简单地继承一个模板中的方法产生类,和添加一个含有Tag的简单JSP来实现动态数据库查询. 废话不说了, 现在开始.1 配置 Tomcat5.0 (或以上版本,我使用了JSP2.0版本的一...&nbsp;&nbsp;<a href='http://www.blogjava.net/jackybu/articles/1577.html'>阅读全文</a><img src ="http://www.blogjava.net/jackybu/aggbug/1577.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jackybu/" target="_blank">辰</a> 2005-02-28 21:37 <a href="http://www.blogjava.net/jackybu/articles/1577.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>我对servlet配置文件的理解 </title><link>http://www.blogjava.net/jackybu/articles/1538.html</link><dc:creator>辰</dc:creator><author>辰</author><pubDate>Sun, 27 Feb 2005 09:36:00 GMT</pubDate><guid>http://www.blogjava.net/jackybu/articles/1538.html</guid><wfw:comment>http://www.blogjava.net/jackybu/comments/1538.html</wfw:comment><comments>http://www.blogjava.net/jackybu/articles/1538.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jackybu/comments/commentRss/1538.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jackybu/services/trackbacks/1538.html</trackback:ping><description><![CDATA[<P dir=ltr style="MARGIN-RIGHT: 0px"><FONT size=5>理解了之后就知道写原来servlet就这么简单!<IMG src="http://blog.csdn.net/Emoticons/hitwall.gif"><BR><BR>下面是一个最简单的servlet的配置(web.xml)<BR><FONT size=4>&nbsp;&lt;servlet&gt;<BR>&nbsp;&nbsp;&nbsp; &lt;servlet-name&gt;Contorller.wc&lt;/servlet-name&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// 这里指定servlet的名称，这个名称随你喜欢，只要不重复就行<BR>&nbsp;&nbsp;&nbsp; &lt;servlet-class&gt;web.Controller.Controller&lt;/servlet-class&gt; //这里servlet类的包路径和名称，注意大小写<BR>&nbsp; &lt;/servlet&gt;<BR></FONT>下面这两行配置的作用就是告诉web容器，在遇到&lt;url-pattern&gt;中的路径请求时就交给名为&lt;servlet-name&gt;的servlet来处理。<BR>&nbsp;</FONT><FONT size=4> &lt;servlet-mapping&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp; &lt;servlet-name&gt;Contorller.wc&lt;/servlet-name&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <BR>&nbsp;&nbsp;&nbsp; &lt;url-pattern&gt;/Contorller.wc&lt;/url-pattern&gt;<BR>&nbsp; &lt;/servlet-mapping&gt;<BR><BR></FONT><FONT size=5>如果你的<FONT size=4>WEB</FONT>项目是通过<FONT size=4>localhost:8080/web/index.jsp</FONT>来访问的，那么上加上上面的<FONT size=4>servlet</FONT>配置后，在IE地址栏中输入<FONT size=4>localhost:8080/web/Contorller.wc，web<FONT size=5>容器就会激发<FONT size=4>&lt;servlet-class&gt;</FONT>指定的<FONT size=4>servlet</FONT>来处理这个请求。</FONT><BR></FONT><IMG src="http://blog.csdn.net/Emoticons/coffee.gif"><BR><BR>如有说错的请指正。</FONT></P><img src ="http://www.blogjava.net/jackybu/aggbug/1538.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jackybu/" target="_blank">辰</a> 2005-02-27 17:36 <a href="http://www.blogjava.net/jackybu/articles/1538.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>JSTL 入门：表达式语言</title><link>http://www.blogjava.net/jackybu/articles/1473.html</link><dc:creator>辰</dc:creator><author>辰</author><pubDate>Thu, 24 Feb 2005 02:57:00 GMT</pubDate><guid>http://www.blogjava.net/jackybu/articles/1473.html</guid><wfw:comment>http://www.blogjava.net/jackybu/comments/1473.html</wfw:comment><comments>http://www.blogjava.net/jackybu/articles/1473.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jackybu/comments/commentRss/1473.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jackybu/services/trackbacks/1473.html</trackback:ping><description><![CDATA[<TABLE border=0 cellPadding=0 cellSpacing=0 width="100%">
<TBODY>
<TR vAlign=top>
<TD width="100%"><FONT size=2><SPAN class=atitle2>通过避免使用脚本编制元素来简化对 JSP 应用程序的软件维护</SPAN><BR></FONT>
<TABLE border=0 cellPadding=0 cellSpacing=0>
<TBODY>
<TR align=left vAlign=top>
<TD>
<P><FONT size=2>级别：中级</FONT></P></TD></TR></TBODY></TABLE>
<P><A href="file:///C:/Documents%20and%20Settings/wangyong/Local%20Settings/Temp/CyberArticle/312.html#author1"><FONT size=2>Mark A. Kolb</FONT></A><FONT size=2>（</FONT><A href="mailto:mak@taglib.com"><FONT size=2>mak@taglib.com</FONT></A><FONT size=2>）<BR>软件工程师<BR>2003 年 5 月</FONT></P>
<BLOCKQUOTE>
<BLOCKQUOTE><FONT size=2>JSP 标准标记库（JSP Standard Tag Library，JSTL）是一个实现 Web 应用程序中常见的通用功能的定制标记库集，这些功能包括迭代和条件判断、数据管理格式化、XML 操作以及数据库访问。在 developerWorks 上其新系列的第一篇文章中，软件工程师 Mark Kolb 向您展示了如何使用 JSTL 标记来避免在 JSP 页面中使用脚本编制元素。您还将了解如何通过从表示层删除源代码来简化软件维护。最后，您将了解 JSTL 经过简化的表达式语言，它允许在不必使用功能齐全的编程语言的情况下对 JSTL 操作指定动态属性值。</FONT></BLOCKQUOTE></BLOCKQUOTE>
<P><FONT size=2>JavaServer Pages（JSP）是用于 J2EE 平台的标准表示层技术。JSP 技术提供了用于执行计算（这些计算用来动态地生成页面内容）的脚本编制元素和操作。脚本编制元素允许在 JSP 页面中包括程序源代码，在为响应用户请求而呈现页面时可以执行这些源代码。操作将计算操作封装到很象 HTML 或 XML 标记的标记中，JSP 页面的模板文本通常包含这些标记。JSP 规范只将几种操作定义成了标准，但从 JSP 1.1 开始，开发人员已经能够以定制标记库的方式创建其自己的操作了。</FONT></P>
<P><FONT size=2>JSP 标准标记库（JSTL）是 JSP 1.2 定制标记库集，这些标记库实现大量服务器端 Java 应用程序常用的基本功能。通过为典型表示层任务（如数据格式化和迭代或条件内容）提供标准实现，JSTL 使 JSP 作者可以专注于特定于应用程序的开发需求，而不是为这些通用操作“另起炉灶”。</FONT></P>
<P><FONT size=2>当然，您可以使用 JSP 脚本编制元素（scriptlet、表达式和声明）来实现此类任务。例如，可以使用三个 scriptlet 实现条件内容，清单 1 中着重显示了这三个 scriptlet。但是，因为脚本编制元素依赖于在页面中嵌入程序源代码（通常是 Java 代码），所以对于使用这些脚本编制元素的 JSP 页面，其软件维护任务的复杂度大大增加了。例如，清单 1 中的 scriptlet 示例严格地依赖于花括号的正确匹配。如果不经意间引入了一个语法错误，则条件内容中的嵌套其它 scriptlet 可能会造成严重破坏，并且在 JSP 容器编译该页面时，要使所产生的错误信息有意义可能会很困难。</FONT></P><A id=listing1 name=listing1><B><FONT size=2>清单 1. 通过 scriptlet 实现条件内容</FONT></B></A><FONT size=2> </FONT>
<TABLE bgColor=#cccccc border=1 cellPadding=5 cellSpacing=0 width="70%">
<TBODY>
<TR>
<TD><PRE><FONT size=2><CODE><SPAN class=boldcode>&lt;% if (user.getRole() == "member")) { %&gt;</SPAN>
    &lt;p&gt;Welcome, member!&lt;/p&gt;
<SPAN class=boldcode>&lt;% } else { %&gt;</SPAN>
    &lt;p&gt;Welcome, guest!&lt;/p&gt;
<SPAN class=boldcode>&lt;% } %&gt;</SPAN></CODE>
</FONT></PRE></TD></TR></TBODY></TABLE>
<P><FONT size=2>修正此类问题通常需要相当丰富的编程经验。尽管通常会由十分精通页面布局和图形设计的设计人员来开发和维护 JSP，但是同一页面中的脚本编制元素出现问题时，需要程序员的介入。这种状况将单个文件中代码的责任分担给多人，因而使得开发、调试和增强此类 JSP 页面成为很麻烦的任务。通过将常用功能包装到定制标记库的标准集合中，JSTL 使 JSP 作者可以减少对编制脚本元素的需求，甚至可以不需要它们，并避免了相关的维护成本。</FONT></P>
<P><A id=IDAMCSVB name=IDAMCSVB><SPAN class=atitle2><FONT size=2>JSTL 1.0</FONT></SPAN></A><BR><FONT size=2>JSTL 1.0 发布于 2002 年 6 月，由四个定制标记库（<CODE>core</CODE>、<CODE>format</CODE>、<CODE>xml</CODE> 和 <CODE>sql</CODE>）和一对通用标记库验证器（<CODE>ScriptFreeTLV</CODE> 和 <CODE>PermittedTaglibsTLV</CODE>）组成。<CODE>core</CODE> 标记库提供了定制操作，通过限制了作用域的变量管理数据，以及执行页面内容的迭代和条件操作。它还提供了用来生成和操作 URL 的标记。顾名思义，<CODE>format</CODE> 标记库定义了用来格式化数据（尤其是数字和日期）的操作。它还支持使用本地化资源束进行 JSP 页面的国际化。<CODE>xml</CODE> 库包含一些标记，这些标记用来操作通过 XML 表示的数据，而 <CODE>sql</CODE> 库定义了用来查询关系数据库的操作。</FONT></P>
<P><FONT size=2>两个 JSTL 标记库验证器允许开发人员在其 JSP 应用程序中强制使用编码标准。可以配置 <CODE>ScriptFreeTLV</CODE> 验证器以在 JSP 页面中禁用各种类型的 JSP 脚本元素 — scriptlet、表达式和声明。类似地，<CODE>PermittedTaglibsTLV</CODE> 验证器可以用来限制可能由应用程序的 JSP 页面访问的定制标记库集（包括 JSTL 标记库）。</FONT></P>
<P><FONT size=2>尽管 JSTL 最终将会成为 J2EE 平台的必需组件，但目前只有少数应用程序服务器包括它。JSTL 1.0 的参考实现可作为 Apache 软件基金会（Apache Software Foundation）的 Jakarta Taglibs 项目（请参阅</FONT><A href="file:///C:/Documents%20and%20Settings/wangyong/Local%20Settings/Temp/CyberArticle/312.html#resources"><FONT size=2>参考资料</FONT></A><FONT size=2>）的一部分而获得。可以将该参考实现中的定制标记库合并到任何支持 JSP 1.2 和 Servlet 2.3 规范的服务器，以添加对 JSTL 的支持。</FONT></P>
<P><A id=IDALESVB name=IDALESVB><SPAN class=atitle2><FONT size=2>表达式语言</FONT></SPAN></A><BR><FONT size=2>在 JSP 1.2 中，可以使用静态字符串或表达式（如果允许的话）指定 JSP 操作的属性。例如，在清单 2 中，对 <CODE>&lt;jsp:setProperty&gt;</CODE> 操作的 <CODE>name</CODE> 和 <CODE>property</CODE> 属性指定了静态值，而用表达式指定了其 <CODE>value</CODE> 属性。这个操作的效果是将请求参数的当前值赋予命名的 bean 特性。以这种形式使用的表达式被称为<I>请求时属性值（request-time attribute value）</I>，这是构建到 JSP 规范中的用于动态指定属性值的唯一机制。</FONT></P><A id=IDAHFSVB name=IDAHFSVB><B><FONT size=2>清单 2. 合并请求时属性值的 JSP 操作</FONT></B></A><FONT size=2> </FONT>
<TABLE bgColor=#cccccc border=1 cellPadding=5 cellSpacing=0 width="100%">
<TBODY>
<TR>
<TD><PRE><FONT size=2><CODE>&lt;jsp:setProperty name="user" property="timezonePref"
                 value='&lt;%= request.getParameter("timezone") %&gt;'/&gt;
</CODE>
</FONT></PRE></TD></TR></TBODY></TABLE>
<P><FONT size=2>因为请求时属性值是用表达式指定的，所以它们往往有和其它脚本元素一样的软件维护问题。因此，JSTL 定制标记支持另一种用于指定动态属性值的机制。可以用简化的<I>表达式语言</I>（EL）而不使用完整的 JSP 表达式来指定 JSTL 操作的属性值。EL 提供了一些标识符、存取器和运算符，用来检索和操作驻留在 JSP 容器中的数据。EL 在某种程度上以 EcmaScript（请参阅</FONT><A href="http://www-900.ibm.com/developerWorks/cn/java/j-jstl0211/resources"><FONT size=2>参考资料</FONT></A><FONT size=2>）和 XML 路径语言（XML Path Language，XPath）为基础，因此页面设计人员和程序员都应该熟悉它的语法。EL 擅长寻找对象及其特性，然后对它们执行简单操作；它不是编程语言，甚至不是脚本编制语言。但是，与 JSTL 标记一起使用时，它就能使用简单而又方便的符号来表示复杂的行为。EL 表达式的格式是这样的：用美元符号（$）定界，内容包括在花括号（{}）中，如清单 3 所示。</FONT></P><A id=IDAYFSVB name=IDAYFSVB><B><FONT size=2>清单 3. 说明 EL 表达式定界符的 JSTL 操作</FONT></B></A><FONT size=2> </FONT>
<TABLE bgColor=#cccccc border=1 cellPadding=5 cellSpacing=0 width="100%">
<TBODY>
<TR>
<TD><PRE><FONT size=2><CODE>&lt;c:out value="<SPAN class=boldcode>${user.firstName}</SPAN>"/&gt;
</CODE>
</FONT></PRE></TD></TR></TBODY></TABLE>
<P><FONT size=2>此外，您可以将多个表达式与静态文本组合在一起以通过字符串并置来构造动态属性值，如清单 4 所示。单独的表达式由标识符、存取器、文字和运算符组成。标识符用来引用存储在数据中心中的数据对象。EL 有 11 个保留标识符，对应于 11 个 EL 隐式对象。假定所有其它标识符都引用<I>限制了作用域的变量</I>。存取器用来检索对象的特性或集合的元素。文字表示固定的值 — 数字、字符、字符串、布尔型或空值。运算符允许对数据和文字进行组合以及比较。</FONT></P><A id=IDAHGSVB name=IDAHGSVB><B><FONT size=2>清单 4. 组合静态文本和多个 EL 表达式以指定动态属性值</FONT></B></A><FONT size=2> </FONT>
<TABLE bgColor=#cccccc border=1 cellPadding=5 cellSpacing=0 width="100%">
<TBODY>
<TR>
<TD><PRE><FONT size=2><CODE>&lt;c:out value="Hello <SPAN class=boldcode>${user.firstName} ${user.lastName}</SPAN>"/&gt;
</CODE>
</FONT></PRE></TD></TR></TBODY></TABLE>
<P><A id=IDASGSVB name=IDASGSVB><SPAN class=atitle2><FONT size=2>限制了作用域的变量</FONT></SPAN></A><BR><FONT size=2>JSP API 通过 <CODE>&lt;jsp:useBean&gt;</CODE> 操作允许从 JSP 容器内的四个不同作用域中存储和检索数据。JSTL 通过提供用于指定和除去这些作用域中的对象的附加操作来扩展这一能力。此外，EL 提供将这些对象作为限制了作用域的变量进行检索的内置支持。特别地，任何出现在 EL 表达式中但不对应于任何 EL 隐式对象的标识符，都被自动假定为引用存储在四个 JSP 作用域的其中某个中的对象，这四个作用域是：</FONT></P>
<UL>
<LI><FONT size=2>页面作用域 </FONT>
<LI><FONT size=2>请求作用域 </FONT>
<LI><FONT size=2>会话作用域 </FONT>
<LI><FONT size=2>应用程序作用域 </FONT></LI></UL>
<P><FONT size=2>您可能还记得，只有在为特定请求处理页面期间才能检索存储在该页面作用域中的对象。如果对象是存储在请求作用域中的，可以在处理所有参与处理某请求的页面期间检索这些对象（譬如在对某个请求的处理中遇到了一个或多个 <CODE>&lt;jsp:include&gt;</CODE> 或 <CODE>&lt;jsp:forward&gt;</CODE> 操作）。如果对象是存储在会话作用域中的，则在与 Web 应用程序的交互式会话期间，可以由用户访问的任何页面检索它（即，直到与该用户交互相关联的 <CODE>HttpSession</CODE> 对象无效为止）。可以由任何用户从任何页面访问存储在应用程序作用域中的对象，直到卸载 Web 应用程序本身为止（通常是由于关闭 JSP 容器所致）。</FONT></P>
<P><FONT size=2>通过将字符串映射为期望作用域中的对象来将对象存储到该作用域。然后，就可以通过提供相同字符串来从该作用域检索该对象。在作用域的映射中查找字符串，并返回被映射的对象。在 Servlet API 中，将此类对象称为相应作用域的<I>属性</I>。但是，在 EL 的上下文中，也将与属性相关联的字符串看作变量的名称，该变量通过属性映射的方式获得特定的值。</FONT></P>
<P><FONT size=2>在 EL 中，与隐式对象无关联的标识符被认为是存储在四个 JSP 作用域中的名称对象。首先对页面作用域检查是否存在这样的标识符，其次对请求作用域、然后对会话作用域、最后对应用程序作用域依次进行这样的检查，然后测试该标识符的名称是否与存储在该作用域中的某个对象的名称匹配。第一个这样的匹配作为 EL 标识符的值被返回。通过这种方法，可以将 EL 标识符看作引用限制了作用域的变量。</FONT></P>
<P><FONT size=2>从更技术的方面来说，没有映射到隐式对象的标识符是用 <CODE>PageContext</CODE> 实例的 <CODE>findAttribute()</CODE> 方法求值的，该实例表示对页面的处理，在该页面上，当前正在处理用于请求的表达式。标识符的名称作为参数传递给这个方法，然后该方法依次在四个作用域中搜索具有相同名称的属性。并将所找到的第一个匹配项作为 <CODE>findAttribute()</CODE> 方法的值返回。如果未在这四个作用域中找到这样的属性，则返回 <CODE>null</CODE>。</FONT></P>
<P><FONT size=2>最终，限制了作用域的变量是四个 JSP 作用域的属性，这些属性具有可以用作 EL 标识符的名称。只要对限制了作用域的变量赋予由字母数字组成的名称，就可以通过 JSP 中提供的用于设置属性的任何机制来创建它们。这包括内置的 <CODE>&lt;jsp:useBean&gt;</CODE> 操作，以及由 Servlet API 中的几个类定义的 <CODE>setAttribute()</CODE> 方法。此外，四个 JSTL 库中定义的许多定制标记本身就能够设置作为限制了作用域的变量使用的属性值。</FONT></P>
<P><A id=IDAOYSVB name=IDAOYSVB><SPAN class=atitle2><FONT size=2>隐式对象</FONT></SPAN></A><BR><FONT size=2>表 1 中列出了 11 个 EL 隐式对象的标识符。不要将这些对象与 JSP 隐式对象（一共只有九个）混淆，其中只有一个对象是它们所共有的。</FONT></P>
<P><B><FONT size=2>表 1. EL 隐式对象</FONT></B></P>
<TABLE border=1 cellPadding=3 cellSpacing=0 width="100%">
<TBODY>
<TR vAlign=top>
<TD><B><FONT size=2>类别</FONT></B></TD>
<TD><B><FONT size=2>标识符</FONT></B></TD>
<TD><B><FONT size=2>描述</FONT></B></TD></TR>
<TR vAlign=top>
<TD><FONT size=2>JSP</FONT></TD>
<TD><CODE type="inline"><FONT size=2>pageContext</FONT></CODE></TD>
<TD><FONT size=2><CODE type="inline">PageContext</CODE> 实例对应于当前页面的处理</FONT></TD></TR>
<TR vAlign=top>
<TD rowSpan=4><FONT size=2>作用域</FONT></TD>
<TD><CODE type="inline"><FONT size=2>pageScope</FONT></CODE></TD>
<TD><FONT size=2>与页面作用域属性的名称和值相关联的 <CODE type="inline">Map</CODE> 类</FONT></TD></TR>
<TR vAlign=top>
<TD><CODE type="inline"><FONT size=2>requestScope</FONT></CODE></TD>
<TD><FONT size=2>与请求作用域属性的名称和值相关联的 <CODE type="inline">Map</CODE> 类</FONT></TD></TR>
<TR vAlign=top>
<TD><CODE type="inline"><FONT size=2>sessionScope</FONT></CODE></TD>
<TD><FONT size=2>与会话作用域属性的名称和值相关联的 <CODE type="inline">Map</CODE> 类</FONT></TD></TR>
<TR vAlign=top>
<TD><CODE type="inline"><FONT size=2>applicationScope</FONT></CODE></TD>
<TD><FONT size=2>与应用程序作用域属性的名称和值相关联的 <CODE type="inline">Map</CODE> 类</FONT></TD></TR>
<TR vAlign=top>
<TD rowSpan=2><FONT size=2>请求参数</FONT></TD>
<TD><CODE type="inline"><FONT size=2>param</FONT></CODE></TD>
<TD><FONT size=2>按名称存储请求参数的主要值的 <CODE type="inline">Map</CODE> 类</FONT></TD></TR>
<TR vAlign=top>
<TD><CODE type="inline"><FONT size=2>paramValues</FONT></CODE></TD>
<TD><FONT size=2>将请求参数的所有值作为 <CODE type="inline">String</CODE> 数组存储的 <CODE type="inline">Map</CODE> 类</FONT></TD></TR>
<TR vAlign=top>
<TD rowSpan=2><FONT size=2>请求头</FONT></TD>
<TD><CODE type="inline"><FONT size=2>header</FONT></CODE></TD>
<TD><FONT size=2>按名称存储请求头主要值的 <CODE type="inline">Map</CODE> 类</FONT></TD></TR>
<TR vAlign=top>
<TD><CODE type="inline"><FONT size=2>headerValues</FONT></CODE></TD>
<TD><FONT size=2>将请求头的所有值作为 <CODE type="inline">String</CODE> 数组存储的 <CODE type="inline">Map</CODE> 类</FONT></TD></TR>
<TR vAlign=top>
<TD><FONT size=2>Cookie</FONT></TD>
<TD><CODE type="inline"><FONT size=2>cookie</FONT></CODE></TD>
<TD><FONT size=2>按名称存储请求附带的 cookie 的 <CODE type="inline">Map</CODE> 类</FONT></TD></TR>
<TR vAlign=top>
<TD><FONT size=2>初始化参数</FONT></TD>
<TD><CODE type="inline"><FONT size=2>initParam</FONT></CODE></TD>
<TD><FONT size=2>按名称存储 Web 应用程序上下文初始化参数的 <CODE type="inline">Map</CODE> 类</FONT></TD></TR></TBODY></TABLE><BR><BR>
<P><FONT size=2>尽管 JSP 和 EL 隐式对象中只有一个公共对象（<CODE>pageContext</CODE>），但通过 EL 也可以访问其它 JSP 隐式对象。原因是 <CODE>pageContext</CODE> 拥有访问所有其它八个 JSP 隐式对象的特性。实际上，这是将它包括在 EL 隐式对象中的主要理由。</FONT></P>
<P><FONT size=2>其余所有 EL 隐式对象都是映射，可以用来查找对应于名称的对象。前四个映射表示先前讨论的各种属性作用域。可以用它们来查找特定作用域中的标识符，而不用依赖于 EL 在缺省情况下使用的顺序查找过程。</FONT></P>
<P><FONT size=2>接下来的四个映射用来获取请求参数和请求头的值。因为 HTTP 协议允许请求参数和请求头具有多个值，所以它们各有一对映射。每对中的第一个映射返回请求参数或头的主要值，通常是恰巧在实际请求中首先指定的那个值。每对中第二个映射允许检索参数或头的所有值。这些映射中的键是参数或头的名称，但这些值是 <CODE>String</CODE> 对象的数组，其中的每个元素都是单一参数值或头值。</FONT></P>
<P><FONT size=2>cookie 隐式对象提供了对由请求设置的 cookie 名称的访问。这个对象将所有与请求相关联的 cookie 名称映射到表示那些 cookie 特性的 <CODE>Cookie</CODE> 对象。</FONT></P>
<P><FONT size=2>最后一个 EL 隐式对象 <CODE>initParam</CODE> 是一个映射，它储存与 Web 应用程序相关联的所有上下文的初始化参数的名称和值。初始化参数是通过 <CODE>web.xml</CODE> 部署描述符文件指定的，该文件位于应用程序的 <CODE>WEB-INF</CODE> 目录中。</FONT></P>
<P><A id=IDA3ZSVB name=IDA3ZSVB><SPAN class=atitle2><FONT size=2>存取器</FONT></SPAN></A><BR><FONT size=2>因为 EL 标识符是作为隐式对象或限制了作用域的变量（通过属性来实现）解析的，因此有必要将它们转换成 Java 对象。EL 可以自动包装和解包其相应的 Java 类中的基本类型（例如，可以在后台将 <CODE>int</CODE> 强制转换成 <CODE>Integer</CODE> 类，反之亦可），但大多数的标识符将成为指向完整的 Java 对象的指针。</FONT></P>
<P><FONT size=2>结果是，对这些对象的特性或（在对象是数组和集合的情况下）对其元素的访问通常是令人满意的。就为了实现这种用途，EL 提供了两种不同的存取器（点运算符（<CODE>.</CODE>）和方括号运算符（<CODE>[]</CODE>）），也支持通过 EL 操作特性和元素。</FONT></P>
<P><FONT size=2>点运算符通常用于访问对象的特性。例如，在表达式 <CODE>${user.firstName}</CODE> 中，使用点运算符来访问 <CODE>user</CODE> 标识符所引用对象的名为 <CODE>firstName</CODE> 的特性。EL 使用 Java bean 约定访问对象特性，因此必须定义这个特性的 getter 方法（通常是名为 <CODE>getFirstName()</CODE> 的方法），以便表达式正确求值。当被访问的特性本身是对象时，可以递归地应用点运算符。例如，如果我们虚构的 <CODE>user</CODE> 对象有一个实现为 Java 对象的 <CODE>address</CODE> 特性，那么也可以用点运算符来访问这个对象的特性。例如，表达式 <CODE>${user.address.city}</CODE> 将会返回这个地址对象嵌套的 <CODE>city</CODE> 特性。</FONT></P>
<P><FONT size=2>方括号运算符用来检索数组和集合的元素。在数组和有序集合（也即，实现了 <CODE>java.util.List</CODE> 接口的集合）的情况下，把要检索的元素的下标放在方括号中。例如，表达式 <CODE>${urls[3]}</CODE> 返回 <CODE>urls</CODE> 标识符所引用的数组或集合的第四个元素（和 Java 语言以及 JavaScript 中一样，EL 中的下标是从零开始的）。</FONT></P>
<P><FONT size=2>对于实现 <CODE>java.util.Map</CODE> 接口的集合，方括号运算符使用关联的键查找存储在映射中的值。在方括号中指定键，并将相应的值作为表达式的值返回。例如，表达式 <CODE>${commands["dir"]}</CODE> 返回与 <CODE>commands</CODE> 标识符所引用的 <CODE>Map</CODE> 中的 <CODE>"dir"</CODE> 键相关联的值。</FONT></P>
<P><FONT size=2>对于上述两种情况，都可允许表达式出现在方括号中。对嵌套表达式求值的结果将被作为下标或键，用来检索集合或数组的适当元素。和点运算符一样，方括号运算符也可以递归应用。这使得 EL 能够从多维数组、嵌套集合或两者的任意组合中检索元素。此外，点运算符和方括号运算符还可以互操作。例如，如果数组的元素本身是对象，则可以使用方括号运算符来检索该数组的元素，并结合点运算符来检索该元素的一个特性（例如 <CODE>${urls[3].protocol}</CODE>）。</FONT></P>
<P><FONT size=2>假定 EL 充当指定动态属性值的简化语言，EL 存取器有一个有趣的功能（与 Java 语言的存取器不同），那就是它们在应用于 <CODE>null</CODE> 时不抛出异常。如果应用 EL 存取器的对象（例如，<CODE>${foo.bar}</CODE> 和 <CODE>${foo["bar"]}</CODE> 中的 <CODE>foo</CODE> 标识符）是 <CODE>null</CODE>，那么应用存取器的结果也是 <CODE>null</CODE>。事实证明，在大多数情况下，这是一个相当有用的行为，不久您就会了解这一点。</FONT></P>
<P><FONT size=2>最后，点运算符和方括号运算符可能实现某种程度的互换。例如，也可以使用 <CODE>${user["firstName"]}</CODE> 来检索 <CODE>user</CODE> 对象的 <CODE>firstName</CODE> 特性，正如可以用 <CODE>${commands.dir}</CODE> 获取与 <CODE>commands</CODE> 映射中的 <CODE>"dir"</CODE> 键相关联的值一样。</FONT></P>
<P><A id=IDAR4SVB name=IDAR4SVB><SPAN class=atitle2><FONT size=2>运算符</FONT></SPAN></A><BR><FONT size=2>EL 还可以通过使用标识符和存取器，遍历包含应用程序数据（通过限制了作用域的变量公开）或关于环境的信息（通过 EL 隐式对象）的对象层次结构。但是，只是访问这些数据，通常不足以实现许多 JSP 应用程序所需的表示逻辑。</FONT></P>
<P><FONT size=2>最终，EL 还包括了几个用来操作和比较 EL 表达式所访问数据的运算符。表 2 中汇总了这些运算符。</FONT></P>
<P><B><FONT size=2>表 2. EL 运算符</FONT></B></P>
<TABLE border=1 cellPadding=3 cellSpacing=0 width="100%">
<TBODY>
<TR vAlign=top>
<TD><B><FONT size=2>类别</FONT></B></TD>
<TD><B><FONT size=2>运算符</FONT></B></TD></TR>
<TR vAlign=top>
<TD><FONT size=2>算术运算符</FONT></TD>
<TD><FONT size=2><CODE type="inline">+</CODE>、<CODE type="inline">-</CODE>、<CODE type="inline">*</CODE>、<CODE type="inline">/</CODE>（或 <CODE type="inline">div</CODE>）和 <CODE type="inline">%</CODE>（或 <CODE type="inline">mod</CODE>）</FONT></TD></TR>
<TR vAlign=top>
<TD><FONT size=2>关系运算符</FONT></TD>
<TD><FONT size=2><CODE type="inline">==</CODE>（或 <CODE type="inline">eq</CODE>）、<CODE type="inline">!=</CODE>（或 <CODE type="inline">ne</CODE>）、<CODE type="inline">&lt;&lt;/code&gt;（或 <CODE type="inline">lt</CODE>）、<CODE type="inline">&gt;</CODE>（或 <CODE type="inline">gt</CODE>）、<CODE type="inline">&lt;=</CODE>（或 <CODE type="inline">le</CODE>）和 <CODE type="inline">&gt;=</CODE>（或 <CODE type="inline">ge</CODE>）</CODE></FONT></TD></TR>
<TR vAlign=top>
<TD><FONT size=2>逻辑运算符</FONT></TD>
<TD><FONT size=2><CODE type="inline">&amp;&amp;</CODE>（或 <CODE type="inline">and</CODE>）、<CODE type="inline">||</CODE>（或 <CODE type="inline">or</CODE>）和 <CODE type="inline">!</CODE>（或 <CODE type="inline">not</CODE>）</FONT></TD></TR>
<TR vAlign=top>
<TD><FONT size=2>验证运算符</FONT></TD>
<TD><CODE type="inline"><FONT size=2>empty</FONT></CODE></TD></TR></TBODY></TABLE><BR><BR>
<P><FONT size=2>算术运算符支持数值的加法、减法、乘法和除法。还提供了一个求余运算符。注：除法和求余运算符都有替代的、非符号的名称（为的是与 XPath 保持一致）。清单 5 中显示了一个演示算术运算符用法的示例表达式。对几个 EL 表达式应用算术运算符的结果是将该算术运算符应用于这些表达式返回的数值所得的结果。</FONT></P><A id=IDAD5SVB name=IDAD5SVB><B><FONT size=2>清单 5. 利用算术运算符的 EL 表达式</FONT></B></A><FONT size=2> </FONT>
<TABLE bgColor=#cccccc border=1 cellPadding=5 cellSpacing=0 width="100%">
<TBODY>
<TR>
<TD><PRE><FONT size=2><CODE>${item.price * (1 + taxRate[user.address.zipcode])}
</CODE>
</FONT></PRE></TD></TR></TBODY></TABLE>
<P><FONT size=2>关系运算符允许比较数字或文本数据。比较的结果作为布尔值返回。逻辑运算符允许合并布尔值，返回新的布尔值。因此，可以将 EL 逻辑运算符应用于嵌套的关系或逻辑运算符的结果，如清单 6 所示。</FONT></P><A id=IDAO5SVB name=IDAO5SVB><B><FONT size=2>清单 6. 利用关系和逻辑运算符的 EL 表达式</FONT></B></A><FONT size=2> </FONT>
<TABLE bgColor=#cccccc border=1 cellPadding=5 cellSpacing=0 width="100%">
<TBODY>
<TR>
<TD><PRE><FONT size=2><CODE>${(x &gt;= min) &amp;&amp; (x &lt;= max)}
</CODE>
</FONT></PRE></TD></TR></TBODY></TABLE>
<P><FONT size=2>最后一种 EL 运算符是 <CODE>empty</CODE>，它对于验证数据特别有用。<CODE>empty</CODE> 运算符采用单个表达式作为其变量（也即，<CODE>${empty input}</CODE>），并返回一个布尔值，该布尔值表示对表达式求值的结果是不是“空”值。求值结果为 <CODE>null</CODE> 的表达式被认为是空，即无元素的集合或数组。如果参数是对长度为零的 <CODE>String</CODE> 求值所得的结果，则 <CODE>empty</CODE> 运算符也将返回 <CODE>true</CODE>。</FONT></P>
<P><FONT size=2>表 3 显示了 EL 运算符的优先级。正如清单 5 和 6 所示，可以用圆括号对表达式分组，高于普通的优先级规则。</FONT></P>
<P><B><FONT size=2>表 3. EL 运算符优先级（自顶到底，从左到右）</FONT></B></P>
<TABLE border=1 cellPadding=3 cellSpacing=0 width="100%">
<TBODY>
<TR vAlign=top>
<TD><FONT size=2><CODE type="inline">[]</CODE>, <CODE type="inline">.</CODE></FONT></TD></TR>
<TR vAlign=top>
<TD><CODE type="inline"><FONT size=2>()</FONT></CODE></TD></TR>
<TR vAlign=top>
<TD><FONT size=2>unary <CODE type="inline">-</CODE>、<CODE type="inline">not</CODE>、<CODE type="inline">!</CODE>、<CODE type="inline">empty</CODE></FONT></TD></TR>
<TR vAlign=top>
<TD><FONT size=2><CODE type="inline">*</CODE>、<CODE type="inline">/</CODE>、<CODE type="inline">div</CODE>、<CODE type="inline">%</CODE>、<CODE type="inline">mod</CODE></FONT></TD></TR>
<TR vAlign=top>
<TD><FONT size=2><CODE type="inline">+</CODE>、binary <CODE type="inline">-</CODE></FONT></TD></TR>
<TR vAlign=top>
<TD><FONT size=2>() <CODE type="inline">&lt;&lt;/code&gt;、<CODE type="inline">&gt;</CODE>、<CODE type="inline">&lt;=</CODE>、<CODE type="inline">&gt;=</CODE>、<CODE type="inline">lt</CODE>、<CODE type="inline">gt</CODE>、<CODE type="inline">le</CODE>、<CODE type="inline">ge</CODE></CODE></FONT></TD></TR>
<TR vAlign=top>
<TD><FONT size=2><CODE type="inline">==</CODE>、<CODE type="inline">!=</CODE>、<CODE type="inline">eq</CODE>、<CODE type="inline">ne</CODE></FONT></TD></TR>
<TR vAlign=top>
<TD><FONT size=2><CODE type="inline">&amp;&amp;</CODE>、<CODE type="inline">and</CODE></FONT></TD></TR>
<TR vAlign=top>
<TD><FONT size=2><CODE type="inline">||</CODE>、<CODE type="inline">or</CODE></FONT></TD></TR></TBODY></TABLE><BR><BR>
<P><A id=IDA4ATVB name=IDA4ATVB><SPAN class=atitle2><FONT size=2>文字</FONT></SPAN></A><BR><FONT size=2>在 EL 表达式中，数字、字符串、布尔值和 <CODE>null</CODE> 都可以被指定为文字值。字符串可以用单引号或双引号定界。布尔值被指定为 <CODE>true</CODE> 和 <CODE>false</CODE>。</FONT></P>
<P><A id=IDATBTVB name=IDATBTVB><SPAN class=atitle2><FONT size=2>Taglib 伪指令</FONT></SPAN></A><BR><FONT size=2>正如我们先前讨论的，JSTL 1.0 包括四个定制标记库。为了演示 JSTL 标记和表达式语言的交互，我们将研究几个来自 JSTL <CODE>core</CODE> 库的标记。和使用任何 JSP 定制标记库一样，必须在您想要使用这个库标记的任何页面中包括 <CODE>taglib</CODE> 伪指令。清单 7 显示了用于这个特定库的伪指令。</FONT></P><A id=IDAFCTVB name=IDAFCTVB><B><FONT size=2>清单 7. 用于 JSTL core 库 EL 版本的 taglib 伪指令</FONT></B></A><FONT size=2> </FONT>
<TABLE bgColor=#cccccc border=1 cellPadding=5 cellSpacing=0 width="100%">
<TBODY>
<TR>
<TD><PRE><FONT size=2><CODE>&lt;%@ taglib uri="http://java.sun.com/jstl/core" prefix="c" %&gt;
</CODE>
</FONT></PRE></TD></TR></TBODY></TABLE>
<P><FONT size=2>实际上，对应于 JSTL <CODE>core</CODE> 库的 <CODE>taglib</CODE> 伪指令有两种，因为在 JSTL 1.0 中，EL 是可选的。所有四个 JSTL 1.0 定制标记库都有使用 JSP 表达式（而不是 EL）指定动态属性值的备用版本。因为这些备用库依赖于 JSP 的更传统的请求时属性值，所以它们被称为 <I>RT</I> 库，而那些使用表达式语言的则被称为 <I>EL</I> 库。开发人员用不同的 <CODE>taglib</CODE> 伪指令来区分每个库的这两个版本。清单 8 显示了使用 core 库的 RT 版本的伪指令。但是，由于现在我们讨论的重点是 EL，所以首先需要这些伪指令。</FONT></P><A id=IDAADTVB name=IDAADTVB><B><FONT size=2>清单 8. 用于 JSTL core 库 RT 版本的 taglib 伪指令</FONT></B></A><FONT size=2> </FONT>
<TABLE bgColor=#cccccc border=1 cellPadding=5 cellSpacing=0 width="100%">
<TBODY>
<TR>
<TD><PRE><FONT size=2><CODE>&lt;%@ taglib uri="http://java.sun.com/jstl/core_rt" prefix="c_rt" %&gt;
</CODE>
</FONT></PRE></TD></TR></TBODY></TABLE>
<P><A id=IDAJDTVB name=IDAJDTVB><SPAN class=atitle2><FONT size=2>变量标记</FONT></SPAN></A><BR><FONT size=2>我们首先要考虑的 JSTL 定制标记是 <CODE>&lt;c:set&gt;</CODE> 操作。正如已经说明的，限制了作用域的变量在 JSTL 中起关键作用，<CODE>&lt;c:set&gt;</CODE> 操作提供基于标记的机制来创建和设置限制了作用域的变量。清单 9 中显示了该操作的语法，其中 <CODE>var</CODE> 属性指定了限制了作用域的变量的名称，<CODE>scope</CODE> 属性表明了该变量驻留在哪个作用域中，<CODE>value</CODE> 属性指定了分配给该变量的值。如果指定变量已经存在，则简单地将所指明的值赋给它。如果不存在，则创建新的限制了作用域的变量，并用该值初始化这个变量。</FONT></P><A id=IDAHETVB name=IDAHETVB><B><FONT size=2>清单 9. &lt;c:set&gt; 操作的语法</FONT></B></A><FONT size=2> </FONT>
<TABLE bgColor=#cccccc border=1 cellPadding=5 cellSpacing=0 width="100%">
<TBODY>
<TR>
<TD><PRE><FONT size=2><CODE>&lt;c:set var="<I>name</I>" scope="<I>scope</I>" value="<I>expression</I>"/&gt;
</CODE>
</FONT></PRE></TD></TR></TBODY></TABLE>
<P><FONT size=2><CODE>scope</CODE> 属性是可选的，其缺省值是 <CODE>page</CODE>。</FONT></P>
<P><FONT size=2>清单 10 中显示了 <CODE>&lt;c:set&gt;</CODE> 的两个示例。在第一个示例中，将会话作用域变量设置成 <CODE>String</CODE> 值。在第二个示例中，用表达式来设置数值：将页面作用域内名为 <CODE>square</CODE> 的变量赋值为名为 <CODE>x</CODE> 的请求参数的值的平方。</FONT></P><A id=IDARFTVB name=IDARFTVB><B><FONT size=2>清单 10. &lt;c:set&gt; 操作示例</FONT></B></A><FONT size=2> </FONT>
<TABLE bgColor=#cccccc border=1 cellPadding=5 cellSpacing=0 width="100%">
<TBODY>
<TR>
<TD><PRE><FONT size=2><CODE>&lt;c:set var="timezone" scope="session" value="CST"/&gt;
&lt;c:set var="square" value="${param['x'] * param['x']}"/&gt;
</CODE>
</FONT></PRE></TD></TR></TBODY></TABLE>
<P><FONT size=2>您还可以将限制了作用域的变量的值指定为 <CODE>&lt;c:set&gt;</CODE> 操作的主体内容，而不是使用属性。使用这种方法，您可以重新编写清单 10 中的第一个示例，如清单 11 所示。此外，正如我们马上可以看到的，<CODE>&lt;c:set&gt;</CODE> 标记的主体内容本身也可以使用定制标记。<CODE>&lt;c:set&gt;</CODE> 主体内生成的所有内容都将作为一个 <CODE>String</CODE> 值赋给指定变量。</FONT></P><A id=listing11 name=listing11><B><FONT size=2>清单 11. 通过主体内容指定 &lt;c:set&gt; 操作的值</FONT></B></A><FONT size=2> </FONT>
<TABLE bgColor=#cccccc border=1 cellPadding=5 cellSpacing=0 width="100%">
<TBODY>
<TR>
<TD><PRE><FONT size=2><CODE>&lt;c:set var="timezone" scope="session"&gt;CST&lt;/c:set&gt;
</CODE>
</FONT></PRE></TD></TR></TBODY></TABLE>
<P><FONT size=2>JSTL core 库包含第二个用于管理限制了作用域的变量的标记 — <CODE>&lt;c:remove&gt;</CODE>。顾名思义，<CODE>&lt;c:remove&gt;</CODE> 操作是用来删除限制了作用域的变量的，它获取两个属性。<CODE>var</CODE> 属性指定待删除变量的名称，<CODE>scope</CODE> 属性是可选的，它表示待删除变量来自哪个作用域，缺省为 <CODE>page</CODE>，如清单 12 所示。</FONT></P><A id=IDALHTVB name=IDALHTVB><B><FONT size=2>清单 12. &lt;c:remove&gt; 操作示例</FONT></B></A><FONT size=2> </FONT>
<TABLE bgColor=#cccccc border=1 cellPadding=5 cellSpacing=0 width="100%">
<TBODY>
<TR>
<TD><PRE><FONT size=2><CODE>&lt;c:remove var="timezone" scope="session"/&gt;
</CODE>
</FONT></PRE></TD></TR></TBODY></TABLE>
<P><A id=IDAUHTVB name=IDAUHTVB><SPAN class=atitle2><FONT size=2>输出</FONT></SPAN></A><BR><FONT size=2>尽管 <CODE>&lt;c:set&gt;</CODE> 操作允许将表达式结果赋给限制了作用域的变量，但开发人员通常会希望只显示表达式的值，而不存储它。JSTL <CODE>&lt;c:out&gt;</CODE> 定制标记承担这一任务，其语法如清单 13 所示。该标记对由其 <CODE>value</CODE> 属性指定的表达式进行求值，然后打印结果。如果指定了可选属性 <CODE>default</CODE>，那么，在对 <CODE>value</CODE> 属性的表达式求值所得结果为 <CODE>null</CODE> 或空 <CODE>String</CODE> 的情况下，<CODE>&lt;c:out&gt;</CODE> 将打印其值。</FONT></P><A id=IDABJTVB name=IDABJTVB><B><FONT size=2>清单 13. &lt;c:out&gt; 操作的语法</FONT></B></A><FONT size=2> </FONT>
<TABLE bgColor=#cccccc border=1 cellPadding=5 cellSpacing=0 width="100%">
<TBODY>
<TR>
<TD><PRE><FONT size=2><CODE>&lt;c:out value="<I>expression</I>" default="<I>expression</I>" escapeXml="<I>boolean</I>"/&gt;
</CODE>
</FONT></PRE></TD></TR></TBODY></TABLE>
<P><FONT size=2><CODE>escapeXml</CODE> 属性也是可选的。它控制当用 <CODE>&lt;c:out&gt;</CODE> 标记输出诸如“&lt;”、“&gt;”和“&amp;”之类的字符（在 HTML 和 XML 中具有特殊意义）时是否应该进行转义。如果将 <CODE>escapeXml</CODE> 设置为 true，则会自动将这些字符转换成相应的 XML 实体（此处提到的字符分别转换成 <CODE>&amp;lt;</CODE>、<CODE>&amp;gt;</CODE> 和 <CODE>&amp;amp;</CODE>）。</FONT></P>
<P><FONT size=2>例如，假定有一个名为 <CODE>user</CODE> 的会话作用域变量，它是一个类的实例，该类为用户定义了两个特性：<CODE>username</CODE> 和 <CODE>company</CODE>。每当用户访问站点时，这个对象被自动分配给会话，但直到用户实际登录后，才会设置这两个特性。假定是这种方案，请考虑清单 14 中的 JSP 片段。在用户登录之后，这个片段将显示单词“Hello”，其后是他／她的用户名和一个惊叹号。但是，在用户登录之前，由这个片段生成的内容则是短语“Hello Guest!”。在这种情况下，因为 <CODE>username</CODE> 特性还有待初始化，所以 <CODE>&lt;c:out&gt;</CODE> 标记将转而打印出 <CODE>default</CODE> 属性的值（即字符串“Guest”）。</FONT></P><A id=IDADLTVB name=IDADLTVB><B><FONT size=2>清单 14. 带缺省内容的 &lt;c:out&gt; 操作示例</FONT></B></A><FONT size=2> </FONT>
<TABLE bgColor=#cccccc border=1 cellPadding=5 cellSpacing=0 width="100%">
<TBODY>
<TR>
<TD><PRE><FONT size=2><CODE>Hello &lt;c:out value="${user.username}" default=="Guest"/&gt;!
</CODE>
</FONT></PRE></TD></TR></TBODY></TABLE>
<P><FONT size=2>接下来，考虑清单 15，它使用了 <CODE>&lt;c:out&gt;</CODE> 标记的 <CODE>escapeXml</CODE> 属性。如果在这种情况下已经将 <CODE>company</CODE> 特性设置成 Java <CODE>String</CODE> 值 <CODE>"Flynn &amp; Sons"</CODE>，那么，实际上该操作生成的内容将是 <CODE>Flynn &amp; Sons</CODE>。如果这个操作是生成 HTML 或 XML 内容的 JSP 页面的一部分，那么，这个字符串中间的“&amp;”符号最终可能被解释为 HTML 或 XML 控制字符，从而妨碍了对该内容的显示或解析。但是，如果将 <CODE>escapeXml</CODE> 属性值设置成 <CODE>true</CODE>，则所生成的内容将是 <CODE>Flynn &amp;amp; Sons</CODE>。浏览器或解析器不会因在解释时遇到这种内容而出问题。假定 HTML 和 XML 是 JSP 应用程序中最常见的内容类型，所以 <CODE>escapeXml</CODE> 属性的缺省值是 <CODE>true</CODE> 就不足为奇了。</FONT></P><A id=IDA0MTVB name=IDA0MTVB><B><FONT size=2>清单 15. 禁用转义的 &lt;c:out&gt; 操作示例</FONT></B></A><FONT size=2> </FONT>
<TABLE bgColor=#cccccc border=1 cellPadding=5 cellSpacing=0 width="100%">
<TBODY>
<TR>
<TD><PRE><FONT size=2><CODE>&lt;c:out value="${user.company}" escapeXml=="false"/&gt;
</CODE>
</FONT></PRE></TD></TR></TBODY></TABLE>
<P><A id=IDADNTVB name=IDADNTVB><SPAN class=atitle2><FONT size=2>用缺省值设置变量</FONT></SPAN></A><BR><FONT size=2>除了简化动态数据的显示之外，当通过 <CODE>&lt;c:set&gt;</CODE> 设置变量值时，<CODE>&lt;c:out&gt;</CODE> 指定缺省值的能力也很有用。正如</FONT><A href="file:///C:/Documents%20and%20Settings/wangyong/Local%20Settings/Temp/CyberArticle/312.html#listing11"><FONT size=2>清单 11</FONT></A><FONT size=2> 所示，用来赋给限制了作用域的变量的值可以指定为 <CODE>&lt;c:set&gt;</CODE> 标记的主体内容，也可以通过其值属性来指定。通过将 <CODE>&lt;c:out&gt;</CODE> 操作嵌套在 <CODE>&lt;c:set&gt;</CODE> 标记的主体内容中，变量赋值就可以利用其缺省值能力。</FONT></P>
<P><FONT size=2>清单 16 中说明了这种方法。外部 <CODE>&lt;c:set&gt;</CODE> 标记的行为非常简单：它根据其主体内容设置会话作用域 <CODE>timezone</CODE> 变量的值。但是，在这种情况下，主体内容是通过 <CODE>&lt;c:out&gt;</CODE> 操作生成的。这个嵌套操作的值属性是表达式 <CODE>${cookie['tzPref'].value}</CODE>，它尝试通过 <CODE>cookie</CODE> 隐式对象返回名为 <CODE>tzPref</CODE> 的 cookie 值。（<CODE>cookie</CODE> 隐式对象将 cookie 名称映射到相应的 <CODE>Cookie</CODE> 实例，这意味着必须通过对象的 <CODE>value</CODE> 特性使用点运算符来检索储存在 cookie 中的实际数据。）</FONT></P><A id=IDAKPTVB name=IDAKPTVB><B><FONT size=2>清单 16. 合并 &lt;c:set&gt; 和 &lt;c:out&gt; 以提供缺省变量值</FONT></B></A><FONT size=2> </FONT>
<TABLE bgColor=#cccccc border=1 cellPadding=5 cellSpacing=0 width="100%">
<TBODY>
<TR>
<TD><PRE><FONT size=2><CODE>&lt;c:set var="timezone" scope=="session"&gt;
   &lt;c:out value="${cookie['tzPref'].value}" default=="CST"/&gt;
&lt;/c:set&gt;
</CODE>
</FONT></PRE></TD></TR></TBODY></TABLE>
<P><FONT size=2>但是，请考虑以下情况，用户是第一次尝试使用这段代码的 Web 应用程序。结果是，请求中没有提供名为 <CODE>tzPref</CODE> 的 cookie。这意味着使用隐式对象的查找将返回 <CODE>null</CODE>，在这种情况下整个表达式将返回 <CODE>null</CODE>。因为对 <CODE>&lt;c:out&gt;</CODE> 标记的 <CODE>value</CODE> 属性求值的结果是 <CODE>null</CODE>，所以 <CODE>&lt;c:out&gt;</CODE> 标记会转而输出对其 <CODE>default</CODE> 属性求值的结果。在这里是字符串 <CODE>CST</CODE>。因此，实际的结果是将 <CODE>timezone</CODE> 限制了作用域的变量设置成用户的 <CODE>tzPref</CODE> cookie 中存储的时区，或者，如果没有，则使用缺省时区 <CODE>CST</CODE>。</FONT></P>
<TABLE align=center border=1 cellPadding=5 cellSpacing=0 width="80%">
<TBODY>
<TR>
<TD background=312_files/bg-gold[1].gif><A id=IDAFRTVB name=IDAFRTVB><B><FONT size=2>EL 和 JSP 2.0</FONT></B></A><BR><FONT size=2>目前，表达式语言仅可用于指定 JSTL 定制标记中的动态属性值。但 JSTL 1.0 表达式语言的一个扩展已经被提出，会把它包括到 JSP 2.0 中去，眼下正在进行最后评审。这个扩展将允许开发人员通过自己的定制标记来使用 EL。页面作者将可以在目前允许使用 JSP 表达式的任何地方使用 EL 表达式，譬如将动态值插入模板文本中：<CODE>&lt;p&gt;Your preferred time zone is ${timezone}&lt;/p&gt;</CODE>。 </FONT>
<P><FONT size=2>这个 JSP 2.0 功能（就象 JSTL 本身一样）将支持页面作者进一步减少对 JSP 编制脚本元素的依赖，从而改进 JSP 应用程序的可维护性。</FONT></P></TD></TR></TBODY></TABLE>
<P><A id=IDASRTVB name=IDASRTVB><SPAN class=atitle2><FONT size=2>结束语</FONT></SPAN></A><BR><FONT size=2>EL（与四个 JSTL 定制标记库提供的操作结合起来）允许页面作者不使用脚本元素即可实现表示层逻辑。例如，对比本文开头</FONT><A href="file:///C:/Documents%20and%20Settings/wangyong/Local%20Settings/Temp/CyberArticle/312.html#listing1"><FONT size=2>清单 1</FONT></A><FONT size=2> 中的 JSP 代码和清单 17 中显示的通过 JSTL 实现的同样功能。（JSTL <CODE>core</CODE> 库中其余的标记，包括 <CODE>&lt;c:choose&gt;</CODE> 及其子标记，将在本系列的下一篇文章中讨论。）尽管显然执行了条件逻辑，但是 JSTL 版本中没有 Java 语言源代码，并且标记之间的关系（尤其是关于嵌套需求）对于任何精通 HTML 语法的人都应该是熟悉的。</FONT></P><A id=IDAISTVB name=IDAISTVB><B><FONT size=2>清单 17. 合并 &lt;c:set&gt; 和 &lt;c:out&gt; 以提供缺省变量值</FONT></B></A><FONT size=2> </FONT>
<TABLE bgColor=#cccccc border=1 cellPadding=5 cellSpacing=0 width="100%">
<TBODY>
<TR>
<TD><PRE><FONT size=2><CODE><SPAN class=boldcode>&lt;c:choose&gt;</SPAN><SPAN class=boldcode>&lt;c:when test="${user.role == 'member'}"&gt;</SPAN>
    &lt;p&gt;Welcome, member!&lt;/p&gt;
  <SPAN class=boldcode>&lt;/c:when&gt;</SPAN><SPAN class=boldcode>&lt;c:otherwise&gt;</SPAN>
    &lt;p&gt;Welcome, guest!&lt;/p&gt;
  <SPAN class=boldcode>&lt;/c:otherwise&gt;</SPAN><SPAN class=boldcode>&lt;/c:choose&gt;</SPAN></CODE>
</FONT></PRE></TD></TR></TBODY></TABLE>
<P><FONT size=2>通过提供大多数 Web 应用程序常用功能的标准实现，JSTL 有助于加速开发周期。与 EL 结合起来，JSTL 可以不需要对表示层程序编写代码，这极大地简化了 JSP 应用程序的维护。</FONT></P>
<P><A id=resources name=resources><SPAN class=atitle2><FONT size=2>参考资料</FONT></SPAN></A></P>
<UL>
<LI><FONT size=2>Sun 的 </FONT><A href="http://java.sun.com/products/jsp/jstl/index.html"><FONT size=2>JSP 标准标记库主页</FONT></A><FONT size=2>是了解关于 JSTL 的更多信息的良好起点。<BR><BR></FONT>
<LI><A href="http://jcp.org/aboutJava/communityprocess/final/jsr052/"><FONT size=2>JSTL 1.0 规范</FONT></A><FONT size=2>是关于 EL 和四个 JSTL 标记库的最终权威文本。<BR><BR></FONT>
<LI><A href="http://jakarta.apache.org/taglibs/index.html"><FONT size=2>Jakarta Taglibs</FONT></A><FONT size=2> 项目是 JSTL 1.0 参考实现的起源。<BR><BR></FONT>
<LI><FONT size=2>Shawn Bayern 所著的 </FONT><A href="http://www.manning.com/bayern/index.html"><I><FONT size=2>JSTL in Action</FONT></I></A><FONT size=2>（Manning Publications Co.，2002 年）提供了对所有 JSTL 功能的精彩论述，作者是该参考实现的领导。<BR><BR></FONT>
<LI><FONT size=2>David Geary 是 Java 技术方面很受欢迎的作者，他也写了一本关于 JSTL 的书，书名是 </FONT><A href="http://www.amazon.com/exec/obidos/tg/detail/-/0131001531/103-4207394-1320606?vi=glance"><I><FONT size=2>Core JSTL</FONT></I></A><FONT size=2>。<BR><BR></FONT>
<LI><A href="http://jsptags.com/index.jsp"><FONT size=2>JSPTags.com</FONT></A><FONT size=2> 是 JSP 技术参考资料的目录，它尤其专注于定制标记库。<BR><BR></FONT>
<LI><FONT size=2>Sun 的 </FONT><A href="http://java.sun.com/webservices/docs/ea2/tutorial/doc/JSTL3.html"><FONT size=2>Java Web Services Tutorial</FONT></A><FONT size=2> 中包含了对 JSTL 的讨论。<BR><BR></FONT>
<LI><FONT size=2>“</FONT><A href="http://www-900.ibm.com/developerWorks/cn/cgi-bin/click.cgi?url=http://www7b.software.ibm.com/wsdd/library/tutorials/vajwebsph353/Part-I/JSP11Part-I.html&amp;origin=j"><FONT size=2>Using JSPs and custom tags within VisualAge for Java and WebSphere Studio</FONT></A><FONT size=2>”（</FONT><A href="http://www7b.software.ibm.com/wsdd/"><FONT size=2>WebSphere 开发者园地</FONT></A><FONT size=2>）是一篇 WBOnline 实用论文，它演示了 servlet、JSP 和定制标记库的使用。<BR><BR></FONT>
<LI><FONT size=2>通过 Jeff Wilson 精彩的文章“</FONT><A href="http://www-900.ibm.com/developerworks/cn/java/j-taglib/index.shtml"><FONT size=2>使用定制标记控制 JSP 页面</FONT></A><FONT size=2>”（<I>developerWorks</I>，2002 年 1 月）了解关于定制标记库的一切。<BR><BR></FONT>
<LI><FONT size=2>Noel Bergman 的文章“</FONT><A href="http://www-900.ibm.com/developerworks/cn/java/j-jsptags/index.shtml"><FONT size=2>JSP 标记库：着意设计的更好的可用性</FONT></A><FONT size=2>”（<I>developerWorks</I>，2001 年 12 月）向您展示了声明性标记是如何帮助提高 JSP 页面的可用性的。<BR><BR></FONT>
<LI><FONT size=2>有关 EcmaScript 的更多详细信息，请参阅 Sing Li 的“</FONT><A href="http://www-900.ibm.com/developerworks/cn/java/j-qdjava/index.shtml"><FONT size=2>快速上手 Java 编程</FONT></A><FONT size=2>”（<I>developerWorks</I>，2001 年 7 月）。<BR><BR></FONT>
<LI><FONT size=2>在 </FONT><A href="http://www-900.ibm.com/developerWorks/cn/java/index.shtml"><FONT size=2><I>developerWorks</I> Java 技术专区</FONT></A><FONT size=2>可以找到多达数百篇的 Java 技术参考资料。 </FONT></LI></UL><BR><BR>
<TABLE border=0 cellPadding=0 cellSpacing=0 width="100%">
<TBODY>
<TR>
<TD><A id=author1 name=author1></A><FONT size=2><SPAN class=atitle2>关于作者</SPAN><BR>Mark Kolb 是一名在德克萨斯州奥斯汀工作的软件工程师。他经常就服务器端 Java 主题在业界发表演讲，并且与人合著了 </FONT><A href="http://www.manning.com/fields2/index.html"><I><FONT size=2>Web Development with JavaServer Pages，第二版</FONT></I></A><FONT size=2>一书。可通过 </FONT><A href="mailto:mak@taglib.com"><FONT size=2>mak@taglib.com</FONT></A><FONT size=2> 与 Mark 联系。</FONT></TD></TR></TBODY></TABLE><!-- END PAPER BODY--></TD>
<TD width=10><FONT size=2><IMG alt="" border=0 height=1 src="file:///C:/Documents%20and%20Settings/wangyong/Local%20Settings/Temp/CyberArticle/312_files/c[3].gif" width=10></FONT></TD></TR></TBODY></TABLE><!-- END PAPER BODY--><BR clear=all><img src ="http://www.blogjava.net/jackybu/aggbug/1473.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jackybu/" target="_blank">辰</a> 2005-02-24 10:57 <a href="http://www.blogjava.net/jackybu/articles/1473.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>JavaBeans 程序开发从入门到精通 </title><link>http://www.blogjava.net/jackybu/articles/1472.html</link><dc:creator>辰</dc:creator><author>辰</author><pubDate>Thu, 24 Feb 2005 02:46:00 GMT</pubDate><guid>http://www.blogjava.net/jackybu/articles/1472.html</guid><wfw:comment>http://www.blogjava.net/jackybu/comments/1472.html</wfw:comment><comments>http://www.blogjava.net/jackybu/articles/1472.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jackybu/comments/commentRss/1472.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jackybu/services/trackbacks/1472.html</trackback:ping><description><![CDATA[JavaBeans的属性 <BR><BR>JavaBeans的属性与一般Java程序中所指的属性，或者说与所有面向对象的程序设计语言中对象的属性是一个概念，在程序中的具体体现就是类中的变量。在JavaBeans设计中，按照属性的不同作用又细分为四类：Simple, Index, Bound与Constrained属性。 <BR><BR>1. Simple属性 <BR><BR>一个简单属性表示一个伴随有一对get/set方法（C语言的过程或函数在Java程序中称为"方法"）的变量。属性名与和该属性相关的get/set方法名对应。例如：如果有setX和getX方法，则暗指有一个名为"X"的属性。如果有一个方法名为isX，则通常暗指"X"是一个布尔属性（即X的值为true或false）。例如在下面这个程序中： <BR><BR><BR>public class alden1 extends Canvas { <BR>string ourString= "Hello"; //属性名为ourString，类型为字符串 <BR>public alden1(){ 　　　　//alden1()是alden1的构造函数， <BR>与C++中构造函数的意义相同 <BR>setBackground(Color.red); <BR>setForeground(Color.blue); <BR>} <BR>/* "set"属性*/ <BR>public void setString(String newString) { <BR>ourString=newString; <BR>} <BR>/* "get"属性 */ <BR>public String getString() { <BR>return ourString; <BR>} <BR>} <BR><BR><BR><BR><BR>2. Indexed属性 <BR><BR>一个Indexed属性表示一个数组值。使用与该属性对应的set/get方法可取得数组中的数值。该属性也可一次设置或取得整个数组的值。例： <BR><BR><BR>public class alden2 extends Canvas { <BR>int[] dataSet={1,2,3,4,5,6}; // dataSet是一个indexed属性 <BR>public alden2() { <BR>setBackground(Color.red); <BR>setForeground(Color.blue); <BR>} <BR>/* 设置整个数组　*/ <BR>public void setDataSet(int[] x){ <BR>dataSet=x; <BR>} <BR>/* 设置数组中的单个元素值 */ <BR>public void setDataSet(int index, int x){ <BR>dataSet[index]=x; <BR>} <BR>/* 取得整个数组值 */ <BR>public int[] getDataSet(){ <BR>return dataSet; <BR>} <BR>/* 取得数组中的指定元素值 */ <BR>public int getDataSet(int x){ <BR>return dataSet[x]; <BR>} <BR>} <BR><BR><BR><BR><BR>3. Bound属性 <BR><BR>一个Bound属性是指当该种属性的值发生变化时，要通知其它的对象。每次属性值改变时，这种属性就点火一个PropertyChange事件(在Java程序中，事件也是一个对象)。事件中封装了属性名、属性的原值、属性变化后的新值。这种事件是传递到其它的Beans，至于接收事件的Beans应做什么动作由其自己定义。当PushButton的background属性与Dialog的background属性bind时，若PushButton的background属性发生变化时，Dialog的background属性也发生同样的变化。 例： <BR><BR><BR>public class alden3 extends Canvas{ <BR>String ourString= "Hello"; <BR>//ourString是一个bound属性 <BR>private PropertyChangeSupport changes = new PropertyChangeSupport(this); <BR>/** 注：Java是纯面向对象的语言， <BR>如果要使用某种方法则必须指明是要使用哪个对象的方法， <BR>在下面的程序中要进行点火事件的操作， <BR>这种操作所使用的方法是在PropertyChangeSupport类中的。 <BR>所以上面声明并实例化了一个changes对象， <BR>在下面将使用changes的firePropertyChange方法来点火ourString的属性改变事件。*/ <BR><BR>public void setString(string newString){ <BR>String oldString = ourString; <BR>ourString = newString; <BR>/* ourString的属性值已发生变化，于是接着点火属性改变事件 */ <BR>changes.firePropertyChange("ourString",oldString,newString); <BR>} <BR>public String getString(){ <BR>return ourString; <BR>} <BR>/** 以下代码是为开发工具所使用的。 <BR>我们不能预知alden3将与哪些其它的Beans组合成为一个应用， <BR>无法预知若alden3的ourString属性发生变化时有哪些其它的组件与此变化有关， <BR>因而alden3这个Beans要预留出一些接口给开发工具， <BR>开发工具使用这些接口， <BR>把其它的JavaBeans对象与alden3挂接。*/ <BR><BR>public void addPropertyChangeListener(PropertyChangeLisener l){ <BR>changes.addPropertyChangeListener(l); <BR>} <BR>public void removePropertyChangeListener(PropertyChangeListener l){ <BR>changes.removePropertyChangeListener(l); <BR>} <BR><BR><BR><BR><BR>通过上面的代码， <BR><BR>开发工具调用changes的addPropertyChangeListener方法 <BR><BR>把其它JavaBeans注册入ourString属性的监听者队列l中， <BR><BR>l是一个Vector数组，可存储任何Java对象。 <BR><BR>开发工具也可使用changes的removePropertyChangeListener方法， <BR><BR>从l中注销指定的对象， <BR><BR>使alden3的ourString属性的改变不再与这个对象有关。 <BR><BR>当然，当程序员手写代码编制程序时， <BR><BR>也可直接调用这两个方法， <BR><BR>把其它Java对象与alden3挂接。 <BR><BR>4. Constrained属性 <BR><BR>一个JavaBeans的constrained属性，是指当这个属性的值要发生变化时，与这个属性已建立了某种连接的其它Java对象可否决属性值的改变。constrained属性的监听者通过抛出PropertyVetoException来阻止该属性值的改变。例：下面程序中的constrained属性是PriceInCents。 <BR><BR><BR>public class JellyBeans extends Canvas{ <BR>private PropertyChangeSupport changes=new PropertyChangeSupport(this); <BR>private VetoableChangeSupport Vetos=new VetoableChangeSupport(this); <BR>/*与前述changes相同， <BR>可使用VetoableChangeSupport对象的实例Vetos中的方法， <BR>在特定条件下来阻止PriceInCents值的改变。*/ <BR><BR><BR>...... <BR>public void setPriceInCents(int newPriceInCents) throws PropertyVetoException { <BR>/*方法名中throws PropertyVetoException的作用是当有 <BR>其它Java对象否决PriceInCents的改变时， <BR>要抛出例外。*/ <BR>/* 先保存原来的属性值*/ <BR><BR>int oldPriceInCents=ourPriceInCents; <BR>/**点火属性改变否决事件*/ <BR>vetos.fireVetoableChange("priceInCents",new Integer(OldPriceInCents), <BR>new Integer(newPriceInCents)); <BR><BR>/**若有其它对象否决priceInCents的改变， <BR>则程序抛出例外，不再继续执行下面的两条语句， <BR>方法结束。若无其它对象否决priceInCents的改变， <BR>则在下面的代码中把ourPriceIncents赋予新值， <BR>并点火属性改变事件*/ <BR><BR>ourPriceInCents=newPriceInCents; <BR>changes.firePropertyChange("priceInCents", <BR>new Integer(oldPriceInCents), <BR>new Integer(newPriceInCents)); <BR>} <BR><BR>/**与前述changes相同， <BR>也要为PriceInCents属性预留接口， <BR>使其它对象可注册入PriceInCents否决改变监听者队列中， <BR>或把该对象从中注销 <BR><BR>public void addVetoableChangeListener(VetoableChangeListener l) <BR>{ vetos.addVetoableChangeListener(l); <BR>} <BR>public void removeVetoableChangeListener(VetoableChangeListener l){ <BR>vetos.removeVetoableChangeListener(l); <BR>} <BR>...... <BR>} <BR><BR><BR><BR><BR>从上面的例子中可看到，一个constrained属性有两种监听者：属性变化监听者和否决属性改变的监听者。否决属性改变的监听者在自己的对象代码中有相应的控制语句，在监听到有constrained属性要发生变化时，在控制语句中判断是否应否决这个属性值的改变。 <BR><BR>总之，某个Beans的constrained属性值可否改变取决于其它的Beans或者是Java对象是否允许这种改变。允许与否的条件由其它的Beans或Java对象在自己的类中进行定义。 <BR><BR>JavaBeans的事件 <BR><BR>事件处理是JavaBeans体系结构的核心之一。通过事件处理机制，可让一些组件作为事件源，发出可被描述环境或其它组件接收的事件。这样，不同的组件就可在构造工具内组合在一起，组件之间通过事件的传递进行通信，构成一个应用。从概念上讲，事件是一种在"源对象"和"监听者对象"之间，某种状态发生变化的传递机制。事件有许多不同的用途，例如在Windows系统中常要处理的鼠标事件、窗口边界改变事件、键盘事件等。在Java和JavaBeans中则是定义了一个一般的、可扩充的事件机制，这种机制能够： <BR><BR>对事件类型和传递的模型的定义和扩充提供一个公共框架，并适合于广泛的应用。 <BR><BR>与Java语言和环境有较高的集成度。 <BR><BR>事件能被描述环境捕获和点火。 <BR><BR>能使其它构造工具采取某种技术在设计时直接控制事件，以及事件源和事件监听者之间的联系。 <BR><BR>事件机制本身不依赖于复杂的开发工具。特别地，还应当： <BR><BR>能够发现指定的对象类可以生成的事件。 <BR><BR>能够发现指定的对象类可以观察（监听）到的事件。 <BR><BR>提供一个常规的注册机制，允许动态操纵事件源与事件监听者之间的关系。 <BR><BR>不需要其它的虚拟机和语言即可实现。 <BR><BR>事件源与监听者之间可进行高效的事件传递。 <BR><BR>能完成JavaBeans事件模型与相关的其它组件体系结构事件模型的中立映射。 <BR><BR>JavaBeans事件模型的主要构成有： 事件从事件源到监听者的传递是通过对目标监听者对象的Java方法调用进行的。对每个明确的事件的发生，都相应地定义一个明确的Java方法。这些方法都集中定义在事件监听者（EventListener）接口中，这个接口要继承java.util.EventListener。实现了事件监听者接口中一些或全部方法的类就是事件监听者。 伴随着事件的发生，相应的状态通常都封装在事件状态对象中，该对象必须继承自java.util.EventObject。事件状态对象作为单参传递给应响应该事件的监听者方法中。 发出某种特定事件的事件源的标识是：遵从规定的设计格式为事件监听者定义注册方法，并接受对指定事件监听者接口实例的引用。 有时，事件监听者不能直接实现事件监听者接口，或者还有其它的额外动作时，就要在一个源与其它一个或多个监听者之间插入一个事件适配器类的实例，来建立它们之间的联系。 <BR><BR>事件状态对象（Event State Object） <BR><BR>与事件发生有关的状态信息一般都封装在一个事件状态对象中，这种对象是java.util.EventObject的子类。按设计习惯，这种事件状态对象类的名应以Event结尾。例如： <BR><BR><BR>public class MouseMovedExampleEvent extends java.util.EventObject <BR><BR>{ protected int x, y； <BR>/*　创建一个鼠标移动事件MouseMovedExampleEvent */ <BR>　MouseMovedExampleEvent(java.awt.Component source, Point location) { <BR>super(source); <BR>x = location.x; <BR>y = location.y; <BR>} <BR>/* 获取鼠标位置*/ <BR>public Point getLocation() { <BR>return new Point(x, y); <BR>}} <BR><BR><BR><BR><BR>事件监听者接口（EventListener Interface）与事件监听者 <BR><BR>由于Java事件模型是基于方法调用，因而需要一个定义并组织事件操纵方法的方式。JavaBeans中，事件操纵方法都被定义在继承了java.util.EventListener类的EventListener接口中，按规定，EventListener接口的命名要以Listener结尾。任何一个类如果想操纵在EventListener接口中定义的方法都必须以实现这个接口方式进行。这个类也就是事件监听者。例如： <BR><BR><BR>/*先定义了一个鼠标移动事件对象*/ <BR>　　public class MouseMovedExampleEvent <BR>extends java.util.EventObject { <BR>// 在此类中包含了与鼠标移动事件有关的状态信息 <BR>　　　　 ... <BR>　　} <BR>　　/*定义了鼠标移动事件的监听者接口*/ <BR>　　interface MouseMovedExampleListener <BR>extends java.util.EventListener { <BR>/*在这个接口中定义了鼠标移动事件监听者所应支持的方法*/ <BR>void mouseMoved(MouseMovedExampleEvent mme); <BR>} <BR><BR>在接口中只定义方法名， <BR>方法的参数和返回值类型。 <BR>如：上面接口中的mouseMoved方法的 <BR>具体实现是在下面的ArbitraryObject类中定义的。 <BR><BR>class ArbitraryObject implements MouseMovedExampleListener { <BR>　　　public void mouseMoved(MouseMovedExampleEvent mme) <BR>　 { ... } <BR>｝ <BR>ArbitraryObject就是MouseMovedExampleEvent事件的监听者。 <BR><BR><BR><BR><BR>事件监听者的注册与注销 <BR><BR>为了各种可能的事件监听者把自己注册入合适的事件源中，建立源与事件监听者间的事件流，事件源必须为事件监听者提供注册和注销的方法。在前面的bound属性介绍中已看到了这种使用过程，在实际中，事件监听者的注册和注销要使用标准的设计格式： <BR><BR><BR>public void add&lt; ListenerType&gt;(&lt; ListenerType&gt; listener)； <BR>public void remove&lt; ListenerType&gt;(&lt; ListenerType&gt; listener)； <BR><BR><BR><BR><BR>例如： <BR><BR>首先定义了一个事件监听者接口： <BR><BR><BR>public interface <BR>ModelChangedListener extends java.util.EventListener { <BR>void modelChanged(EventObject e); <BR>} <BR><BR><BR><BR><BR>接着定义事件源类： <BR><BR><BR>public abstract class Model { <BR>private Vector listeners = new Vector(); // 定义了一个储存事件监听者的数组 <BR><BR>/*上面设计格式中的&lt; ListenerType&gt;在此处即是下面的ModelChangedListener*/ <BR><BR>public synchronized void addModelChangedListener(ModelChangedListener mcl) <BR>　　{ listeners.addElement(mcl); }//把监听者注册入listeners数组中 <BR>public synchronized void removeModelChangedListener(ModelChangedListener mcl) <BR>　　　　{ listeners.removeElement(mcl); //把监听者从listeners中注销 <BR>　　　　｝ <BR>　　/*以上两个方法的前面均冠以synchronized， <BR>是因为运行在多线程环境时， <BR>可能同时有几个对象同时要进行注册和注销操作， <BR>使用synchronized来确保它们之间的同步。 <BR>开发工具或程序员使用这两个方法建立源与监听者之间的事件流*/ <BR><BR>protected void notifyModelChanged() { <BR>/**事件源使用本方法通知监听者发生了modelChanged事件*/ <BR>　　　 Vector l; <BR>　　　　EventObject e = new EventObject(this); <BR>/* 首先要把监听者拷贝到l数组中， <BR>冻结EventListeners的状态以传递事件。 <BR>这样来确保在事件传递到所有监听者之前， <BR>已接收了事件的目标监听者的对应方法暂不生效。*/ <BR>　　　　synchronized(this) { <BR>　　　　　　l = (Vector)listeners.clone(); <BR>　　　　} <BR>　　　　for (int i = 0; i &lt; l.size(); i++) { <BR>　　　　 /* 依次通知注册在监听者队列中的每个监听者发生了modelChanged事件， <BR>　　　　 并把事件状态对象e作为参数传递给监听者队列中的每个监听者*/ <BR>((ModelChangedListener)l.elementAt(i)).modelChanged(e); <BR>　　　　} <BR>　　　 } <BR>　　　} <BR><BR><BR><BR><BR>在程序中可见事件源Model类显式地调用了接口中的modelChanged方法，实际是把事件状态对象e作为参数，传递给了监听者类中的modelChanged方法。 <BR><BR>适配类 <BR><BR>适配类是Java事件模型中极其重要的一部分。在一些应用场合，事件从源到监听者之间的传递要通过适配类来"转发"。例如：当事件源发出一个事件，而有几个事件监听者对象都可接收该事件，但只有指定对象做出反应时，就要在事件源与事件监听者之间插入一个事件适配器类，由适配器类来指定事件应该是由哪些监听者来响应。 <BR><BR>适配类成为了事件监听者，事件源实际是把适配类作为监听者注册入监听者队列中，而真正的事件响应者并未在监听者队列中，事件响应者应做的动作由适配类决定。目前绝大多数的开发工具在生成代码时，事件处理都是通过适配类来进行的。 <BR><BR>JavaBeans用户化 <BR><BR>JavaBeans开发者可以给一个Beans添加用户化器（Customizer）、属性编辑器（PropertyEditor）和BeansInfo接口来描述一个Beans的内容，Beans的使用者可在构造环境中通过与Beans附带在一起的这些信息来用户化Beans的外观和应做的动作。一个Beans不必都有BeansCustomizer、PrpertyEditor和BeansInfo，根据实际情况，这些是可选的，当有些Beans较复杂时，就要提供这些信息，以Wizard的方式使Beans的使用者能够用户化一个Beans。有些简单的Beans可能这些信息都没有，则构造工具可使用自带的透视装置，透视出Beans的内容，并把信息显示到标准的属性表或事件表中供使用者用户化Beans，前几节提到的Beans的属性、方法和事件名要以一定的格式命名，主要的作用就是供开发工具对Beans进行透视。当然也是给程序员在手写程序中使用Beans提供方便，使他能观其名、知其意。 <BR><BR>用户化器接口（Customizer Interface） <BR><BR>当一个Beans有了自己的用户化器时，在构造工具内就可展现出自己的属性表。在定义用户化器时必须要实现java.Beanss.Customizer接口。例如，下面是一个"按钮"Beans的用户化一器： <BR><BR><BR>public class OurButtonCustomizer <BR>extends Panel implements Customizer { <BR>... ... <BR>/*当实现象OurButtonCustomizer这样的常规属性表时， <BR>一定要在其中实现addProperChangeListener <BR>和removePropertyChangeListener,这样， <BR>构造工具可用这些功能代码为属性事件添加监听者。*/ <BR>... ... <BR>private PropertyChangeSupport changes=new PropertyChangeSupport(this); <BR>public void addPropertyChangeListener(PropertyChangeListener l) { <BR>changes.addPropertyChangeListener(l); <BR>public void removePropertyChangeListener(PropertyChangeListener l) { <BR>changes.removePropertyChangeListener(l); <BR>} <BR>... ... <BR><BR><BR><BR><BR>属性编辑器接口（PropertyEditor Interface） <BR><BR>一个JavaBeans可提供PropertyEditor类，为指定的属性创建一个编辑器。这个类必须继承自java.Beanss.PropertyEditorSupport类。构造工具与手写代码的程序员不直接使用这个类，而是在下一小节的BeansInfo中实例化并调用这个类。例： <BR><BR><BR>public class MoleculeNameEditor extends java.Beanss.PropertyEditorSupport { <BR>public String[] getTags() { <BR>String resule[]={ <BR>"HyaluronicAcid","Benzene","buckmisterfullerine", <BR>"cyclohexane","ethane","water"}; <BR>return resule;} <BR>} <BR><BR><BR><BR><BR>上例中是为Tags属性创建了属性编辑器，在构造工具内，可从下拉表格中选择MoleculeName的属性应是"HyaluronicAid"或是"water"。 <BR><BR>BeansInfo接口 <BR><BR>每个Beans类也可能有与之相关的BeansInfo类，在其中描述了这个Beans在构造工具内出现时的外观。BeansInfo中可定义属性、方法、事件，显示它们的名称，提供简单的帮助说明。 例如： <BR><BR><BR>public class MoleculeBeansInfo extends SimpleBeansInfo { <BR>public PropertyDescriptor[] getPropertyDescriptors() { <BR>try { <BR>PropertyDescriptor pd=new PropertyDescriptor("moleculeName",Molecule.class); <BR>/*通过pd引用了上一节的MoleculeNameEditor类,取得并返回moleculeName属性*/ <BR>pd.setPropertyEditorClass(MoleculeNameEditor.class); <BR>PropertyDescriptor result[]={pd}; <BR>return result; <BR>} catch(Exception ex) { <BR>System.err.println("MoleculeBeansInfo: unexpected exeption: "+ex); <BR>return null; <BR>} <BR>} <BR>} <BR><BR><BR><BR><BR>JavaBeans持久化 <BR><BR>当一个JavaBeans在构造工具内被用户化，并与其它Beans建立连接之后，它的所有状态都应当可被保存，下一次被load进构造工具内或在运行时，就应当是上一次修改完的信息。为了能做到这一点，要把Beans的某些字段的信息保存下来，在定义Beans时要使它实现java.io.Serializable接口。例如： <BR><BR>public class Button <BR>implements java.io.Serializable { <BR>} <BR><BR><BR><BR>实现了序列化接口的Beans中字段的信息将被自动保存。若不想保存某些字段的信息则可在这些字段前冠以transient或static关键字，transient和static变量的信息是不可被保存的。通常，一个Beans所有公开出来的属性都应当是被保存的，也可有选择地保存内部状态。 Beans开发者在修改软件时，可以添加字段，移走对其它类的引用，改变一个字段的private/protected/public状态，这些都不影响类的存储结构关系。然而，当从类中删除一个字段，改变一个变量在类体系中的位置，把某个字段改成transient/static，或原来是transient/static，现改为别的特性时，都将引起存储关系的变化。 <BR><BR>JavaBeans的存储格式 <BR><BR>JavaBeans组件被设计出来后，一般是以扩展名为jar的Zip格式文件存储，在jar中包含与JavaBeans有关的信息，并以MANIFEST文件指定其中的哪些类是JavaBeans。以jar文件存储的JavaBeans在网络中传送时极大地减少了数据的传输数量，并把JavaBeans运行时所需要的一些资源捆绑在一起，本章主要论述了JavaBeans的一些内部特性及其常规设计方法，参考的是JavaBeans规范1.0A版本。随着世界各大ISV对JavaBeans越来越多的支持，规范在一些细节上还在不断演化，但基本框架不会再有大的变动。<B><BR></B><img src ="http://www.blogjava.net/jackybu/aggbug/1472.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jackybu/" target="_blank">辰</a> 2005-02-24 10:46 <a href="http://www.blogjava.net/jackybu/articles/1472.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>jsp文件操作之读取篇 </title><link>http://www.blogjava.net/jackybu/articles/1366.html</link><dc:creator>辰</dc:creator><author>辰</author><pubDate>Sun, 20 Feb 2005 03:03:00 GMT</pubDate><guid>http://www.blogjava.net/jackybu/articles/1366.html</guid><wfw:comment>http://www.blogjava.net/jackybu/comments/1366.html</wfw:comment><comments>http://www.blogjava.net/jackybu/articles/1366.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jackybu/comments/commentRss/1366.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jackybu/services/trackbacks/1366.html</trackback:ping><description><![CDATA[文件操作是网站编程的重要内容之一，asp关于文件操作讨论的已经很多了，让我们来看看jsp中是如何实现的。 <BR>　　这里用到了两个文件，一个jsp文件一个javabean文件，通过jsp中调用javabean可以轻松读取文本文件，注意请放置一个文本文件afile.txt到web根目录的test目录下，javabean文件编译后将class文件放到对应的class目录下(tomcat环境)。 <BR>Read.jsp 
<P></P>
<P>&lt;html&gt;<BR>&lt;head&gt;<BR>&lt;title&gt;读取一个文件&lt;/title&gt;<BR>&lt;/head&gt;<BR>&lt;body bgcolor="#000000"&gt;<BR>&lt;%--调用javabean --%&gt;<BR>&lt;jsp:useBean id="reader" class="DelimitedDataFile" scope="request"&gt;<BR>&lt;jsp:setProperty name="reader" property="path" value="/test/afile.txt" /&gt;<BR>&lt;/jsp:useBean&gt;</P>
<P>&lt;h3&gt;文件内容:&lt;/h3&gt;</P>
<P>&lt;p&gt;</P>
<P>&lt;% int count = 0; %&gt; <BR>&lt;% while (reader.nextRecord() != -1) { %&gt;<BR>&lt;% count++; %&gt; <BR>&lt;b&gt;第&lt;% out.print(count); %&gt;行:&lt;/b&gt; <BR>&lt;% out.print(reader.returnRecord()); %&gt;&lt;br&gt;　　　　<BR>&lt;% } %&gt; <BR>&lt;/p&gt;<BR>&lt;/body&gt;<BR>&lt;/html&gt;</P>
<P><BR>//DelimitedDataFile.java bean文件源代码<BR>//导入java包<BR>import java.io.*;<BR>import java.util.StringTokenizer;</P>
<P>public class DelimitedDataFile <BR>{</P>
<P>private String currentRecord = null;<BR>private BufferedReader file;<BR>private String path;<BR>private StringTokenizer token;<BR>//创建文件对象<BR>public DelimitedDataFile()<BR>{<BR>　　　　 file = new BufferedReader(new InputStreamReader(System.in),1);<BR>} <BR>public DelimitedDataFile(String filePath) throws FileNotFoundException<BR>{<BR>　　　　 <BR>　　　　 path = filePath;<BR>　　　　 file = new BufferedReader(new FileReader(path));<BR>} <BR>　　　　 //设置文件路径<BR>　　　　 public void setPath(String filePath)<BR>　　　　　　　　{<BR>　　　　　　　　　　　　<BR>　　　　　　　　　　　　path = filePath;<BR>try {<BR>file = new BufferedReader(new<BR>FileReader(path));<BR>} catch (FileNotFoundException e) {<BR>　　　　　　　　　　　　System.out.println("file not found");<BR>　　　　　　　　　　　　}<BR>　　　　<BR>　　　　　　　　} <BR>//得到文件路径<BR>　　　　 public String getPath() {<BR>　　　　　　　　return path;<BR>} <BR>//关闭文件<BR>public void fileClose() throws IOException<BR>{<BR>　　　　 <BR>　　　　 file.close();<BR>} <BR>//读取下一行记录，若没有则返回-1<BR>public int nextRecord()<BR>{<BR>　　　　 <BR>　　　　<BR>　　　　 int returnInt = -1;<BR>　　　　 try<BR>　　　　 {<BR>　　　　 currentRecord = file.readLine();<BR>　　　　 } <BR>　　　　<BR>　　　　 catch (IOException e)<BR>　　　　 {<BR>　　　　 System.out.println("readLine problem, terminating.");<BR>　　　　 } <BR>　　　　<BR>　　　　 if (currentRecord == null)<BR>　　　　 returnInt = -1;<BR>　　　　 else<BR>　　　　 {<BR>　　　　 token = new StringTokenizer(currentRecord);<BR>　　　　 returnInt = token.countTokens();<BR>　　　　 } <BR>　　　　 return returnInt;<BR>} </P>
<P>　　　　//以字符串的形式返回整个记录<BR>public String returnRecord()<BR>{</P>
<P>return currentRecord;<BR>} <BR>} </P><img src ="http://www.blogjava.net/jackybu/aggbug/1366.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jackybu/" target="_blank">辰</a> 2005-02-20 11:03 <a href="http://www.blogjava.net/jackybu/articles/1366.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>究竟什么是MVC </title><link>http://www.blogjava.net/jackybu/articles/1273.html</link><dc:creator>辰</dc:creator><author>辰</author><pubDate>Thu, 17 Feb 2005 07:33:00 GMT</pubDate><guid>http://www.blogjava.net/jackybu/articles/1273.html</guid><wfw:comment>http://www.blogjava.net/jackybu/comments/1273.html</wfw:comment><comments>http://www.blogjava.net/jackybu/articles/1273.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jackybu/comments/commentRss/1273.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jackybu/services/trackbacks/1273.html</trackback:ping><description><![CDATA[1 解释一 <A href="http://dev.csdn.net/article/52/52575.shtm">http://dev.csdn.net/article/52/52575.shtm</A><BR><BR><SPAN id=ArticleContent1_ArticleContent1_lblContent>&nbsp; 
<DIV class=title>模型－视图－控制器（MVC）是Xerox　PARC在八十年代为编程语言Smalltalk－80发明的一种软件设计模式，至今已被广泛使用。最近几年被推荐为Sun公司J2EE平台的设计模式，并且受到越来越多的使用 ColdFusion 和 PHP 的开发者的欢迎。模型－视图－控制器模式是一个有用的工具箱，它有很多好处，但也有一些缺点。</DIV>
<DIV class=content>
<P>MVC如何工作</P>
<P>MVC是一个设计模式，它强制性的使应用程序的输入、处理和输出分开。使用MVC应用程序被分成三个核心部件：模型、视图、控制器。它们各自处理自己的任务。</P>
<P>视图<BR>视图是用户看到并与之交互的界面。对老式的Web应用程序来说，视图就是由HTML元素组成的界面，在新式的Web应用程序中，HTML依旧在视图中扮演着重要的角色，但一些新的技术已层出不穷，它们包括Macromedia　Flash和象XHTML，XML/XSL，WML等一些标识语言和Web　services.</P>
<P>如何处理应用程序的界面变得越来越有挑战性。MVC一个大的好处是它能为你的应用程序处理很多不同的视图。在视图中其实没有真正的处理发生，不管这些数据是联机存储的还是一个雇员列表，作为视图来讲，它只是作为一种输出数据并允许用户操纵的方式。</P>
<P>模型<BR>模型表示企业数据和业务规则。在MVC的三个部件中，模型拥有最多的处理任务。例如它可能用象EJBs和ColdFusion　Components这样的构件对象来处理数据库。被模型返回的数据是中立的，就是说模型与数据格式无关，这样一个模型能为多个视图提供数据。由于应用于模型的代码只需写一次就可以被多个视图重用，所以减少了代码的重复性。</P>
<P>控制器<BR>控制器接受用户的输入并调用模型和视图去完成用户的需求。所以当单击Web页面中的超链接和发送HTML表单时，控制器本身不输出任何东西和做任何处理。它只是接收请求并决定调用哪个模型构件去处理请求，然后用确定用哪个视图来显示模型处理返回的数据。</P>
<P>现在我们总结ＭVC的处理过程，首先控制器接收用户的请求，并决定应该调用哪个模型来进行处理，然后模型用业务逻辑来处理用户的请求并返回数据，最后控制器用相应的视图格式化模型返回的数据，并通过表示层呈现给用户。</P>
<P>为什么要使用 MVC</P>
<P>大部分Web应用程序都是用像ASP，PHP，或者CFML这样的过程化语言来创建的。它们将像数据库查询语句这样的数据层代码和像HTML这样的表示层代码混在一起。经验比较丰富的开发者会将数据从表示层分离开来，但这通常不是很容易做到的，它需要精心的计划和不断的尝试。MVC从根本上强制性的将它们分开。尽管构造MVC应用程序需要一些额外的工作，但是它给我们带来的好处是无庸质疑的。</P>
<P>首先，最重要的一点是多个视图能共享一个模型，正如我所提及的，现在需要用越来越多的方式来访问你的应用程序。对此，其中一个解决之道是使用MVC，无论你的用户想要Flash界面或是 WAP 界面；用一个模型就能处理它们。由于你已经将数据和业务规则从表示层分开，所以你可以最大化的重用你的代码了。</P>
<P>由于模型返回的数据没有进行格式化，所以同样的构件能被不同界面使用。例如，很多数据可能用HTML来表示，但是它们也有可能要用Macromedia Flash和WAP来表示。模型也有状态管理和数据持久性处理的功能，例如，基于会话的购物车和电子商务过程也能被Flash网站或者无线联网的应用程序所重用。</P>
<P>因为模型是自包含的，并且与控制器和视图相分离，所以很容易改变你的应用程序的数据层和业务规则。如果你想把你的数据库从MySQL移植到Oracle，或者改变你的基于RDBMS数据源到LDAP，只需改变你的模型即可。一旦你正确的实现了模型，不管你的数据来自数据库或是LDAP服务器，视图将会正确的显示它们。由于运用MVC的应用程序的三个部件是相互对立，改变其中一个不会影响其它两个，所以依据这种设计思想你能构造良好的松偶合的构件。</P>
<P>对我来说，控制器的也提供了一个好处，就是可以使用控制器来联接不同的模型和视图去完成用户的需求，这样控制器可以为构造应用程序提供强有力的手段。给定一些可重用的模型和视图，控制器可以根据用户的需求选择模型进行处理，然后选择视图将处理结果显示给用户。</P>
<P>MVC的缺点<BR>MVC的缺点是由于它没有明确的定义，所以完全理解MVC并不是很容易。使用MVC需要精心的计划，由于它的内部原理比较复杂，所以需要花费一些时间去思考。</P>
<P>你将不得不花费相当可观的时间去考虑如何将MVC运用到你的应用程序，同时由于模型和视图要严格的分离，这样也给调试应用程序到来了一定的困难。每个构件在使用之前都需要经过彻底的测试。一旦你的构件经过了测试，你就可以毫无顾忌的重用它们了。</P>
<P>根据我个人经验，由于我们将一个应用程序分成了三个部件，所以使用MVC同时也意味着你将要管理比以前更多的文件，这一点是显而易见的。这样好像我们的工作量增加了，但是请记住这比起它所能带给我们的好处是不值一提。</P>
<P>MVC并不适合小型甚至中等规模的应用程序，花费大量时间将MVC应用到规模并不是很大的应用程序通常会得不偿失。</P>
<P>MVC是一条创建软件的好途径<BR>MVC设计模式是一个很好创建软件的途径，它所提倡的一些原则，像内容和显示互相分离可能比较好理解。但是如果你要隔离模型、视图和控制器的构件，你可能需要重新思考你的应用程序，尤其是应用程序的构架方面。如果你肯接受MVC，并且有能力应付它所带来的额外的工作和复杂性，MVC将会使你的软件在健壮性，代码重用和结构方面上一个新的台阶。<BR><BR><BR>2解释二&nbsp; <A href="http://www.ask321.com/ask8/ask151598.htm">http://www.ask321.com/ask8/ask151598.htm</A><BR>Model-View-Controller<BR><BR>a.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 问题<BR><BR>如果开发一个企业级应用，只需要一种客户端的话，那么一切都非常容易解决。但真实情况是，我们必须面对运行在各种设备上客户端，象PDA，WAP浏览器以及运行在桌面上的浏览器，我们不得不开发不同的应用程序来处理来自不同客户端的请求。数据访问与现实将混淆在一起，可能会出现重复的数据访问，导致整个开发周期没有必要的延长。<BR><BR><BR><BR>b.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 建议的解决方法<BR><BR>Model-View-Controller (MVC) 开发模式被证明是有效的处理方法之一。它可以分离数据访问和数据表现。你可以开发一个有伸缩性的，便于扩展的控制器，来维护整个流程。如图1所示为整个模式的结构。MVC模式可以被映射到多层企业级的J2EE应用上。<BR><BR>§&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 所有的企业数据以及商业逻辑可以作为模式。<BR><BR>§&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 视图可以通过模式访问数据，并根据客户端的要求来显示数据。视图必须保证当模式改变的时候，数据显示也必须同时改变。<BR><BR>§&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 控制器用来结合模式和视图，把客户端来的请求转换成模式能够理解并执行的请求，并且根据请求以及执行结果来决定下一次显示那一个视图。<BR><BR>根据以上的逻辑，你可以象这样建立一个应用：<BR><BR>§&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 应用的商业逻辑由MVC中的模式也就是EJB来表现。模式必须处理由控制器传递过来的对数据的访问请求。<BR><BR>§&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 多个页面组成了MVC中的视图，这些视图必须随模式一起更新。<BR><BR>§&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 控制器是一系列接收用户动作的对象，他们把用户的请求转换成模式可理解的请求，并决定显示那一个页面当模式处理完请求后。<BR><BR><BR><BR>图 1<BR><BR>c.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 要点<BR><BR>§&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; MVC结构适用于那些多用户的，可扩展的，可维护的，具有很高交互性的系统。<BR><BR>§&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; MVC可以很好的表达用户的交互和系统模式。<BR><BR>§&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 很方便的用多个视图来显示多套数据，是系统很方便的支持其他新的客户端类型。<BR><BR>§&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 代码重复达到最低。<BR><BR>§&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 由于分离了模式中的流控制和数据表现，可以分清开发者的责任，另外，也可以加快产品推向市场的时间<BR><BR>3 解释三 <A href="http://www.chinaunix.net/bbsjh/14/1135.html">http://www.chinaunix.net/bbsjh/14/1135.html</A><BR>
<TABLE cellSpacing=0 cellPadding=0 width=750 align=center border=0>
<TBODY>
<TR>
<TD><SPAN style="FONT-SIZE: 14px">
<CENTER><B>[转帖]了解MVC架构对于用Struts构建的强大的Web应用程序很重要 </B></CENTER><BR>
<DIV></DIV></SPAN></TD></TR>
<TR>
<TD>
<DIV align=center>作者：<A href="http://www.chinaunix.net/cgi-bin/bbs/profile.cgi?action=show&amp;member=cinc" target=_blank><FONT color=#000000>cinc</FONT></A> &nbsp;&nbsp;&nbsp;&nbsp;发表时间：2002/12/03 08:48am</DIV><BR></TD></TR>
<TR>
<TD align=middle>
<TABLE cellSpacing=0 cellPadding=0 width="90%" border=0>
<TBODY>
<TR>
<TD><SPAN style="FONT-SIZE: 14px">了解MVC架构对于用Struts构建的强大的Web应用程序很重要 
<P>Struts是雅加达的一个项目，它提供了一个方法，可以在一个Web应用程序中一起使用JavaServer &nbsp;<BR>Pages（JSP）和servlets。它的目的是要解决完全由JSP或完全由servlet实现的应用程序中的固有的问 <BR>题。 例如，servelts可以生成HTML页面，但这么做很麻烦。另一方面，JSP可以很容易地用于传统的 <BR>HTML页面，但JSP页面有其它的缺点。特别是，用JSP很难将内容同内容的显示分开。 很容易将Java 代 <BR>码同HTML混在一起，结果做出的东西又慢又难以维护。 
<P>然而，因为JSP页面容易使用，所以它们成为用Java构建动态的Web应用程序的首选方法。除了容易编程 <BR>外，JSP页面也被改进了，所以现在它们克服了以前的某些局限性。JavaBeans和标记库只是在基础的 <BR>JSP技术上的几个改进。这种类型的方法——JSP页面单独负责处理输入的请求和回复客户端——被称为 <BR>Model 1架构。 
<P>JavaServer Pages是servlets的特殊情况，所以两者可以一起工作以弥补每个的不足，这似乎是合乎逻 <BR>辑的。这种类型的方法——你的Web架构包含截然不同的但又互联的处理数据模式、显示代码和程序控 <BR>制逻辑的JSP和servlet组件——被称为Model 2架构，或Model-View-Controller（MVC）架构。 
<P>为了使用Struts架构以及用JSP和servlets有效地编程，对MVC架构的了解是很必要的。Model 1和MVC架 <BR>构的主要不同就是请求是在哪里处理的。在Model 1架构中，请求通过JSP接收，主要通过JSP处理。如 <BR>果JSP页面需要来自任何其它应用程序组件的服务，如一个数据库，那么你就从页面做适当的调用，把 <BR>数据返回到页面，安排数据的格式并显示出来。你可以把一些代码放到一个或多个JavaBean中，但是这 <BR>么做本身没有将逻辑同显示完全分离。 
<P>MVC方法采用了JSP和servlet方法的最佳特性，使这两种技术可以协同工作。明确的是，servlet是处理 <BR>层（控制器）。Servlet接收请求，很像Model 1架构中JSP页面所做的那样，并确定如何满足那些请 <BR>求。这就意味着，servlet控制输入的请求和输出的回应。 
<P>商业逻辑体现了MVC架构中的模式。商业逻辑代码为页面做处理。如果进入servlet的请求是一个数据库 <BR>查询，servlet就将这个请求传送到一个SQL调用或类似的数据库代码。如果请求是一个包括输入信用卡 <BR>号的购买请求，那么事物处理代码就接管了。在某种意义上，架构的模式部分是让应用程序处于领先地 <BR>位的全部原因。 
<P>JSP页面是显示层（视图），是用户与应用程序交互的地方。它提供输入并显示结果。页面不应该包括 <BR>任何脚本。它只是将数据传送到servlet，并接收和显示返回的数据。 
<P>该架构的优势应该是很明显的。首先，它将计算和显示清楚地分开了。结果很理想，在JSP页面上没有 <BR>出现处理过程，在servlet或商业逻辑中没有数据格式。这种分离的另一个好处是Java程序员可以专注 <BR>于servlet代码，HTML编写者可以专注于JSP。 第二点，控制器servlet做页面上的所有的决定。 在你 <BR>的页面和逻辑中不会出现任何决策。这就提高了一个应用程序的性能和可扩展性，因为请求可以被导向 <BR>架构的不同的组件，甚至是不同的服务器。 
<P><BR>运用MVC架构 
<P>MVC架构没有必要成为用于所有Java应用程序的最佳方法。 如你想象的那样，它在准备和编码时往往很 <BR>复杂——这对简单的应用程序来说是没必要的。当页面导航相对来说比较简单和固定，而且应用程序中 <BR>的页面结构可以由一个简单的目录结构管理时, Model 1架构仍然是最好的方法。这些应用程序往往将 <BR>页面流动信息嵌入到页面间的链接中。（JSP中出现forward()就告诉你，在该页中有嵌入的逻辑，让你 <BR>对显示下一页作出决定。）对于对流量或可扩展性需求有限的静态的应用程序来说，标准的JSP模式仍 <BR>然是一个可行的选择方案。 
<P>在一些情况下，你可能想把一个JSP应用程序移植到MVC架构中。例如，你可能开始时用的是Model 1， <BR>简单的JSP架构，随着你的需求的增加，你会发现维护起来太复杂或太难了。如果你花很长的时间对应 <BR>用程序做相对来说较简单的修改，或者如果你经常在你的代码中发现bug，那么你的JSP导向的应用程序 <BR>也许就不再是合适的方法了。 
<P>随着应用程序的发展和变化，页面的流动和商业逻辑也增加了。应用程序变得难以维护，因为页面流动 <BR>逻辑跨多个页面分布，而且商业逻辑可能开始存在于未计划的地方。从Model 1转到MVC的最佳时机就是 <BR>当这些类型的维护问题出现的时候。 
<P>你也可以预先计划将你的应用程序从一个架构移植到另一个架构。当你的应用程序中的JSP页面包含脚 <BR>本元素，定制标记或JavaScript来执行一个forward()操作时，你可能想调整你最初的设计，变成一种 <BR>用MVC架构的设计。 
<P>Refactoring用在这儿是个不错的术语。它指的是以一种高度严谨的方式重建代码结构的一种技术。当 <BR>你的代码变得难以理解、修改和调试时，你通常就开始考虑调整了。你可以用几种方式来调整代码：你 <BR>可以简单地重新命名变量和方法，或者将部分代码移植到不同类型的执行模式中。更多的关于调整及其 <BR>技术方面的信息，请访问Martin Fowler的网站www.refactoring.com 或者阅读他写的书 &nbsp;<BR>Refactoring: Improving the Design of Existing Code。 
<P>在许多情况下，一开始就选择MVC架构是很有意义的，例如你的应用程序是为广泛的企业应用而设计 <BR>的，或者在几年内，你的应用程序可能扩展到一个相当高的流量。 设计一个MVC架构需要有深谋远虑。 <BR>大多数程序员发现写逻辑脚本或JavaBeans，以及用HTML显示很容易。当你设计一个MVC架构时，你必须 <BR>首先进行一个完整的设计。这就意味着，分析需要处理的请求的类型，确定哪些组件（JavaBean、数据 <BR>库或其它servlets）将处理这些请求，以及对那些请求的回应是如何显示给用户的。 该设计的关键就 <BR>是请求和数据的流动性。为MVC架构设计应用程序组件只是对你现在用JSP和servlets所做工作的扩展。 <BR>面临的挑战就是构建一个servlet，它接收请求并把那些请求分到应用程序的不同的组件。将一个数据 <BR>库请求传送到一个数据库，或将一个处理请求传送到一个JavaBean是很容易的，但是如果一个请求包含 <BR>这两种元素，会怎样呢？或者如果请求的性质在一些处理出现前不能确定，又怎样呢？ 
<P><BR>Struts 构架 
<P>该挑战使我们又回到Struts构架。Struts提供了一个实现MVC架构的高度自动化的方式。它的结构实现 <BR>了MVC，并包括一个控制器servlet、一组JSP页面和应用程序的商业逻辑。控制器将用户请求打包，并 <BR>把它们导向架构中的其他对象。 
<P>Struts构架是围绕一个ActionMapping 结构的。控制器用 ActionMapping 把HTTP消息形式的用户请求 <BR>转换成应用程序的动作。ActionMapping指定请求的路径、计划处理请求的对象以及任何服务该请求需 <BR>要的其它信息。ActionMapping创建了一个 Action 对象来处理请求。一旦Action对象完成了一个任 <BR>务，它就通过在一个JSP页面上写结果来直接回应一个用户请求，或者它可以让一个应用程序流动到其 <BR>它地方做回应。 </SPAN></P></TD></TR></TBODY></TABLE></TD></TR></TBODY></TABLE></P></DIV></SPAN><PRE>http://www.chinaunix.net/bbsjh/14/1135.html
http://www.huihoo.com/java/java_web/java-web-6.html
http://www.jdon.com/idea/application.htm
http://sunrise.x168.net/java/020712,15,02,45.html
http://www-900.ibm.com/developerWorks/cn/java/l-struts-mvc/index.shtml
http://www.fawcette.com/china/Java/2002_04/article.asp?page=1&amp;xml=StrutStuff

http://jakarta.apache.org/struts/<BR><BR><A href="http://dev.csdn.net/article/58/58688.shtm">http://dev.csdn.net/article/58/58688.shtm</A>
</PRE><img src ="http://www.blogjava.net/jackybu/aggbug/1273.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jackybu/" target="_blank">辰</a> 2005-02-17 15:33 <a href="http://www.blogjava.net/jackybu/articles/1273.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>JSP的mysql_jdbc驱动程序 </title><link>http://www.blogjava.net/jackybu/articles/1214.html</link><dc:creator>辰</dc:creator><author>辰</author><pubDate>Tue, 15 Feb 2005 03:38:00 GMT</pubDate><guid>http://www.blogjava.net/jackybu/articles/1214.html</guid><wfw:comment>http://www.blogjava.net/jackybu/comments/1214.html</wfw:comment><comments>http://www.blogjava.net/jackybu/articles/1214.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jackybu/comments/commentRss/1214.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jackybu/services/trackbacks/1214.html</trackback:ping><description><![CDATA[mm.mysql是个类型4(即纯java),符合jdbc&nbsp;2规范的mysql&nbsp;jdbc驱动程序。当前版本为2.0&nbsp;pre&nbsp;5(beta)&nbsp;<BR>你可以从http://www.worldserver.com/mm.mysql/下载最新的驱动程序&nbsp;<BR>本文只是简单描述一下mm.mysql的安装和使用&nbsp;<BR><FONT face="Courier new, Courier, Mono">安装&nbsp;<BR>1、下载mm.mysql&nbsp;<BR>2、解压到某驱动器，如c:&nbsp;<BR>3、修改classpath,加入mm.mysql的路径，如你原来的classpath可能是:&nbsp;<BR>.;c:jdk1.2.2lib ools.jar;c:jdk1.2.2libdt.jar;&nbsp;<BR>修改后可能是&nbsp;<BR>.;c:jdk1.2.2lib ools.jar;c:jdk1.2.2libdt.jar;C:mm.mysql.jdbc-2.0pre5;&nbsp;<BR><BR>编程&nbsp;<BR><BR>1、用DriverManager登记mm.mysql&nbsp;<BR>mm.mysql的class名为org.gjt.mm.mysql.Driver,登记时必须写成&nbsp;<BR>Class.forName("org.gjt.mm.mysql.Driver").newInstance();&nbsp;<BR><BR>2、jdbc&nbsp;url参数说明&nbsp;<BR>url格式：jdbc:mysql://[hostname][:port]/dbname[?param1=value1][¶m2=value2]...&nbsp;<BR>参数名&nbsp;取值&nbsp;缺省&nbsp;<BR>user&nbsp;数据库用户名&nbsp;无&nbsp;<BR>password&nbsp;数据库用户口令&nbsp;无&nbsp;<BR>autoReconnect&nbsp;当数据库连接丢失时是否自动连接，取值true/false&nbsp;false&nbsp;<BR>maxReconnects&nbsp;如果autoReconnect为true,此参数为重试次数，缺省为3次&nbsp;3&nbsp;<BR>initialTimeout&nbsp;如果autoReconnect为true,此参数为重新连接前等待的秒数&nbsp;2&nbsp;<BR>maxRows&nbsp;设置查询时返回的行数，0表示全部&nbsp;0&nbsp;<BR>useUnicode&nbsp;是否使用unicode输出，true/false&nbsp;false&nbsp;<BR>characterEncoding&nbsp;如果useUnicode,该参数制定encoding类型，建议使用8859_1&nbsp;无&nbsp;<BR><BR>提示&nbsp;<BR>同时使用useUnicode,characterEncoding,能解决数据库输出时的中文问题&nbsp;<BR>如:jdbc:mysql://localhost/test?user=root&amp;useUnicode=true;characterEncoding=8859_1&nbsp;<BR><BR>实际例子，举一个简单的例子&nbsp;<BR>这个jsp例子使用一个库，该库只有一个表（地址簿)&nbsp;<BR><BR>create&nbsp;database&nbsp;addressbook&nbsp;<BR>use&nbsp;addressbook&nbsp;<BR>create&nbsp;table&nbsp;addressbook&nbsp;(id&nbsp;int&nbsp;auto_increment&nbsp;primary&nbsp;key,name&nbsp;varchar(30),address&nbsp;varchar(255),phone&nbsp;varchar(20));&nbsp;<BR><BR>插入记录&nbsp;<BR>insert&nbsp;into&nbsp;addressbook&nbsp;(name,address,phone)&nbsp;values&nbsp;(jjx,zhejiang&nbsp;yuyao,0574-2222222);&nbsp;<BR><BR>jsp代码：代码中使用了absolute,ResultSet.TYPE_SCROOL_SENSITIVE等的目录是为了测试mm.mysql是否符合jdbc&nbsp;2.0的规范&nbsp;<BR>&lt;%@&nbsp;page&nbsp;import="java.sql.*"&nbsp;%&gt;&nbsp;<BR>&lt;%&nbsp;<BR>out.println("通讯录！");&nbsp;<BR><BR>try&nbsp;{&nbsp;<BR>Class.forName("org.gjt.mm.mysql.Driver").newInstance();&nbsp;<BR><BR>}&nbsp;<BR>catch&nbsp;(Exception&nbsp;E)&nbsp;{&nbsp;<BR>out.println("Unable&nbsp;to&nbsp;load&nbsp;driver.");&nbsp;<BR><BR>}&nbsp;<BR><BR>try&nbsp;{&nbsp;<BR>Connection&nbsp;C&nbsp;=&nbsp;DriverManager.getConnection("jdbc:mysql://localhost/addressbook?user=root&amp;password=jjx&amp;useUnicode=true&amp;characterEncoding=8859_1");&nbsp;<BR>Statement&nbsp;s=C.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,ResultSet.CONCUR_READ_ONLY);&nbsp;<BR>ResultSet&nbsp;rs=s.executeQuery("select&nbsp;*&nbsp;from&nbsp;addressbook");&nbsp;<BR>out.println("&lt;table&nbsp;border=1&gt;");&nbsp;<BR>int&nbsp;i=1;&nbsp;<BR>for&nbsp;(i=10;i&lt;20;i++)&nbsp;<BR>{&nbsp;<BR>if&nbsp;(rs.absolute(i))&nbsp;<BR>{&nbsp;<BR>out.println("&lt;tr&gt;&lt;td&gt;");&nbsp;<BR>out.println(rs.getString(1));&nbsp;<BR>out.println("&lt;/td&gt;");&nbsp;<BR>out.println("&lt;td&gt;");&nbsp;<BR>out.print(rs.getString(2));&nbsp;<BR>out.println("&lt;/td&gt;");&nbsp;<BR>out.println("&lt;td&gt;");&nbsp;<BR>out.print(rs.getString(3));&nbsp;<BR>out.println("&lt;/td&gt;&lt;/tr&gt;");&nbsp;<BR>}&nbsp;<BR>else&nbsp;<BR>{&nbsp;<BR>break;&nbsp;<BR>}&nbsp;<BR><BR>}&nbsp;<BR>out.println("&lt;/table&gt;");&nbsp;<BR>rs.close();&nbsp;<BR>s.close();&nbsp;<BR>C.close();&nbsp;<BR><BR><BR>}&nbsp;<BR>catch&nbsp;(SQLException&nbsp;E)&nbsp;{&nbsp;<BR>out.println("SQLException:&nbsp;"&nbsp;+&nbsp;E.getMessage());&nbsp;<BR>out.println("SQLState:&nbsp;"&nbsp;+&nbsp;E.getSQLState());&nbsp;<BR>out.println("VendorError:&nbsp;"&nbsp;+&nbsp;E.getErrorCode());&nbsp;<BR>}&nbsp;<BR><BR>%&gt;</FONT><B><BR></B><img src ="http://www.blogjava.net/jackybu/aggbug/1214.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jackybu/" target="_blank">辰</a> 2005-02-15 11:38 <a href="http://www.blogjava.net/jackybu/articles/1214.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Hibernate学习笔记</title><link>http://www.blogjava.net/jackybu/articles/1215.html</link><dc:creator>辰</dc:creator><author>辰</author><pubDate>Tue, 15 Feb 2005 03:38:00 GMT</pubDate><guid>http://www.blogjava.net/jackybu/articles/1215.html</guid><wfw:comment>http://www.blogjava.net/jackybu/comments/1215.html</wfw:comment><comments>http://www.blogjava.net/jackybu/articles/1215.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jackybu/comments/commentRss/1215.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jackybu/services/trackbacks/1215.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 1．&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Hibernate介绍Hibernate是一个开放源代码的O/R Mapping (对象关系映射框架)，它对JDBC进行了轻量级的对象封装，使Java程序员可以随心所欲的使用对象编程思维来操纵数据库。Hibernate 是一个面向Java 环境的对象/关系数据库映射...&nbsp;&nbsp;<a href='http://www.blogjava.net/jackybu/articles/1215.html'>阅读全文</a><img src ="http://www.blogjava.net/jackybu/aggbug/1215.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jackybu/" target="_blank">辰</a> 2005-02-15 11:38 <a href="http://www.blogjava.net/jackybu/articles/1215.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>JSP数据库连接大全 </title><link>http://www.blogjava.net/jackybu/articles/1213.html</link><dc:creator>辰</dc:creator><author>辰</author><pubDate>Tue, 15 Feb 2005 03:35:00 GMT</pubDate><guid>http://www.blogjava.net/jackybu/articles/1213.html</guid><wfw:comment>http://www.blogjava.net/jackybu/comments/1213.html</wfw:comment><comments>http://www.blogjava.net/jackybu/articles/1213.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jackybu/comments/commentRss/1213.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jackybu/services/trackbacks/1213.html</trackback:ping><description><![CDATA[testoracle.jsp如下： <BR>&lt; %@ page contentType="text/html;charset=gb2312"% &gt; <BR>&lt; %@ page import="java.sql.*"% &gt; <BR>&lt; html &gt; <BR>&lt; body &gt; <BR>&lt; %Class.forName("oracle.jdbc.driver.OracleDriver").newInstance(); <BR>String url="jdbc:oracle:thin:@localhost:1521:orcl"; <BR>//orcl为你的数据库的SID <BR>String user="scott"; <BR>String password="tiger"; <BR>Connection conn= DriverManager.getConnection(url,user,password); <BR>Statement stmt=conn.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,ResultSet.CONCUR_UPDATABLE); <BR>String sql="select * from test"; <BR>ResultSet rs=stmt.executeQuery(sql); <BR>while(rs.next()) {% &gt; <BR>您的第一个字段内容为：&lt; %=rs.getString(1)% &gt; <BR>您的第二个字段内容为：&lt; %=rs.getString(2)% &gt; <BR>&lt; %}% &gt; <BR>&lt; %out.print("数据库操作成功，恭喜你");% &gt; <BR>&lt; %rs.close(); <BR>stmt.close(); <BR>conn.close(); <BR>% &gt; <BR>&lt; /body &gt; <BR>&lt; /html &gt; <BR><BR><B>二、jsp连接Sql Server7.0/2000数据库 </B><BR><BR>testsqlserver.jsp如下： <BR>&lt; %@ page contentType="text/html;charset=gb2312"% &gt; <BR>&lt; %@ page import="java.sql.*"% &gt; <BR>&lt; html &gt; <BR>&lt; body &gt; <BR>&lt; %Class.forName("com.microsoft.jdbc.sqlserver.SQLServerDriver").newInstance(); <BR>String url="jdbc:microsoft:sqlserver://localhost:1433;DatabaseName=pubs"; <BR>//pubs为你的数据库的 <BR>String user="sa"; <BR>String password=""; <BR>Connection conn= DriverManager.getConnection(url,user,password); <BR>Statement stmt=conn.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,ResultSet.CONCUR_UPDATABLE); <BR>String sql="select * from test"; <BR>ResultSet rs=stmt.executeQuery(sql); <BR>while(rs.next()) {% &gt; <BR>您的第一个字段内容为：&lt; %=rs.getString(1)% &gt; <BR>您的第二个字段内容为：&lt; %=rs.getString(2)% &gt; <BR>&lt; %}% &gt; <BR>&lt; %out.print("数据库操作成功，恭喜你");% &gt; <BR>&lt; %rs.close(); <BR>stmt.close(); <BR>conn.close(); <BR>% &gt; <BR>&lt; /body &gt; <BR>&lt; /html &gt; <BR><STRONG>三、jsp连接DB2数据库 <BR><BR></STRONG>testdb2.jsp如下： <BR>&lt; %@ page contentType="text/html;charset=gb2312"% &gt; <BR>&lt; %@ page import="java.sql.*"% &gt; <BR>&lt; html &gt; <BR>&lt; body &gt; <BR>&lt; %Class.forName("com.ibm.db2.jdbc.app.DB2Driver ").newInstance(); <BR>String url="jdbc:db2://localhost:5000/sample"; <BR>//sample为你的数据库名 <BR>String user="admin"; <BR>String password=""; <BR>Connection conn= DriverManager.getConnection(url,user,password); <BR>Statement stmt=conn.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,ResultSet.CONCUR_UPDATABLE); <BR>String sql="select * from test"; <BR>ResultSet rs=stmt.executeQuery(sql); <BR>while(rs.next()) {% &gt; <BR>您的第一个字段内容为：&lt; %=rs.getString(1)% &gt; <BR>您的第二个字段内容为：&lt; %=rs.getString(2)% &gt; <BR>&lt; %}% &gt; <BR>&lt; %out.print("数据库操作成功，恭喜你");% &gt; <BR>&lt; %rs.close(); <BR>stmt.close(); <BR>conn.close(); <BR>% &gt; <BR>&lt; /body &gt; <BR>&lt; /html &gt; <BR><BR><B>四、jsp连接Informix数据库</B><BR><BR>testinformix.jsp如下： <BR>&lt; %@ page contentType="text/html;charset=gb2312"% &gt; <BR>&lt; %@ page import="java.sql.*"% &gt; <BR>&lt; html &gt; <BR>&lt; body &gt; <BR>&lt; %Class.forName("com.informix.jdbc.IfxDriver").newInstance(); <BR>String url = <BR>"jdbc:informix-sqli://123.45.67.89:1533/testDB:INFORMIXSERVER=myserver; <BR>user=testuser;password=testpassword"; <BR>//testDB为你的数据库名 <BR>Connection conn= DriverManager.getConnection(url); <BR>Statement stmt=conn.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,ResultSet.CONCUR_UPDATABLE); <BR>String sql="select * from test"; <BR>ResultSet rs=stmt.executeQuery(sql); <BR>while(rs.next()) {% &gt; <BR>您的第一个字段内容为：&lt; %=rs.getString(1)% &gt; <BR>您的第二个字段内容为：&lt; %=rs.getString(2)% &gt; <BR>&lt; %}% &gt; <BR>&lt; %out.print("数据库操作成功，恭喜你");% &gt; <BR>&lt; %rs.close(); <BR>stmt.close(); <BR>conn.close(); <BR>% &gt; <BR>&lt; /body &gt; <BR>&lt; /html &gt; <BR><STRONG>五、jsp连接Sybase数据库 <BR><BR></STRONG>testmysql.jsp如下： <BR>&lt; %@ page contentType="text/html;charset=gb2312"% &gt; <BR>&lt; %@ page import="java.sql.*"% &gt; <BR>&lt; html &gt; <BR>&lt; body &gt; <BR>&lt; %Class.forName("com.sybase.jdbc.SybDriver").newInstance(); <BR>String url =" jdbc:sybase:Tds:localhost:5007/tsdata"; <BR>//tsdata为你的数据库名 <BR>Properties sysProps = System.getProperties(); <BR>SysProps.put("user","userid"); <BR>SysProps.put("password","user_password"); <BR>Connection conn= DriverManager.getConnection(url, SysProps); <BR>Statement stmt=conn.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,ResultSet.CONCUR_UPDATABLE); <BR>String sql="select * from test"; <BR>ResultSet rs=stmt.executeQuery(sql); <BR>while(rs.next()) {% &gt; <BR>您的第一个字段内容为：&lt; %=rs.getString(1)% &gt; <BR>您的第二个字段内容为：&lt; %=rs.getString(2)% &gt; <BR>&lt; %}% &gt; <BR>&lt; %out.print("数据库操作成功，恭喜你");% &gt; <BR>&lt; %rs.close(); <BR>stmt.close(); <BR>conn.close(); <BR>% &gt; <BR>&lt; /body &gt; <BR>&lt; /html &gt; <BR><BR><B>六、jsp连接MySQL数据库 </B><BR><BR>testmysql.jsp如下： <BR>&lt; %@ page contentType="text/html;charset=gb2312"% &gt; <BR>&lt; %@ page import="java.sql.*"% &gt; <BR>&lt; html &gt; <BR>&lt; body &gt; <BR>&lt; %Class.forName("org.gjt.mm.mysql.Driver").newInstance(); <BR>String url ="jdbc:mysql://localhost/softforum?user=soft&amp;password=soft1234&amp;useUnicode=true&amp;characterEncoding=8859_1" <BR>//testDB为你的数据库名 <BR>Connection conn= DriverManager.getConnection(url); <BR>Statement stmt=conn.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,ResultSet.CONCUR_UPDATABLE); <BR>String sql="select * from test"; <BR>ResultSet rs=stmt.executeQuery(sql); <BR>while(rs.next()) {% &gt; <BR>您的第一个字段内容为：&lt; %=rs.getString(1)% &gt; <BR>您的第二个字段内容为：&lt; %=rs.getString(2)% &gt; <BR>&lt; %}% &gt; <BR>&lt; %out.print("数据库操作成功，恭喜你");% &gt; <BR>&lt; %rs.close(); <BR>stmt.close(); <BR>conn.close(); <BR>% &gt; <BR>&lt; /body &gt; <BR>&lt; /html &gt; <BR><BR><B>七、jsp连接PostgreSQL数据库 </B><BR><BR>testmysql.jsp如下： <BR>&lt; %@ page contentType="text/html;charset=gb2312"% &gt; <BR>&lt; %@ page import="java.sql.*"% &gt; <BR>&lt; html &gt; <BR>&lt; body &gt; <BR>&lt; %Class.forName("org.postgresql.Driver").newInstance(); <BR>String url ="jdbc:postgresql://localhost/soft" <BR>//soft为你的数据库名 <BR>String user="myuser"; <BR>String password="mypassword"; <BR>Connection conn= DriverManager.getConnection(url,user,password); <BR>Statement stmt=conn.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,ResultSet.CONCUR_UPDATABLE); <BR>String sql="select * from test"; <BR>ResultSet rs=stmt.executeQuery(sql); <BR>while(rs.next()) {% &gt; <BR>您的第一个字段内容为：&lt; %=rs.getString(1)% &gt; <BR>您的第二个字段内容为：&lt; %=rs.getString(2)% &gt; <BR>&lt; %}% &gt; <BR>&lt; %out.print("数据库操作成功，恭喜你");% &gt; <BR>&lt; %rs.close(); <BR>stmt.close(); <BR>conn.close(); <BR>% &gt; <BR>&lt; /body &gt; <BR>&lt; /html &gt; <B><BR></B><img src ="http://www.blogjava.net/jackybu/aggbug/1213.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jackybu/" target="_blank">辰</a> 2005-02-15 11:35 <a href="http://www.blogjava.net/jackybu/articles/1213.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>EJB工作原理学习笔记! </title><link>http://www.blogjava.net/jackybu/articles/1212.html</link><dc:creator>辰</dc:creator><author>辰</author><pubDate>Tue, 15 Feb 2005 03:34:00 GMT</pubDate><guid>http://www.blogjava.net/jackybu/articles/1212.html</guid><wfw:comment>http://www.blogjava.net/jackybu/comments/1212.html</wfw:comment><comments>http://www.blogjava.net/jackybu/articles/1212.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jackybu/comments/commentRss/1212.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jackybu/services/trackbacks/1212.html</trackback:ping><description><![CDATA[<P>EJB工作原理学习笔记</P>
<P>1 RMI工作原理<BR>2 websphere实现<BR>3 weblogic实现<BR>4 理解体会</P>
<P>1：RMI工作原理<BR>首先说说RMI的工作原理，因为EJB毕竟是基于RMI的嘛。废话就不多讲了，RMI的本质就是实现在不同JVM之间的</P>
<P>调用<BR>它的实现方法就是在两个JVM中各开一个Stub和Skeleton，二者通过socket通信来实现参数和返回值的传递。 </P>
<P>有关RMI的例子代码网上可以找到不少，但绝大部分都是通过extend the interface java.rmi.Remote实现，已</P>
<P>经封装的很完善了，不免使人有雾里看花的感觉。下面的例子是我在《Enterprise JavaBeans》里看到的，虽</P>
<P>然很粗糙，但很直观，利于很快了解它的工作原理。 </P>
<P>1. 定义一个Person的接口，其中有两个business method, getAge() 和getName() </P>
<P>代码: </P>
<P>public interface Person { <BR>&nbsp;&nbsp;&nbsp; public int getAge() throws Throwable; <BR>&nbsp;&nbsp;&nbsp; public String getName() throws Throwable; <BR>} <BR>&nbsp;</P>
<P><BR>2. Person的实现PersonServer类 <BR>代码: </P>
<P>public class PersonServer implements Person { <BR>&nbsp;&nbsp;&nbsp; int age; <BR>&nbsp;&nbsp;&nbsp; String name; </P>
<P>&nbsp;&nbsp;&nbsp; public PersonServer(String name, int age) { <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.age = age; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.name = name; <BR>&nbsp;&nbsp;&nbsp; } </P>
<P>&nbsp;&nbsp;&nbsp; public int getAge() { <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return age; <BR>&nbsp;&nbsp;&nbsp; } </P>
<P>&nbsp;&nbsp;&nbsp; public String getName() { <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return name; <BR>&nbsp;&nbsp;&nbsp; } <BR>} <BR>&nbsp;</P>
<P><BR>3. 好，我们现在要在Client机器上调用getAge()和getName()这两个business </P>
<P>method，那么就得编写相应的Stub(Client端)和Skeleton(Server端)程序。这是Stub的实现： <BR>代码: </P>
<P>import java.io.ObjectOutputStream; <BR>import java.io.ObjectInputStream; <BR>import java.net.Socket; </P>
<P>public class Person_Stub implements Person { <BR>&nbsp;&nbsp;&nbsp; Socket socket; </P>
<P>&nbsp;&nbsp;&nbsp; public Person_Stub() throws Throwable { <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // connect to skeleton <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; socket = new Socket("computer_name", 9000); <BR>&nbsp;&nbsp;&nbsp; } </P>
<P>&nbsp;&nbsp;&nbsp; public int getAge() throws Throwable { <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // pass method name to skeleton <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ObjectOutputStream outStream = <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; new ObjectOutputStream(socket.getOutputStream()); <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; outStream.writeObject("age"); <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; outStream.flush(); </P>
<P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ObjectInputStream inStream = <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; new ObjectInputStream(socket.getInputStream()); <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return inStream.readInt(); <BR>&nbsp;&nbsp;&nbsp; } </P>
<P>&nbsp;&nbsp;&nbsp; public String getName() throws Throwable { <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // pass method name to skeleton <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ObjectOutputStream outStream = <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; new ObjectOutputStream(socket.getOutputStream()); <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; outStream.writeObject("name"); <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; outStream.flush(); </P>
<P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ObjectInputStream inStream = <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; new ObjectInputStream(socket.getInputStream()); <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return (String)inStream.readObject(); <BR>&nbsp;&nbsp;&nbsp; } <BR>} <BR>&nbsp;</P>
<P><BR>注意，Person_Stub和PersonServer一样，都implements </P>
<P>Person。它们都实现了getAge()和getName()两个business </P>
<P>method，不同的是PersonServer是真的实现，Person_Stub是建立socket连接，并向Skeleton发请求，然后通过</P>
<P>Skeleton调用PersonServer的方法，最后接收返回的结果。 </P>
<P>4. Skeleton实现 <BR>代码: </P>
<P>import java.io.ObjectOutputStream; <BR>import java.io.ObjectInputStream; <BR>import java.net.Socket; <BR>import java.net.ServerSocket; </P>
<P>public class Person_Skeleton extends Thread { <BR>&nbsp;&nbsp;&nbsp; PersonServer myServer; </P>
<P>&nbsp;&nbsp;&nbsp; public Person_Skeleton(PersonServer server) { <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // get reference of object server <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.myServer = server; <BR>&nbsp;&nbsp;&nbsp; } </P>
<P>&nbsp;&nbsp;&nbsp; public void run() { <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; try { <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // new socket at port 9000 <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ServerSocket serverSocket = new ServerSocket(9000); <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // accept stub's request <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Socket socket = serverSocket.accept(); </P>
<P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; while (socket != null) { <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // get stub's request <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ObjectInputStream inStream = <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; new ObjectInputStream(socket.getInputStream()); <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; String method = (String)inStream.readObject(); </P>
<P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // check method name <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (method.equals("age")) { <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // execute object server's business method <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int age = myServer.getAge(); <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ObjectOutputStream outStream = <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; new ObjectOutputStream(socket.getOutputStream()); </P>
<P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // return result to stub <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; outStream.writeInt(age); <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; outStream.flush(); <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } </P>
<P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(method.equals("name")) { <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // execute object server's business method <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; String name = myServer.getName(); <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ObjectOutputStream outStream = <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; new ObjectOutputStream(socket.getOutputStream()); </P>
<P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // return result to stub <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; outStream.writeObject(name); <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; outStream.flush(); <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } catch(Throwable t) { <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; t.printStackTrace(); <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.exit(0); <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } <BR>&nbsp;&nbsp;&nbsp; } </P>
<P>&nbsp;&nbsp;&nbsp; public static void main(String args []) { <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // new object server <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; PersonServer person = new PersonServer("Richard", 34); </P>
<P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Person_Skeleton skel = new Person_Skeleton(person); <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; skel.start(); <BR>&nbsp;&nbsp;&nbsp; } <BR>} <BR>&nbsp;</P>
<P><BR>Skeleton类 extends from Thread，它长驻在后台运行，随时接收client发过来的request。并根据发送过来的</P>
<P>key去调用相应的business method。 </P>
<P>5. 最后一个，Client的实现 <BR>代码: </P>
<P>public class PersonClient { <BR>&nbsp;&nbsp;&nbsp; public static void main(String [] args) { <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; try { <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Person person = new Person_Stub(); <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int age = person.getAge(); <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; String name = person.getName(); <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println(name + " is " + age + " years old"); <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } catch(Throwable t) { <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; t.printStackTrace(); <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } <BR>&nbsp;&nbsp;&nbsp; } <BR>} <BR>&nbsp;</P>
<P><BR>Client的本质是，它要知道Person接口的定义，并实例一个Person_Stub，通过Stub来调用business method，</P>
<P>至于Stub怎么去和Server沟通，Client就不用管了。 </P>
<P>注意它的写法： <BR>Person person = new Person_Stub(); <BR>而不是 <BR>Person_Stub person = new Person_Stub(); </P>
<P>为什么？因为要面向接口编程嘛，呵呵。</P>
<P>2：websphere实现<BR>EJB类一览&nbsp;&nbsp;&nbsp; <BR>这里结合WebSphere来讲讲各个类的调用关系吧。 </P>
<P>假定我们要创建一个读取User信息的SessionBean，需要我们写的有3个文件： <BR>1. UserServiceHome.java <BR>Home接口 </P>
<P>2. UserService.java <BR>Remote接口 </P>
<P>3. UserServiceBean.java <BR>Bean实现 </P>
<P>WSAD最终会生成10个class。其它7个是什么呢？我们一个一个数过来： </P>
<P>4. _UserServiceHome_Stub.java <BR>这个当然就是Home接口在Client端(动态加载)的Stub类了，它implements UserServiceHome。 </P>
<P>5. _EJSRemoteStatelessUserServiceHome_a940aa04_Tie.java <BR>Home接口在Server端的Skeleton类，"a940aa04"应该是随机生成的，所有其他的相关class名里都会有这个标志</P>
<P>串，Tie是Corba对Skeleton的叫法。 </P>
<P>6. EJSRemoteStatelessUserServiceHome_a940aa04.java <BR>Home接口在Server端的实现，当然，它也implements UserServiceHome。 </P>
<P>7. EJSStatelessUserServiceHomeBean_a940aa04.java <BR>由#6调用，create _UserService_Stub。(为什么#6不能直接create _UserService_Stub呢？后面再讲。) </P>
<P>8. _UserService_Stub.java <BR>Remote接口在Client端(动态加载)的Stub类。它implements UserService。 </P>
<P>9. _EJSRemoteStatelessUserService_a940aa04_Tie.java <BR>Remote接口在Server端的Skeleton类。 </P>
<P>10. EJSRemoteStatelessUserService_a940aa04.java <BR>Remote接口在Server端的实现，当然，它也implements UserService。并且，它负责调用UserServiceBean——</P>
<P>也就是我们所写的Bean实现类——里面的business method。 </P>
<P>那么，各个类之间的调用关系到底是怎么样的呢？简单的说，就是两次RMI循环。 <BR>&nbsp;<BR>&nbsp;&nbsp;&nbsp; <BR>&nbsp;&nbsp; <BR>&nbsp;<BR>第一个RMI循环&nbsp;&nbsp;&nbsp; <BR>先来看看Client端的程序是怎么写的： </P>
<P>代码: </P>
<P>try { <BR>&nbsp;&nbsp;&nbsp; InitialContext ctx = new InitialContext(); </P>
<P>&nbsp;&nbsp;&nbsp; //第一步 <BR>&nbsp;&nbsp;&nbsp; UserServiceHome home = <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (UserServiceHome) PortableRemoteObject.narrow( <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ctx.lookup(JNDIString), <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; UserServiceHome.class); </P>
<P>&nbsp;&nbsp;&nbsp; //home: _UserServiceHome_Stub <BR>&nbsp;&nbsp;&nbsp; System.out.println(home.toString()); </P>
<P>&nbsp;&nbsp;&nbsp; //第二步 <BR>&nbsp;&nbsp;&nbsp; UserService object = home.create(); </P>
<P>&nbsp;&nbsp;&nbsp; //ojbect: _UserService_Stub <BR>&nbsp;&nbsp;&nbsp; System.out.println(object.toString()); </P>
<P>&nbsp;&nbsp;&nbsp; //第三步 <BR>&nbsp;&nbsp;&nbsp; int userId = 1; <BR>&nbsp;&nbsp;&nbsp; UserInfo ui = object.getUserInfo(userId); <BR>} <BR>&nbsp;</P>
<P><BR>在第一步之后，我们得到了一个UserServiceHome(interface)定义的对象home，那么，home到底是哪个class的</P>
<P>instance呢？用debug看一下，知道了home原来就是_UserServiceHome_Stub的实例。 </P>
<P>从第二步开始，就是我们的关注所在，虽然只有简单的一行代码， <BR>UserService object = home.create(); <BR>但是他背后的系统是怎么运做的呢？我们进入代码来看吧： </P>
<P>1. 调用home.create() <BR>代码: </P>
<P>UserServiceHome home; <BR>UserService obj = home.create(); <BR>&nbsp;</P>
<P><BR>2. 实际是调用_UserServiceHome_Stub.create()，在这个方法里面，Stub向Skeleton发送了一个create的字串</P>
<P>： <BR>代码: </P>
<P>org.omg.CORBA.portable.OutputStream out = _request("create", true); <BR>in = (org.omg.CORBA_2_3.portable.InputStream)_invoke(out); <BR>&nbsp;</P>
<P><BR>3. Server端的Skeleton接收Stub发来的request，并调用相应的方法： <BR>代码: </P>
<P>_EJSRemoteStatelessUserServiceHome_a940aa04_Tie._invoke() { <BR>&nbsp;&nbsp;&nbsp; ...... <BR>&nbsp;&nbsp;&nbsp; switch (method.length()) { <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; case 6: <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (method.equals("create")) { <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return create(in, reply); <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ...... <BR>&nbsp;&nbsp;&nbsp; } <BR>} <BR>&nbsp;</P>
<P><BR>代码: </P>
<P>_EJSRemoteStatelessUserServiceHome_a940aa04_Tie.create() { <BR>&nbsp;&nbsp;&nbsp; EJSRemoteStatelessUserServiceHome_a940aa04 target = null; <BR>&nbsp;&nbsp;&nbsp; result = target.create(); <BR>&nbsp;&nbsp;&nbsp; org.omg.CORBA.portable.OutputStream out = reply.createReply(); <BR>&nbsp;&nbsp;&nbsp; Util.writeRemoteObject(out,result); <BR>&nbsp;&nbsp;&nbsp; return out; <BR>} <BR>&nbsp;</P>
<P><BR>4. Skeleton调用的是UserServiceHome的Server端实现类的create方法 <BR>代码: </P>
<P>EJSRemoteStatelessUserServiceHome_a940aa04.create() { <BR>&nbsp;&nbsp;&nbsp; UserService _EJS_result; <BR>&nbsp;&nbsp;&nbsp; _EJS_result = EJSStatelessUserServiceHomeBean_a940aa04.create(); <BR>} <BR>&nbsp;</P>
<P><BR>5. #4又调用EJSStatelessUserServiceHomeBean_a940aa04.create() <BR>代码: </P>
<P>&nbsp;&nbsp;&nbsp; UserService result = super.createWrapper(new BeanId(this, null)); <BR>&nbsp;</P>
<P><BR>至此，我们终于结束了第一个RMI循环，并得到了Remote接口UserService的Stub类_UserService_Stub，就是#5</P>
<P>里面的result。 </P>
<P>这里有一个问题，为什么#4不直接create _UserService_Stub，而又转了一道#5的手呢？因为#4 extends from </P>
<P>EJSWrapper，它没有能力create Stub，因此必须借助#5，which extends from EJSHome，这样才可以生成一个</P>
<P>Stub。如果不是为了生成这个Stub，应该可以不走#5这一步。 <BR>&nbsp;&nbsp; <BR>&nbsp;&nbsp;&nbsp; <BR>&nbsp;<BR>第二个RMI循环&nbsp;&nbsp;&nbsp; <BR>OK, now we got the object which is instanceOf _UserService_Stub, and implements UserService </P>
<P>现在我们的Client端走到第三步了： <BR>UserInfo ui = object.getUserInfo(userId); </P>
<P>继续看代码，开始第二个RMI循环： </P>
<P>1. 调用object.getUserInfo() <BR>代码: </P>
<P>UserService object; <BR>object.getUserInfo(userId); <BR>&nbsp;</P>
<P><BR>2. 实际是调用_UserService_Stub.getUserInfo(int </P>
<P>arg0)，在这个方法里面，Stub向Skeleton发送了一个getUserInfo的字串和arg0这个参数： </P>
<P>代码: </P>
<P>org.omg.CORBA.portable.OutputStream out = _request("getUserInfo", true); <BR>out.write_long(arg0); <BR>in = (org.omg.CORBA_2_3.portable.InputStream)_invoke(out); <BR>&nbsp;</P>
<P><BR>3. Server端的Skeleton接收Stub发来的request，并调用相应的方法： <BR>代码: </P>
<P>_EJSRemoteStatelessUserService_a940aa04_Tie._invoke() { <BR>&nbsp;&nbsp;&nbsp; switch (method.charAt(5)) <BR>&nbsp;&nbsp;&nbsp; { <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; case 83: <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (method.equals("getUserInfo")) { <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return getUserInfo(in, reply); <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ...... <BR>&nbsp;&nbsp;&nbsp; } <BR>} </P>
<P>_EJSRemoteStatelessUserService_a940aa04_Tie.getUserInfo() { <BR>&nbsp;&nbsp;&nbsp; EJSRemoteStatelessUserService_a940aa04 target = null; <BR>&nbsp;&nbsp;&nbsp; int arg0 = in.read_long(); <BR>&nbsp;&nbsp;&nbsp; UserDTO result = target.getUserInfo(arg0); <BR>&nbsp;&nbsp;&nbsp; org.omg.CORBA_2_3.portable.OutputStream out = reply.createReply(); <BR>&nbsp;&nbsp;&nbsp; out.write_value(result,UserDTO.class); <BR>&nbsp;&nbsp;&nbsp; return out; <BR>} <BR>&nbsp;</P>
<P><BR>4. Skeleton调用的是UserService的Server端实现类的getUserInfo方法 <BR>代码: </P>
<P>EJSRemoteStatelessUserService_a940aa04.getUserInfo() { <BR>&nbsp;&nbsp;&nbsp; UserServiceBean _EJS_beanRef = container.preInvoke(this, 0, _EJS_s); <BR>&nbsp;&nbsp;&nbsp; _EJS_result = _EJS_beanRef.getUserInfo(id); <BR>} <BR>&nbsp;</P>
<P><BR>最后的最后，#4终于调用了我们写的UserServiceBean里的getUserInfo方法，这才是我们真正想要去做的事情</P>
<P>。 </P>
<P>至此，第二个RMI循环也终于结束了。 <BR>&nbsp;&nbsp; <BR>&nbsp;&nbsp;&nbsp; <BR>&nbsp;<BR>调用流程图&nbsp;&nbsp;&nbsp; <BR>回顾一下上面的分析，可以很清晰的看到两次RMI循环的过程，下图(见链接)描述了整个流程： </P>
<P><A href="http://www.pbase.com/image/27229257"><FONT color=#000080>http://www.pbase.com/image/27229257</FONT></A> </P>
<P>黄色的1，6，10是程序员要写的，其余是系统生成的。 </P>
<P>#1是Home interface, #2和#4都implements 了它。 <BR>#6是Remote interface, #7和#9都implements 了它。 <BR>#10是Bean实现。 <BR>&nbsp;<BR>&nbsp;<BR>3：weblogic实现<BR>一个远程对象至少要包括4个class文件：远程对象；远程对象的接口；实现远程接口的对象的stub；对象的ske</P>
<P>leton这4个class文件。</P>
<P>在EJB中则至少要包括10个class：</P>
<P>Bean类，特定App Server的Bean实现类</P>
<P>Bean的remote接口，特定App Server的remote接口实现类，特定App </P>
<P>Server的remote接口的实现类的stub类和skeleton类</P>
<P>Bean的home接口，特定App Server的home接口实现类，特定App </P>
<P>Server的home接口的实现类的stub类和skeleton类</P>
<P>和RMI不同的是，EJB中这10个class真正需要用户编写的只有3个，分别是Bean类和它的remote接口，home接口</P>
<P>，至于其它的7个class到底是怎么生成，被打包在什么地方，或者是否需要更多的类文件，会根据不同的App </P>
<P>Server表现出比较大的差异，不能一概而论。</P>
<P>拿Weblogic的来说吧，Weblogic的Bean实现类，以及两个接口的Weblogic的实现类是在ejbc的时候被打包到EJB</P>
<P>的jar包里面的，这3个class文件可以看到。而home接口和remote接口的Weblogic的实现类的stub类和skeleton</P>
<P>类是在EJB被部署到Weblogic的时候，由Weblogic动态生成stub类和Skeleton类的字节码，因此看不到这4个类</P>
<P>文件。</P>
<P>对于一次客户端远程调用EJB，要经过两个远程对象的多次RMI循环。首先是通过JNDI查找Home接口，获得Home</P>
<P>接口的实现类，这个过程其实相当复杂，首先是找到Home接口的Weblogic实现类，然后创建一个Home接口的Web</P>
<P>logic实现类的stub类的对象实例，将它序列化传送给客户端（注意stub类的实例是在第1次RMI循环中，由服务</P>
<P>器动态发送给客户端的，因此不需要客户端保存Home接口的Weblogic实现类的stub类），最后客户端获得该stu</P>
<P>b类的对象实例（普通的RMI需要在客户端保存stub类，而EJB不需要，因为服务器会把stub类的对象实例发送给</P>
<P>客户端）。</P>
<P>客户端拿到服务器给它的Home接口的Weblogic实现类的stub类对象实例以后，调用stub类的create方法，(在代</P>
<P>码上就是home.create()，但是后台要做很多事情),于是经过第2次RMI循环，在服务器端，Home接口的Weblogic</P>
<P>实现类的skeleton类收到stub类的调用信息后，由它再去调用Home接口的Weblogic实现类的create方法。</P>
<P>在服务端，Home接口的Weblogic实现类的create方法再去调用Bean类的Weblogic实现类的ejbCreate方法，在服</P>
<P>务端创建或者分配一个EJB实例，然后将这个EJB实例的远程接口的Weblogic实现类的stub类对象实例序列化发</P>
<P>送给客户端。</P>
<P>客户端收到remote接口的Weblogic实现类的stub类的对象实例，对该对象实例的方法调用（在客户端代码中实</P>
<P>际上就是对remote接口的调用），将传送给服务器端remote接口的Weblogic实现类的skeleton类对象，而skele</P>
<P>ton类对象再调用相应的remote接口的Weblogic实现类，然后remote接口的Weblogic实现类再去调用Bean类的We</P>
<P>blogic实现类，如此就完成一次EJB对象的远程调用。</P>
<P>看了一遍帖子，感觉还是没有说太清楚，既然写了帖子，就想彻底把它说清楚。</P>
<P>先拿普通RMI来说，有4个class，分别是远程对象，对象的接口，对象的stub类和skeleton类。而对象本身和对</P>
<P>象的stub类同时都实现了接口类。而我们在客户端代码调用远程对象的时候，虽然在代码中操纵接口，实质上</P>
<P>是在操纵stub类，例如：</P>
<P>接口类：Hello</P>
<P>远程对象：Hello_Server </P>
<P>stub类：Hello_Stub</P>
<P>skeleton类：Hello_Skeleton</P>
<P>客户端代码要这样写：</P>
<P>Hello h = new Hello_Stub();<BR>h.getString();</P>
<P>我们不会这样写：</P>
<P>Hello_Stub h = new Hello_Stub();<BR>h.getString();</P>
<P>因为使用接口适用性更广，就算更换了接口实现类，也不需要更改代码。因此客户端需要Hello.class和Hello_</P>
<P>Stub.class这两个文件。但是对于EJB来说，就不需要Hello_Stub.class，因为服务器会发送给它，但是Hello.</P>
<P>class文件客户端是省不了的，必须有。表面上我们的客户端代码在操纵Hello，但别忘记了Hello只是一个接口</P>
<P>，抽象的，实质上是在操纵Hello_Stub。</P>
<P>拿Weblogic上的EJB举例子，10个class分别是：</P>
<P>Bean类：HelloBean （用户编写）<BR>Bean类的Weblogic实现类：HelloBean_Impl （EJBC生成）<BR>Home接口：HelloHome （用户编写）<BR>Home接口的Weblogic实现类 ((Hello Bean))_HomeImpl（EJBC生成）<BR>Home接口的Weblogic实现类的stub类 ((Hello Bean))_HomeImpl_WLStub（部署的时候动态生成字节码）<BR>Home接口的Weblogic实现类的skeleton类 ((Hello Bean))_HomeImpl_WLSkeleton（部署的时候动态生成字节码</P>
<P>）<BR>Remote接口： Hello （用户编写）<BR>Remote接口的Weblogic实现类 ((Hello Bean))_EOImpl（EJBC生成）<BR>Remote接口的Weblogic实现类的stub类 ((Hello Bean))_EOImpl_WLStub（部署的时候动态生成字节码）<BR>Remote接口的Weblogic实现类的skeleton类 ((Hello Bean))_EOImpl_WLSkeleton（部署的时候动态生成字节码</P>
<P>）</P>
<P>客户端只需要Hello.class和HelloHome.class这两个文件。</P>
<P>((Hello Home)) home = (Home) ((Portable Remote Object)).narrow(ctx.lookup("Hello"), ((Hello </P>
<P>Home)).class);</P>
<P>这一行代码是从JNDI获得Home接口，但是请记住！接口是抽象的，那么home这个对象到底是什么类的对象实例</P>
<P>呢？很简单，用toString()输出看一下就明白了，下面一行是输出结果：</P>
<P>((Hello Bean))_HomeImpl_WLStub@18c458</P>
<P>这表明home这个通过从服务器的JNDI树上查找获得的对象实际上是HelloBean_HomeImpl_WLStub类的一个实例。</P>
<P>接下来客户端代码：</P>
<P>Hello h = home.create()</P>
<P>同样Hello只是一个抽象的接口，那么h对象是什么东西呢？打印一下：</P>
<P>((Hello Bean))_EOImpl_WLStub@8fa0d1</P>
<P>原来是HelloBean_EOImpl_WLStub的一个对象实例。</P>
<P>用这个例子来简述一遍EJB调用过程：</P>
<P>首先客户端JNDI查询，服务端JNDI树上Hello这个名字实际上绑定的对象是HelloBean_HomeImpl_WLStub，所以</P>
<P>服务端将创建HelloBean_HomeImpl_WLStub的一个对象实例，序列化返回给客户端。</P>
<P>于是客户端得到home对象，表面上是得到HelloHome接口的实例，实际上是进行了一次远程调用得到了HelloBea</P>
<P>n_HomeImpl_WLStub类的对象实例，别忘记了HelloBean_HomeImpl_WLStub也实现了HelloHome接口。</P>
<P>然后home.create()实质上就是HelloBean_HomeImpl_WLStub.create()，该方法将发送信息给HelloBean_HomeIm</P>
<P>pl_WLSkeleton，而HelloBean_HomeImpl_WLSkeleton接受到信息后，再去调用HelloBean_HomeImpl的create方</P>
<P>法，至此完成第1次完整的RMI循环。</P>
<P>注意在这次RMI循环过程中，远程对象是HelloBean_HomeImpl，远程对象的接口是HelloHome，对象的stub是Hel</P>
<P>loBean_HomeImpl_WLStub，对象的skeleton是HelloBean_HomeImpl_WLSkeleton。</P>
<P>然后HelloBean_HomeImpl再去调用HelloBean_Impl的ejbCreate方法，而HelloBean_Impl的ejbCreate方法将负</P>
<P>责创建或者分配一个Bean实例，并且创建一个HelloBean_EOImpl_WLStub的对象实例。</P>
<P>这一步比较有趣的是，在前一步RMI循环中，远程对象HelloBean_HomeImpl在客户端有一个代理类HelloBean_Ho</P>
<P>meImpl_WLStub，但在这一步，HelloBean_HomeImpl自己却充当了HelloBean_Impl的代理类，只不过HelloBean_</P>
<P>HomeImpl不在客户端，而是在服务端，因此不进行RMI。</P>
<P>然后HelloBean_EOImpl_WLStub的对象实例序列化返回给客户端，这一步也很有趣，上次RMI过程，主角是Hello</P>
<P>Bean_HomeImpl和它的代理类HelloBean_HomeImpl_WLStub，但这这一次换成了HelloBean_EOImpl和它的代理类H</P>
<P>elloBean_EOImpl_WLStub来玩了。</P>
<P>Hello h = home.create();h.helloWorld();</P>
<P>假设Hello接口有一个helloWorld远程方法，那么表面上是在调用Hello接口的helloWorld方法，实际上是在调</P>
<P>用HelloBean_EOImpl_WLStub的helloWorld方法。</P>
<P>然后HelloBean_EOImpl_WLStub的helloWorld方法将发送信息给服务器上的HelloBean_EOImpl_WLSkeleton，而H</P>
<P>elloBean_EOImpl_WLSkeleton收到信息以后，再去调用HelloBean_EOImpl的helloWorld方法。至此，完成第2次</P>
<P>完整的RMI循环过程。</P>
<P>在刚才HelloBean_EOImpl是作为远程对象被调用的，它的代理类是HelloBean_EOImpl_WLStub，但现在HelloBea</P>
<P>n_EOImpl要作为HelloBean_Impl的代理类了。现在HelloBean_EOImpl去调用HelloBean_Impl的helloWorld方法</P>
<P>。注意！HelloBean_Impl继承了HelloBean，而HelloBean中的helloWorld方法是我们亲自编写的代码，现在终</P>
<P>于调用到了我们编写的代码了！</P>
<P>至此，一次EJB调用过程终于完成。在整个过程中，服务端主要要调用的类是HelloBean_Impl， Hello </P>
<P>Bean?_HomeImpl，HelloBean_HomeImpl_WLSkeleton，HelloBean_EOImpl，HelloBean_EOImpl_WLSkeleton。客</P>
<P>户端主要调用的类是HelloBean_HomeImpl_WLStub，HelloBean_EOImpl_WLStub，这两个类在客户端代码中并不</P>
<P>会直接出现，出现在代码中的类是他们的接口HelloHome和Hello，因此客户端需要这两个接口文件，而Stub是</P>
<P>服务器传送给他们的。</P>
<P>4 理解体会<BR>简单讲，就是为了适应分布式开发的需要。 </P>
<P>首先，回到我最后给出的流程图。 <BR><A href="http://www.pbase.com/nobo123/image/27229257"><FONT color=#000080>http://www.pbase.com/nobo123/image/27229257</FONT></A></P>
<P>Client端最原始的冲动，肯定是能直接调用#10.UserServiceBean就爽了。那么第一个问题来了， <BR>Client和Server不在一个JVM里。 </P>
<P>这好办，我们不是有RMI吗，好，这个问题就这么解决了： <BR>1. UserServiceBeanInterface.getUserInfo() <BR>2. UserServiceBeanStub <BR>3. UserServiceBeanSkeleton <BR>4. UserServiceBean </P>
<P>用着用着，第二个问题来了， <BR>UserServiceBean只有人用，没人管理，transaction logic, security logic, bean instance pooling logic</P>
<P>这些不得不考虑的问题浮出水面了。 </P>
<P>OK，我们想到用一个delegate，EJBObject，来进行所有这些logic的管理。client和EJBObject打交道，EJBObj</P>
<P>ect调用UserServiceBean。 </P>
<P>注意，这个EJBObject也是一个Interface，#6.UserService这个interface正是从它extends而来。并且EJBObje</P>
<P>ct所管理的这些logic，正是AppServer的一部分。 </P>
<P>现在的流程变为了： <BR>EJBObject <BR>1. UserService.getUserInfo() <BR>2. UserServiceStub <BR>3. UserServiceSkeleton <BR>4. UserServiceImp <BR>5. UserServiceBean </P>
<P>这已经和整幅图里的#6, #7, #8, #9, #10一一对应了。 </P>
<P>现在能满足我们的需求了吗？不，第三个问题又来了： <BR>既然是分布式开发，那么我当然没理由只用一个Specified Server，我可能需要用到好几个不同的Server，而</P>
<P>且EJBObject也需要管理呀 </P>
<P>OK，为了适应你的需要，我们还得加再一个HomeObject，首先它来决定用哪个Server(当然，是由你用JNDI </P>
<P>String设定的)，其次，它来管理EJBObject。 </P>
<P>注意，这个EJBHome也是一个Interface，#1.UserServiceHome这个interface正是从它extends而来。并且EJBHo</P>
<P>me管理EJBObject的logic，也是AppServer的一部分。 </P>
<P>现在的调用次序是 <BR>1. EJBHome.create() <BR>2. EJBHomeStub <BR>3. EJBHomeSkeleton <BR>4. EJBHomeImp(EJSWrapper) <BR>5. EJSHome </P>
<P>得到EJBObject </P>
<P>6. UserService.getUserInfo() <BR>7. UserServiceStub <BR>8. UserServiceSkeleton <BR>9. UserServiceImp <BR>10. UserServiceBean </P>
<P>现在已经完全和流程图的调用顺序一致了。 </P>
<P>综上所述，EJB的调用确实很麻烦，但是搞的这么麻烦，确实是有搞的麻烦的道理，实在是不得不为也。 </P><img src ="http://www.blogjava.net/jackybu/aggbug/1212.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jackybu/" target="_blank">辰</a> 2005-02-15 11:34 <a href="http://www.blogjava.net/jackybu/articles/1212.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>JSP2.0标签学习笔记</title><link>http://www.blogjava.net/jackybu/articles/1211.html</link><dc:creator>辰</dc:creator><author>辰</author><pubDate>Tue, 15 Feb 2005 03:33:00 GMT</pubDate><guid>http://www.blogjava.net/jackybu/articles/1211.html</guid><wfw:comment>http://www.blogjava.net/jackybu/comments/1211.html</wfw:comment><comments>http://www.blogjava.net/jackybu/articles/1211.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jackybu/comments/commentRss/1211.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jackybu/services/trackbacks/1211.html</trackback:ping><description><![CDATA[<H2 style="MARGIN: 9pt 0cm; TEXT-INDENT: 0cm"><SPAN lang=EN-US><FONT face=Arial>1. </FONT></SPAN><SPAN style="FONT-FAMILY: 黑体; mso-ascii-font-family: Arial">说明</SPAN></H2>
<P class=a2 style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 24pt"><SPAN style="FONT-FAMILY: 华文楷体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">本文档是学习</SPAN><SPAN lang=EN-US>tomcat</SPAN><SPAN style="FONT-FAMILY: 华文楷体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">中例子的笔记，并没有参考相应的说明文档，因此不能保证本文观点的正确性。如果有不对之处，不妨</SPAN><SPAN lang=EN-US>email</SPAN><SPAN style="FONT-FAMILY: 华文楷体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">至</SPAN><SPAN lang=EN-US>8280338@tzenet.com</SPAN><SPAN style="FONT-FAMILY: 华文楷体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">，大家共同进步。</SPAN></P>
<H2 style="MARGIN: 9pt 0cm; TEXT-INDENT: 0cm"><FONT face=Arial><SPAN lang=EN-US>2. </SPAN><SPAN lang=EN-US>JSP2.0</SPAN></FONT><SPAN style="FONT-FAMILY: 黑体; mso-ascii-font-family: Arial">标签使用方法</SPAN></H2>
<P class=a2 style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 24pt"><SPAN lang=EN-US>JSP2.0</SPAN><SPAN style="FONT-FAMILY: 华文楷体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">中标签的使用由多个部分组成：</SPAN></P>
<P class=9 style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US style="FONT-FAMILY: 楷体_GB2312; mso-ascii-font-family: 'Times New Roman'">（1） </SPAN><SPAN lang=EN-US>WEB_INF/web.xml</SPAN><SPAN style="FONT-FAMILY: 楷体_GB2312; mso-ascii-font-family: 'Times New Roman'">中添加标签引用</SPAN></P>
<P class=9 style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US style="FONT-FAMILY: 楷体_GB2312; mso-ascii-font-family: 'Times New Roman'">（2） </SPAN><SPAN style="FONT-FAMILY: 楷体_GB2312; mso-ascii-font-family: 'Times New Roman'">标签的实现，可能是</SPAN><SPAN lang=EN-US>class</SPAN><SPAN style="FONT-FAMILY: 楷体_GB2312; mso-ascii-font-family: 'Times New Roman'">也可能是</SPAN><SPAN lang=EN-US>web templet</SPAN></P>
<P class=9 style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US style="FONT-FAMILY: 楷体_GB2312; mso-ascii-font-family: 'Times New Roman'">（3） </SPAN><SPAN style="FONT-FAMILY: 楷体_GB2312; mso-ascii-font-family: 'Times New Roman'">在</SPAN><SPAN lang=EN-US>jsp</SPAN><SPAN style="FONT-FAMILY: 楷体_GB2312; mso-ascii-font-family: 'Times New Roman'">文件中添加引用</SPAN></P>
<P class=a2 style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 24pt"><SPAN style="FONT-FAMILY: 华文楷体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">在实际使用中，分析</SPAN><SPAN lang=EN-US>jsp2.0</SPAN><SPAN style="FONT-FAMILY: 华文楷体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">标签可以先从</SPAN><SPAN lang=EN-US>jsp</SPAN><SPAN style="FONT-FAMILY: 华文楷体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">文件入手，然后再分析</SPAN><SPAN lang=EN-US>web.xml</SPAN><SPAN style="FONT-FAMILY: 华文楷体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">及相应的标签库文件。</SPAN></P>
<H3 style="MARGIN: 9pt 0cm; TEXT-INDENT: 0cm"><FONT size=5><FONT face=Arial><SPAN lang=EN-US>2.2</SPAN><SPAN lang=EN-US> </SPAN></FONT><SPAN style="FONT-FAMILY: 黑体; mso-ascii-font-family: Arial">基本标签的使用方法</SPAN></FONT></H3>
<H4 style="MARGIN: 9pt 0cm; TEXT-INDENT: 0cm"><FONT size=5><FONT face=Arial><SPAN lang=EN-US>2.2.1</SPAN><SPAN lang=EN-US> jsp</SPAN></FONT><SPAN style="FONT-FAMILY: 黑体; mso-ascii-font-family: Arial">文件中的标签引用及使用方法</SPAN></FONT></H4>
<P class=a2 style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 24pt"><SPAN style="FONT-FAMILY: 华文楷体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">以下是一个简单的</SPAN><SPAN lang=EN-US>jsp</SPAN><SPAN style="FONT-FAMILY: 华文楷体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">文件：</SPAN></P>
<P class=a2 style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 0cm; mso-char-indent-count: 0; mso-char-indent-size: 0cm"><SPAN lang=EN-US style="FONT-SIZE: 10pt; FONT-FAMILY: 黑体; mso-hansi-font-family: 'Courier New'; mso-font-kerning: 0pt; mso-bidi-font-family: 'Courier New'">&lt;%@ taglib prefix="mytag" uri="/WEB-INF/jsp2/jsp2-example-taglib.tld" %&gt;<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /><o:p></o:p></SPAN></P>
<P class=a2 style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 0cm; mso-char-indent-count: 0; mso-char-indent-size: 0cm"><SPAN lang=EN-US style="FONT-SIZE: 10pt; FONT-FAMILY: 黑体; mso-hansi-font-family: 'Courier New'; mso-font-kerning: 0pt; mso-bidi-font-family: 'Courier New'">&lt;html&gt; &lt;body&gt; &lt;mytag:helloWorld/&gt; &lt;/body&gt;&lt;/html&gt;<o:p></o:p></SPAN></P>
<P class=a2 style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 24pt"><SPAN style="FONT-FAMILY: 华文楷体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">说明：</SPAN></P>
<P class=9 style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US style="FONT-FAMILY: 楷体_GB2312; mso-ascii-font-family: 'Times New Roman'">（1） </SPAN><SPAN style="FONT-FAMILY: 楷体_GB2312; mso-ascii-font-family: 'Times New Roman'">首先以</SPAN><SPAN lang=EN-US>&lt;%@ taglib prefix="mytag" uri="…" %&gt;</SPAN><SPAN style="FONT-FAMILY: 楷体_GB2312; mso-ascii-font-family: 'Times New Roman'">说明标签前缀及该前缀引用的标签所在路径，在这个例子中</SPAN><SPAN lang=EN-US>uri</SPAN><SPAN style="FONT-FAMILY: 楷体_GB2312; mso-ascii-font-family: 'Times New Roman'">值是一个相对路径（本地路径），即当前项目根目录下</SPAN><SPAN lang=EN-US>WEB-INF/ jsp2/ jsp2-example-taglib.tld</SPAN><SPAN style="FONT-FAMILY: 楷体_GB2312; mso-ascii-font-family: 'Times New Roman'">。如果使用的是本地路径就不需要在</SPAN><SPAN lang=EN-US>web.xml</SPAN><SPAN style="FONT-FAMILY: 楷体_GB2312; mso-ascii-font-family: 'Times New Roman'">中配置路径映射了；</SPAN></P>
<P class=9 style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US style="FONT-FAMILY: 楷体_GB2312; mso-ascii-font-family: 'Times New Roman'">（2） </SPAN><SPAN style="FONT-FAMILY: 楷体_GB2312; mso-ascii-font-family: 'Times New Roman'">指定了标签前缀后，在</SPAN><SPAN lang=EN-US>jsp</SPAN><SPAN style="FONT-FAMILY: 楷体_GB2312; mso-ascii-font-family: 'Times New Roman'">页面的</SPAN><SPAN lang=EN-US>body</SPAN><SPAN style="FONT-FAMILY: 楷体_GB2312; mso-ascii-font-family: 'Times New Roman'">内就可以使用这个前缀来引用标签库中的指定标签了，如</SPAN><SPAN lang=EN-US>&lt;mytag:helloWorld/&gt;</SPAN><SPAN style="FONT-FAMILY: 楷体_GB2312; mso-ascii-font-family: 'Times New Roman'">，就是引用</SPAN><SPAN lang=EN-US>mytag</SPAN><SPAN style="FONT-FAMILY: 楷体_GB2312; mso-ascii-font-family: 'Times New Roman'">所指定的标签库中的</SPAN><SPAN lang=EN-US>helloWorld</SPAN><SPAN style="FONT-FAMILY: 楷体_GB2312; mso-ascii-font-family: 'Times New Roman'">标签。</SPAN></P>
<H4 style="MARGIN: 9pt 0cm; TEXT-INDENT: 0cm"><FONT size=5><FONT face=Arial><SPAN lang=EN-US>2.2.2</SPAN><SPAN lang=EN-US> web.xml</SPAN></FONT><SPAN style="FONT-FAMILY: 黑体; mso-ascii-font-family: Arial">中的配置</SPAN></FONT></H4>
<P class=a2 style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 24pt"><SPAN style="FONT-FAMILY: 华文楷体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">如果在上述例子中使用的不是本地路径，那么就需要在</SPAN><SPAN lang=EN-US>web.xml</SPAN><SPAN style="FONT-FAMILY: 华文楷体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">中配置路径转换，如使用：</SPAN><SPAN lang=EN-US>&lt;%@ taglib prefix="mytag" uri=" http://mytaglib/myTestTags1 " %&gt;</SPAN><SPAN style="FONT-FAMILY: 华文楷体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">来引用标签库，那么就需要在</SPAN><SPAN lang=EN-US>web.xml</SPAN><SPAN style="FONT-FAMILY: 华文楷体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">文件的</SPAN><SPAN lang=EN-US>jsp-config</SPAN><SPAN style="FONT-FAMILY: 华文楷体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">节点中添加如下配置：</SPAN></P>
<P class=a2 style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 0cm; mso-char-indent-count: 0; mso-char-indent-size: 0cm"><SPAN lang=EN-US style="FONT-SIZE: 10pt; FONT-FAMILY: 黑体; mso-hansi-font-family: 'Courier New'; mso-font-kerning: 0pt; mso-bidi-font-family: 'Courier New'">&lt;taglib&gt;<o:p></o:p></SPAN></P>
<P class=a2 style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 0cm; mso-char-indent-count: 0; mso-char-indent-size: 0cm"><SPAN lang=EN-US style="FONT-SIZE: 10pt; FONT-FAMILY: 黑体; mso-hansi-font-family: 'Courier New'; mso-font-kerning: 0pt; mso-bidi-font-family: 'Courier New'"><SPAN style="mso-tab-count: 1">&nbsp;&nbsp;&nbsp; </SPAN><SPAN style="mso-spacerun: yes">&nbsp;</SPAN>&lt;taglib-uri&gt;http://mytaglib/myTestTags1&lt;/taglib-uri&gt;<o:p></o:p></SPAN></P>
<P class=a2 style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 0cm; mso-char-indent-count: 0; mso-char-indent-size: 0cm"><SPAN lang=EN-US style="FONT-SIZE: 10pt; FONT-FAMILY: 黑体; mso-hansi-font-family: 'Courier New'; mso-font-kerning: 0pt; mso-bidi-font-family: 'Courier New'"><SPAN style="mso-tab-count: 1">&nbsp;&nbsp;&nbsp; </SPAN><SPAN style="mso-spacerun: yes">&nbsp;</SPAN>&lt;taglib-location&gt;/WEB-INF/jsp2/jsp2-example-taglib.tld &lt;/taglib-location&gt;</SPAN></P>
<P class=a2 style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 0cm; mso-char-indent-count: 0; mso-char-indent-size: 0cm"><SPAN lang=EN-US style="FONT-SIZE: 10pt; FONT-FAMILY: 黑体; mso-hansi-font-family: 'Courier New'; mso-font-kerning: 0pt; mso-bidi-font-family: 'Courier New'">&lt;/taglib&gt;<o:p></o:p></SPAN></P>
<P class=a2 style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 24pt"><SPAN lang=EN-US><SPAN style="mso-spacerun: yes">&nbsp;</SPAN>JSP</SPAN><SPAN style="FONT-FAMILY: 华文楷体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">解释器会将</SPAN><SPAN lang=EN-US><A href="http://mytaglib/myTestTags1根据web.xml">http://mytaglib/myTestTags1<SPAN style="FONT-FAMILY: 华文楷体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">根据</SPAN>web.xml</A></SPAN><SPAN style="FONT-FAMILY: 华文楷体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">中的配置转化为本地路径。当然</SPAN><SPAN lang=EN-US>&lt;taglib-uri&gt;</SPAN><SPAN style="FONT-FAMILY: 华文楷体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">中文本可以是任何值，但不能和其它的配置冲突，所以在规划时最好加上前缀，如：</SPAN><SPAN lang=EN-US><A href="http://mytaglib等/">http://mytaglib<SPAN style="FONT-FAMILY: 华文楷体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">等</SPAN></A></SPAN><SPAN style="FONT-FAMILY: 华文楷体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">。</SPAN></P>
<H4 style="MARGIN: 9pt 0cm; TEXT-INDENT: 0cm"><FONT size=5><FONT face=Arial><SPAN lang=EN-US>2.2.3</SPAN><SPAN lang=EN-US> </SPAN></FONT><SPAN style="FONT-FAMILY: 黑体; mso-ascii-font-family: Arial">标签库中的配置</SPAN></FONT></H4>
<P class=a2 style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 24pt"><SPAN style="FONT-FAMILY: 华文楷体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">在标签库中的配置实际上就是配置对实现类的引用，</SPAN><SPAN lang=EN-US>JSP</SPAN><SPAN style="FONT-FAMILY: 华文楷体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">解释器会根据</SPAN><SPAN lang=EN-US>jsp</SPAN><SPAN style="FONT-FAMILY: 华文楷体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">文件中对标签的引用，在标签库中找到相应的标签，然后再根据标签中的定义调用具体的实现类，本例中在</SPAN><SPAN lang=EN-US>jsp</SPAN><SPAN style="FONT-FAMILY: 华文楷体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">文件中对标签的引用：</SPAN><SPAN lang=EN-US>&lt;mytag:helloWorld/&gt;</SPAN><SPAN style="FONT-FAMILY: 华文楷体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">，即引用了</SPAN><SPAN lang=EN-US>helloWorld</SPAN><SPAN style="FONT-FAMILY: 华文楷体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">这个标签，这个标签在标签库中的定义如下：</SPAN></P><PRE><SPAN lang=EN-US><FONT face=黑体 size=2>&lt;tag&gt;</FONT></SPAN></PRE><PRE style="tab-stops: 21.75pt 91.6pt 137.4pt 183.2pt 229.0pt 274.8pt 320.6pt 366.4pt 412.2pt 458.0pt 503.8pt 549.6pt 595.4pt 641.2pt 687.0pt 732.8pt"><SPAN lang=EN-US><FONT size=2><FONT face=黑体><SPAN style="mso-tab-count: 1">&nbsp;&nbsp;&nbsp; </SPAN>&lt;description&gt;Outputs Hello, World&lt;/description&gt;</FONT></FONT></SPAN></PRE><PRE><SPAN lang=EN-US><FONT size=2><FONT face=黑体><SPAN style="mso-spacerun: yes">&nbsp;&nbsp; </SPAN><SPAN style="mso-spacerun: yes">&nbsp;</SPAN>&lt;name&gt;helloWorld&lt;/name&gt;</FONT></FONT></SPAN></PRE><PRE style="tab-stops: 21.75pt 91.6pt 137.4pt 183.2pt 229.0pt 274.8pt 320.6pt 366.4pt 412.2pt 458.0pt 503.8pt 549.6pt 595.4pt 641.2pt 687.0pt 732.8pt"><SPAN lang=EN-US><FONT size=2><FONT face=黑体><SPAN style="mso-tab-count: 1">&nbsp;&nbsp;&nbsp; </SPAN>&lt;tag-class&gt;jsp2.examples.simpletag.HelloWorldSimpleTag&lt;/tag-class&gt;</FONT></FONT></SPAN></PRE><PRE style="tab-stops: 21.75pt 91.6pt 137.4pt 183.2pt 229.0pt 274.8pt 320.6pt 366.4pt 412.2pt 458.0pt 503.8pt 549.6pt 595.4pt 641.2pt 687.0pt 732.8pt"><SPAN lang=EN-US><FONT size=2><FONT face=黑体><SPAN style="mso-tab-count: 1">&nbsp;&nbsp;&nbsp; </SPAN>&lt;body-content&gt;empty&lt;/body-content&gt; </FONT></FONT></SPAN></PRE><PRE><SPAN lang=EN-US><FONT size=2><FONT face=黑体><SPAN style="mso-spacerun: yes">&nbsp;</SPAN>&lt;/tag&gt;</FONT></FONT></SPAN></PRE>
<P class=a2 style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 24pt"><SPAN style="FONT-FAMILY: 华文楷体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">该标签由四个部分组成：</SPAN></P>
<P class=9 style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US style="FONT-FAMILY: 楷体_GB2312; mso-ascii-font-family: 'Times New Roman'">（1） </SPAN><SPAN lang=EN-US>description</SPAN><SPAN style="FONT-FAMILY: 楷体_GB2312; mso-ascii-font-family: 'Times New Roman'">：描述该标签的作用</SPAN></P>
<P class=9 style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US style="FONT-FAMILY: 楷体_GB2312; mso-ascii-font-family: 'Times New Roman'">（2） </SPAN><SPAN lang=EN-US>name</SPAN><SPAN style="FONT-FAMILY: 楷体_GB2312; mso-ascii-font-family: 'Times New Roman'">：标签的名字，该名字在</SPAN><SPAN lang=EN-US>jsp</SPAN><SPAN style="FONT-FAMILY: 楷体_GB2312; mso-ascii-font-family: 'Times New Roman'">文件使用，相当由类名；</SPAN></P>
<P class=9 style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US style="FONT-FAMILY: 楷体_GB2312; mso-ascii-font-family: 'Times New Roman'">（3） </SPAN><SPAN lang=EN-US>tag-class</SPAN><SPAN style="FONT-FAMILY: 楷体_GB2312; mso-ascii-font-family: 'Times New Roman'">：标签的实现索引，相当于类的实现；本例索引指定</SPAN><SPAN lang=EN-US>jsp2.examples.simpletag.HelloWorldSimpleTag</SPAN><SPAN style="FONT-FAMILY: 楷体_GB2312; mso-ascii-font-family: 'Times New Roman'">，是一个</SPAN><SPAN lang=EN-US>java</SPAN><SPAN style="FONT-FAMILY: 楷体_GB2312; mso-ascii-font-family: 'Times New Roman'">的类文件，应放在</SPAN><SPAN lang=EN-US>WEB_INF/classes/jsp2/examples/simpletag</SPAN><SPAN style="FONT-FAMILY: 楷体_GB2312; mso-ascii-font-family: 'Times New Roman'">目录下的</SPAN><SPAN lang=EN-US>HelloWorldSimpleTag.class</SPAN><SPAN style="FONT-FAMILY: 楷体_GB2312; mso-ascii-font-family: 'Times New Roman'">文件；</SPAN></P>
<P class=9 style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US style="FONT-FAMILY: 楷体_GB2312; mso-ascii-font-family: 'Times New Roman'">（4） </SPAN><SPAN lang=EN-US>body-content</SPAN><SPAN style="FONT-FAMILY: 楷体_GB2312; mso-ascii-font-family: 'Times New Roman'">：在</SPAN><SPAN lang=EN-US>jsp</SPAN><SPAN style="FONT-FAMILY: 楷体_GB2312; mso-ascii-font-family: 'Times New Roman'">文件中使用标签时，标签中的内容类别，本例的值是</SPAN><SPAN lang=EN-US>empty</SPAN><SPAN style="FONT-FAMILY: 楷体_GB2312; mso-ascii-font-family: 'Times New Roman'">，表示</SPAN><SPAN lang=EN-US>helloWorld</SPAN><SPAN style="FONT-FAMILY: 楷体_GB2312; mso-ascii-font-family: 'Times New Roman'">这个标签中没有内容。如果在</SPAN><SPAN lang=EN-US>jsp</SPAN><SPAN style="FONT-FAMILY: 楷体_GB2312; mso-ascii-font-family: 'Times New Roman'">页面中在该标签中加入了内容，如</SPAN><SPAN lang=EN-US>&lt;mytag:helloWorld&gt;hell&lt;/mytag:helloWorld&gt;</SPAN><SPAN style="FONT-FAMILY: 楷体_GB2312; mso-ascii-font-family: 'Times New Roman'">，页面会报错，当然</SPAN><SPAN lang=EN-US>&lt;mytag:helloWorld&gt;&lt;/mytag:helloWorld&gt;</SPAN><SPAN style="FONT-FAMILY: 楷体_GB2312; mso-ascii-font-family: 'Times New Roman'">是不会错的（注意不能有空格式）。</SPAN></P>
<H4 style="MARGIN: 9pt 0cm; TEXT-INDENT: 0cm"><FONT size=5><FONT face=Arial><SPAN lang=EN-US>2.2.4</SPAN><SPAN lang=EN-US> </SPAN></FONT><SPAN style="FONT-FAMILY: 黑体; mso-ascii-font-family: Arial">类的实现</SPAN></FONT></H4>
<P class=a2 style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 24pt"><SPAN style="FONT-FAMILY: 华文楷体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">类</SPAN><SPAN lang=EN-US>HelloWorldSimpleTag</SPAN><SPAN style="FONT-FAMILY: 华文楷体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">实现如下：</SPAN></P><PRE><SPAN lang=EN-US><FONT face=黑体 size=2>package jsp2.examples.simpletag;</FONT></SPAN></PRE><PRE><SPAN lang=EN-US><FONT size=2><FONT face=黑体>&nbsp;<o:p></o:p></FONT></FONT></SPAN></PRE><PRE><SPAN lang=EN-US><FONT face=黑体 size=2>import javax.servlet.jsp.JspException;</FONT></SPAN></PRE><PRE><SPAN lang=EN-US><FONT face=黑体 size=2>import javax.servlet.jsp.tagext.SimpleTagSupport;</FONT></SPAN></PRE><PRE><SPAN lang=EN-US><FONT face=黑体 size=2>import java.io.IOException;</FONT></SPAN></PRE><PRE><SPAN lang=EN-US><FONT size=2><FONT face=黑体>&nbsp;<o:p></o:p></FONT></FONT></SPAN></PRE><PRE><SPAN lang=EN-US><FONT face=黑体 size=2>public class HelloWorldSimpleTag extends SimpleTagSupport {</FONT></SPAN></PRE><PRE><SPAN lang=EN-US><FONT size=2><FONT face=黑体><SPAN style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp; </SPAN>public void doTag() throws JspException, IOException {</FONT></FONT></SPAN></PRE><PRE><SPAN lang=EN-US><FONT size=2><FONT face=黑体><SPAN style="mso-tab-count: 1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN>getJspContext().getOut().write( "Hello, world!" );</FONT></FONT></SPAN></PRE><PRE><SPAN lang=EN-US><FONT size=2><FONT face=黑体><SPAN style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp; </SPAN>}}</FONT></FONT></SPAN></PRE>
<P class=a2 style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 24pt"><SPAN style="FONT-FAMILY: 华文楷体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">说明：</SPAN></P>
<P class=9 style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US style="FONT-FAMILY: 楷体_GB2312; mso-ascii-font-family: 'Times New Roman'">（1） </SPAN><SPAN lang=EN-US>jsp</SPAN><SPAN style="FONT-FAMILY: 楷体_GB2312; mso-ascii-font-family: 'Times New Roman'">标签调用的类一般继承于</SPAN><SPAN lang=EN-US>SimpleTagSupport</SPAN></P>
<P class=9 style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US style="FONT-FAMILY: 楷体_GB2312; mso-ascii-font-family: 'Times New Roman'">（2） </SPAN><SPAN lang=EN-US>SimpleTagSupport</SPAN><SPAN style="FONT-FAMILY: 楷体_GB2312; mso-ascii-font-family: 'Times New Roman'">中实现了</SPAN><SPAN lang=EN-US>getJspContext()</SPAN><SPAN style="FONT-FAMILY: 楷体_GB2312; mso-ascii-font-family: 'Times New Roman'">这个方法，这个方法可以获取指向</SPAN><SPAN lang=EN-US>jsp</SPAN><SPAN style="FONT-FAMILY: 楷体_GB2312; mso-ascii-font-family: 'Times New Roman'">页面的输出流。</SPAN></P>
<P class=9 style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US style="FONT-FAMILY: 楷体_GB2312; mso-ascii-font-family: 'Times New Roman'">（3） </SPAN><SPAN lang=EN-US>getJspContext().getOut().write( "Hello, world!" )</SPAN><SPAN style="FONT-FAMILY: 楷体_GB2312; mso-ascii-font-family: 'Times New Roman'">：输出</SPAN><SPAN lang=EN-US>Hellow,World!</SPAN></P>
<H3 style="MARGIN: 9pt 0cm; TEXT-INDENT: 0cm"><FONT size=5><SPAN lang=EN-US><FONT face=Arial>2.3</FONT></SPAN><SPAN style="FONT-FAMILY: 黑体; mso-ascii-font-family: Arial">含有变量的</SPAN><SPAN lang=EN-US><FONT face=Arial>tag</FONT></SPAN><SPAN style="FONT-FAMILY: 黑体; mso-ascii-font-family: Arial">配置</SPAN></FONT></H3>
<H4 style="MARGIN: 9pt 0cm; TEXT-INDENT: 0cm"><FONT size=5><FONT face=Arial><SPAN lang=EN-US>2.3.1</SPAN><SPAN lang=EN-US> jsp</SPAN></FONT><SPAN style="FONT-FAMILY: 黑体; mso-ascii-font-family: Arial">文件中的标签引用及使用方法</SPAN></FONT></H4>
<P class=a2 style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 24pt"><SPAN style="FONT-FAMILY: 华文楷体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">以下是引用了带有变量标签的</SPAN><SPAN lang=EN-US>jsp</SPAN><SPAN style="FONT-FAMILY: 华文楷体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">页面：</SPAN></P><PRE><SPAN lang=EN-US><FONT face=黑体 size=2>&lt;%@ taglib prefix="mytag" uri="/WEB-INF/jsp2/my_taglib.tld" %&gt;</FONT></SPAN></PRE><PRE><SPAN lang=EN-US><FONT face=黑体 size=2>&lt;html&gt;&lt;body&gt;</FONT></SPAN></PRE><PRE><SPAN lang=EN-US><FONT size=2><FONT face=黑体><SPAN style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp; </SPAN>&lt;mytag:repeat num1="15"&gt;</FONT></FONT></SPAN></PRE><PRE><SPAN lang=EN-US><FONT size=2><FONT face=黑体><SPAN style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp;&nbsp; </SPAN><SPAN style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="mso-spacerun: yes">&nbsp;</SPAN>Invocation ${count} of 5&lt;br&gt;</FONT></FONT></SPAN></PRE><PRE><SPAN lang=EN-US><FONT size=2><FONT face=黑体><SPAN style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp; </SPAN>&lt;/mytag:repeat&gt;</FONT></FONT></SPAN></PRE><PRE><SPAN lang=EN-US><FONT size=2><FONT face=黑体><SPAN style="mso-spacerun: yes">&nbsp; </SPAN>&lt;/body&gt;</FONT></FONT></SPAN></PRE><PRE><SPAN lang=EN-US><FONT face=黑体 size=2>&lt;/html&gt;</FONT></SPAN></PRE>
<P class=a2 style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 24pt"><SPAN style="FONT-FAMILY: 华文楷体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">说明：</SPAN></P>
<P class=9 style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US style="FONT-FAMILY: 楷体_GB2312; mso-ascii-font-family: 'Times New Roman'">（1） </SPAN><SPAN lang=EN-US>&lt;mytag:repeat num="15"&gt;</SPAN><SPAN style="FONT-FAMILY: 楷体_GB2312; mso-ascii-font-family: 'Times New Roman'">，输入参数的传入方法：即在标签中将要传入的参数做为标签的一个属性，并指定其属性值，本例中传入参数</SPAN><SPAN lang=EN-US>num1</SPAN><SPAN style="FONT-FAMILY: 楷体_GB2312; mso-ascii-font-family: 'Times New Roman'">，它的值为</SPAN><SPAN lang=EN-US>15</SPAN><SPAN style="FONT-FAMILY: 楷体_GB2312; mso-ascii-font-family: 'Times New Roman'">；</SPAN></P>
<P class=9 style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US style="FONT-FAMILY: 楷体_GB2312; mso-ascii-font-family: 'Times New Roman'">（2） </SPAN><SPAN lang=EN-US>${count}</SPAN><SPAN style="FONT-FAMILY: 楷体_GB2312; mso-ascii-font-family: 'Times New Roman'">，在页面中显示输出参数的值，</SPAN><SPAN lang=EN-US>count</SPAN><SPAN style="FONT-FAMILY: 楷体_GB2312; mso-ascii-font-family: 'Times New Roman'">是输出参数的名字</SPAN></P>
<H4 style="MARGIN: 9pt 0cm; TEXT-INDENT: 0cm"><FONT size=5><FONT face=Arial><SPAN lang=EN-US>2.3.2</SPAN><SPAN lang=EN-US> </SPAN></FONT><SPAN style="FONT-FAMILY: 黑体; mso-ascii-font-family: Arial">标签库中的配置</SPAN></FONT></H4>
<P class=a2 style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 24pt"><SPAN style="FONT-FAMILY: 华文楷体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">标签库中的相应配置如下：</SPAN></P><PRE><SPAN lang=EN-US><FONT size=2><FONT face=黑体><SPAN style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp; </SPAN>&lt;tag&gt;</FONT></FONT></SPAN></PRE><PRE><SPAN lang=EN-US><FONT size=2><FONT face=黑体><SPAN style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN>&lt;description&gt;Repeats the body of the tag 'num' times&lt;/description&gt;</FONT></FONT></SPAN></PRE><PRE><SPAN lang=EN-US><FONT size=2><FONT face=黑体><SPAN style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN>&lt;name&gt;repeat&lt;/name&gt;</FONT></FONT></SPAN></PRE><PRE><SPAN lang=EN-US><FONT size=2><FONT face=黑体><SPAN style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN>&lt;tag-class&gt;jsp2.examples.simpletag.RepeatSimpleTag&lt;/tag-class&gt;</FONT></FONT></SPAN></PRE><PRE><SPAN lang=EN-US><FONT size=2><FONT face=黑体><SPAN style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN>&lt;body-content&gt;scriptless&lt;/body-content&gt;--标签内容是脚本</FONT></FONT></SPAN></PRE><PRE><SPAN lang=EN-US><FONT size=2><FONT face=黑体><SPAN style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN>&lt;variable&gt;</FONT></FONT></SPAN></PRE><PRE><SPAN lang=EN-US><FONT size=2><FONT face=黑体><SPAN style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN>&lt;description&gt;Current invocation count (1 to num)&lt;/description&gt;</FONT></FONT></SPAN></PRE><PRE><SPAN lang=EN-US><FONT size=2><FONT face=黑体><SPAN style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN>&lt;name-given&gt;count&lt;/name-given&gt;<SPAN style="mso-spacerun: yes">&nbsp; </SPAN>--输出参数说明</FONT></FONT></SPAN></PRE><PRE><SPAN lang=EN-US><FONT size=2><FONT face=黑体><SPAN style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN>&lt;/variable&gt;</FONT></FONT></SPAN></PRE><PRE><SPAN lang=EN-US><FONT size=2><FONT face=黑体><SPAN style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN>&lt;attribute&gt;</FONT></FONT></SPAN></PRE><PRE><SPAN lang=EN-US><FONT size=2><FONT face=黑体><SPAN style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN>&lt;name&gt;num&lt;/name&gt;<SPAN style="mso-spacerun: yes">&nbsp; </SPAN>--输入参数说明</FONT></FONT></SPAN></PRE><PRE><SPAN lang=EN-US><FONT size=2><FONT face=黑体><SPAN style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN>&lt;required&gt;true&lt;/required&gt;</FONT></FONT></SPAN></PRE><PRE><SPAN lang=EN-US><FONT size=2><FONT face=黑体><SPAN style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN>&lt;rtexprvalue&gt;true&lt;/rtexprvalue&gt;</FONT></FONT></SPAN></PRE><PRE><SPAN lang=EN-US><FONT size=2><FONT face=黑体><SPAN style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN>&lt;/attribute&gt;</FONT></FONT></SPAN></PRE><PRE><SPAN lang=EN-US><FONT size=2><FONT face=黑体><SPAN style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp; </SPAN>&lt;/tag&gt;</FONT></FONT></SPAN></PRE>
<P class=a2 style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 24pt"><SPAN style="FONT-FAMILY: 华文楷体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">该标签由六个部分组成：</SPAN></P>
<P class=9 style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US style="FONT-FAMILY: 楷体_GB2312; mso-ascii-font-family: 'Times New Roman'">（1） </SPAN><SPAN lang=EN-US>description</SPAN><SPAN style="FONT-FAMILY: 楷体_GB2312; mso-ascii-font-family: 'Times New Roman'">：见上文</SPAN></P>
<P class=9 style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US style="FONT-FAMILY: 楷体_GB2312; mso-ascii-font-family: 'Times New Roman'">（2） </SPAN><SPAN lang=EN-US>name</SPAN><SPAN style="FONT-FAMILY: 楷体_GB2312; mso-ascii-font-family: 'Times New Roman'">：见上文</SPAN></P>
<P class=9 style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US style="FONT-FAMILY: 楷体_GB2312; mso-ascii-font-family: 'Times New Roman'">（3） </SPAN><SPAN lang=EN-US>tag-class</SPAN><SPAN style="FONT-FAMILY: 楷体_GB2312; mso-ascii-font-family: 'Times New Roman'">：见上文</SPAN></P>
<P class=9 style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US style="FONT-FAMILY: 楷体_GB2312; mso-ascii-font-family: 'Times New Roman'">（4） </SPAN><SPAN lang=EN-US>body-content</SPAN><SPAN style="FONT-FAMILY: 楷体_GB2312; mso-ascii-font-family: 'Times New Roman'">：这个例子的值是</SPAN><SPAN lang=EN-US>scriptless</SPAN><SPAN style="FONT-FAMILY: 楷体_GB2312; mso-ascii-font-family: 'Times New Roman'">，表示标签中的内容是脚本</SPAN></P>
<P class=9 style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US style="FONT-FAMILY: 楷体_GB2312; mso-ascii-font-family: 'Times New Roman'">（5） </SPAN><SPAN lang=EN-US>variable</SPAN><SPAN style="FONT-FAMILY: 楷体_GB2312; mso-ascii-font-family: 'Times New Roman'">：输出参数，在</SPAN><SPAN lang=EN-US>jsp</SPAN><SPAN style="FONT-FAMILY: 楷体_GB2312; mso-ascii-font-family: 'Times New Roman'">中使用</SPAN><SPAN lang=EN-US>${count}</SPAN><SPAN style="FONT-FAMILY: 楷体_GB2312; mso-ascii-font-family: 'Times New Roman'">来引用这个输出变量的值，输出参数名并不是强制性的，这里只是一个约定，即要求</SPAN><SPAN lang=EN-US>repeat</SPAN><SPAN style="FONT-FAMILY: 楷体_GB2312; mso-ascii-font-family: 'Times New Roman'">实现类最后有</SPAN><SPAN lang=EN-US>count</SPAN><SPAN style="FONT-FAMILY: 楷体_GB2312; mso-ascii-font-family: 'Times New Roman'">这个输出参数，以便在</SPAN><SPAN lang=EN-US>jsp</SPAN><SPAN style="FONT-FAMILY: 楷体_GB2312; mso-ascii-font-family: 'Times New Roman'">页中方便引用，如果没有也不会报错；</SPAN></P>
<P class=9 style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US style="FONT-FAMILY: 楷体_GB2312; mso-ascii-font-family: 'Times New Roman'">（6） </SPAN><SPAN lang=EN-US>attribute</SPAN><SPAN style="FONT-FAMILY: 楷体_GB2312; mso-ascii-font-family: 'Times New Roman'">：输入参数，在</SPAN><SPAN lang=EN-US>jsp</SPAN><SPAN style="FONT-FAMILY: 楷体_GB2312; mso-ascii-font-family: 'Times New Roman'">中使用</SPAN><SPAN lang=EN-US>&lt; mytag:repeat num="5"&gt;</SPAN><SPAN style="FONT-FAMILY: 楷体_GB2312; mso-ascii-font-family: 'Times New Roman'">来设置这个输入参数</SPAN><SPAN lang=EN-US>num</SPAN><SPAN style="FONT-FAMILY: 楷体_GB2312; mso-ascii-font-family: 'Times New Roman'">，这个参数名是强制性的，即要在</SPAN><SPAN lang=EN-US>repeat</SPAN><SPAN style="FONT-FAMILY: 楷体_GB2312; mso-ascii-font-family: 'Times New Roman'">实现类中有</SPAN><SPAN lang=EN-US>setNum</SPAN><SPAN style="FONT-FAMILY: 楷体_GB2312; mso-ascii-font-family: 'Times New Roman'">这个方法，如果没有相应的方法</SPAN><SPAN lang=EN-US>jsp</SPAN><SPAN style="FONT-FAMILY: 楷体_GB2312; mso-ascii-font-family: 'Times New Roman'">页面会报错；</SPAN></P>
<H4 style="MARGIN: 9pt 0cm; TEXT-INDENT: 0cm"><FONT size=5><FONT face=Arial><SPAN lang=EN-US>2.3.3</SPAN><SPAN lang=EN-US> </SPAN></FONT><SPAN style="FONT-FAMILY: 黑体; mso-ascii-font-family: Arial">类的实现</SPAN></FONT></H4><PRE><SPAN lang=EN-US><FONT face=黑体 size=2>package jsp2.examples.simpletag;</FONT></SPAN></PRE><PRE><SPAN lang=EN-US><FONT size=2><FONT face=黑体>&nbsp;<o:p></o:p></FONT></FONT></SPAN></PRE><PRE><SPAN lang=EN-US><FONT face=黑体 size=2>import javax.servlet.jsp.JspException;</FONT></SPAN></PRE><PRE><SPAN lang=EN-US><FONT face=黑体 size=2>import javax.servlet.jsp.tagext.SimpleTagSupport;</FONT></SPAN></PRE><PRE><SPAN lang=EN-US><FONT face=黑体 size=2>import java.util.HashMap;</FONT></SPAN></PRE><PRE><SPAN lang=EN-US><FONT face=黑体 size=2>import java.io.IOException;</FONT></SPAN></PRE><PRE><SPAN lang=EN-US><FONT size=2><FONT face=黑体>&nbsp;<o:p></o:p></FONT></FONT></SPAN></PRE><PRE><SPAN lang=EN-US><FONT face=黑体 size=2>public class RepeatSimpleTag1 extends SimpleTagSupport {</FONT></SPAN></PRE><PRE><SPAN lang=EN-US><FONT size=2><FONT face=黑体><SPAN style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp; </SPAN>private int num;</FONT></FONT></SPAN></PRE><PRE><SPAN lang=EN-US><FONT size=2><FONT face=黑体>&nbsp;<o:p></o:p></FONT></FONT></SPAN></PRE><PRE><SPAN lang=EN-US><FONT size=2><FONT face=黑体><SPAN style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp; </SPAN>public void doTag() throws JspException, IOException {</FONT></FONT></SPAN></PRE><PRE><SPAN lang=EN-US><FONT size=2><FONT face=黑体><SPAN style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN>for (int i=0; i&lt;num; i++) {</FONT></FONT></SPAN></PRE><PRE><SPAN lang=EN-US><FONT size=2><FONT face=黑体><SPAN style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN>getJspContext().setAttribute("count", String.valueOf( i + 1 ) );</FONT></FONT></SPAN></PRE><PRE><SPAN lang=EN-US><FONT size=2><FONT face=黑体><SPAN style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN>getJspBody().invoke(null);</FONT></FONT></SPAN></PRE><PRE><SPAN lang=EN-US><FONT size=2><FONT face=黑体><SPAN style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN>}<SPAN style="mso-spacerun: yes">&nbsp; </SPAN>}</FONT></FONT></SPAN></PRE><PRE><SPAN lang=EN-US><FONT size=2><FONT face=黑体>&nbsp;<o:p></o:p></FONT></FONT></SPAN></PRE><PRE><SPAN lang=EN-US><FONT size=2><FONT face=黑体><SPAN style="mso-spacerun: yes">&nbsp;&nbsp; </SPAN>public void setNum(int num) {</FONT></FONT></SPAN></PRE><PRE><SPAN lang=EN-US><FONT size=2><FONT face=黑体><SPAN style="mso-tab-count: 1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN><SPAN style="mso-spacerun: yes">&nbsp;&nbsp; </SPAN>this.num = num; }}</FONT></FONT></SPAN></PRE>
<P class=a2 style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 24pt"><SPAN style="FONT-FAMILY: 华文楷体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">说明：</SPAN></P>
<P class=9 style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US style="FONT-FAMILY: 楷体_GB2312; mso-ascii-font-family: 'Times New Roman'">（1） </SPAN><SPAN lang=EN-US>getJspContext().setAttribute</SPAN><SPAN style="FONT-FAMILY: 楷体_GB2312; mso-ascii-font-family: 'Times New Roman'">定义了输出到</SPAN><SPAN lang=EN-US>jsp</SPAN><SPAN style="FONT-FAMILY: 楷体_GB2312; mso-ascii-font-family: 'Times New Roman'">页面的输出参数</SPAN><SPAN lang=EN-US>count</SPAN><SPAN style="FONT-FAMILY: 楷体_GB2312; mso-ascii-font-family: 'Times New Roman'">，这里的</SPAN><SPAN lang=EN-US>count</SPAN><SPAN style="FONT-FAMILY: 楷体_GB2312; mso-ascii-font-family: 'Times New Roman'">是一个字符串，它的值可以不与标签库中</SPAN><SPAN lang=EN-US>variable</SPAN><SPAN style="FONT-FAMILY: 楷体_GB2312; mso-ascii-font-family: 'Times New Roman'">定义相同，如，它可以是</SPAN><SPAN lang=EN-US>len</SPAN><SPAN style="FONT-FAMILY: 楷体_GB2312; mso-ascii-font-family: 'Times New Roman'">，当然在</SPAN><SPAN lang=EN-US>jsp</SPAN><SPAN style="FONT-FAMILY: 楷体_GB2312; mso-ascii-font-family: 'Times New Roman'">引用时应以这里为准，即使用</SPAN><SPAN lang=EN-US>${len}</SPAN><SPAN style="FONT-FAMILY: 楷体_GB2312; mso-ascii-font-family: 'Times New Roman'">引用；</SPAN></P>
<P class=9 style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US style="FONT-FAMILY: 楷体_GB2312; mso-ascii-font-family: 'Times New Roman'">（2） </SPAN><SPAN lang=EN-US>setNum(int num)</SPAN><SPAN style="FONT-FAMILY: 楷体_GB2312; mso-ascii-font-family: 'Times New Roman'">方法：接收输入参数，这个方法命名规则为</SPAN><SPAN lang=EN-US>set+</SPAN><SPAN style="FONT-FAMILY: 楷体_GB2312; mso-ascii-font-family: 'Times New Roman'">输入参数名，该方法带一个参数，用于接收输入参数的值。</SPAN></P>
<H3 style="MARGIN: 9pt 0cm; TEXT-INDENT: 0cm"><FONT size=5><FONT face=Arial><SPAN lang=EN-US>2.4</SPAN><SPAN lang=EN-US> </SPAN></FONT><SPAN style="FONT-FAMILY: 黑体; mso-ascii-font-family: Arial">函数标签的定义方法</SPAN></FONT></H3>
<H4 style="MARGIN: 9pt 0cm; TEXT-INDENT: 0cm"><FONT size=5><FONT face=Arial><SPAN lang=EN-US>2.4.1</SPAN><SPAN lang=EN-US> jsp</SPAN></FONT><SPAN style="FONT-FAMILY: 黑体; mso-ascii-font-family: Arial">文件中函数标签引用及使用方法</SPAN></FONT></H4><PRE><SPAN lang=EN-US><FONT face=黑体 size=2>&lt;%@ taglib prefix="my" uri="/WEB-INF/jsp2/jsp2-example-taglib.tld" %&gt;</FONT></SPAN></PRE><PRE><SPAN lang=EN-US><FONT face=黑体 size=2>&lt;html&gt;</FONT></SPAN></PRE>
<P class=a2 style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 20pt"><SPAN lang=EN-US style="FONT-SIZE: 10pt; FONT-FAMILY: 黑体; mso-hansi-font-family: 'Courier New'; mso-font-kerning: 0pt; mso-bidi-font-family: 'Courier New'">&lt;body&gt;&lt;span&gt;${my:caps(</SPAN><SPAN lang=EN-US style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-ascii-font-family: 黑体; mso-fareast-font-family: 黑体; mso-font-kerning: 0pt">“</SPAN><SPAN lang=EN-US style="FONT-SIZE: 10pt; FONT-FAMILY: 黑体; mso-hansi-font-family: 'Courier New'; mso-font-kerning: 0pt; mso-bidi-font-family: 'Courier New'">HELLO WORLD</SPAN><SPAN lang=EN-US style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-ascii-font-family: 黑体; mso-fareast-font-family: 黑体; mso-font-kerning: 0pt">”</SPAN><SPAN lang=EN-US style="FONT-SIZE: 10pt; FONT-FAMILY: 黑体; mso-hansi-font-family: 'Courier New'; mso-font-kerning: 0pt; mso-bidi-font-family: 'Courier New'">)}&lt;/span&gt;&lt;/body&gt;<o:p></o:p></SPAN></P>
<P class=a2 style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 0cm; mso-char-indent-count: 0; mso-char-indent-size: 0cm"><SPAN lang=EN-US style="FONT-SIZE: 10pt; FONT-FAMILY: 黑体; mso-hansi-font-family: 'Courier New'; mso-font-kerning: 0pt; mso-bidi-font-family: 'Courier New'">&lt;/html&gt;<o:p></o:p></SPAN></P>
<P class=a2 style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 24pt"><SPAN style="FONT-FAMILY: 华文楷体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">说明：</SPAN></P>
<P class=9 style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US style="FONT-FAMILY: 楷体_GB2312; mso-ascii-font-family: 'Times New Roman'">（1） </SPAN><SPAN style="FONT-FAMILY: 楷体_GB2312; mso-ascii-font-family: 'Times New Roman'">函数标签的引用比其它标签的引用都要简单，它的引用与高级语言中的函数调用方法类似，直接在函数名后的括号后面输入相应的参数值即可，不需要另加用标签的其它属性来说明输入参数。</SPAN></P>
<H4 style="MARGIN: 9pt 0cm; TEXT-INDENT: 0cm"><FONT size=5><FONT face=Arial><SPAN lang=EN-US>2.4.2</SPAN><SPAN lang=EN-US> </SPAN></FONT><SPAN style="FONT-FAMILY: 黑体; mso-ascii-font-family: Arial">函数标签在标签库中配置</SPAN></FONT></H4><PRE><SPAN lang=EN-US><FONT face=黑体 size=2>&lt;function&gt;</FONT></SPAN></PRE><PRE style="TEXT-INDENT: 10pt; mso-char-indent-count: 1.0; mso-char-indent-size: 10.0pt"><SPAN lang=EN-US><FONT face=黑体 size=2>&lt;description&gt;Converts the string to all caps&lt;/description&gt;</FONT></SPAN></PRE><PRE style="TEXT-INDENT: 10pt; mso-char-indent-count: 1.0; mso-char-indent-size: 10.0pt"><SPAN lang=EN-US><FONT face=黑体 size=2>&lt;name&gt;caps&lt;/name&gt;</FONT></SPAN></PRE><PRE style="TEXT-INDENT: 10pt; mso-char-indent-count: 1.0; mso-char-indent-size: 10.0pt"><SPAN lang=EN-US><FONT face=黑体 size=2>&lt;function-class&gt;jsp2.examples.el.Functions&lt;/function-class&gt;</FONT></SPAN></PRE><PRE style="TEXT-INDENT: 10pt; mso-char-indent-count: 1.0; mso-char-indent-size: 10.0pt"><SPAN lang=EN-US><FONT face=黑体 size=2>&lt;function-signature&gt;java.lang.String caps( java.lang.String )&lt;/function-signature&gt;</FONT></SPAN></PRE><PRE><SPAN lang=EN-US><FONT face=黑体 size=2>&lt;/function&gt;</FONT></SPAN></PRE>
<P class=a2 style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 0cm; mso-char-indent-count: 0; mso-char-indent-size: 0cm"><SPAN style="FONT-FAMILY: 华文楷体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">说明如下：</SPAN></P>
<P class=9 style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US style="FONT-FAMILY: 楷体_GB2312; mso-ascii-font-family: 'Times New Roman'">（1） </SPAN><SPAN style="FONT-FAMILY: 楷体_GB2312; mso-ascii-font-family: 'Times New Roman'">这种方法的定义包含在</SPAN><SPAN lang=EN-US>function</SPAN><SPAN style="FONT-FAMILY: 楷体_GB2312; mso-ascii-font-family: 'Times New Roman'">元素中；</SPAN></P>
<P class=9 style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US style="FONT-FAMILY: 楷体_GB2312; mso-ascii-font-family: 'Times New Roman'">（2） </SPAN><SPAN lang=EN-US>name</SPAN><SPAN style="FONT-FAMILY: 楷体_GB2312; mso-ascii-font-family: 'Times New Roman'">：函数名</SPAN></P>
<P class=9 style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US style="FONT-FAMILY: 楷体_GB2312; mso-ascii-font-family: 'Times New Roman'">（3） </SPAN><SPAN lang=EN-US>function-class</SPAN><SPAN style="FONT-FAMILY: 楷体_GB2312; mso-ascii-font-family: 'Times New Roman'">：该函数真正的实现</SPAN><SPAN lang=EN-US>class</SPAN><SPAN style="FONT-FAMILY: 楷体_GB2312; mso-ascii-font-family: 'Times New Roman'">，本例中，</SPAN><SPAN lang=EN-US>caps</SPAN><SPAN style="FONT-FAMILY: 楷体_GB2312; mso-ascii-font-family: 'Times New Roman'">函数是由</SPAN><SPAN lang=EN-US>WEB_INF/classes/ jsp2/examples/el</SPAN><SPAN style="FONT-FAMILY: 楷体_GB2312; mso-ascii-font-family: 'Times New Roman'">路径中的</SPAN><SPAN lang=EN-US>Functions</SPAN><SPAN style="FONT-FAMILY: 楷体_GB2312; mso-ascii-font-family: 'Times New Roman'">类来实现的；</SPAN></P>
<P class=9 style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US style="FONT-FAMILY: 楷体_GB2312; mso-ascii-font-family: 'Times New Roman'">（4） </SPAN><SPAN lang=EN-US>function-signature</SPAN><SPAN style="FONT-FAMILY: 楷体_GB2312; mso-ascii-font-family: 'Times New Roman'">：说明函数的输入及输出参数类型，不用指明参数名。</SPAN></P>
<H4 style="MARGIN: 9pt 0cm; TEXT-INDENT: 0cm"><FONT size=5><FONT face=Arial><SPAN lang=EN-US>2.4.3</SPAN><SPAN lang=EN-US> </SPAN></FONT><SPAN style="FONT-FAMILY: 黑体; mso-ascii-font-family: Arial">类的实现</SPAN></FONT></H4><PRE style="TEXT-INDENT: 10pt; mso-char-indent-count: 1.0; mso-char-indent-size: 10.0pt"><SPAN lang=EN-US><FONT face=黑体 size=2>package jsp2.examples.el;</FONT></SPAN></PRE><PRE style="TEXT-INDENT: 10pt; mso-char-indent-count: 1.0; mso-char-indent-size: 10.0pt"><SPAN lang=EN-US><FONT face=黑体 size=2>import java.util.*;</FONT></SPAN></PRE><PRE style="TEXT-INDENT: 10pt; mso-char-indent-count: 1.0; mso-char-indent-size: 10.0pt"><SPAN lang=EN-US><FONT size=2><FONT face=黑体>&nbsp;<o:p></o:p></FONT></FONT></SPAN></PRE><PRE style="TEXT-INDENT: 10pt; mso-char-indent-count: 1.0; mso-char-indent-size: 10.0pt"><SPAN lang=EN-US><FONT face=黑体 size=2>public class Functions {</FONT></SPAN></PRE><PRE style="TEXT-INDENT: 10pt; mso-char-indent-count: 1.0; mso-char-indent-size: 10.0pt"><SPAN lang=EN-US><FONT size=2><FONT face=黑体><SPAN style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN>public static String caps( String text ) {</FONT></FONT></SPAN></PRE><PRE style="TEXT-INDENT: 10pt; mso-char-indent-count: 1.0; mso-char-indent-size: 10.0pt"><SPAN lang=EN-US><FONT size=2><FONT face=黑体><SPAN style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN>return text.toUpperCase();</FONT></FONT></SPAN></PRE><PRE style="TEXT-INDENT: 10pt; mso-char-indent-count: 1.0; mso-char-indent-size: 10.0pt"><SPAN lang=EN-US><FONT size=2><FONT face=黑体><SPAN style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp; </SPAN>}}</FONT></FONT></SPAN></PRE>
<P class=a2 style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 24pt"><SPAN style="FONT-FAMILY: 华文楷体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">说明：</SPAN></P>
<P class=9 style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US style="FONT-FAMILY: 楷体_GB2312; mso-ascii-font-family: 'Times New Roman'">（1） </SPAN><SPAN style="FONT-FAMILY: 楷体_GB2312; mso-ascii-font-family: 'Times New Roman'">函数标签实现类就是普通的类，它不需要从某个父类继承；</SPAN></P>
<P class=9 style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US style="FONT-FAMILY: 楷体_GB2312; mso-ascii-font-family: 'Times New Roman'">（2） </SPAN><SPAN style="FONT-FAMILY: 楷体_GB2312; mso-ascii-font-family: 'Times New Roman'">函数标签实现类中必须有相应的方法与标签库中相应的函数字义相同（包括函数名，输入参数个数及输入参数类型，函数的返回值）；</SPAN></P>
<H3 style="MARGIN: 9pt 0cm; TEXT-INDENT: 0cm"><FONT size=5><FONT face=Arial><SPAN lang=EN-US>2.5</SPAN><SPAN lang=EN-US> </SPAN></FONT><SPAN style="FONT-FAMILY: 黑体; mso-ascii-font-family: Arial">标签模板</SPAN></FONT></H3>
<P class=a2 style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 24pt"><SPAN style="FONT-FAMILY: 华文楷体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">标签模板的特点：</SPAN></P>
<P class=9 style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US style="FONT-FAMILY: 楷体_GB2312; mso-ascii-font-family: 'Times New Roman'; mso-font-kerning: 0pt">（1） </SPAN><SPAN style="FONT-FAMILY: 楷体_GB2312; mso-ascii-font-family: 'Times New Roman'">没有</SPAN><SPAN lang=EN-US>tld</SPAN><SPAN style="FONT-FAMILY: 楷体_GB2312; mso-ascii-font-family: 'Times New Roman'">文件在</SPAN><SPAN lang=EN-US>jsp</SPAN><SPAN style="FONT-FAMILY: 楷体_GB2312; mso-ascii-font-family: 'Times New Roman'">中通过</SPAN><SPAN lang=EN-US style="FONT-SIZE: 10pt; FONT-FAMILY: 黑体; mso-hansi-font-family: 'Courier New'; mso-font-kerning: 0pt; mso-bidi-font-family: 'Courier New'">&lt;%@ taglib prefix="tags" tagdir="/WEB-INF/tags" %&gt;</SPAN><SPAN style="FONT-FAMILY: 楷体_GB2312; mso-ascii-font-family: 'Times New Roman'; mso-font-kerning: 0pt">引用，即使用</SPAN><SPAN lang=EN-US style="mso-font-kerning: 0pt">tagdir</SPAN><SPAN style="FONT-FAMILY: 楷体_GB2312; mso-ascii-font-family: 'Times New Roman'; mso-font-kerning: 0pt">代替了</SPAN><SPAN lang=EN-US style="mso-font-kerning: 0pt">uri</SPAN><SPAN style="FONT-FAMILY: 楷体_GB2312; mso-ascii-font-family: 'Times New Roman'; mso-font-kerning: 0pt">，这里的</SPAN><SPAN lang=EN-US style="mso-font-kerning: 0pt">tags</SPAN><SPAN style="FONT-FAMILY: 楷体_GB2312; mso-ascii-font-family: 'Times New Roman'; mso-font-kerning: 0pt">是一个文件夹，不是文件，在该文件夹中包含了所需的标签模板；</SPAN><SPAN lang=EN-US style="mso-font-kerning: 0pt"><o:p></o:p></SPAN></P>
<P class=9 style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US style="FONT-FAMILY: 楷体_GB2312; mso-ascii-font-family: 'Times New Roman'">（2） </SPAN><SPAN style="FONT-FAMILY: 楷体_GB2312; mso-ascii-font-family: 'Times New Roman'">通过以下方式传入参数值：</SPAN></P><PRE style="TEXT-INDENT: 10pt; mso-char-indent-count: 1.0; mso-char-indent-size: 10.0pt"><SPAN lang=EN-US><FONT face=黑体 size=2>&lt;tags:displayProducts&gt;</FONT></SPAN></PRE><PRE style="TEXT-INDENT: 10pt; mso-char-indent-count: 1.0; mso-char-indent-size: 10.0pt"><SPAN lang=EN-US><FONT size=2><FONT face=黑体><SPAN style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN>&lt;jsp:attribute name="normalPrice"&gt;....&lt;/jsp:attribute&gt;</FONT></FONT></SPAN></PRE><PRE style="TEXT-INDENT: 10pt; mso-char-indent-count: 1.0; mso-char-indent-size: 10.0pt"><SPAN lang=EN-US><FONT size=2><FONT face=黑体><SPAN style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN>&lt;jsp:attribute name="onSale"&gt;....&lt;/jsp:attribute&gt;</FONT></FONT></SPAN></PRE><PRE style="TEXT-INDENT: 10pt; mso-char-indent-count: 1.0; mso-char-indent-size: 10.0pt"><SPAN lang=EN-US><FONT size=2><FONT face=黑体><SPAN style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN>.....</FONT></FONT></SPAN></PRE><PRE style="TEXT-INDENT: 10pt; mso-char-indent-count: 1.0; mso-char-indent-size: 10.0pt"><SPAN lang=EN-US><FONT face=黑体 size=2>&lt;/tags:displayProducts&gt;</FONT></SPAN></PRE>
<P class=9 style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US style="FONT-FAMILY: 楷体_GB2312; mso-ascii-font-family: 'Times New Roman'">（3） </SPAN><SPAN lang=EN-US>displayProducts</SPAN><SPAN style="FONT-FAMILY: 楷体_GB2312; mso-ascii-font-family: 'Times New Roman'">是与</SPAN><SPAN lang=EN-US>/WEB-INF/tags</SPAN><SPAN style="FONT-FAMILY: 楷体_GB2312; mso-ascii-font-family: 'Times New Roman'">目录中的某个文件名；</SPAN></P>
<P class=9 style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US style="FONT-FAMILY: 楷体_GB2312; mso-ascii-font-family: 'Times New Roman'">（4） </SPAN><SPAN style="FONT-FAMILY: 楷体_GB2312; mso-ascii-font-family: 'Times New Roman'">通过</SPAN><SPAN lang=EN-US>&lt;jsp:attribute name="…. "&gt;</SPAN><SPAN style="FONT-FAMILY: 楷体_GB2312; mso-ascii-font-family: 'Times New Roman'">来赋值</SPAN></P>
<P class=9 style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US style="FONT-FAMILY: 楷体_GB2312; mso-ascii-font-family: 'Times New Roman'">（5） </SPAN><SPAN style="FONT-FAMILY: 楷体_GB2312; mso-ascii-font-family: 'Times New Roman'">标签模板是一个纯文本文件，类似于</SPAN><SPAN lang=EN-US>html</SPAN><SPAN style="FONT-FAMILY: 楷体_GB2312; mso-ascii-font-family: 'Times New Roman'">文件，而不需要通过</SPAN><SPAN lang=EN-US>java</SPAN><SPAN style="FONT-FAMILY: 楷体_GB2312; mso-ascii-font-family: 'Times New Roman'">的类来实现标签的定义；</SPAN></P>
<P class=9 style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US style="FONT-FAMILY: 楷体_GB2312; mso-ascii-font-family: 'Times New Roman'">（6） </SPAN><SPAN style="FONT-FAMILY: 楷体_GB2312; mso-ascii-font-family: 'Times New Roman'">个人认为标签模板的主要作用重在排版，而其它标签的作用重在功能的实现；本人不打算在以后的开发使用标签模板，因此本文不再进一步分析标签模板。</SPAN></P>
<H2 style="MARGIN: 9pt 0cm; TEXT-INDENT: 0cm"><SPAN lang=EN-US><FONT face=Arial>3. </FONT></SPAN><SPAN style="FONT-FAMILY: 黑体; mso-ascii-font-family: Arial">参考</SPAN></H2>
<P class=a2 style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 24pt"><SPAN lang=EN-US><A href="http://localhost:8080/jsp-examples/">http://localhost:8080/jsp-examples/</A></SPAN></P><img src ="http://www.blogjava.net/jackybu/aggbug/1211.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jackybu/" target="_blank">辰</a> 2005-02-15 11:33 <a href="http://www.blogjava.net/jackybu/articles/1211.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Tomcat5.5的基本配置说明 </title><link>http://www.blogjava.net/jackybu/articles/1210.html</link><dc:creator>辰</dc:creator><author>辰</author><pubDate>Tue, 15 Feb 2005 03:32:00 GMT</pubDate><guid>http://www.blogjava.net/jackybu/articles/1210.html</guid><wfw:comment>http://www.blogjava.net/jackybu/comments/1210.html</wfw:comment><comments>http://www.blogjava.net/jackybu/articles/1210.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jackybu/comments/commentRss/1210.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jackybu/services/trackbacks/1210.html</trackback:ping><description><![CDATA[Tomcat是apache的一个子项目，也是一个开源项目，主要是用于J2EE web容器，由于是一个开源项目，在学习与开发测试中经常被用到<IMG src="http://blog.csdn.net/Emoticons/regular_smile.gif">，（而目前商业最为经常用到的web服务器是BEA WebLogic）。在开源项目中，鼎鼎大名的apache基金会大家肯定有所了解，网站链接：<A href="http://www.apache.org/">http://www.apache.org/</A>，而旗下的Jakarta Project 主要包括了Tomcat、Alexanda等Java项目，有兴趣者可看：<A href="http://jakarta.apache.org/">http://jakarta.apache.org/</A>。考虑到各位学习者的机器配置与学习成本问题，这里选了Tomcat作为我们学习与测试J2EE的环境<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;以下为一些基本配置：<BR>&nbsp;一、先从网上下载tomcat，目前最新版本是5.57，下载地址是：<A href="http://apache.freelamp.com/jakarta/tomcat-5/v5.5.7/bin/jakarta-tomcat-5.5.7.zip">http://apache.freelamp.com/jakarta/tomcat-5/v5.5.7/bin/jakarta-tomcat-5.5.7.zip</A>，下载安装完后，在安装目录下有以下目录，主要介绍一下conf、common、webapps：<BR>&nbsp;&nbsp;&nbsp;&nbsp; 如果你现在等不急了，就想体验一下tomcat的魅力的话，把你的网页拷到webapps/ROOT目录下，然后再通过浏览器访问即可，默认如下格式：<A href="http://localhost:8080/">http://localhost:8080/</A>&lt;你的网页&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp; 1)webapps文件夹主要用于web应用程序部署，比如你可以把你的应用程序包，如war文件拷到该目录下，容器会自动部署。<BR>&nbsp;&nbsp;&nbsp;&nbsp; 2)conf文件夹下主要是放置tomcat的服务器的相关配置文件<BR>&nbsp;&nbsp;&nbsp;&nbsp; 3)common文件夹主要是对容器全局变量的文件放置地方，如common/lib下就是放置一些需要全文配置的文件包。<BR><BR>二、j2ee的相关部署规范：<BR>&nbsp;&nbsp;&nbsp;&nbsp; 一般来说作为一个符合规范的web程序，会包括以下文件夹和文件：/WEB-INF/（主要是放置一些配置文件与不希望外部程序访问的隐私文件），在网络上是不允许访问该文件夹的，如当你输入以下<A href="http://localhost:8080/WEB-INF/">http://localhost:8080/WEB-INF/</A>的话就会出现错误。<BR>&nbsp;&nbsp;&nbsp;&nbsp; 在WEB-INF文件夹下有一个web.xml文件，这是对当前应用程序的相关设置，资源寻找等，/WEN-INF/文件夹下有个classes子文件夹，该文件夹是应用程序的根路径（等于是classpath的路径），/WEN-INF下还要有个lib文件夹，主要是放置需要引入的包，应用程序导入的包先从这里开始寻找，其次到容器的全局路径下$TOMCAT_HOME/common/lib下寻找。<BR>&nbsp;&nbsp;&nbsp;&nbsp; 以下是基本文件夹:<BR>/tomcat<BR>&nbsp;&nbsp;&nbsp;&nbsp; /common<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/lib<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /classes<BR>&nbsp;&nbsp;&nbsp; /conf<BR>&nbsp;&nbsp;&nbsp; /webapps<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /ROOT<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; web.xml&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;/WEB-INF<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /lib<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /classes<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /你部署的程序包<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; web.xml&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;/WEB-INF<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /lib<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /classes<BR>三、容器的配置（server.xml)<BR>&nbsp;&nbsp;&nbsp;&nbsp;到主目录/conf文件夹下server.xml文件是对web服务器的配置：<BR>&nbsp;&nbsp;&nbsp; 以下是一些常见的设置，http端口设置，找到以下：<BR>&lt;Connector&nbsp; port="8080"&nbsp;&nbsp;&nbsp;maxThreads="150" minSpareThreads="25" maxSpareThreads="75"<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; enableLookups="false" redirectPort="8443" acceptCount="100"<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; connectionTimeout="20000" disableUploadTimeout="true" /&gt;<BR>&nbsp;&nbsp;&nbsp; 把8080端口改为你喜欢使用的端口，如常见的80，以后你就可以利用该端口进行访问你的网站了：<A href="http://localhost/">http://localhost:80</A> 期中80是默认的，可以不写，其他的一下配置，可以参观相关的内容，入门就是这么简单。<BR>&nbsp;&nbsp;&nbsp;&nbsp;web.xml为servlet的一些相关配置，可以参照一下规范。可以看我写的其他文章。<BR>&nbsp;&nbsp;&nbsp; 继续说一下server.xml文件的设置，<BR>&nbsp;&nbsp;&nbsp; 找到以下：<BR>&nbsp;&nbsp;&nbsp;&lt;Host name="localhost" appBase="webapps"<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; unpackWARs="true" autoDeploy="true"<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xmlValidation="false" xmlNamespaceAware="false"&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp; ....<BR>&nbsp; &lt;/Host&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp; 在他们之间可以添加一个&lt;Context&gt;元素，如：&lt;Context path="/axis" reloadable="true" docBase="axis"&nbsp; workDir="webapps/axis/work"/&gt;，其中属性path代表是网络访问的上下文路径，reloadable表示可以在运行时在classes与lib文件夹下自动加载类包，docBase属性表示你的应用程序的路径，在windows在如：docBase="E:\Sun\axis"，workDir表示是缓存文件的放置地点，可以方便跨平台移植时不用重编译。这样，你的应用程序就可以放到硬盘上的任意地方了。还有一个方法可以做到这点（推荐）：编写一个xml文件，然后放到tomcat目录/conf/Catalina/&lt;相应的网站&gt;/目录下，如：现在我有个应用程序ACMEWeb，我编了一个文件ACMEWeb.xml内容如下：<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;Context path="/ACMEWeb" reloadable="true" docBase="E:\eclipseproject\ACMEWeb" workDir="E:\eclipseproject\ACMEWeb\work" /&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 我把它放到了tomcat目录/conf/Cataline/localhost下，在浏览器打开<A href="http://localhost/ACMEWeb">http://localhost/ACMEWeb</A> 就会转向我放在E:\eclipseproject\ACMEWeb下的程序了<BR>补充两点： <BR>1.针对网页中文get提交参数情况，http connector可能需要加上 <BR>URIEncoding="GBK"防止乱码。若post提交则无所谓 <BR>2.tomcat5.5版本以上,独立的context xml配置文件既可以放到&lt;tomcat_home&gt;/conf/Catalina/&lt;site name&gt;/,也可放到&lt;your web app's dir&gt;/META-INF/ 下 <img src ="http://www.blogjava.net/jackybu/aggbug/1210.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jackybu/" target="_blank">辰</a> 2005-02-15 11:32 <a href="http://www.blogjava.net/jackybu/articles/1210.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>彻底解决Tomcat 5.0.19中文乱码 </title><link>http://www.blogjava.net/jackybu/articles/1209.html</link><dc:creator>辰</dc:creator><author>辰</author><pubDate>Tue, 15 Feb 2005 03:29:00 GMT</pubDate><guid>http://www.blogjava.net/jackybu/articles/1209.html</guid><wfw:comment>http://www.blogjava.net/jackybu/comments/1209.html</wfw:comment><comments>http://www.blogjava.net/jackybu/articles/1209.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jackybu/comments/commentRss/1209.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jackybu/services/trackbacks/1209.html</trackback:ping><description><![CDATA[一、Include的页面乱码<BR><BR>　　现象：include进来的页面出现乱码，其它页面正常。<BR><BR>　　原因：Tomcat在缺省情况下使用ISO-8859-1编码，但是在include时有时Tomcat不能正确根据外层.jsp文件的编码解析include进来的文件，造成include进来的文件中的中文乱码。<BR><BR>　　解决：这儿可以有很多解决办法，但是对于我们的中文环境，从根本上的解决办法是将Tomcat 5.0.19的核心缺省编码从ISO-8859-1修改为GBK 。可以在下面地址下载修改过的jar文件，<BR><A href="http://www.javaresearch.org/dn/tomcat-5.0.19-jar-zh.rar" target=_blank><BR></A>　　jasper-compiler.jar，jasper-runtime.jar位于/common/lib下，其它位于/server/lib下，将新的.jar文件替代原.jar即可。<BR>　　<BR>　　二、提交的数据乱码<BR><BR>　　现象：通过表单提交的数据出现乱码。<BR><BR>　　原因：原因未明。可能是Tomcat在接收到请求后，并没有能够根据request中的信息提前正确的编码方式。<BR><BR>　　解决：可以添加一个设置字符集的Filter。<BR><BR>//=================初学者注意，请将此文件放在WEB-INF\classes\filters下，<BR>//注意先以SetCharacterEncodingFilter.java保存，然后编译一下，推荐使用eclipse<BR>
<TABLE width="100%" bgColor=#ffffff>
<TBODY>
<TR>
<TD><STRONG>package</STRONG> filters;<BR><BR><B>import</B> java.io.IOException;<BR><B>import</B> javax.servlet.Filter;<BR><B>import</B> javax.servlet.FilterChain;<BR><B>import</B> javax.servlet.FilterConfig;<BR><B>import</B> javax.servlet.ServletException;<BR><B>import</B> javax.servlet.ServletRequest;<BR><B>import</B> javax.servlet.ServletResponse;<BR><B>import</B> javax.servlet.UnavailableException;<BR><BR><B>public</B> <B>class</B> SetCharacterEncodingFilter <B>implements</B> Filter {<BR><B>　protected</B> String encoding = null;<BR><B>　protected</B> FilterConfig filterConfig = null;<BR><B>　protected</B> <B>boolean</B> ignore = <B>true</B>;<BR><BR><B>　public</B> <B>void</B> destroy() {<BR><B>　　this</B>.encoding = null;<BR><B>　　this</B>.filterConfig = null;<BR>　}<BR><BR><B>public</B> <B>void</B> doFilter(ServletRequest request, ServletResponse response,<BR>FilterChain chain)<BR><B>throws</B> IOException, ServletException {<BR><BR><FONT color=#006600><I>　// Conditionally select and set the character encoding to be used</I></FONT><BR><B>　if</B> (ignore || (request.getCharacterEncoding() == null)) {<BR>　　String encoding = selectEncoding(request);<BR><B>　　if</B> (encoding != null)<BR>　　　request.setCharacterEncoding(encoding);<BR>　}<BR><BR><FONT color=#006600><I>　// Pass control on to the next filter</I></FONT><BR>　chain.doFilter(request, response);<BR><BR>}<BR><BR><B>public</B> <B>void</B> init(FilterConfig filterConfig) <B>throws</B> ServletException {<BR><BR><B>　this</B>.filterConfig = filterConfig;<BR><B>　this</B>.encoding = filterConfig.getInitParameter(<FONT color=#000099>"encoding"</FONT>);<BR>　String value = filterConfig.getInitParameter(<FONT color=#000099>"ignore"</FONT>);<BR><B>　if</B> (value == null)<BR><B>　　this</B>.ignore = <B>true</B>;<BR><B>　else</B> <B>if</B> (value.equalsIgnoreCase(<FONT color=#000099>"true"</FONT>))<BR><B>　　this</B>.ignore = <B>true</B>;<BR><B>　else</B> <B>if</B> (value.equalsIgnoreCase(<FONT color=#000099>"yes"</FONT>))<BR><B>　　this</B>.ignore = <B>true</B>;<BR><B>　else</B><BR><B>　　this</B>.ignore = <B>false</B>;<BR><BR>}<BR><BR><B>protected</B> String selectEncoding(ServletRequest request) {<BR><B>　return</B> (<B>this</B>.encoding);<BR>}<BR><BR>}</TD></TR></TBODY></TABLE>//==================这段代码是我在网上摘录的，因为不知到出处所以无法标明作者<BR>//然后将下面&lt;filter&gt;开始的代码加入到web.xml中,它位于WEB-INF下。<BR>//我的QQ：22070699<BR>//配置web.xml<BR><BR>
<TABLE width="100%" bgColor=#ffffff>
<TBODY>
<TR>
<TD>＜filter＞<BR>　＜filter-name＞Set Character Encoding＜/filter-name＞<BR>　＜filter-class＞filters.SetCharacterEncodingFilter＜/filter-class＞<BR>　＜init-param＞<BR>　　＜param-name＞encoding＜/param-name＞<BR>　　＜param-value＞GBK＜/param-value＞<BR>　＜/init-param＞<BR>＜/filter＞<BR><BR>＜filter-mapping＞<BR>　＜filter-name＞Set Character Encoding＜/filter-name＞<BR>　＜url-pattern＞/*＜/url-pattern＞<BR>＜/filter-mapping＞</TD></TR></TBODY></TABLE><img src ="http://www.blogjava.net/jackybu/aggbug/1209.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jackybu/" target="_blank">辰</a> 2005-02-15 11:29 <a href="http://www.blogjava.net/jackybu/articles/1209.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Struts 的安装、配置与运行 </title><link>http://www.blogjava.net/jackybu/articles/1205.html</link><dc:creator>辰</dc:creator><author>辰</author><pubDate>Tue, 15 Feb 2005 03:20:00 GMT</pubDate><guid>http://www.blogjava.net/jackybu/articles/1205.html</guid><wfw:comment>http://www.blogjava.net/jackybu/comments/1205.html</wfw:comment><comments>http://www.blogjava.net/jackybu/articles/1205.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jackybu/comments/commentRss/1205.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jackybu/services/trackbacks/1205.html</trackback:ping><description><![CDATA[<SPAN id=ArticleContent1_ArticleContent1_lblContent>一、Struts的起源 
<P>　　Struts最早是作为Apache Jakarta项目的组成部分，项目的创立者希望通过对该项目的研究，改进和提高JavaServer Pages 、Servlet、标签库以及面向对象的技术水准。Struts这个名字来源于在建筑和旧式飞机中使用的支持金属架。这个框架之所以叫"Struts"，是为了提醒我们记住那些支撑我们房屋，建筑，桥梁，甚至我们踩高跷时候的基础支撑。这也是一个解释Struts在开发Web应用程序中所扮演的角色的精彩描述。当建立一个物理建筑时，建筑工程师使用支柱为建筑的每一层提供支持。同样，软件工程师使用Struts为业务应用的每一层提供支持。它的目的是为了帮助我们减少在运用MVC设计模型来开发Web应用的时间。我们仍然需要学习和应用该架构，不过它将可以完成其中一些繁重的工作。如果想混合使用Servlets和JSP的优点来建立可扩展的应用，Struts是一个不错的选择。</P>
<P>　　早期Smalltalk 程序语言便采用了MVC(Model-View -Controller) 模式( Patterns ) 以增加程序代码弹性，MVC模式将程序代码整理切割为三部份，Model 部分是业务与应用领域( Business domain) 相关逻辑、管理状态之对象，Controller 部分接收来自View 所输入的资料并与Model 部分互动，是业务流程控制( Flow Control) 之处，View 部分则负责展现资料、接收使用者输入资料。在Java 应用中，JFC/Swing、AWT、JSP 皆是可用作View 之技术规格，而JavaBean 与Enterprise JavaBean 规格则可用于Model 程序代码，一旦应用程序以MVC 模式加以适当之分割，Model 部分程序代码可在不同使用者接口外观之应用程序中重复使用。</P>
<P>　　随着JSP 与Servlet 技术大量应用于以Web 为基础之应用程序，Java 开发人员群体认为应以较佳之模式以提升Web 应用程序之可维护性与重复使用性。早期JSP 规格书中曾列举两种可行之JSP 应用架构，分别为Model1 与Model 2。</P>
<P>　　在Model 1 架构中，JSP 直接处理Web 浏览器送来之请求( Request )，并辅以JavaBean 处理应用相关逻辑。Model 1 架构单纯编写比较容易，但在Model 1 中JSP 可能同时肩负View 与Controller 角色，两类程序代码有可能混杂而不易维护。而Model 2 中将Servlet 纳入架构中扮演前端Controller 角色，将Web 浏览器送出之请求集中送至Servlet ，Servlet 可集中管理使用者登入、权限控制、多国语言转换等前置处理，再视需求转向给对应之JSP 处理。Model 2 中采用了较佳之MVC 模式，但增加了编写复杂度。</P>
<P>　　Struts是Apache软件基金下Jakarta项目的一部分。除Struts之外，还有其他成功的开源产品，包括Tomcat， Ant 和Velocity。2000 年Craig R. McClanahan 先生贡献了他编写的JSP Model 2 架构之Application Framework 原始程序代码给Apache 基金会，成为Apache Jakarta 计划Struts Framework 前身。</P>
<P>　　开始的代码基础从2000年5月开始开发，直到2001年6月，1.0版本发布。有30 多个开发者参与进来，并有数千人参与到讨论组中。Struts 代码基础由一个志愿的Commnitter团队来管理。到2002年，Struts 小组共有9个志愿Commnitter。</P>
<P>　　Struts框架的主要架构设计和开发者是Craig R.McClanahan。Craig 也是Tomcat 4的主要架构师，以及Java Web Services Developer Pack的主要架构师和实现者。他现在是Sun的JavaServer Faces (JSR-127) 以及J2EE平台的Web层架构的规范领导。Craig R. McClanahan 先生是JCP ExpertGroup 成员之一，曾参与JSP 规格制定与Tomcat 4 之编写，因此Struts Framework 广受Java 开发人员群体所重视。Borland 自2002 年底开始于开发工具JBuilder 中支持Struts Framework。</P>
<P>二、Struts安装</P>
<P>　　1、安装Struts需要的软件 </P>
<P>　　Java Development Kit-- 我们需要download和install 1.2(或之后)版本的JDK。</P>
<P>　　　下载地址：</P>
<P>　　　http://java.sun.com/j2se</P>
<P>　　Servlet Container -- 通常的选择是下载Tomcat(至少是3.1版，推荐使用4.0以上的版本)。</P>
<P>　　　下载地址：</P>
<P>　　　http://jakarta.apache.org/tomcat</P>
<P>　　Ant Build System -- 如果我们通过Struts源码发布包安装，我们必须下载1.1或之后版本的ant build system。在我们通过Struts来开发我们自己的Web应用程序是，推荐使用ant来build我们的应用。</P>
<P>　　　下载地址：</P>
<P>　　　http://jakarta.apache.org/ant</P>
<P>　　Servlet API Classes -- 为了编译Structs自己，或应用程序使用Struts，我们需要一个包含Servlet和JSP API对象的servlet.jar包。大多数Servlet container（例如Tomcat)已经自带了这个文件。否则，我们必需下载：http://jakarta.apache.org/builds/jakarta-servletapi</P>
<P>　　XML Parser -- Structs需要一个与Java API for XML Parsing(JAXP)规格兼容的XML处理器，我们可以使用Xerces。</P>
<P>　　　下载地址： </P>
<P>　　　http://xml.apache.org/xerces-j</P>
<P>　　Xalan XSLT Processor -- 如果我们通过Structs源码发布版来构造我们的Structs系统，我们必须下载和安装1_2_D01或之后版本的Xalan XSLT处理器(Xerces中已自带Xalan)。这个处理器用于将基于XML的Structs文档转换为Html文档。</P>
<P>　　2、通过源码构造Structs </P>
<P>　　1）下载Structs的源码发布包。</P>
<P>　　2）设置ANT_HOME环境变量，指向我们的Ant目录。</P>
<P>　　3）设置JAVA_HOME环境变量，指向我们的JDK目录。</P>
<P>　　4）设置SERVLETAPI_HOME环境变量，指向我们的Servlet API目录（如果我们的CLASSPATH已经包含了servlet.jar，就不需要指定该目录）</P>
<P>　　5）将Structs的源码发布包进行解包。</P>
<P>　　6）进入Structs目录，运行以下命令：</P>
<P>　　./build.sh dist</P>
<P>　　该命令将创建Struts的二进制发布包，目录在../dist/structs(相对于我们的编译目录）。</P>
<P>　　3、通过Struts的二进制发布包安装Structs </P>
<P>　　1）下载Struts的二进制发布版。</P>
<P>　　2）将Struts的二进制发布版进行解包。(如果我们是通过Struts源码构造Struts，build的结果就已经是已解包的Struts)。解包后的Struts包含以下内容：</P>
<P>　　lib/struts.jar -- 这个文件包含了Struts的所有Java对象。我们需要把它拷贝到我们的Web应用的WEB-INF/lib目录。</P>
<P>　　lib/structs.tld --这是一个"tag library descriptor"文件，它描述了Struts库的自由tag。需要将它拷贝到我们的Web应用的WEB-INF目录。</P>
<P>　　webapps/struts-documentation.war -- 这是一个"web application archive"文件，包含了所有的Struts文档。我们可以将它安装到支持Servlet API 2.2或之后版本的servlet container(推荐使用tomcat)中。</P>
<P>　　webapps/struts-example.war -- 这是一个web应用实例，它广泛地演示了Struts的许多功能。我们可以将它安装到兼容Servlet2.2或之后版本以及JSP1.1或之后版本规范的servlet容器中(推荐使用tomcat)。<BR>webapps/struts-test.war -- 这个web应用包含了Struts支持的许多tag的测试网页，可以作为使用Struts tag的例子。</P>
<P>　　4、Struts的基本组件包</P>
<P>　　安装好的struts大约有15包，近200个类所组成，而且数量还在不断的扩展。在此我们不能一一介绍，只能列举几个主要的简要的介绍一下。下表说明了目前struts api中基本的几个组件包，包括<BR>action,actions,config,util,taglib,validator。如下表1所示：</P>
<P>org.apache.struts.action <BR>　基本上，控制整个struts framework的运行的核心类、组件都在这个包中，比如我们上面提到的控制器ActionServlet。已经Action,ActionForm,ActionMapping等等。struts1.1比1.0多了 DynaActionForm 类。增加了动态扩展生成FormBean功能 <BR>org.apache.struts.actions <BR>　这个包是主要作用是提供客户的http请求和业务逻辑处理之间的特定适配器转换功能，而1.0版本中的部分动态增删FromBean的类，也在struts1.1中被Action包的DynaActionForm组件所取代 <BR>org.apache.struts.config <BR>　提供对配置文件struts-config.xml元素的映射。这也是sturts1.1中新增的功能 <BR>org.apache.struts.util <BR>　Strtuts为了更好支持web application的应用，体统了一个些常用服务的支持，比如Connection Pool和Message Source。详细信息请参考http://jakarta.apache.org/struts/api/org/apache/struts/util/package-summary.html <BR>org.apache.struts.taglib <BR>　这不是一个包，而是是一个客户标签类的集合。下面包括Bean Tags，HTML Tags，Logic Tags，Nested Tags，Template Tags这几个用于构建用户界面的标签类。 <BR>org.apache.struts.validator <BR>　Struts1.1 framework中增加了validator framework，用于动态的配置from表单的验证。详细信息请参阅 http://home.earthlink.net/~dwinterfeldt/ </P>
<P>三、Struts 配置与组件介绍</P>
<P>　　有关struts组件配置struts-config.xml文件说明在前面的文章中已经介绍过，这里就不再说了，下面主要介绍框架中组件与配置。</P>
<P>　　下表列出了Struts的核心类，即对应的经典的MVC组件职责。</P>
<P>　　表格2 核心Struts 类和MVC 的对应</P>
<P>类 描述 <BR>ActionForward 用户指向或者视图选择 <BR>ActionForm 状态改变的数据 <BR>ActionMapping 状态改变事件 <BR>ActionServlet 控制器，接受用户请求和状态改变，以及发出视图选择 <BR>Action 控制器的一部分，于模型交互，执行状态改变或状态查询，以及告诉ActionServlet 下一个选择的视图 </P>
<P>　　除了这些核心类， Struts 使用一些配置文件和视图助手（view helpers）来沟通控制器和模型。下表列出了Struts 配置文件和描述了他们在架构中的角色。</P>
<P>　　表格3 Strtuts 配置文件</P>
<P>文件 目的 <BR>ApplicationResources.properties 存储本地化信息和标签，以使应用可以国际化 <BR>struts-config.xml 存储控制器对象的缺省配置，包括模型支持的用户指向，状态改变，状态查询 </P>
<P>　　为将Struts配置数据暴露给视图，框架以JSP标签的形式提供了大量的助手类，如表4 Strtus 视图助手。</P>
<P><BR>标记库描述符 目的 <BR>struts-html.tld 扩展HTML Form的JSP标记 <BR>struts-bean.tld 扩展处理JavaBean的JSP标记 <BR>struts-logic.tld 扩展测试属性值的JSP标记 </P>
<P>　　控制器组件的配置</P>
<P>　　框架中的控制器组件是有org.apache.struts.action.ActionServlet类实现的，这个类是javax.servlet.http.HttpServlet类的扩展。</P>
<P>　　ActionServlet配置：</P>
<P>　　我们需要在web.xml中声明ActionServlet，并且将它配置成启动时进行加载。以下为可以配置的初始化参数：</P>
<P>参数 默认值 描述 <BR>application Null 应用程序的资源集合的类 <BR>bufferSize 4096 文件上传的缓冲区大小 <BR>config /WEB-INF/struts-config.xml 配置文件的位置和名称 <BR>content Text/html 默认的内容类型 <BR>debug 0 程序调试的级别 <BR>detail 0 程序调试细节的级别 <BR>factory Null 消息资源工厂，糜诠驶薪馐拖⒆试?/TD&gt; <BR>formBean org.apache.struts.action.ActionFormBean 封装ActionForm bean信息的类的名称 <BR>forward Org.apache.struts.action.ActionForward 封装ActionForward对象信息的类的名称 <BR>locale True 为true,将在用户会话中存储一个本地对象 <BR>mapping Org.apache.struts.action.ActionForward 封装ActionMapping信息的类的名称 <BR>maxFileSize 250M 上传文件的最大尺寸 <BR>multipartClass Org.apache.struts.action.ActionForward 处理多部分请求的类的名称 <BR>noCache False HTTP标头是否要设置为禁止缓寸 <BR>Null True 设置为true，对于无效的信息关键字将返回null <BR>tempDir 作为一个servlet参数提供给程序的工作目录 处理下载文件是使用的临时工作目录 <BR>validate True 是否使用新格式的配置文件 <BR>vallidating True 是否对配置文件进行有效性分析 </P>
<P>　　大多数情况下，标准的servlet就能够满足用户需要。</P>
<P>　　第一次收到特定请求的URI时，ActionServlet将适当的Action类进行实例化，然后ActionServlet在Action类实例中以servlet为变量名存储一个引用。当被实例化后，Action类会被暂存以备再用。</P>
<P>　　错误处理</P>
<P>　　struts提供了两个类来处理错误：ActionErrors和ActionError，它们都扩展org.apache.struts.action。ActionErrors保存着ActionError对象的集合，其中每一个代表了独立的错误信息。每个ActionError都包含了关键字，能够映射到资源文件中存储的错误信息，而这个资源文件是在ActionServlet初始化参数中指定的。</P>
<P>四、Struts的运行</P>
<P>　　可通过以下的步骤在我们自己的应用程序中使用Struts：</P>
<P>　　1、将Struts目录的lib/struts.jar拷贝到web应用的WEB-INF/lib目录。</P>
<P>　　2、将Struts目录的lib/struts*.tld拷贝到web应用的WEB-INF目录。</P>
<P>　　3、修改Web应用目录的WEB-INF/web.xml文件，增加一个＜servlet＞元素来定义controller servlet，增加一个＜servlet-mapping＞元素来建立URI请求与servlet的对应关系。可以参照Struts例子中的WEB-INF/web.xml文件来了解详细的语法要求。</P>
<P>　　4、修改Web应用目录的WEB-INF/web.xml文件，使之包含以下的tag库定义：</P>
<P>＜taglib＞<BR>＜taglib-uri＞/WEB-INF/struts.tld＜/taglib-uri＞<BR>＜taglib-location＞/WEB-INF/struts.tld＜/taglib-location＞<BR>＜/taglib＞<BR>＜taglib＞<BR>＜taglib-uri＞/WEB-INF/struts-bean.tld＜/taglib-uri＞<BR>＜taglib-location＞/WEB-INF/struts-bean.tld＜/taglib-location＞<BR>＜/taglib＞<BR>＜taglib＞<BR>＜taglib-uri＞/WEB-INF/struts-logic.tld＜/taglib-uri＞<BR>＜taglib-location＞/WEB-INF/struts-logic.tld＜/taglib-location＞<BR>＜/taglib＞ </P>
<P>　　5、创建一个WEB-INF/action.xml文件来定义我们的web应用的action映射关系。可以参照Struts例子中的action.xml文件来了解详细的语法要求。</P>
<P>　　6、在使用Struts tag库的JSP网页中加入以下tag库定义：</P>
<P>＜@ taglib uri="/WEB-INF/struts.tld" prefix="struts" %＞<BR>＜@ taglib uri="/WEB-INF/struts-bean.tld" prefix="bean" %＞<BR>＜@ taglib uri="/WEB-INF/struts-logic.tld" prefix="logic" %＞ </P>
<P>　　7、最后，在编译我们的web应用的java程序时，不要忘了在CLASSPATH中包含struts.jar文件。</P>
<P>　　五、Struts优缺点</P>
<P>　　优点：</P>
<P>　　Struts跟Tomcat、Turbine等诸多Apache项目一样，是开源软件，这是它的一大优点。使开发者能更深入的了解其内部实现机制。除此之外，Struts的优点主要集中体现在两个方面：Taglib和页面导航。Taglib是Struts的标记库，灵活动用，能大大提高开发效率。另外，就目前国内的JSP开发者而言，除了使用JSP自带的常用标记外，很少开发自己的标记，或许Struts是一个很好的起点。</P>
<P>　　关于页面导航，我们认为那将是今后的一个发展方向，事实上，这样做，使系统的脉络更加清晰。通过一个配置文件，即可把握整个系统各部分之间的联系，这对于后期的维护有着莫大的好处。尤其是当另一批开发者接手这个项目时，这种优势体现得更加明显。</P>
<P>　　缺点：</P>
<P>　　Taglib是Struts的一大优势，但对于初学者而言，却需要一个持续学习的过程，甚至还会打乱我们网页编写的习惯，但是，当我们习惯了它时，我们会觉得它真的很棒。Struts将MVC的Controller一分为三，在竦媒峁垢忧逦耐保苍黾恿讼低车母丛佣取：廖抟晌剩斫?Struts 必须接受一定的培训。随着变化的不断加入，这有时会令人很沮丧。</P>
<P>　　Struts从产生到现在还不过3-4年时间，就已逐步越来越多运用于商业软件。虽然它现在还有不少缺点，但它是一种非常优秀的J2EE MVC实现方式，如果我们的系统准备采用J2EE MVC架构，那么，不妨考虑一下Struts。</P>
<P>　　Struts 是一种基于 Web 的 MVC 解决方案，所以必须用 HTML、JSP 文件和 servlet 来实现它，Struts 需要支持 JSP 1.1 和 Servlet 2.2 规范的 servlet 容器。学习、理解和掌握Struts是我们每个基于J2EE软件开发人员一门必修的课程，也是我们对企业J2EE技术应用的进一步深化。</P></SPAN><img src ="http://www.blogjava.net/jackybu/aggbug/1205.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jackybu/" target="_blank">辰</a> 2005-02-15 11:20 <a href="http://www.blogjava.net/jackybu/articles/1205.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>java连接MySql数据库 </title><link>http://www.blogjava.net/jackybu/articles/1099.html</link><dc:creator>辰</dc:creator><author>辰</author><pubDate>Sat, 12 Feb 2005 15:24:00 GMT</pubDate><guid>http://www.blogjava.net/jackybu/articles/1099.html</guid><wfw:comment>http://www.blogjava.net/jackybu/comments/1099.html</wfw:comment><comments>http://www.blogjava.net/jackybu/articles/1099.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jackybu/comments/commentRss/1099.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jackybu/services/trackbacks/1099.html</trackback:ping><description><![CDATA[<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US>package com.roytel.rtccp.util;</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US><?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /><o:p>&nbsp;</o:p></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US>import java.sql.*;</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US><o:p>&nbsp;</o:p></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US>public class DBManager {</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US>//</SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">用户名</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US><SPAN style="mso-spacerun: yes">&nbsp; </SPAN>private String user = "";</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US>//</SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">密码</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US><SPAN style="mso-spacerun: yes">&nbsp; </SPAN>private String password = "";</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US>//</SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">主机</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US><SPAN style="mso-spacerun: yes">&nbsp; </SPAN>private String host = "";</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US>//</SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">数据库名字</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US><SPAN style="mso-spacerun: yes">&nbsp; </SPAN>private String database = "";</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US><o:p>&nbsp;</o:p></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US><SPAN style="mso-spacerun: yes">&nbsp; </SPAN>/*</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US><SPAN style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp;&nbsp; </SPAN>private String url="jdbc:mysql://"+host+"/"+"useUnicode=true&amp;characterEncoding=GB2312";</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US><SPAN style="mso-spacerun: yes">&nbsp;&nbsp; </SPAN>*/</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US><SPAN style="mso-spacerun: yes">&nbsp; </SPAN>private String url ="";</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US><SPAN style="mso-spacerun: yes">&nbsp; </SPAN>private Connection con = null;</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US><o:p>&nbsp;</o:p></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US><SPAN style="mso-spacerun: yes">&nbsp; </SPAN>Statement stmt;</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US><SPAN style="mso-spacerun: yes">&nbsp; </SPAN>/**</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US><SPAN style="mso-spacerun: yes">&nbsp;&nbsp; </SPAN>* </SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">根据主机、数据库名称、数据库用户名、数据库用户密码取得连接。</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US><SPAN style="mso-spacerun: yes">&nbsp;&nbsp; </SPAN>* @param host String</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US><SPAN style="mso-spacerun: yes">&nbsp;&nbsp; </SPAN>* @param database String</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US><SPAN style="mso-spacerun: yes">&nbsp;&nbsp; </SPAN>* @param user String</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US><SPAN style="mso-spacerun: yes">&nbsp;&nbsp; </SPAN>* @param password String</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US><SPAN style="mso-spacerun: yes">&nbsp;&nbsp; </SPAN>*/</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US><SPAN style="mso-spacerun: yes">&nbsp; </SPAN>public DBManager(String host, String database, String user, String password) {</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US><o:p>&nbsp;</o:p></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US><SPAN style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp; </SPAN>this.host = host;</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US><SPAN style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp; </SPAN>this.database = database;</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US><SPAN style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp; </SPAN>this.user = user;</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21.75pt"><SPAN lang=EN-US>this.password = password;</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21.75pt"><SPAN lang=EN-US>//</SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">显示中文</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US><SPAN style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp; </SPAN>this.url = "jdbc:mysql://" + host + "/" + database +</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US><SPAN style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN>"?useUnicode=true&amp;characterEncoding=GB2312";</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US><o:p>&nbsp;</o:p></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US><SPAN style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp; </SPAN>try {</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US><SPAN style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN>Class.forName("org.gjt.mm.mysql.Driver");</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US><SPAN style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp; </SPAN>}</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US><SPAN style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp; </SPAN>catch (ClassNotFoundException e) {</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US><SPAN style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN>System.err.println("class not found:" + e.getMessage());</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US><SPAN style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp; </SPAN>}</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US><o:p>&nbsp;</o:p></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US><SPAN style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp; </SPAN>try {</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US><SPAN style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN>con = DriverManager.getConnection(this.url, this.user, this.password);</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US>//</SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">连接类型为</SPAN><SPAN lang=EN-US>ResultSet.TYPE_SCROLL_INSENSITIVE,<SPAN style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN><SPAN style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN>ResultSet.CONCUR_READ_ONLY</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US><SPAN style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN>stmt = con.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US><SPAN style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN>ResultSet.CONCUR_READ_ONLY);</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US><SPAN style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp; </SPAN>}</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US><SPAN style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp; </SPAN>catch (SQLException a) {</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US><SPAN style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN>System.err.println("sql exception:" + a.getMessage());</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US><SPAN style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp; </SPAN>}</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US><SPAN style="mso-spacerun: yes">&nbsp; </SPAN>}</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US>/**</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US>* </SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">返回取得的连接</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US>*/</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US><SPAN style="mso-spacerun: yes">&nbsp; </SPAN>public Connection getCon() {</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US><SPAN style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp; </SPAN>return con;</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US><SPAN style="mso-spacerun: yes">&nbsp; </SPAN>}</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US>/**</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US>* </SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">执行一条简单的查询语句</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US>* </SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">返回取得的结果集</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US>*/</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US><SPAN style="mso-spacerun: yes">&nbsp; </SPAN>public ResultSet executeQuery(String sql) {</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US><SPAN style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp; </SPAN>ResultSet rs = null;</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US><SPAN style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp; </SPAN>try {</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US><SPAN style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN>rs = stmt.executeQuery(sql);</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US><SPAN style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp; </SPAN>}</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US><SPAN style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp; </SPAN>catch (SQLException e) {</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US><SPAN style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN>e.printStackTrace();</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US><SPAN style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp; </SPAN>}</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US><SPAN style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp; </SPAN>return rs;</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US><SPAN style="mso-spacerun: yes">&nbsp; </SPAN>}</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US>/**</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US>* </SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">执行一条简单的更新语句</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US>* </SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">执行成功则返回</SPAN><SPAN lang=EN-US>true</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US>*/</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US><SPAN style="mso-spacerun: yes">&nbsp; </SPAN>public boolean executeUpdate(String sql) {</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US><SPAN style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp; </SPAN>boolean v = false;</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US><SPAN style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp; </SPAN>try {</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US><SPAN style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN>v = stmt.executeUpdate(sql) &gt; 0 ? true : false;</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US><SPAN style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp; </SPAN>}</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US><SPAN style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp; </SPAN>catch (SQLException e) {</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US><SPAN style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN>e.printStackTrace();</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US><SPAN style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp; </SPAN>}</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US><SPAN style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp; </SPAN>finally {</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US><SPAN style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN>return v;</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US><SPAN style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp; </SPAN>}</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US><SPAN style="mso-spacerun: yes">&nbsp; </SPAN>}</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US><o:p>&nbsp;</o:p></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US>}<BR><o:p><BR>能用的，你可以扩充，比如增加执行预编译语句的方法、执行存储过程的方法，也可以用连接池的方法。</o:p></SPAN></P><img src ="http://www.blogjava.net/jackybu/aggbug/1099.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jackybu/" target="_blank">辰</a> 2005-02-12 23:24 <a href="http://www.blogjava.net/jackybu/articles/1099.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>cnjbb Java技术及应用基础 精华帖列表一瞥 </title><link>http://www.blogjava.net/jackybu/articles/1097.html</link><dc:creator>辰</dc:creator><author>辰</author><pubDate>Sat, 12 Feb 2005 15:22:00 GMT</pubDate><guid>http://www.blogjava.net/jackybu/articles/1097.html</guid><wfw:comment>http://www.blogjava.net/jackybu/comments/1097.html</wfw:comment><comments>http://www.blogjava.net/jackybu/articles/1097.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jackybu/comments/commentRss/1097.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jackybu/services/trackbacks/1097.html</trackback:ping><description><![CDATA[<P><STRONG>精华帖列表一瞥</STRONG> <BR><BR>1.乱码问题类<BR><A href="http://www.cnjsp.org/cnjbb/showthread.jsp?forumID=17&amp;rootID=439&amp;announceID=439" target=_blank>中文字符集的一些解决方法</A><BR><BR><A href="http://www.cnjsp.org/cnjbb/showthread.jsp?forumID=17&amp;rootID=22077&amp;announceID=22092" target=_blank>中文乱码不完全解决方法</A><BR><BR><A href="http://www.cnjsp.org/cnjbb/showthread.jsp?forumID=4&amp;rootID=13721&amp;announceID=13721" target=_blank>utfToGBK</A><BR><BR><A href="http://www.cnjsp.org/cnjbb/showthread.jsp?forumID=4&amp;rootID=34755&amp;announceID=34755" target=_blank>JSP中GET传递中文出现乱码，亟待解决</A><BR><BR>-------------------------------------------------------<BR>2.数据库问题类<BR><A href="http://www.cnjsp.org/cnjbb/showthread.jsp?forumID=4&amp;rootID=33780&amp;announceID=34013&amp;Page=1&amp;skin=1" target=_blank>no&nbsp;suitable&nbsp;driver&nbsp;found</A><BR><BR><A href="http://www.cnjsp.org/cnjbb/showthread.jsp?forumID=23&amp;rootID=25278&amp;announceID=25278" target=_blank>有关大对象的读取</A><BR><BR><A href="http://www.cnjsp.org/cnjbb/showthread.jsp?forumID=3&amp;rootID=6864&amp;announceID=6864" target=_blank>如何在ORACLE里进行大段的文字存储并读取？</A><BR><BR><A href="http://www.cnjsp.org/cnjbb/showthread.jsp?forumID=17&amp;rootID=32562&amp;announceID=32562#32562" target=_blank>关于生成图片的问题</A><BR><BR><A href="http://www.cnjsp.org/cnjbb/showthread.jsp?forumID=10&amp;rootID=4006&amp;announceID=4006" target=_blank>Mysql数据库的备份</A><BR><BR><A href="http://www.cnjsp.org/cnjbb/showthread.jsp?forumID=10&amp;rootID=4931&amp;announceID=4931" target=_blank>Oracle在Solaris上的安装</A><BR><BR><A href="http://www.cnjsp.org/cnjbb/showthread.jsp?forumID=10&amp;rootID=20804&amp;announceID=20804" target=_blank>使用MySQL内建复制功能来最佳化可用性</A><BR><BR><A href="http://www.cnjsp.org/cnjbb/showthread.jsp?forumID=10&amp;rootID=9191&amp;announceID=9807" target=_blank>JDBC驱动大全</A><BR><BR><A href="http://www.cnjsp.org/cnjbb/list.jsp?forumID=23" target=_blank>JDBC专栏</A><BR><BR><A href="http://www.cnjsp.org/cnjbb/showthread.jsp?forumID=4&amp;rootID=34357&amp;announceID=34386#34386" target=_blank>浏览：java.sql.SQLException:&nbsp;违反协议</A><BR><BR>-------------------------------------------------------<BR>3.分页问题类<BR><A href="http://www.cnjsp.org/cnjbb/showthread.jsp?forumID=17&amp;rootID=21259&amp;announceID=21259" target=_blank>JSP中常用到的分页显示程序</A><BR><BR>-------------------------------------------------------<BR>4.环境配置类<BR><A href="http://www.cnjsp.org/cnjbb/showthread.jsp?forumID=17&amp;rootID=16652&amp;announceID=16652" target=_blank>Windows下配置JAVA环境</A><BR><BR><A href="http://www.cnjsp.org/cnjbb/showthread.jsp?forumID=17&amp;rootID=2037&amp;announceID=2037" target=_blank>Apache2.0.43与Tomcat4.1.12的配置</A><BR><BR><A href="http://www.cnjsp.org/cnjbb/showthread.jsp?forumID=3&amp;rootID=29987&amp;announceID=29987" target=_blank>JSP&nbsp;环境安装</A><BR><BR><A href="http://www.cnjsp.org/cnjbb/showthread.jsp?forumID=3&amp;rootID=27854&amp;announceID=27854" target=_blank>正确安装及配置&nbsp;Java&nbsp;开发环境</A><BR><BR><A href="http://www.cnjsp.org/cnjbb/showthread.jsp?forumID=3&amp;rootID=27393&amp;announceID=27393" target=_blank>为采用&nbsp;Tomcat&nbsp;建立的&nbsp;JSP&nbsp;虚拟主机提供&nbsp;MySQL&nbsp;数据库支持</A><BR><BR><A href="http://www.cnjsp.org/cnjbb/showthread.jsp?forumID=3&amp;rootID=27386&amp;announceID=27386" target=_blank>Tomcat虚拟主机的安全配置</A><BR><BR><A href="http://www.cnjsp.org/cnjbb/showthread.jsp?forumID=3&amp;rootID=24925&amp;announceID=24925" target=_blank>配置&nbsp;Tomcat&nbsp;集群</A><BR><BR><A href="http://www.cnjsp.org/cnjbb/showthread.jsp?forumID=3&amp;rootID=21431&amp;announceID=21431" target=_blank>Linux&nbsp;下安装支持&nbsp;JSP/PHP&nbsp;的&nbsp;WEB&nbsp;server</A><BR><BR><A href="http://www.cnjsp.org/cnjbb/showthread.jsp?forumID=3&amp;rootID=2951&amp;announceID=2951" target=_blank>整理过的server.xml</A><BR><BR><BR>-------------------------------------------------------<BR>5.工具资源类<BR><A href="http://www.cnjsp.org/cnjbb/showthread.jsp?forumID=17&amp;rootID=8285&amp;announceID=8285" target=_blank>JBuilder&nbsp;学习资料</A><BR><BR><A href="http://www.cnjsp.org/cnjbb/showthread.jsp?forumID=17&amp;rootID=2847&amp;announceID=2849" target=_blank>11.开发WebLogic&nbsp;Server&nbsp;应用（一）</A><BR><BR><A href="http://www.cnjsp.org/cnjbb/showthread.jsp?forumID=3&amp;rootID=27855&amp;announceID=27855" target=_blank>Java&nbsp;Servlet&nbsp;和&nbsp;JSP教程</A><BR><BR><A href="http://www.cnjsp.org/cnjbb/showthread.jsp?forumID=4&amp;rootID=33550&amp;announceID=33550" target=_blank>有关JSP多文件上传组件的问题</A><BR><BR>-------------------------------------------------------<BR>6.其它类<BR><A href="http://www.cnjsp.org/cnjbb/showthread.jsp?forumID=17&amp;rootID=21258&amp;announceID=21258" target=_blank>JSP中显示数据中常用到的树</A><BR><BR><A href="http://www.cnjsp.org/cnjbb/showthread.jsp?forumID=17&amp;rootID=27892&amp;announceID=27955" target=_blank>JAVA命名规范</A><BR><BR><A href="http://www.cnjsp.org/cnjbb/showthread.jsp?forumID=17&amp;rootID=25083&amp;announceID=25083" target=_blank>JavaBean&nbsp;+&nbsp;EJB(Stateless&nbsp;Session&nbsp;Bean&nbsp;+&nbsp;CMP&nbsp;or&nbsp;DAO)&nbsp;常用方法示例</A><BR><BR><A href="http://www.cnjsp.org/cnjbb/showthread.jsp?forumID=3&amp;rootID=5749&amp;announceID=5749" target=_blank>关于JSP学习方法的讨论</A><BR><BR><A href="http://www.cnjsp.org/cnjbb/showthread.jsp?forumID=4&amp;rootID=9058&amp;announceID=9058" target=_blank>ServletConfig和ServletConfig参数访问</A><BR><BR><A href="http://www.cnjsp.org/cnjbb/showthread.jsp?forumID=4&amp;rootID=1375&amp;announceID=1375" target=_blank>Servlet饼图工具</A><BR><BR><A href="http://www.cnjsp.org/cnjbb/showthread.jsp?forumID=6&amp;rootID=7287&amp;announceID=7287" target=_blank>使用JSP&nbsp;+&nbsp;JAVABEAN&nbsp;+&nbsp;XML&nbsp;开发的一个例子&nbsp;</A><BR><BR>-------------------------------------------------------<BR>7.mail&nbsp;类<BR><A href="http://www.cnjsp.org/cnjbb/showthread.jsp?forumID=4&amp;rootID=5082&amp;announceID=5082" target=_blank>JAVA&nbsp;平台的MAIL实战精华(一)</A><BR><BR>-------------------------------------------------------<BR>8.ejb&nbsp;类<BR><A href="http://www.cnjsp.org/cnjbb/showthread.jsp?forumID=7&amp;rootID=19974&amp;announceID=19974" target=_blank>EJB&nbsp;资料</A><BR><BR><A href="http://www.cnjsp.org/cnjbb/showthread.jsp?forumID=7&amp;rootID=657&amp;announceID=657" target=_blank>JBuilder7+Weblogic7+mysql&nbsp;开发EJB的配置(加入BMP,CMP开发实例)</A><BR><BR><A href="http://www.cnjsp.org/cnjbb/showthread.jsp?forumID=7&amp;rootID=8744&amp;announceID=8744" target=_blank>什么是Entity&nbsp;Bean中的bmp模式以及cmp模式</A><BR><BR><A href="http://www.cnjsp.org/cnjbb/showthread.jsp?forumID=17&amp;rootID=25083&amp;announceID=25083" target=_blank>浏览：JavaBean&nbsp;+&nbsp;EJB(Stateless&nbsp;Session&nbsp;Bean&nbsp;+&nbsp;CMP&nbsp;or&nbsp;DAO)&nbsp;常用方法示例</A><BR>-------------------------------------------------------<BR><BR><BR><BR>9.xml资料&nbsp;<BR><BR><A href="http://www.cnjsp.org/cnjbb/showthread.jsp?forumID=6&amp;rootID=33718&amp;announceID=33762#33762" target=_blank>浏览：XSL=XSLT+XSL-FO,请下载相关</A><BR>-------------------------------------------------------<BR><BR>10.excel的部分资料<BR><A href="http://www.cnjsp.org/cnjbb/showthread.jsp?forumID=17&amp;rootID=33170&amp;announceID=33170" target=_blank>java操作excel,从excel导入数据库</A><BR><BR><BR><A href="http://www.cnjsp.org/cnjbb/showthread.jsp?forumID=24&amp;rootID=26438&amp;announceID=26438" target=_blank>一个太太太大亨让人激动的IE功能&nbsp;</A><BR>-------------------------------------------------------<BR><BR>11.tomcat<BR><A href="http://www.cnjsp.org/cnjbb/showthread.jsp?forumID=3&amp;rootID=33815&amp;announceID=33842#33842" target=_blank>浏览：如何把tomcat运行前的startup.bat安装成服务啊?</A><BR>-------------------------------------------------------<BR><BR><BR>12.resin<BR><A href="http://www.cnjsp.org/cnjbb/showthread.jsp?forumID=17&amp;rootID=33776&amp;announceID=33776" target=_blank>Apache和Resin如何整合？</A><BR><BR><A href="http://www.cnjsp.org/cnjbb/showthread.jsp?forumID=3&amp;rootID=26236&amp;announceID=26236" target=_blank>iis+resin的详细配置说明</A><BR></P>
<P>&nbsp;</P>
<P><A href="http://www.cnjbb.org/thread.jsp?boardid=3&amp;threadid=32562">http://www.cnjbb.org/thread.jsp?boardid=3&amp;threadid=32562</A></P><img src ="http://www.blogjava.net/jackybu/aggbug/1097.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jackybu/" target="_blank">辰</a> 2005-02-12 23:22 <a href="http://www.blogjava.net/jackybu/articles/1097.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>使用command模式实现自己的一个小型web MVC </title><link>http://www.blogjava.net/jackybu/articles/1096.html</link><dc:creator>辰</dc:creator><author>辰</author><pubDate>Sat, 12 Feb 2005 15:21:00 GMT</pubDate><guid>http://www.blogjava.net/jackybu/articles/1096.html</guid><wfw:comment>http://www.blogjava.net/jackybu/comments/1096.html</wfw:comment><comments>http://www.blogjava.net/jackybu/articles/1096.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jackybu/comments/commentRss/1096.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jackybu/services/trackbacks/1096.html</trackback:ping><description><![CDATA[<A href="http://www.cnjbb.org/thread.jsp?boardid=3&amp;threadid=43224">http://www.cnjbb.org/thread.jsp?boardid=3&amp;threadid=43224</A><BR><A href="http://www.cnjbb.org/thread.jsp?boardid=3&amp;threadid=43902">http://www.cnjbb.org/thread.jsp?boardid=3&amp;threadid=43902</A><img src ="http://www.blogjava.net/jackybu/aggbug/1096.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jackybu/" target="_blank">辰</a> 2005-02-12 23:21 <a href="http://www.blogjava.net/jackybu/articles/1096.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>ServletConfig和ServletConfig参数访问. </title><link>http://www.blogjava.net/jackybu/articles/1095.html</link><dc:creator>辰</dc:creator><author>辰</author><pubDate>Sat, 12 Feb 2005 15:18:00 GMT</pubDate><guid>http://www.blogjava.net/jackybu/articles/1095.html</guid><wfw:comment>http://www.blogjava.net/jackybu/comments/1095.html</wfw:comment><comments>http://www.blogjava.net/jackybu/articles/1095.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/jackybu/comments/commentRss/1095.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jackybu/services/trackbacks/1095.html</trackback:ping><description><![CDATA[关于Config参数和Context参数的访问<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;虽然在论坛中已经回答过不止一次,但现在看来,真正掌握这两个参数的区别的人5%都不到.<BR>&nbsp;&nbsp;&nbsp;&nbsp;所以有必要专门写出来,供大家学习.<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;我们先来回顾一下各种内置对象的作用范围<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;HttpServletRequest,HttpServletResponse:这两个属性的作用范围最小。<BR>&nbsp;&nbsp;&nbsp;&nbsp;时间上：只是本身请求和应答完成就失效，当然转发是把当前的request对象取出来传给另一<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;个资源，其实本身的request对象还是只生存到本次请求结束，response也同样。<BR>&nbsp;&nbsp;&nbsp;&nbsp;空间上：只能发送请求的客户端有效。<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;HttpSession:一次连结到客户端关闭，时间作用范围比上面两个大，空间任用范围相同。<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;ServletConfig:从一个servlet被实例化后，对任何客户端在任何时候访问有效，但仅对本servlet<BR>&nbsp;&nbsp;&nbsp;&nbsp;有效，一个servlet的ServletConfig对象不能被另一个servlet访问。<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;ServletContext:对任何servlet，任何人在任何时间都有效，这才是真正全局的对象。<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;那么，ServletConfig参数和ServletContext参数到底应该如何使用，如何取得？<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;一般来说，对整个应用的配置，为了不使用“硬编码”，应该配置为ServletContext参数，比如字<BR>&nbsp;&nbsp;&nbsp;&nbsp;符集设定。<BR>&nbsp;&nbsp;&nbsp;&nbsp;&lt;web-app&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.................<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;init-param&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;param-name&gt;charset&lt;/param-name&gt;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;param-value&gt;GB2312&lt;/param-value&gt;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/init-param&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.................<BR>&nbsp;&nbsp;&nbsp;&nbsp;&lt;/web-app&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;注意以上格式只是2。0以后的标准格式，旧容器（引擎）采用服务商自己的格式配置。注意它的<BR>&nbsp;&nbsp;&nbsp;&nbsp;父元素应该是&lt;web-app&gt;也就是说它是对一个应用作用的。<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;而如果只有一个特定的servlet要设定的参数，其它servlet不能共享，应该配置为ServletConfig<BR>&nbsp;&nbsp;&nbsp;&nbsp;参数，如一个读取附件的servlet要用到绝对目录，而别的servlet不会用到：<BR>&nbsp;&nbsp;&nbsp;&nbsp;&lt;servlet&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;servlet-name&gt;GetAtt&lt;/servlet-name&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;servlet-class&gt;mail.GetAttServlet&lt;/servlet-class&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;init-param&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;param-name&gt;absPath&lt;/param-name&gt;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;param-value&gt;/usr/mail/ax/axman/Maildir/&lt;/param-value&gt;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/init-param&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&lt;/servlet&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;不用说，因为在&lt;servlet&gt;标签中已经指定了name和class,也就是说只有mail.GetAttServlet这个<BR>&nbsp;&nbsp;&nbsp;&nbsp;servlet中才能取到path,而别的Servlet是不能取到的。<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;那么如何访问这两个对象的参数呢？<BR>&nbsp;&nbsp;&nbsp;&nbsp;访问ServletConfig参数：<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;首先要取得ServletConfig对象，然后调用它的getInitParameter();方法。要访问<BR>&nbsp;&nbsp;&nbsp;&nbsp;ServletConfig对象，jsp中直接使用config内置对象，但因为你的JSP编译后的servlet一般不会被<BR>&nbsp;&nbsp;&nbsp;&nbsp;加到web.xml中的，所以一般不会通过jsp来取对本JSP编译后的servlet的配置参数，那么在servlet<BR>&nbsp;&nbsp;&nbsp;&nbsp;中要得到ServletConfig对象有两种方法：<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;在inii()方法中取到：通过init的重载方法传递<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;.....<BR>&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;class&nbsp;Test&nbsp;extends&nbsp;HttpServlet&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;{<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ServletConfig&nbsp;config;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;void&nbsp;init(ServletConfig&nbsp;config)&nbsp;throws&nbsp;ServletException&nbsp;{<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.config&nbsp;=&nbsp;config;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;..................<BR>&nbsp;&nbsp;&nbsp;&nbsp;}<BR>&nbsp;&nbsp;&nbsp;&nbsp;然后在下面的方法中就可以访问config对象。但要注意，为了确保能从构造方法中到到当前servlet的<BR>&nbsp;&nbsp;&nbsp;&nbsp;config对象，应该调用父类的构造方法：<BR>&nbsp;&nbsp;&nbsp;&nbsp;.....<BR>&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;class&nbsp;Test&nbsp;extends&nbsp;HttpServlet&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;{<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ServletConfig&nbsp;config;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;void&nbsp;init(ServletConfig&nbsp;config)&nbsp;throws&nbsp;ServletException&nbsp;{<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;super.init(config);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.config&nbsp;=&nbsp;config;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;..................<BR>&nbsp;&nbsp;&nbsp;&nbsp;}<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;通过getServletConfig()方法直接到时，这样做的好处是不必调手工传递属性，想在任何时候都可<BR>&nbsp;&nbsp;&nbsp;&nbsp;以得到。<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;还有第三种方法，要自己实现一些接口，这里作为一般讨论就不介绍了。<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;要访问ServletContext对象，只要从现有的ServletConfig对象getServletContext（）就可以了，然后<BR>&nbsp;&nbsp;&nbsp;&nbsp;调用它的getInitParameter()方法就可以获取它的参数。<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;按说：ServletContext对象的作用域比ServletConfig作用域大，为什么要从ServletConfig中到得<BR>&nbsp;&nbsp;&nbsp;&nbsp;ServletContext对象呢？我个人认为：容器保存了很多个ServletContext对象，请求时容器到底取哪一个<BR>&nbsp;&nbsp;&nbsp;&nbsp;给你呢？那就取其中包含ServletConfig信息的那个给你，就是说取ServletConfig对象的父级对象。就好<BR>&nbsp;&nbsp;&nbsp;&nbsp;象HttpSession要从requset中取得一样，就是取那个包含当前requese对象的session对象给你，这只是我<BR>&nbsp;&nbsp;&nbsp;&nbsp;的个人想法，还没有来得及看具体实现。反正就这么用吧。 <B><BR></B><img src ="http://www.blogjava.net/jackybu/aggbug/1095.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jackybu/" target="_blank">辰</a> 2005-02-12 23:18 <a href="http://www.blogjava.net/jackybu/articles/1095.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>excel相关问题</title><link>http://www.blogjava.net/jackybu/articles/1094.html</link><dc:creator>辰</dc:creator><author>辰</author><pubDate>Sat, 12 Feb 2005 15:17:00 GMT</pubDate><guid>http://www.blogjava.net/jackybu/articles/1094.html</guid><wfw:comment>http://www.blogjava.net/jackybu/comments/1094.html</wfw:comment><comments>http://www.blogjava.net/jackybu/articles/1094.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jackybu/comments/commentRss/1094.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jackybu/services/trackbacks/1094.html</trackback:ping><description><![CDATA[<P><A href="http://www.cnjbb.org/thread.jsp?boardid=4&amp;threadid=14651&amp;messageid=14767">http://www.cnjbb.org/thread.jsp?boardid=4&amp;threadid=14651&amp;messageid=14767</A></P>
<P><A href="http://www.cnjbb.org/thread.jsp?boardid=4&amp;threadid=43335&amp;pageno=1&amp;perpage=10&amp;mode=block">http://www.cnjbb.org/thread.jsp?boardid=4&amp;threadid=43335&amp;pageno=1&amp;perpage=10&amp;mode=block</A></P><img src ="http://www.blogjava.net/jackybu/aggbug/1094.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jackybu/" target="_blank">辰</a> 2005-02-12 23:17 <a href="http://www.blogjava.net/jackybu/articles/1094.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>