网上图书商城项目学习笔记-001工具类测试

工具类测试

工具类分析图

1.BeanHandler

 

2.MapHandler

3.多表查询映射

 

1.CommonUtilsTest.java

 1 package cn.itcast.test;
 2 
 3 import java.util.HashMap;
 4 import java.util.Map;
 5 
 6 import org.junit.Test;
 7 
 8 import cn.itcast.commons.CommonUtils;
 9 
10 /**
11  * 测试CommonUtils类
12 // *   CommonUtils类依赖的jar:commons-beanutils.jar、commons-logging.jar
13  * @author qdmmy6
14  *
15  */
16 public class CommonUtilsTest {
17     /**
18      * 测试uuid()
19      *   返回一个随机的32长的字符串
20      *  用途:
21      *  1. 用来做id,数据库表中的主键是不能重复的,它就是不重复的!
22      *  2. 激活码也是不能重复的!也可以用它
23      *  
24      */
25     @Test
26     public void testUuid() {
27         String s = CommonUtils.uuid();
28         System.out.println(s);
29     }
30     
31     /**
32      * 作用:把一个map中的数据封装到javabean中
33      * 要求:
34      * 1. 要求map中的key名称与javabean中的属性名称相同
35      */
36     @Test
37     public void testToBean() {
38         /*
39          * 1. 创建Map
40          */
41         Map<String,Object> map = new HashMap<String,Object>();
42         map.put("pid", "123");
43         map.put("pname", "张三");
44         map.put("age", "23");
45         map.put("xxx", "XXX");
46         
47         // 通过map的数据来创建Person类型的JavaBean对象
48         Person p = CommonUtils.toBean(map, Person.class);
49         System.out.println(p);
50     }
51 }

 源码:CommonUtils.java

 1 package cn.itcast.commons;
 2 
 3 import java.util.Map;
 4 import java.util.UUID;
 5 
 6 import org.apache.commons.beanutils.BeanUtils;
 7 import org.apache.commons.beanutils.ConvertUtils;
 8 
 9 /**
10  * 小小工具
11  * @author qdmmy6
12  *
13  */
14 public class CommonUtils {
15     /**
16      * 返回一个不重复的字符串
17      * @return
18      */
19     public static String uuid() {
20         return UUID.randomUUID().toString().replace("-", "").toUpperCase();
21     }
22 
23     /**
24      * 把map转换成对象
25      * @param map
26      * @param clazz
27      * @return
28      * 
29      * 把Map转换成指定类型
30      */
31     @SuppressWarnings("rawtypes")
32     public static <T> T toBean(Map map, Class<T> clazz) {
33         try {
34             /*
35              * 1. 通过参数clazz创建实例
36              * 2. 使用BeanUtils.populate把map的数据封闭到bean中
37              */
38             T bean = clazz.newInstance();
39             ConvertUtils.register(new DateConverter(), java.util.Date.class);
40             BeanUtils.populate(bean, map);
41             return bean;
42         } catch(Exception e) {
43             throw new RuntimeException(e);
44         }
45     }
46 }

 

 

2.JdbcUtilsTest.java

 1 package cn.itcast.test;
 2 
 3 import java.sql.Connection;
 4 import java.sql.SQLException;
 5 
 6 import org.junit.Test;
 7 
 8 import cn.itcast.jdbc.JdbcUtils;
 9 
10 /**
11  * JdbcUtils用来获取Connection
12  *   * 底层使用了c3p0连接池!
13  *   * 还需要mysql驱动
14  * @author qdmmy6
15  *
16  */
17 public class JdbcUtilsTest {
18     /**
19      * 底层使用了c3p0连接池,说明我们还要提供c3p0配置文件
20      * @throws SQLException 
21      */
22     @Test
23     public void testGetConnection() throws SQLException {
24         Connection con = JdbcUtils.getConnection();
25         System.out.println(con);;
26         JdbcUtils.releaseConnection(con);
27         System.out.println(con.isClosed());
28     }
29     
30     /**
31      * JdbcUtilst还提供了与事务相关的功能
32      * 
33      */
34     @Test
35     public void testTransaction() {
36         try {
37             JdbcUtils.beginTransaction();//开启事务
38             
39             // 多次操作
40             
41             JdbcUtils.commitTransaction();//提交事务
42         } catch(Exception e) {
43             try {
44                 JdbcUtils.rollbackTransaction();//回滚事务
45             } catch (SQLException e1) {
46             }
47         }
48     }
49 }

源码:JdbcUtils.java

 1 package cn.itcast.jdbc;
 2 
 3 import java.sql.Connection;
 4 import java.sql.SQLException;
 5 
 6 import javax.sql.DataSource;
 7 
 8 import com.mchange.v2.c3p0.ComboPooledDataSource;
 9 
10 /**
11  * 使用本类的方法,必须提供c3p0-copnfig.xml文件
12  * @author qdmmy6
13  */
14 public class JdbcUtils {
15     // 饿汉式
16     private static DataSource ds = new ComboPooledDataSource();
17     
18     /**
19      * 它为null表示没有事务
20      * 它不为null表示有事务
21      * 当开启事务时,需要给它赋值
22      * 当结束事务时,需要给它赋值为null
23      * 并且在开启事务时,让dao的多个方法共享这个Connection
24      */
25     private static ThreadLocal<Connection> tl = new ThreadLocal<Connection>();
26     
27     public static DataSource getDataSource() {
28         return ds;
29     }
30     
31     /**
32      * dao使用本方法来获取连接
33      * @return
34      * @throws SQLException
35      */
36     public static Connection getConnection() throws SQLException {
37         /*
38          * 如果有事务,返回当前事务的con
39          * 如果没有事务,通过连接池返回新的con
40          */
41         Connection con = tl.get();//获取当前线程的事务连接
42         if(con != null) return con;
43         return ds.getConnection();
44     }
45     
46     /**
47      * 开启事务
48      * @throws SQLException 
49      */
50     public static void beginTransaction() throws SQLException {
51         Connection con = tl.get();//获取当前线程的事务连接
52         if(con != null) throw new SQLException("已经开启了事务,不能重复开启!");
53         con = ds.getConnection();//给con赋值,表示开启了事务
54         con.setAutoCommit(false);//设置为手动提交
55         tl.set(con);//把当前事务连接放到tl中
56     }
57     
58     /**
59      * 提交事务
60      * @throws SQLException 
61      */
62     public static void commitTransaction() throws SQLException {
63         Connection con = tl.get();//获取当前线程的事务连接
64         if(con == null) throw new SQLException("没有事务不能提交!");
65         con.commit();//提交事务
66         con.close();//关闭连接
67         con = null;//表示事务结束!
68         tl.remove();
69     }
70     
71     /**
72      * 回滚事务
73      * @throws SQLException 
74      */
75     public static void rollbackTransaction() throws SQLException {
76         Connection con = tl.get();//获取当前线程的事务连接
77         if(con == null) throw new SQLException("没有事务不能回滚!");
78         con.rollback();
79         con.close();
80         con = null;
81         tl.remove();
82     }
83     
84     /**
85      * 释放Connection
86      * @param con
87      * @throws SQLException 
88      */
89     public static void releaseConnection(Connection connection) throws SQLException {
90         Connection con = tl.get();//获取当前线程的事务连接
91         if(connection != con) {//如果参数连接,与当前事务连接不同,说明这个连接不是当前事务,可以关闭!
92             if(connection != null &&!connection.isClosed()) {//如果参数连接没有关闭,关闭之!
93                 connection.close();
94             }
95         }
96     }
97 }

 

 

3.TxQueryRunnerTest.java

  1 package cn.itcast.test;
  2 
  3 import java.sql.SQLException;
  4 import java.util.List;
  5 import java.util.Map;
  6 
  7 import org.apache.commons.dbutils.QueryRunner;
  8 import org.apache.commons.dbutils.handlers.BeanHandler;
  9 import org.apache.commons.dbutils.handlers.BeanListHandler;
 10 import org.apache.commons.dbutils.handlers.MapHandler;
 11 import org.apache.commons.dbutils.handlers.MapListHandler;
 12 import org.apache.commons.dbutils.handlers.ScalarHandler;
 13 import org.junit.Test;
 14 
 15 import cn.itcast.commons.CommonUtils;
 16 import cn.itcast.jdbc.JdbcUtils;
 17 import cn.itcast.jdbc.TxQueryRunner;
 18 
 19 /**
 20  * TxQueryRunner它是QueryRunner的子类!(commons-dbutils.jar)
 21  *   可用起来与QueryRunner相似的!
 22  *   我们的类支持事务!它底层使用了JdbcUtils来获取连接!
 23  *   
 24  * 简化jdbc的操作
 25  * QueryRunner的三个方法:
 26  * * update() --> insert、update、delete
 27  * * query() --> select
 28  * * batch() --> 批处理
 29  * @author qdmmy6
 30  *
 31  */
 32 public class TxQueryRunnerTest {
 33     /**
 34      * 测试update()方法,用来执行insert、update、delete语句
 35      * @throws SQLException
 36      */
 37     @Test
 38     public void testUpdate() throws SQLException {
 39         String sql = "insert into t_person(pid,pname,age,sex) values(?,?,?,?)";
 40         Object[] params = {"1", "p1", 1, "男"};//给sql中对应的参数
 41         
 42         QueryRunner qr = new TxQueryRunner();//我们没有给对象提供连接池
 43         qr.update(sql, params);//执行sql,也不提供连接,它内部会使用JdbcUtils来获取连接
 44     }
 45     
 46     /**
 47      * 使用事务
 48      * @throws SQLException
 49      */
 50     @Test
 51     public void testUpdate2() throws Exception {
 52         try {
 53             JdbcUtils.beginTransaction();//开启事务
 54             
 55             String sql = "insert into t_person(pid,pname,age,sex) values(?,?,?,?)";
 56             QueryRunner qr = new TxQueryRunner();
 57             Object[] params = {"2", "p2", 2, "女"};
 58             qr.update(sql, params);//执行
 59             
 60             if(false) {
 61                 throw new Exception();
 62             }
 63             
 64             params = new Object[]{"3", "p3", 3, "女"};
 65             qr.update(sql, params);//执行            
 66             
 67             JdbcUtils.commitTransaction();//提交事务
 68         } catch(Exception e) {
 69             try {
 70                 JdbcUtils.rollbackTransaction();//回滚事务
 71             } catch (SQLException e1) {
 72             }
 73             throw e;
 74         }        
 75     }
 76     
 77     /**
 78      * 测试查询方法
 79      *   我们知道JDBC查询的结果的是ResultSet
 80      *   而QueryRunner查询的结果是通过ResultSet映射后的数据。
 81      *     * QueryRunner第一步是执行select,得到ResultSet
 82      *     * 把ResultSet转换成其他类型的!
 83      *   通过转换结果:
 84      *      * javaBean:把结果集封装到javaBean中
 85      *      * Map:把结果集封装到Map中
 86      *      * 把结果集封装到Object中(结果集是单行单列)
 87      * @throws SQLException 
 88      *      
 89      *  
 90      */
 91     /*
 92      * 单行结果集映射到javaBean中
 93      */
 94     @Test
 95     public void testQuery1() throws SQLException {
 96         String sql = "select * from t_person where pid=?";
 97         QueryRunner qr = new TxQueryRunner();
 98         /*
 99          * 第二个参数类型为ResultSetHandler,它是一个接口,表示映射的结果类型。
100          * 
101          * BeanHandler --> 它是ResultSetHandler的实现类,它的作用是把结果集封装到Person对象中
102          */
103         Person p = qr.query(sql, new BeanHandler<Person>(Person.class), "1");
104         System.out.println(p);
105     }
106     
107     /**
108      * 使用BeanListHandler
109      *   把多行结果集映射到List<Bean>,即多个JavaBean对象。
110      *   一行结果集记录对应一个javaBean对象,多行就对应List<Bean>
111      * @throws SQLException
112      */
113     @Test
114     public void testQuery2() throws SQLException {
115         String sql = "select * from t_person";
116         QueryRunner qr = new TxQueryRunner();
117         /*
118          * 第二个参数类型为ResultSetHandler,它是一个接口,表示映射的结果类型。
119          * 
120          * BeanListHandler --> 它是ResultSetHandler的实现类,
121          *   它的作用是把结果集封装到List<Person>对象中
122          */
123         List<Person> list = qr.query(sql, new BeanListHandler<Person>(Person.class));
124         System.out.println(list);
125     }
126     
127     /**
128      * 使用MapHandler,把单行结果集封装到Map对象中
129      * @throws SQLException
130      */
131     @Test
132     public void testQuery3() throws SQLException {
133         String sql = "select * from t_person where pid=?";
134         QueryRunner qr = new TxQueryRunner();
135         /*
136          * 第二个参数类型为ResultSetHandler,它是一个接口,表示映射的结果类型。
137          * 
138          * BeanListHandler --> 它是ResultSetHandler的实现类,
139          *   它的作用是把结果集封装到List<Person>对象中
140          */
141         Map<String, Object> map = qr.query(sql, new MapHandler(), "1");
142         System.out.println(map);
143     }
144     
145     /**
146      * 使用MapListHandler,把多行结果集封装到List<Map>中,即多个Map
147      *   一行对应一个Map,多行对应List<Map>
148      * @throws SQLException
149      */
150     @Test
151     public void testQuery4() throws SQLException {
152         String sql = "select * from t_person";
153         QueryRunner qr = new TxQueryRunner();
154         /*
155          * 第二个参数类型为ResultSetHandler,它是一个接口,表示映射的结果类型。
156          * 
157          * BeanListHandler --> 它是ResultSetHandler的实现类,
158          *   它的作用是把结果集封装到List<Person>对象中
159          */
160         List<Map<String, Object>> mapList = qr.query(sql, new MapListHandler());
161         System.out.println(mapList);
162     }
163     
164     /**
165      * 使用ScalarHandler,把单行单列的结果集封装到Object中
166      * @throws SQLException
167      */
168     @Test
169     public void testQuery5() throws SQLException {
170         String sql = "select count(*) from t_person";//结果集是单行单列的
171         QueryRunner qr = new TxQueryRunner();
172 
173         Object obj = qr.query(sql, new ScalarHandler());
174         /*
175          * 我们知道select count(1),结果一定是个整数!
176          * > Integer
177          * > Long
178          * > BigInteger
179          * 
180          * 不同的驱动,结果不同!
181          * 无论是哪种类型,它都是Number类型!强转成Number一定不出错
182          */
183         Number number = (Number)obj;
184         long cnt = number.longValue();
185         System.out.println(cnt);
186     }
187     
188     /**
189      * 一行结果集中包含了两张表的列
190      * 使用MapHandler来处理
191      * 1. 把结果集封装到map中
192      * 2. 使用map生成Person对象
193      * 3. 使用map生成address对象
194      * 4. 把两个实体对象建立关系
195      * @throws SQLException
196      */
197     @Test
198     public void testQuery6() throws SQLException {
199         String sql = "SELECT * FROM t_person p, t_address a WHERE p.aid=a.aid AND p.pid=?";
200         QueryRunner qr = new TxQueryRunner();
201         /*
202          * 1. 得到Map
203          */
204         Map map = qr.query(sql, new MapHandler(), "aaa");
205         /*
206          * 2. 把Map中部分数据封装到Person中
207          */
208         Person p = CommonUtils.toBean(map, Person.class);
209         /*
210          * 3. 把Map中部分数据封装到Address中
211          */
212         Address addr = CommonUtils.toBean(map, Address.class);
213         /*
214          * 4. 建立两个实体的关系
215          */
216         p.setAddress(addr);
217         
218         System.out.println(p);
219     }
220 }

 源码:TxQueryRunner.java

 1 package cn.itcast.jdbc;
 2 
 3 import java.sql.Connection;
 4 import java.sql.SQLException;
 5 
 6 import org.apache.commons.dbutils.QueryRunner;
 7 import org.apache.commons.dbutils.ResultSetHandler;
 8 
 9 public class TxQueryRunner extends QueryRunner {
10 
11     @Override
12     public int[] batch(String sql, Object[][] params) throws SQLException {
13         Connection con = JdbcUtils.getConnection();
14         int[] result = super.batch(con, sql, params);
15         JdbcUtils.releaseConnection(con);
16         return result;
17     }
18 
19     @Override
20     public <T> T query(String sql, ResultSetHandler<T> rsh, Object... params)
21             throws SQLException {
22         Connection con = JdbcUtils.getConnection();
23         T result = super.query(con, sql, rsh, params);
24         JdbcUtils.releaseConnection(con);
25         return result;
26     }
27     
28     @Override
29     public <T> T query(String sql, ResultSetHandler<T> rsh) throws SQLException {
30         Connection con = JdbcUtils.getConnection();
31         T result = super.query(con, sql, rsh);
32         JdbcUtils.releaseConnection(con);
33         return result;
34     }
35 
36     @Override
37     public int update(String sql) throws SQLException {
38         Connection con = JdbcUtils.getConnection();
39         int result = super.update(con, sql);
40         JdbcUtils.releaseConnection(con);
41         return result;
42     }
43 
44     @Override
45     public int update(String sql, Object param) throws SQLException {
46         Connection con = JdbcUtils.getConnection();
47         int result = super.update(con, sql, param);
48         JdbcUtils.releaseConnection(con);
49         return result;
50     }
51 
52     @Override
53     public int update(String sql, Object... params) throws SQLException {
54         Connection con = JdbcUtils.getConnection();
55         int result = super.update(con, sql, params);
56         JdbcUtils.releaseConnection(con);
57         return result;
58     }
59 }

 

 

 

