1、service業務層(biz(bussiness)層)
a)業務層:業務層裏面主要封裝的是一些業務功能是由對DAO的一次到多次的調用來完成。
b)service開發標準流程:
1)定義service接口:接口的定義利於寫作開發。命名:表名Service
注意:service接口中方法的定義,取決於網站要給用戶提供什麼樣的功能,完成什麼樣的需求。
2)接口的實現 命名:接口名Impl
2、在service中必須做手動控制事務
a)JDBC中的事務:
1)JDBC中的事務的管理對象時Connection
2)JDBC中事務默認自動提交,一條sql自成一個事務。
3)設置手動控制事務:
conn.setAutoCommit(false); //寫在獲取Connection之後
手動提交事務:conn.commit(); //業務操作完成後
手動迴歸滾事務:conn.rollback(); //出現異常的時候回滾
b)在service中必須做手動控制事務:
1)目的:保證Dao與service使用同一連接對象;
注意:DAO層不關閉連接,在service中關閉;
c)如何保證dao、service使用同一個連接:
1)在dao的方法上聲明形參,來接收service的Connection 不建議使用,這種方法存在API的入侵,不利於程序維護
2)JDBCUtil重構
顯然我們的程序每次都處於一個線程當中,所以我們將Connection對象存入當前線程中,未來只要當前線程中的組件需要Connection,不必創建新的,直接到當前線程中拿即可。
實現方式:利用ThreadLocal對象:
作用:ThreadLocal可以維護一個當前線程的局部變量,將一個對象綁定到當前線程中保存。這個對象被當前線程共享。
使用:創建:ThreadLocal<T> tol = new ThreadLocal<T>();
存值:tol.set(T value);
取值:T t = tol.get();
移除:tol.remove();
特點:一個線程,只能獲取到自己線程內部的局部變量,多個線程間不會相互影響。
d)ThreadLocal原理:
tol.set(value); // 將當前對象(tol)作爲key, value作爲值,存入當前線程
tol.get(); // 將當前對象(tol)作爲key , 到當前線程中取出對應的值
源代碼剖析如下:
JDBCUtil.java 更改後:
import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Properties;
public class JDBCUtil {
public static Properties p = new Properties();
static{
InputStream ins = null;
try {
//借用類加載的輸入流
ins = JDBCUtil.class.getResourceAsStream("/JDBC.properties");
p.load(ins);//載入配置文件
Class.forName(p.getProperty("driverClassName"));
} catch (Exception e) {
e.printStackTrace();
}finally{
try {
ins.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
//創建一個ThreadLocal對象,用於將Connection綁定到當前線程中
private static ThreadLocal<Connection> tol = new ThreadLocal<Connection>();
public static Connection getConnection(){
Connection conn = tol.get();
if(conn==null){
try {
conn = DriverManager.getConnection(p.getProperty("url"),p.getProperty("username"),p.getProperty("password"));
} catch (SQLException e) {
e.printStackTrace();
}
tol.set(conn);
}
return conn;
}
public static void closeAll(PreparedStatement ps,Connection conn,ResultSet rs){
try{
if(rs != null){ // 避免空指針異常
rs.close();
}
if(ps != null){
ps.close();
}
if(conn != null){
conn.close();
tol.remove(); //要移除
}
}catch(Exception e){
e.printStackTrace();
}
}
}
3、三層架構:
a)三層架構體系,是邏輯上的三層,按照完成功能不同,所做事宜不同,將項目分爲三個層次;
b) 視圖層: 涉及技術:HTML/JSP 主要職責:與用戶進行交互
業務邏輯層:service層:使用JDBC技術 主要職責:完成業務功能
數據訪問層: Dao層:使用JDBC技術 主要職責:對數據庫表進行CRUD操作
c)分層的優點:
1)整個項目的組件之間耦合度低,某一層的改變,不會影響整個系統的運行。
2)開發人員可以只去關注系統中的某一個層次
3)利於協作開發
4)後期的可維護性高
4、封裝一個日期類型轉換的工具類
java.sql.Date ----------> java.util.Date java.util.Date ----------->java.sql.Date
DateUtil.java
public class DateUtil {
public static java.util.Date utilDate(java.sql.Date date) throws ParseException{
SimpleDateFormat dsf = new SimpleDateFormat("yyyy-MM-dd");
java.util.Date utilDate = dsf.parse(date.toString());
return utilDate;
}
public static java.sql.Date sqlDate(java.util.Date date){
long time = date.getTime();
java.sql.Date sqlDate = new java.sql.Date(time);
return sqlDate;
}
}
5、service層步驟總結:
service層的概念: 主要封裝業務功能。 需要通過調用DAO來完成。
service中需要做的事:
1. 必須手動控制事務: conn.setAutoCommit(false);
2. 手動提交事務: conn.commit();
3. 手動回滾事務: conn.rollback();
4. 調用DAO
5. 數據的處理和驗證
注意事項: 當service和 dao 使用同一個連接對象時, 連接不在dao關閉, 在service中關閉。
6、完整的事例:(通訊錄實現)
JDBCUtil.java、Person.java、PersonDao.java在JDBC(2)中有詳細代碼:
TelBookService.java
import java.util.List;
public interface TelbookService {
//通過Id查找聯繫人
public Person getPersonById(Integer id);
//添加聯繫人需要使用的業務方法
public void regist(String name,String mobile,String telphone,String email,String city,String birth) ;
//獲得所有的聯繫人的業務方法
public List<Person> getAllPerson() ;
//根據聯繫人姓名查找聯繫人的業務方法
public List<Person> getPersonByName(String name);
//根據手機號碼查詢相關的聯繫人的業務方法
public List<Person> getPersonByMobile(String mobile);
//刪除聯繫人需要調用的業務方法
public void dropPersonById(Integer id) ;
//編輯聯繫人信息需要調用的業務方法
public void editPersonMessage(Integer id,String name,String mobile,String telphone,String email,String city,String date );
//獲得本月過生日的聯繫人編號
public List<Person> happyBirthday() ;
}
TelBookServiceImpl.java
import java.sql.Connection;
import java.sql.SQLException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
public class TelBookServiceImpl implements TelbookService {
@Override
public Person getPersonById(Integer id) {
Connection conn = null;
try{
conn = JDBCUtil.getConnection();
//手動控制事務
conn.setAutoCommit(false);
PersonDao personDao = new PersonDaoImpl();
Person person = personDao.queryPersonById(id);
conn.commit();
return person;
}catch(Exception e){
try {
conn.rollback();
} catch (SQLException e1) {
e1.printStackTrace();
}
e.printStackTrace();
throw new RuntimeException("獲取信息失敗,請檢查網絡!");
}finally{
JDBCUtil.closeAll(null, conn, null);
}
}
@Override
public void regist(String name, String mobile, String telphone,
String email, String city, String birth) {
Person p = new Person();
p.setName(name);
p.setMobile(mobile);
p.setTelphone(telphone);
p.setEmail(email);
p.setCity(city);
SimpleDateFormat date = new SimpleDateFormat("yyyy-MM-dd");
Date d;
try {
d = date.parse(birth);
} catch (ParseException e1) {
e1.printStackTrace();
throw new RuntimeException("日期格式錯誤!");
}
p.setDate(d);
Connection conn = null;
try{
conn = JDBCUtil.getConnection();
conn.setAutoCommit(false);//手動設置控制事務
PersonDao personDao = new PersonDaoImpl();
personDao.insertPerson(p);
conn.commit();//手動提交
return ;
}catch(Exception e){
try {
conn.rollback();
} catch (SQLException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
e.printStackTrace();
throw new RuntimeException("提交失敗!");
}finally{
JDBCUtil.closeAll(null, conn, null);
}
}
@Override
public List<Person> getAllPerson() {
List<Person> list = new ArrayList<Person>();
Connection conn = null;
try{
PersonDao personDao = new PersonDaoImpl();
conn = JDBCUtil.getConnection();
conn.setAutoCommit(false);
list = personDao.queryAllPersons();
System.out.println(conn);
conn.commit();
return list;
}catch(Exception e){
try {
conn.rollback();
} catch (SQLException e1) {
e1.printStackTrace();
}
throw new RuntimeException("網絡出故障!");
}finally{
JDBCUtil.closeAll(null, conn, null);
}
}
@Override
public List<Person> getPersonByName(String name) {
Connection conn = null;
List<Person> list = new ArrayList<Person>();
try{
conn = JDBCUtil.getConnection();
conn.setAutoCommit(false);
PersonDao personDao = new PersonDaoImpl();
list = personDao.queryPersonsByName(name);
conn.commit();
return list;
}catch(Exception e){
try {
conn.rollback();
} catch (SQLException e1) {
e1.printStackTrace();
}
throw new RuntimeException("網絡出故障!");
}finally{
JDBCUtil.closeAll(null, conn, null);
}
}
@Override
public List<Person> getPersonByMobile(String mobile) {
List<Person> list = new ArrayList<Person>();
Connection conn = null;
try{
conn = JDBCUtil.getConnection();
conn.setAutoCommit(false);
PersonDao personDao = new PersonDaoImpl();
list = personDao.queryPersonsByMobile(mobile);
conn.commit();
return list;
}catch(Exception e){
try {
conn.rollback();
} catch (SQLException e1) {
e1.printStackTrace();
}
throw new RuntimeException("網絡出現問題!");
}finally{
JDBCUtil.closeAll(null, conn, null);
}
}
@Override
public void dropPersonById(Integer id) {
Connection conn = null;
try{
conn = JDBCUtil.getConnection();
conn.setAutoCommit(false);
PersonDao personDao = new PersonDaoImpl();
personDao.deletePerson(id);
conn.commit();
}catch(Exception e){
e.printStackTrace();
try {
conn.rollback();
} catch (SQLException e1) {
e1.printStackTrace();
}
}finally{
JDBCUtil.closeAll(null, conn, null);
}
}
@Override
public void editPersonMessage(Integer id, String name, String mobile,
String telphone, String email, String city, String date) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
Date d = null;
try {
d = sdf.parse(date);
} catch (ParseException e) {
e.printStackTrace();
}
Person person = new Person(id,name,mobile,telphone,email,city,d);
Connection conn = null;
try{
conn = JDBCUtil.getConnection();
conn.setAutoCommit(false);
PersonDao personDao = new PersonDaoImpl();
personDao.updatePerson(person);
conn.commit();
}catch(Exception e){
try {
conn.rollback();
} catch (SQLException e1) {
e1.printStackTrace();
}
}finally{
JDBCUtil.closeAll(null, conn, null);
}
}
@Override
public List<Person> happyBirthday() {
Connection conn = null;
List<Person> list = new ArrayList<Person>();
try{
conn = JDBCUtil.getConnection();
conn.setAutoCommit(false);
PersonDao personDao = new PersonDaoImpl();
list = personDao.queryPersonsByMonth();
conn.commit();
return list;
}catch(Exception e){
try {
conn.rollback();
} catch (SQLException e1) {
e1.printStackTrace();
}
throw new RuntimeException("網絡故障!");
}finally{
JDBCUtil.closeAll(null, conn, null);
}
}
}
TelBookView.java
import java.util.List;
import java.util.Scanner;
import org.junit.Test;
public class TelBookView {
private Scanner sc=new Scanner(System.in);
private TelbookService service=null;
public TelBookView() {
try{
service = new TelBookServiceImpl();
}catch(Exception e){}
}
@Test
public void showMainView(){
while(true){
System.out.println("***************歡迎訪問通訊錄***************");
System.out.println("1.顯示所有聯繫人 2.按姓名查找聯繫人 3.按號碼查找聯繫人");
System.out.println("4.添加聯繫人 5.刪除聯繫人 6.修改聯繫人信息");
System.out.println("7.生日快樂 8.退出");
System.out.println("請選擇操作:");
int selected=sc.nextInt();
requestDispatcher(selected);
}
}
public void requestDispatcher(int selected) {
try {
switch(selected){
case 1:{ showAllPerson(); break;}
case 2:{ showPersonsByName(); break;}
case 3:{ showPersonsByMobil();break;}
case 4:{ addPerson(); break;}
case 5:{ dropPersonById(); break;}
case 6:{changePersonMessageById(); break;}
case 7:{ sayHappy(); break;}
case 8:{
System.out.println("--------------------謝謝使用,再見------------------");
System.exit(0);
break;
}
default:{
throw new Exception("輸入錯誤,請考慮重新選擇!");
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
//用戶選擇功能1,顯示所有聯繫人
public void showAllPerson() throws Exception{
//調用service的查詢方法,查詢所有的聯繫人
List<Person> list=service.getAllPerson();
//調用本類的方法顯示聯繫人信息
showPersons(list);
}
//只供本類其他方法是用,用表格形式顯示list集合裏的聯繫人信息
private void showPersons(List<Person> list) throws Exception{
System.out.println("Id\tName\t Mobile \t Telphone \t Email \t City \t Birthday ");
for(Person p:list){
System.out.println(p.getId()+"\t"+p.getName()+"\t"+p.getMobile()+"\t"+p.getTelphone()+"\t"+p.getEmail()+"\t"+p.getCity()+"\t"+p.getDate());
}
}
//用戶選擇功能2,按姓名查詢聯繫人,允許模糊查詢
public void showPersonsByName() throws Exception{
System.out.println("請輸入需要查詢的聯繫人姓名(可以模糊查詢):");
String name=sc.next();
//調用service方法查詢相關數據
List<Person> list=service.getPersonByName(name);
//調用本類的方法顯示聯繫人信息
showPersons(list);
}
//用戶選擇功能3,按手機查詢聯繫人,允許模糊查詢
public void showPersonsByMobil() throws Exception{
System.out.println("請輸入需要查詢的聯繫人手機號碼(可以模糊查詢):");
String mobile=sc.next();
//調用service方法查詢相關數據
List<Person> list=service.getPersonByMobile(mobile);
//調用本類的方法顯示聯繫人信息
showPersons(list);
}
//用戶選擇功能4,添加聯繫人,允許用戶名重複
public void addPerson() throws Exception{
System.out.println("請輸入聯繫人姓名:");
String name=sc.next();
System.out.println("請輸入聯繫人手機號碼:");
String mobile=sc.next();
System.out.println("請輸入聯繫人座機號碼:");
String telphone=sc.next();
System.out.println("請輸入聯繫人email:");
String email=sc.next();
System.out.println("請輸入聯繫人地址:");
String city=sc.next();
System.out.println("請輸入生日(1980-6-23):");
String date=sc.next();
//調用service的regist()
service.regist(name, mobile, telphone, email, city, date);
System.out.println("添加聯繫人成功!!!!");
}
//用戶選擇功能5,刪除聯繫人,需要輸入聯繫人的id
public void dropPersonById() throws Exception{
System.out.println("請輸入需要刪除的聯繫人的id:");
int id=sc.nextInt();
//調用service的方法刪除聯繫人
service.dropPersonById(id);
System.out.println("-----------刪除成功----------");
}
//首先需要用戶輸入被修改用戶的id,將該用戶信息顯示在屏幕上.
//目前修改聯繫人只能全表修改,必須給定除id以外的所有值
public void changePersonMessageById() throws Exception{
System.out.println("請輸入需要修改的聯繫人的編號(id): ");
int id=sc.nextInt();
//調用service的根據id查詢聯繫人方法,獲得聯繫人具體信息並且顯示
Person p=service.getPersonById(id);
System.out.println("您要修改的聯繫人具體信息如下:");
System.out.println("Id\tName\t Mobile \t Telphone \t Email \t City \t Birthday ");
System.out.println(p.getId()+"\t"+p.getName()+"\t"+p.getMobile()+"\t"+p.getTelphone()+"\t"+p.getEmail()+"\t"+p.getCity()+"\t"+p.getDate());
//用戶輸入修改信息
System.out.println("請輸入聯繫人姓名:");
String name=sc.next();
System.out.println("請輸入聯繫人手機號碼:");
String mobile=sc.next();
System.out.println("請輸入聯繫人座機號碼:");
String telphone=sc.next();
System.out.println("請輸入聯繫人email:");
String email=sc.next();
System.out.println("請輸入聯繫人地址:");
String city=sc.next();
System.out.println("請輸入生日(1980-6-23):");
String date=sc.next();
//調用service裏的修改聯繫人的方法
service.editPersonMessage(id,name,mobile,telphone,email,city,date);
System.out.println("-----------修改成功----------");
}
//向本月過生日的聯繫人發送happybirthday短信
public void sayHappy(){
//調用service的查詢方法,查詢所有過生日的聯繫人
List<Person> list=service.happyBirthday();
//調用本類的方法顯示聯繫人信息
try {
showPersons(list);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("哈哈,祝你年年有今日,歲歲有今朝");
}
}
以上均是java project工程;