1.项目中用到的小工具
1.CommonUtils
CommonUtils类就两个方法:
1.String uuid():生成长度32的随机字符,通常用来做实体类的ID。底层使用了UUID类完成;
2.T toBean(Map, Class<T>):把Map转换成指定类型的Bean对象。通常用来获取表单数据(request.getParameterMap())封装到JavaBean中,底层使用了common-beanutils。注意,本方法要求map中键的名称要与Bean的属性名称相同才能完成映射,否则不能完成映射;
1.源码
1 import java.util.Map; 2 import java.util.UUID; 3 4 import org.apache.commons.beanutils.BeanUtils; 5 import org.apache.commons.beanutils.ConvertUtils; 6 7 /** 8 * 小工具 9 * 10 * 11 */ 12 public class CommonUtils { 13 /** 14 * 返回一个不重复的字符串 15 * @return 16 */ 17 public static String uuid() { 18 return UUID.randomUUID().toString().replace("-", "").toUpperCase(); 19 } 20 21 /** 22 * 把map转换成对象 23 * @param map 24 * @param clazz 25 * @return 26 * 27 * 把Map转换成指定类型 28 */ 29 @SuppressWarnings("rawtypes") 30 public static <T> T toBean(Map map, Class<T> clazz) { 31 try { 32 /* 33 * 1. 通过参数clazz创建实例 34 * 2. 使用BeanUtils.populate把map的数据封闭到bean中 35 */ 36 T bean = clazz.newInstance(); 37 ConvertUtils.register(new DateConverter(), java.util.Date.class); 38 BeanUtils.populate(bean, map); 39 return bean; 40 } catch(Exception e) { 41 throw new RuntimeException(e); 42 } 43 } 44 }
2.测试代码
1 /** 2 * 随机生成32位长的字符串,通常用来做实体类的ID 3 */ 4 @Test 5 public void testUuid() { 6 String s = CommonUtils.uuid();//生成随机32位长的字符串 7 System.out.println(s); 8 } 9 10 /** 11 * 把Map类型映射成Bean类型。 12 * 要求map中键的名称与Person类的属性名称相同。 13 * 即map的key分别为:pid、name、age、birthday,person的属性名称也是pid、name、age、birthday 14 */ 15 @Test 16 public void testToBean() { 17 Map<String,String> map = new HashMap<String,String>(); 18 /* 19 * map的key:pid、age、birthday、myname 20 * person的属性:pid、age、birthday、name 21 * map中没有名为name的键值,而多出一个名为myname的键值,所以映射后的person对象的name属性值为null。 22 * map中的age和birthday都是字符串类型,而person的age是int类型、birthday是Date类型,但toBean()方法会自动对Map中值进行类型转换。 23 */ 24 map.put("pid", CommonUtils.uuid()); 25 map.put("age", "23"); 26 map.put("birthday", "2014-01-30"); 27 map.put("myname", "张三"); 28 29 Person p = CommonUtils.toBean(map, Person.class); 30 System.out.println(p); 31 }
=========================================================================================================================================
2.JdbcUtils
JdbcUtils用来获取Connection对象,以及开启和关闭事务。
l Connection getConnection():从c3p0连接池获取Connection对象,所以需要提供c3p0-config.xml配置文件;
l beginTransaction():为当前线程开启事务;
l commitTransaction():提交当前线程的事务;
l rollbackTransaction():回滚当前线程的事务;
l releaseConnection(Connection):如果参数连接对象不是当前事务的连接对象,那么关闭它,否则什么都不做;
1.源码
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 }
2.测试代码
c3p0-config.xml
1 <?xml version="1.0" encoding="UTF-8" ?> 2 <c3p0-config> 3 <default-config> 4 <property name="jdbcUrl">jdbc:mysql://localhost:3306/mydb1</property> 5 <property name="driverClass">com.mysql.jdbc.Driver</property> 6 <property name="user">root</property> 7 <property name="password">root</property> 8 9 <property name="acquireIncrement">3</property> 10 <property name="initialPoolSize">10</property> 11 <property name="minPoolSize">2</property> 12 <property name="maxPoolSize">10</property> 13 </default-config> 14 </c3p0-config>
1 /** 2 * 测试JdbcUtils类 3 * 4 * 5 */ 6 public class JdbcUtilsTest { 7 /** 8 * 通过C3P0连接池获取连接对象 9 * @throws SQLException 10 */ 11 @Test 12 public void testGetConnection() throws SQLException { 13 Connection con = JdbcUtils.getConnection();//获取连接 14 System.out.println(con); 15 JdbcUtils.releaseConnection(con);//如果参数con不是当前线程的连接对象,那么关闭之 16 } 17 18 /** 19 * 当开始事务后,调用getConnection()会为当前线程创建Connection,而且多次调用getConnection()返回的是同一个对象 20 * @throws SQLException 21 */ 22 @Test 23 public void testTansaction() throws SQLException { 24 JdbcUtils.beginTransaction();//开启事务 25 Connection c1 = JdbcUtils.getConnection();//第一次获取当前线程的事务连接对象 26 Connection c2 = JdbcUtils.getConnection();//第二次获取当前线程的事务连接对象 27 Assert.assertEquals(true, c1 == c2);//比较两次是否相同 28 JdbcUtils.commitTransaction();//提交事务 29 } 30 }
=========================================================================================================================================
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类中的方法。
1.源码
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 }
2.测试代码
Person.java
1 public class Person { 2 private String pid; 3 private String name; 4 private int age; 5 private Date birthday; 6 … 7 }
PersonDao.java
1 /** 2 * 测试TxQueryRunner 3 * 4 * 5 */ 6 public class PersonDao { 7 private QueryRunner qr = new TxQueryRunner(); 8 9 public void add(Person person) throws SQLException { 10 String sql = "insert into t_person values(?,?,?,?)"; 11 Object[] params = {person.getPid(), 12 person.getName(), 13 person.getAge(), 14 new java.sql.Date(person.getBirthday().getTime())}; 15 qr.update(sql, params); 16 } 17 18 public void edit(Person person) throws SQLException { 19 String sql = "update t_person set name=?,age=?,birthday=? where pid=?"; 20 Object[] params = { 21 person.getName(), 22 person.getAge(), 23 new java.sql.Date(person.getBirthday().getTime()), 24 person.getPid()}; 25 qr.update(sql, params); 26 } 27 28 public void delete(String pid) throws SQLException { 29 String sql = "delete from t_person where pid=?"; 30 qr.update(sql, pid); 31 } 32 33 public Person load(String pid) throws SQLException { 34 String sql = "select * from t_person where pid=?"; 35 return qr.query(sql, new BeanHandler<Person>(Person.class), pid); 36 } 37 38 public List<Person> findAll() throws SQLException { 39 String sql = "select * from t_person"; 40 return qr.query(sql, new BeanListHandler<Person>(Person.class)); 41 } 42 }
PersonDaoTest.java
1 public class PersonDaoTest { 2 @Test 3 public void testAdd() throws SQLException { 4 Person p1 = new Person(CommonUtils.uuid(), "张三", 18, new Date()); 5 Person p2 = new Person(CommonUtils.uuid(), "李四", 81, new Date()); 6 Person p3 = new Person(CommonUtils.uuid(), "王五", 66, new Date()); 7 8 PersonDao dao = new PersonDao(); 9 dao.add(p1); 10 dao.add(p2); 11 dao.add(p3); 12 } 13 14 @Test 15 public void testEdit() throws SQLException { 16 PersonDao dao = new PersonDao(); 17 Person person = dao.load("2F371BE415984DE89781CCCA7B8734CB"); 18 person.setAge(88); 19 dao.edit(person); 20 } 21 22 @Test 23 public void testDelete() throws SQLException { 24 PersonDao dao = new PersonDao(); 25 dao.delete("2F371BE415984DE89781CCCA7B8734CB"); 26 } 27 28 @Test 29 public void testFindAll() throws SQLException { 30 PersonDao dao = new PersonDao(); 31 List<Person> list = dao.findAll(); 32 System.out.println(list); 33 } 34 }
=========================================================================================================================================
4.MailUtils
MailUtils是用来发邮件的小工具,底层使用JavaMail完成,依赖mail.jar和activaion.jar。
1.源码
MailUtils.java
1 package cn.itcast.mail; 2 3 import java.io.IOException; 4 import java.util.List; 5 import java.util.Properties; 6 7 import javax.mail.Authenticator; 8 import javax.mail.Message.RecipientType; 9 import javax.mail.MessagingException; 10 import javax.mail.PasswordAuthentication; 11 import javax.mail.Session; 12 import javax.mail.Transport; 13 import javax.mail.internet.InternetAddress; 14 import javax.mail.internet.MimeBodyPart; 15 import javax.mail.internet.MimeMessage; 16 import javax.mail.internet.MimeMultipart; 17 import javax.mail.internet.MimeUtility; 18 19 /** 20 * 21 * @author itcast 本类只有这么一个方法,用来发邮件! 22 */ 23 public class MailUtils { 24 public static Session createSession(String host, final String username, final String password) { 25 Properties prop = new Properties(); 26 prop.setProperty("mail.host", host);// 指定主机 27 prop.setProperty("mail.smtp.auth", "true");// 指定验证为true 28 29 // 创建验证器 30 Authenticator auth = new Authenticator() { 31 public PasswordAuthentication getPasswordAuthentication() { 32 return new PasswordAuthentication(username, password); 33 } 34 }; 35 36 // 获取session对象 37 return Session.getInstance(prop, auth); 38 } 39 40 /** 41 * 发送指定的邮件 42 * 43 * @param mail 44 */ 45 public static void send(Session session, final Mail mail) throws MessagingException, 46 IOException { 47 48 MimeMessage msg = new MimeMessage(session);// 创建邮件对象 49 msg.setFrom(new InternetAddress(mail.getFrom()));// 设置发件人 50 msg.addRecipients(RecipientType.TO, mail.getToAddress());// 设置收件人 51 52 // 设置抄送 53 String cc = mail.getCcAddress(); 54 if (!cc.isEmpty()) { 55 msg.addRecipients(RecipientType.CC, cc); 56 } 57 58 // 设置暗送 59 String bcc = mail.getBccAddress(); 60 if (!bcc.isEmpty()) { 61 msg.addRecipients(RecipientType.BCC, bcc); 62 } 63 64 msg.setSubject(mail.getSubject());// 设置主题 65 66 MimeMultipart parts = new MimeMultipart();// 创建部件集对象 67 68 MimeBodyPart part = new MimeBodyPart();// 创建一个部件 69 part.setContent(mail.getContent(), "text/html;charset=utf-8");// 设置邮件文本内容 70 parts.addBodyPart(part);// 把部件添加到部件集中 71 72 /////////////////////////////////////////// 73 74 // 添加附件 75 List<AttachBean> attachBeanList = mail.getAttachs();// 获取所有附件 76 if (attachBeanList != null) { 77 for (AttachBean attach : attachBeanList) { 78 MimeBodyPart attachPart = new MimeBodyPart();// 创建一个部件 79 attachPart.attachFile(attach.getFile());// 设置附件文件 80 attachPart.setFileName(MimeUtility.encodeText(attach 81 .getFileName()));// 设置附件文件名 82 String cid = attach.getCid(); 83 if(cid != null) { 84 attachPart.setContentID(cid); 85 } 86 parts.addBodyPart(attachPart); 87 } 88 } 89 90 msg.setContent(parts);// 给邮件设置内容 91 Transport.send(msg);// 发邮件 92 } 93 }
Mail.java
1 package cn.itcast.mail; 2 3 import java.util.ArrayList; 4 import java.util.List; 5 6 /** 7 * 表示邮件类,你需要设置:账户名和密码、收件人、抄送(可选)、暗送(可选)、主题、内容,以及附件(可选) 8 * 9 * 在创建了Mail对象之后 10 * 可以调用它的setSubject()、setContent(),设置主题和正文 11 * 也可以调用setFrom()和 addToAddress(),设置发件人,和添加收件人。 12 * 也可以调用addAttch()添加附件 13 * 创建AttachBean:new AttachBean(new File("..."), "fileName"); 14 */ 15 public class Mail { 16 private String from;//发件人 17 private StringBuilder toAddress = new StringBuilder();//收件人 18 private StringBuilder ccAddress = new StringBuilder();//抄送 19 private StringBuilder bccAddress = new StringBuilder();//暗送 20 21 private String subject;//主题 22 private String content;//正文 23 24 // 附件列表 25 private List<AttachBean> attachList = new ArrayList<AttachBean>(); 26 27 public Mail() {} 28 29 public Mail(String from, String to) { 30 this(from, to, null, null); 31 } 32 33 public Mail(String from, String to, String subject, String content) { 34 this.from = from; 35 this.toAddress.append(to); 36 this.subject = subject; 37 this.content = content; 38 } 39 40 /** 41 * 返回发件人 42 * @return 43 */ 44 public void setFrom(String from) { 45 this.from = from; 46 } 47 48 /** 49 * 返回发件人 50 * @return 51 */ 52 public String getFrom() { 53 return from; 54 } 55 56 /** 57 * 返回主题 58 */ 59 public String getSubject() { 60 return subject; 61 } 62 63 /** 64 * 设置主题 65 */ 66 public void setSubject(String subject) { 67 this.subject = subject; 68 } 69 70 /** 71 * 获取主题内容 72 */ 73 public String getContent() { 74 return content; 75 } 76 77 /** 78 * 设置主题内容 79 * @param content 80 */ 81 public void setContent(String content) { 82 this.content = content; 83 } 84 85 /** 86 * 获取收件人 87 * @return 88 */ 89 public String getToAddress() { 90 return toAddress.toString(); 91 } 92 93 /** 94 * 获取抄送 95 * @return 96 */ 97 public String getCcAddress() { 98 return ccAddress.toString(); 99 } 100 101 /** 102 * 获取暗送 103 * @return 104 */ 105 public String getBccAddress() { 106 return bccAddress.toString(); 107 } 108 109 /** 110 * 添加收件人,可以是多个收件人 111 * @param to 112 */ 113 public void addToAddress(String to) { 114 if(this.toAddress.length() > 0) { 115 this.toAddress.append(","); 116 } 117 this.toAddress.append(to); 118 } 119 120 /** 121 * 添加抄送人,可以是多个抄送人 122 * @param cc 123 */ 124 public void addCcAddress(String cc) { 125 if(this.ccAddress.length() > 0) { 126 this.ccAddress.append(","); 127 } 128 this.ccAddress.append(cc); 129 } 130 131 /** 132 * 添加暗送人,可以是多个暗送人 133 * @param bcc 134 */ 135 public void addBccAddress(String bcc) { 136 if(this.bccAddress.length() > 0) { 137 this.bccAddress.append(","); 138 } 139 this.bccAddress.append(bcc); 140 } 141 142 /** 143 * 添加附件,可以添加多个附件 144 * @param attachBean 145 */ 146 public void addAttach(AttachBean attachBean) { 147 this.attachList.add(attachBean); 148 } 149 150 /** 151 * 获取所有附件 152 * @return 153 */ 154 public List<AttachBean> getAttachs() { 155 return this.attachList; 156 } 157 }
2.测试代码
1 /** 2 * 测试发送普通邮件 3 * @throws IOException 4 * @throws MessagingException 5 */ 6 @Test 7 public void fun() throws MessagingException, IOException { 8 Session session = MailUtils.createSession("smtp.163.com", "itcast_cxf", "itcastitcast"); 9 Mail mail = new Mail("itcast_cxf@163.com", "itcast_cxf@126.com", "测试MailUtils", "这是正文!"); 10 MailUtils.send(session, mail); 11 }
=========================================================================================================================================
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的参数来指定要请求的方法名称。