第二十七章: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頁面的表單: