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
存值: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 tol = new ThreadLocal();
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 getAllPerson() ;
//根据联系人姓名查找联系人的业务方法
public List getPersonByName(String name);
//根据手机号码查询相关的联系人的业务方法
public List 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 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 getAllPerson() {
List list = new ArrayList();
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 getPersonByName(String name) {
Connection conn = null;
List list = new ArrayList();
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 getPersonByMobile(String mobile) {
List list = new ArrayList();
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 happyBirthday() {
Connection conn = null;
List list = new ArrayList();
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 list=service.getAllPerson();
//调用本类的方法显示联系人信息
showPersons(list);
}
//只供本类其他方法是用,用表格形式显示list集合里的联系人信息
private void showPersons(List 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 list=service.getPersonByName(name);
//调用本类的方法显示联系人信息
showPersons(list);
}
//用户选择功能3,按手机查询联系人,允许模糊查询
public void showPersonsByMobil() throws Exception{
System.out.println("请输入需要查询的联系人手机号码(可以模糊查询):");
String mobile=sc.next();
//调用service方法查询相关数据
List 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 list=service.happyBirthday();
//调用本类的方法显示联系人信息
try {
showPersons(list);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("哈哈,祝你年年有今日,岁岁有今朝");
}
}