源码链接:

http://pan.baidu.com/s/1pKnA7NH

 

 

 

 

小工具

工欲善其事,必先利其器。下面我们来介绍一下在项目中要使用的小工具(itcast-tools-1.4.jar)。这个小工具底层使用了:

l  c3p0数据库连接池;

l  common-beanutils;

l  common-dbutils;

l  javaMail;

1 CommonUtils

CommonUtils类就两个方法:

l  String uuid():生成长度32的随机字符,通常用来做实体类的ID。底层使用了UUID类完成;

l  T toBean(Map, Class<T>):把Map转换成指定类型的Bean对象。通常用来获取表单数据(request.getParameterMap())封装到JavaBean中,底层使用了common-beanutils。注意,本方法要求map中键的名称要与Bean的属性名称相同才能完成映射,否则不能完成映射。

    /**

     * 随机生成32位长的字符串,通常用来做实体类的ID

     */

    @Test

    public void testUuid() {

       String s = CommonUtils.uuid();//生成随机32位长的字符串

       System.out.println(s);

    }

   

    /**

     * 把Map类型映射成Bean类型。

     * 要求map中键的名称与Person类的属性名称相同。

     * 即map的key分别为:pid、name、age、birthday,person的属性名称也是pid、name、age、birthday

     */

    @Test

    public void testToBean() {

       Map<String,String> map = new HashMap<String,String>();

       /*

        * map的key:pid、age、birthday、myname

        * person的属性:pid、age、birthday、name

        * map中没有名为name的键值,而多出一个名为myname的键值,所以映射后的person对象的name属性值为null。

        * map中的age和birthday都是字符串类型,而person的age是int类型、birthday是Date类型,但toBean()方法会自动对Map中值进行类型转换。

        */

       map.put("pid", CommonUtils.uuid());

       map.put("age", "23");

       map.put("birthday", "2014-01-30");

       map.put("myname", "张三");

      

       Person p = CommonUtils.toBean(map, Person.class);

       System.out.println(p);

    }

 

