專案01-JavaWeb網上書城01之工具類
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 returnUUID.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("[email protected]", "[email protected]", "測試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的引數來指定要請求的方法名稱。