1. 程式人生 > >第二十七章:JavaEE專案的三層架構

第二十七章:JavaEE專案的三層架構

作者:java_wxid

JavaEE專案的三層架構
在這裡插入圖片描述
分層的作用
方便專案後期的維護和升級,以及擴充套件。
分層的好處是降低程式碼的耦合度

分層後的程式碼包結構

Dao持久層的包		com.dao		放dao層的介面
			com.dao.impl	放dao層的實現類
Service業務層		com.service	放Service層的介面
			com.service.impl放Service層的實現類
web層			com.servlet	放web層的實現類
bean層			com.pojo	JavaBean物件	com.entity	com.domain	
測試層			com.test	測試
工具層			com.utils	工具類層

步驟:
1、建立資料庫和表

drop database if exists book;   
create database book;    
use book; 
-- 使用者名稱
-- 密碼
-- 郵箱

create table t_user(
	`id` int primary key auto_increment,
	`username` varchar(20) not null unique,
	`password` varchar(32) not null,
	`email` varchar(200)
);  
insert into t_user(`username`,`password`,`email`) values('admin','admin','
[email protected]
'); select * from t_user;

2、建立對應的JavaBean物件

public class User {

	private Integer id;
	private String username;
	private String password;
	private String email;

3、編寫工具類
JdbcUtils類 === 使用資料庫連線池
getConnection() 獲取連線
closeConnection() 關閉連線

1、匯入jar包:
druid-1.1.9.jar
mysql-connector-java-5.1.7-bin.jar

2、建立config原始碼目錄,新增jdbc.properties屬性配置檔案

url=jdbc:mysql://localhost:3306/book
username=root
password=root
driverClassName=com.mysql.jdbc.Driver
initialSize=5
maxActive=10

JdbcUtils原始碼:

public class JdbcUtils {
	// 阿里資料庫連線池
	private static DataSource dataSource;
	static {
		try {
			Properties properties = new Properties();
			properties.load(JdbcUtils.class.getClassLoader()
					.getResourceAsStream("jdbc.properties"));
			dataSource = DruidDataSourceFactory.createDataSource(properties);
		} catch (Exception e) {
			e.printStackTrace();
		} 
	}
	/**
	 * 返回資料庫連線物件
	 * @return
	 */
	public static Connection getConnection() {
		Connection connection = null;  
		try {
			connection = dataSource.getConnection();
			return connection;
		} catch (SQLException e) {
			e.printStackTrace();
		}    
		return connection;
	}   
	/**
	 * 釋放 連線
	 * 
	 * @param connection
	 */
	public static void closeConnection(Connection connection) {
		if (connection != null) {
			try {
				connection.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
	}
}

JdbcUtils測試程式碼:

public class JdbcUtilsTest {

	@Test
	public void test1() throws Exception {
		for (int i = 0; i < 100; i++) {
			Connection connection = JdbcUtils.getConnection();
			System.out.println( connection );
			JdbcUtils.closeConnection(connection);
		}
	}
}

4、去編寫Dao層(包含測試)
BaseDaoImpl原始碼:

public class BaseDaoImpl { 
	private QueryRunner queryRunner = new QueryRunner();
	/**
	 * 執行insert,update,delete語句
	 * @param sql
	 * @param args
	 * @return -1表示執行失敗
	 */
	public int update(String sql, Object... args) {
		Connection connection = JdbcUtils.getConnection();
		try {
			return queryRunner.update(connection, sql, args);
		} catch (SQLException e) {
			e.printStackTrace();
		} finally {
			JdbcUtils.closeConnection(connection);
		}
		return -1;
	}    
	/**
	 * 查詢一條記錄 
	 * @param type
	 * @param sql
	 * @param args
	 * @return
	 */
	public <T> T queryForOne(Class<T> type, String sql, Object... args) {
		Connection connection = JdbcUtils.getConnection();
		try {
			return queryRunner.query(connection, sql, new BeanHandler<T>(type),
					args);
		} catch (SQLException e) {
			e.printStackTrace();
		} finally {
			JdbcUtils.closeConnection(connection);
		}
		return null;
	}    
	/**
	 * 查詢返回多個物件的情況
	 * 
	 * @param type
	 * @param sql
	 * @param args
	 * @return
	 */
	public <T> List<T> queryForList(Class<T> type, String sql, Object... args) {
		Connection connection = JdbcUtils.getConnection();
		try {
			return queryRunner.query(connection, sql, new BeanListHandler<T>(
					type), args);
		} catch (SQLException e) {
			e.printStackTrace();
		} finally {
			JdbcUtils.closeConnection(connection);
		}
		return null;
	}    
	/**
	 * 查詢返回單個列的情況
	 * 
	 * @param sql
	 * @param args
	 * @return
	 */
	public Object queryForSingleValue(String sql, Object... args) {
		Connection connection = JdbcUtils.getConnection();
		try {
			return queryRunner
					.query(connection, sql, new ScalarHandler(), args);
		} catch (SQLException e) {
			e.printStackTrace();
		} finally {
			JdbcUtils.closeConnection(connection);
		}
		return null;
	}
}

UserDao介面
saveUser 儲存使用者
queryUserByUsername 根據使用者名稱查詢使用者
queryUserByUsernameAndPassword 根據使用者名稱和密碼查詢使用者

UserDao介面程式碼:

public interface UserDao {
	// 儲存使用者
	public int saveUser(User user); 
	// 根據使用者名稱查詢使用者
	public User queryUserByUsername(String username);
	// 根據使用者名稱和密碼查詢使用者
	public User queryUserByUsernameAndPassword(String username, String password);
}

UserDaoImpl程式碼:

public class UserDaoImpl extends BaseDaoImpl implements UserDao {
	@Override
	public int saveUser(User user) {
		String sql = "insert into t_user(`username`,`password`,`email`) values(?,?,?)";
		return update(sql, user.getUsername(), user.getPassword(),
				user.getEmail());
	}
	@Override
	public User queryUserByUsername(String username) {
		String sql = "select id,username,password,email from t_user where username = ?";
		return queryForOne(User.class, sql, username);
	}
	@Override
	public User queryUserByUsernameAndPassword(String username, String password) {
		String sql = "select id,username,password,email from t_user where username = ? and password = ?";
		return queryForOne(User.class, sql, username, password);
	}
}

UserDao的測試:

public class UserDaoTest {

	private static UserDao userDao;
	/**
	 * 被標註了@BeforeClass註解的方法會在所有方法執行之前執行,做一些初始化工作。
	 * @throws Exception
	 */
	@BeforeClass
	public static void setUpBeforeClass() throws Exception {
		userDao = new UserDaoImpl();
	}
	@Test
	public void testSaveUser() {
		userDao.saveUser(new User(null, "wzg168", "123456", "[email protected]"));
	}
	@Test
	public void testQueryUserByUsername() {
		System.out.println(userDao.queryUserByUsername("username"));
		System.out.println(userDao.queryUserByUsername("wzg168"));
	}
	@Test
	public void testQueryUserByUsernameAndPassword() {
		System.out.println(userDao.queryUserByUsernameAndPassword("wzg168",
				"1234"));
		System.out.println(userDao.queryUserByUsernameAndPassword("wzg168",
				"123456"));
	}
}

5、去編寫Service層(包含業務)

Service介面
login 登入
regist 註冊
existsUsername 檢查使用者名稱是否存在

UserService介面

public interface UserService {
	/**
	 * 登入
	 * @param username
	 * @param password
	 * @return
	 */
	public User login(String username, String password);    
	/**
	 * 註冊
	 * @param user
	 */
	public void regist(User user);   
	/**
	 * 檢查使用者名稱是否存在
	 * 
	 * @param username
	 * @return
	 */
	public boolean existsUsername(String username);
}

UserServiceImpl的實現

public class UserServiceImpl implements UserService {

	private UserDao userDao = new UserDaoImpl();
	@Override
	public User login(String username, String password) {
		return userDao.queryUserByUsernameAndPassword(username, password);
	}
	@Override
	public void regist(User user) {
		userDao.saveUser(user);
	}
	@Override
	public boolean existsUsername(String username) {
		User user = userDao.queryUserByUsername(username);
		// 使用者沒有查到,說明,使用者名稱不存在
		if (user == null) {
			// 使用者名稱可用
			return false;
		} else {
			// 使用者名稱已存在
			return true;
		}		
	}
}

測試程式碼:

public class UserServiceTest {   
	private static UserService userService;
	@BeforeClass
	public static void setUpBeforeClass() throws Exception {
		userService = new UserServiceImpl();
	}
	@Test
	public void testLogin() {
		System.out.println( userService.login("admin", "admin") );
		System.out.println( userService.login("admin", "123456") );
	}  
	@Test
	public void testRegist() {
		userService.regist(new User(null, "aaa168", "123456", "[email protected]"));
	}
	@Test
	public void testExistsUsername() {
		if (userService.existsUsername("admin1")) {
			System.out.println("使用者名稱已存在!");
		} else {
			System.out.println("使用者名稱可用!");
		}
	}
}

6、編寫web層
使用者註冊功能實現:
RegistServlet程式:

public class RegistServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;
	private UserService userService = new UserServiceImpl();
	protected void doPost(HttpServletRequest request,
			HttpServletResponse response) throws ServletException, IOException {
		// 1、獲取請求引數
		String username = request.getParameter("username");
		String password = request.getParameter("password");
		String email = request.getParameter("email");
		String code = request.getParameter("code");
		// 比較驗證碼是否正確 寫死比較abcde
		if ("abcde".equalsIgnoreCase(code)) {
			// 驗證碼正確
			// 比較使用者名稱是否可用
			boolean existsUsername = userService.existsUsername(username);
			if (existsUsername) {
				// 說明使用者名稱已存在!!!
				System.out.println("註冊失敗【" + username + "】使用者名稱已存在!!");
				// 轉發中的斜槓表示到http://ip:port/工程名/ 對映到程式碼的WebContent目錄
				request.getRequestDispatcher("/pages/user/regist.html")
						.forward(request, response);
			} else {
				// 2、呼叫Service方法處理業務
				userService.regist(new User(null, username, password, email));
				System.out.println("使用者註冊成功!");
				// 轉發中的斜槓表示到http://ip:port/工程名/ 對映到程式碼的WebContent目錄
				request.getRequestDispatcher("/pages/user/regist_success.html")
						.forward(request, response);
			}
		} else {
			// 驗證碼不正確
			System.out.println("驗證碼不正確:" + code);
			// 轉發中的斜槓表示到http://ip:port/工程名/ 對映到程式碼的WebContent目錄
			request.getRequestDispatcher("/pages/user/regist.html").forward(
					request, response);
		}
	}
}

所有頁面都要統一加上base標籤:
1、<base href=“http://localhost:8080/book/” />
2、去掉頁面中原相對路徑前面的…/…/

修改regist.html頁面中表單:
修改請求的地址和請求的方式為post
在這裡插入圖片描述
如何在Eclipse中使用Debug除錯功能
除錯程式碼需要有斷點+debug執行模式

在你需要讓程式碼停下來的所在行,找到左邊行號雙擊,就可以出現如下圖所示的斷點標記。
在這裡插入圖片描述debug啟動Tomcat伺服器。

當出現如下視窗,選中yes
在這裡插入圖片描述
在這裡插入圖片描述讓程式碼往下執行一行。
在這裡插入圖片描述讓程式碼進入到當前方法體內執行。
在這裡插入圖片描述跳出當前方法外
在這裡插入圖片描述直接終止程式(伺服器也停止)
在這裡插入圖片描述讓程式碼繼續執行,直到遇到下一個斷點才停止。
大綱視窗
在這裡插入圖片描述
變數視窗:
在這裡插入圖片描述
斷點視窗:
在這裡插入圖片描述
方法(呼叫)棧視窗
1、下一行,呼叫上一行方法
2、快速切換當前方法
在這裡插入圖片描述
使用者登入功能實現:
LoginServlet程式

public class LoginServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;

	private UserService userService = new UserServiceImpl();

	protected void doPost(HttpServletRequest request,
			HttpServletResponse response) throws ServletException, IOException {

		// 1、獲取請求的引數
		String username = request.getParameter("username");
		String password = request.getParameter("password");
		// 2、呼叫Service處理業務
		// userService.login( user );
		User user = userService.login(username, password);
		if (user == null) {
			// 登入失敗
			// login.html
			request.getRequestDispatcher("/pages/user/login.html").forward(
					request, response);
		} else {
			// 登入成功
			// login_success.html
			request.getRequestDispatcher("/pages/user/login_success.html")
					.forward(request, response);
		}
	}
}

修改login.html頁面的表單:
在這裡插入圖片描述