2 JdbcUtils

JdbcUtils用来获取Connection对象,以及开启和关闭事务。

l  Connection getConnection():从c3p0连接池获取Connection对象,所以需要提供c3p0-config.xml配置文件;

l  beginTransaction():为当前线程开启事务;

l  commitTransaction():提交当前线程的事务;

l  rollbackTransaction():回滚当前线程的事务;

l  releaseConnection(Connection):如果参数连接对象不是当前事务的连接对象,那么关闭它,否则什么都不做;

c3p0-config.xml

<?xml version="1.0" encoding="UTF-8" ?>

<c3p0-config>

    <default-config>

       <property name="jdbcUrl">jdbc:mysql://localhost:3306/mydb1</property>

       <property name="driverClass">com.mysql.jdbc.Driver</property>

       <property name="user">root</property>

       <property name="password">123</property>

      

       <property name="acquireIncrement">3</property>

       <property name="initialPoolSize">10</property>

       <property name="minPoolSize">2</property>

       <property name="maxPoolSize">10</property>

    </default-config>

</c3p0-config>

 

JdbcUtilsTest.java

/**

 * 测试JdbcUtils类

 * @author qdmmy6

 *

 */

public class JdbcUtilsTest {

    /**

     * 通过C3P0连接池获取连接对象

     * @throws SQLException

     */

    @Test

    public void testGetConnection() throws SQLException {

       Connection con = JdbcUtils.getConnection();//获取连接

       System.out.println(con);

       JdbcUtils.releaseConnection(con);//如果参数con不是当前线程的连接对象,那么关闭之

    }

   

    /**

     * 当开始事务后,调用getConnection()会为当前线程创建Connection,而且多次调用getConnection()返回的是同一个对象

     * @throws SQLException

     */

    @Test

    public void testTansaction() throws SQLException {

       JdbcUtils.beginTransaction();//开启事务

       Connection c1 = JdbcUtils.getConnection();//第一次获取当前线程的事务连接对象

       Connection c2 = JdbcUtils.getConnection();//第二次获取当前线程的事务连接对象

       Assert.assertEquals(true, c1 == c2);//比较两次是否相同

       JdbcUtils.commitTransaction();//提交事务

    }

}

 

3 TxQueryRunner

TxQueryRunner类是common-dbutils下QueryRunner类的子类,用来简化JDBC操作。TxQueryRunner类内部使用了JdbcUtils.getConnection()类来获取连接对象,以及使用JdbcUtils.releaseConnection()关闭连接。

l  int[] batch(String sql, Object[][] params):执行批处理,参数sql是SQL语句模板,params为参数;

l  T query(String sql, ResultSetHandler<T> rh):执行查询,执行查询,参数sql为要执行的查询语句模板,rh是结果集处理,用来把结果集映射成你想要的结果;

l  T query(String sql, ResultSetHandler<T> rh, Object… params):执行查询,参数sql为要执行的查询语句模板,rh是结果集处理,用来把结果集映射成你想要的结果,params是sql语句的参数;

l  int update(String sql):执行增、删、改语句,参数sql是要执行的SQL语句;

l  int update(Stringsql, Object param):执行增、删、改语句,参数sql是要执行的SQL语句,参数param是参数(一个参数);

l  int update(String sql, Object… params):执行增、删、改语句,参数sql是要执行的SQL语句,参数params是参数(多个参数);

为了测试TxQueryRunner,我们在mydb1数据库下创建t_person表,然后再创建Person实体类,以及PersonDao类,最后测试PersonDao类中的方法。

t_person

字段

说明

pid

主键

name

姓名

age

年龄

birthday

生日

 

Person.java

public class Person {

    private String pid;

    private String name;

    private int age;

    private Date birthday;

}

 

PersonDao.java

/**

 * 测试TxQueryRunner

 * @author qdmmy6

 *

 */

public class PersonDao {

    private QueryRunner qr = new TxQueryRunner();

   

    public void add(Person person) throws SQLException {

       String sql = "insert into t_person values(?,?,?,?)";

       Object[] params = {person.getPid(),

              person.getName(),

              person.getAge(),

              new java.sql.Date(person.getBirthday().getTime())};

       qr.update(sql, params);

    }

   

    public void edit(Person person) throws SQLException {

       String sql = "update t_person set name=?,age=?,birthday=? where pid=?";

       Object[] params = {

              person.getName(),

              person.getAge(),

              new java.sql.Date(person.getBirthday().getTime()),

              person.getPid()};

       qr.update(sql, params);

    }

   

    public void delete(String pid) throws SQLException {

       String sql = "delete from t_person where pid=?";

       qr.update(sql, pid);

    }

   

    public Person load(String pid) throws SQLException {

       String sql = "select * from t_person where pid=?";

       return qr.query(sql, new BeanHandler<Person>(Person.class), pid);

    }

   

    public List<Person> findAll() throws SQLException {

       String sql = "select * from t_person";

       return qr.query(sql, new BeanListHandler<Person>(Person.class));

    }

}

 

PersonDaoTest.java

public class PersonDaoTest {

    @Test

    public void testAdd() throws SQLException {

       Person p1 = new Person(CommonUtils.uuid(), "张三", 18, new Date());

       Person p2 = new Person(CommonUtils.uuid(), "李四", 81, new Date());

       Person p3 = new Person(CommonUtils.uuid(), "王五", 66, new Date());

      

       PersonDao dao = new PersonDao();

       dao.add(p1);

       dao.add(p2);

       dao.add(p3);

    }

   

    @Test

    public void testEdit() throws SQLException {

       PersonDao dao = new PersonDao();

       Person person = dao.load("2F371BE415984DE89781CCCA7B8734CB");

       person.setAge(88);

       dao.edit(person);

    }

   

    @Test

    public void testDelete() throws SQLException {

       PersonDao dao = new PersonDao();

       dao.delete("2F371BE415984DE89781CCCA7B8734CB");

    }

   

    @Test

    public void testFindAll() throws SQLException {

       PersonDao dao = new PersonDao();

       List<Person> list = dao.findAll();

       System.out.println(list);

    }

}

 

4 MailUtils

MailUtils是用来发邮件的小工具,底层使用JavaMail完成,所以它这件事mail.jar和activaion.jar。

MailUtilsTest.java

    /**

     * 测试发送普通邮件

     * @throws IOException

     * @throws MessagingException

     */

    @Test

    public void fun() throws MessagingException, IOException {

       Session session = MailUtils.createSession("smtp.163.com", "itcast_cxf", "itcastitcast");[q1] 

       Mail mail = new Mail("itcast_cxf@163.com", "itcast_cxf@126.com", "测试MailUtils", "这是正文!");[q2] 

       MailUtils.send(session, mail);[q3] 

    }

 

5 BaseServlet

BaseServlet是用来作为其它Servlet父类的,它有如下两个优点:

一个Servlet多个处理方法

BaseServlet的作用是用来简化Servlet。通过我们需要为每个功能编写一个Servlet,例如用户注册写一个RegistServlet,用户登录写一个LoginServlet。如果使用BaseServlet,那么我们可以只写一个UserServlet,然后让UserServlet去继承BaseServlet,然后在UserServlet给出两个请求处理方法,一个方法叫regist(),一个叫login()。

BaseServlet来简化了Servlet中请求转发和重定向的代码。

 

简化了请求转发和重定向的代码

BaseServlet中的请求处理方法有一个String类型的返回值,返回值表示转发或重定向的目标页面。例如:

l  f:/index.jsp:其中f:表示转发,即forward的意思,/index.jsp表示转发到/index.jsp页面;

l  r:/index.jsp:其中r:表示重定向,即redirect的意思,/index.jsp表示重定向到/index.jsp页面。

l  null:表示不转发也不重定向;

 

因为BaseServlet中可以有多个请求处理方法,所以在访问BaseServlet时一定要给出名为method的参数来指定要请求的方法名称。

AServlet.java

public class AServlet extends BaseServlet {

    /**

     * 请求处理方法的参数都与doGet()和doPost()相同,即request和response

     * 但请求处理方法有String类型的返回值,而doGet()和doPost()没有返回值。

     * 在请求本方法时需要给出method=regist参数!

     */

    public String regist[q4] (HttpServletRequest req, HttpServletResponse resp)

           throws ServletException, IOException {

       System.out.println("AServlet regist()...");

       return "f:/index.jsp";[q5] 

    }

   

    /**

     * 在请求本方法时需要给出method=login参数!

     */

    public String login[q6] (HttpServletRequest req, HttpServletResponse resp)

           throws ServletException, IOException {

       System.out.println("AServlet login()...");

       return "r:/index.jsp"[q7] ;

    }

}

 

6 EncodingFilter

EncodingFilter用来处理请求编码问题。

我们知道,如果是POST请求,我们需要调用request.setCharacterEncoding(“utf-8”)方法来设计编码;如果是GET请求,我们需要自己手动来处理编码问题。如果我们使用了EncodingFilter,那么就处理了POST和GET请求的编码问题。

web.xml

<filter>

    <filter-name>EncdoingFilter</filter-name>

    <filter-class>cn.itcast.filter.EncodingFilter</filter-class>

</filter>

<filter-mapping>

    <filter-name>EncdoingFilter</filter-name>

    <url-pattern>/*</url-pattern>

</filter-mapping>

 

index.jsp

<a href="<c:url value='/EncodingServlet?method=test[q8] &name=张三'/>">点击这里发出GET请求</a><br/>

<form action="<c:url value='/EncodingServlet'/>" method="post">

  <input type="hidden" name="method" value="test"/>[q9] 

  <input type="text" name="name" value="李四"/>

  <input type="submit" value="请求这里发出POST请求"/>

</form>

 

EncodingServlet

/**

 * 测试EncodingFilter

 * @author qdmmy6

 *

 */

public class EncodingServlet [q10] extends BaseServlet {

    /**

     * 可以使用POST和GET两种方式请求test()方法!查看输出是否为乱码!

     */

    public String test(HttpServletRequest request, HttpServletResponse response)

           throws ServletException, IOException {

       String name = request.getParameter("name");

       System.out.println(name);

       return null;

    }

}

 

7 VerifyCodeServlet(一次性验证码)

通过在表单中总是需要使用一次性验证码,这一问题可以使用VerifyCodeServlet来处理。让<img>元素的src指向VerifyCodeServlet即可在页面中生成一次性验证码。而且VerifyCodeServlet还会把验证码保存到session中,名称为:vCode,也就是说,你可以通过session来获取验证码文本:session.getAttribute(“vCode”)。

web.xml

<servlet>

  <servlet-name>VerifyCodeServlet</servlet-name>

  <servlet-class>cn.itcast.vcode.servlet.VerifyCodeServlet</servlet-class>

</servlet>

<servlet-mapping>

  <servlet-name>VerifyCodeServlet</servlet-name>

  <url-pattern>/VerifyCodeServlet</url-pattern>

</servlet-mapping>

 

MyJsp.jsp

<form action="<c:url value='/UserServlet'/>" method="post">

    <input type="hidden" name="method" value="regist"/>

    验证码:<input type="text" name="verifyCode"/>

    <img src="<c:url value='/VerifyCodeServlet'/>"[q11]  border="1"/><br/>

    <input type="submit" value="注册"/>

</form>

 

  因为用户可能看不清楚图片上的文本,所以我们需要给用户提供一个“换一张”超链接。其实实现这一步很简单,只需要使用javascript让<img>元素src指向VerifyCodeServlet即可。但因为浏览器可能会缓存上一次生成的图片,所以我们还需要使用时间为参数“强迫”浏览器访问服务器,而不是使用缓存。

MyJsp.jsp

    <script type="text/javascript" src="<c:url value='/js/jquery-1.5.1.js'/>"></script>[q12] 

    <script type="text/javascript">

       function change[q13] () {

           $("#img").attr("src", "<c:url value='/VerifyCodeServlet?'/>" + new Date().getTime());[q14] 

       }

    </script>

<form action="<c:url value='/UserServlet'/>" method="post">

    <input type="hidden" name="method" value="regist"/>

    验证码:<input type="text" name="verifyCode"/>

    <img id="img"[q15]  src="<c:url value='/VerifyCodeServlet'/>" border="1"/>

    <a href="javascript:change();">换一张</a>[q16] 

    <br/>

    <input type="submit" value="注册"/>

</form>

 

当用户在表单中填写了验证码,而且提交了表单,到达UserServlet的regist()方法,在regist() 方法中需要比较用户在表单中输入的验证码,与验证码图片上的文本是否相同。

l  获取用户输入的验证码:request.getParameter(“verifyCode”);

l  获取图片上的验证码:session.getAttribute(“vCode”);

 

 

 

 


 [q1]创建session

 [q2]创建邮箱对象,参数分别为:发件人、收件人、主题、正文

 [q3]发送邮件

 [q4]访问本方法的URL为http://localhost:8080/day01/AServlet?method=regist

 [q5]转发到/index.jsp页面

 [q6]访问本方法的URL为http://localhost:8080/day01/AServlet?method=login

 [q7]重定向到/index.jsp

 [q8]请求EncdoingServlet的test方法

 [q9]请求EncodingServlet的test方法

 [q10]因为添加了EncodingFilter过滤器,那么所有的Servlet都不用再去处理请求编码的问题了。

 [q11]让<img>的src指向VerifyCodeServlet即可生成一次性验证码

 [q12]导入jquery

 [q13]在点击“换一张”时会调用本方法

 [q14]指定<img>元素的src属性值为VerifyCodeServlet,并且追加参数为当前时间毫秒,它是不会重复的值,所以浏览器不会使用缓存,而是访问服务器。

 [q15]指定id为img,方法使用jquery来查找该元素。

 [q16]点击该超链接会调用change()方法

posted @ 2016-01-23 14:25  shamgod  阅读(1607)  评论(0编辑  收藏  举报
haha