流程圖:
1)編寫前端界面
2)在web.xml中設置歡迎頁面(首頁)
1 <!-- 設置歡迎頁面--> 2 <welcome-file-list> 3 <welcome-file>login.jsp</welcome-file> 4 </welcome-file-list>
3)編寫dao層登錄用戶登錄的接口
1 // 設置為面向接口編程的格式 2 public interface UserDao { 3 // 得到登錄的用戶 4 public User getLoginUser(Connection connection, String userCode) throws SQLException; 5 }
4)編寫dao接口的實現類
1 package com.mine.dao.user; 2 3 import com.mine.dao.BaseDao; 4 import com.mine.pojo.User; 5 6 import java.sql.Connection; 7 import java.sql.PreparedStatement; 8 import java.sql.ResultSet; 9 import java.sql.SQLException; 10 11 public class UserDaoImpl implements UserDao { 12 // 去數據庫中查詢得到用戶 13 public User getLoginUser(Connection connection, String userCode) throws SQLException { 14 15 // 1)准備三個對象 16 PreparedStatement pstm = null; // 因為下面執行函數execute需要這兩個參數,所以在這初始化 17 ResultSet rs = null; // 結果 18 User user = null; // 可能會查出來的用戶 19 20 21 // 2)判斷數據庫連接是否成功 22 if (connection != null) { 23 // 3)如果連接成功了,丟一個sql 24 String sql = "select * from smbms_user where userCode=?"; // 用問號保證安全 25 Object[] params = {userCode}; // 封裝參數,它就是唯一的數據 26 27 // 4)執行sql 28 // sql也好了,userCode也好了,接下來需要PreparedStatement和ResultSet就可以調用執行方法了 29 rs = BaseDao.execute(connection, pstm, rs, sql, params); 30 // 遍歷用戶信息 31 if (rs.next()) { 32 user = new User(); // new 一個User對象 33 user.setId(rs.getInt("id")); // 設置id為查出來的對象的id 34 user.setUserCode(rs.getString("userCode")); 35 user.setUserName(rs.getString("userName")); 36 user.setUserPassword(rs.getString("userPassword")); 37 user.setGender(rs.getInt("gender")); 38 user.setBirthday(rs.getDate("birthday")); 39 user.setPhone(rs.getString("phone")); 40 user.setAddress(rs.getString("address")); 41 user.setUserRole(rs.getInt("userRole")); 42 user.setCreatedBy(rs.getInt("createdBy")); 43 user.setCreationDate(rs.getTimestamp("creationDate")); 44 user.setModifyBy(rs.getInt("modifyBy")); 45 user.setModifyDate(rs.getTimestamp("modifyDate")); 46 } 47 // 上面這些是從數據庫查出來的,查完要關閉數據庫 48 BaseDao.closeResource(null, pstm, rs); 49 // 最后返回user 50 51 52 } 53 return user; 54 55 } 56 }
5)業務層接口
1 public interface UserService { 2 // 用戶登錄,去公司寫的大多就是這個業務層 3 public User login(String userCode, String password) throws SQLException; 4 }
6)業務層實現類
1 package com.mine.service.user; 2 3 import com.mine.dao.BaseDao; 4 import com.mine.dao.user.UserDao; 5 import com.mine.dao.user.UserDaoImpl; 6 import com.mine.pojo.User; 7 import org.junit.Test; 8 9 import java.sql.Connection; 10 import java.sql.SQLException; 11 12 public class UserServiceImpl implements UserService { 13 // 業務層都會調用dao層,所以我們要引入dao層; 14 private UserDao userDao; 15 public UserServiceImpl() { 16 userDao = new UserDaoImpl(); 17 } 18 /* 19 userCode:用戶名 20 password:密碼 21 22 */ 23 // 調這個方法的人就能拿到用戶 24 public User login(String userCode, String password) { 25 Connection connection = null; 26 User user = null; 27 28 29 try { 30 connection = BaseDao.getConnection(); // 建立連接 31 // 通過業務層調用對應的具體的數據庫操作 32 user = userDao.getLoginUser(connection, userCode); 33 } catch (SQLException e) { 34 e.printStackTrace(); 35 } finally { 36 BaseDao.closeResource(connection, null, null); 37 } 38 return user; 39 } 40 41 @Test // 這個是在junit包里面的,所以要引入junit包 42 public void test() { 43 UserServiceImpl userService = new UserServiceImpl(); 44 User admin = userService.login("admin", "1234567"); 45 System.out.println(admin.getUserPassword()); 46 } 47 }
7)編寫servlet
1 package com.mine.servlet.user; 2 3 import com.mine.pojo.User; 4 import com.mine.service.user.UserService; 5 import com.mine.service.user.UserServiceImpl; 6 import com.mine.util.Constants; 7 8 import javax.servlet.ServletException; 9 import javax.servlet.http.HttpServlet; 10 import javax.servlet.http.HttpServletRequest; 11 import javax.servlet.http.HttpServletResponse; 12 import java.io.IOException; 13 import java.sql.SQLException; 14 15 public class LoginServlet extends HttpServlet { 16 // servlet:控制層。去調業務層的代碼,要么私有進來,要么去new 17 @Override 18 protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { 19 System.out.println("LoginServlet -- start...."); 20 21 // 獲取用戶名和密碼,去前端拿 22 String userCode = req.getParameter("userCode"); 23 String userPassword = req.getParameter("userPassword"); 24 25 // 和數據庫中的密碼進行對比,調業務層 26 UserService userService = new UserServiceImpl(); 27 try { 28 User user = userService.login(userCode, userPassword); // 這里已經把登錄的人查出來 29 if (user != null) { // 查有此人,可以登錄 30 // 將用戶的信息放到session中 31 req.getSession().setAttribute(Constants.USER_SESSION, user); 32 // 登錄成功之后跳轉到內部主頁 33 resp.sendRedirect("jsp/frame.jsp"); 34 35 } else { // 查無此人,無法登錄 36 // 轉發回登錄頁面,順帶提示用戶名或密碼錯誤 37 req.setAttribute("error", "用戶名或密碼不正確"); 38 req.getRequestDispatcher("login.jsp").forward(req, resp); 39 40 } 41 } catch (SQLException e) { 42 e.printStackTrace(); 43 } 44 45 46 } 47 48 @Override 49 protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { 50 doGet(req, resp); 51 } 52 }
上面代碼中的
Constants.USER_SESSION
8)注冊servlet
1 <!--Servlet--> 2 <servlet> 3 <servlet-name>LoginServlet</servlet-name> 4 <servlet-class>com.mine.servlet.user.LoginServlet</servlet-class> 5 </servlet> 6 <servlet-mapping> 7 <servlet-name>LoginServlet</servlet-name> 8 <url-pattern>/login.do</url-pattern> 9 </servlet-mapping> 10
9)測試訪問,確保以上成功
出現bug:用戶名和密碼都正確,但是就是沒有跳轉到下一個頁面,而是提示錯誤
錯誤信息:java.sql.SQLException: No suitable driver found for jdbc:mysql:/localhost:3306?useUnicode=true&characterEncoding=utf-8
preparedStatement = connection.prepareStatement(sql)和resultSet = preparedStatement.executeQuery(sql)是功能相同的兩行代碼。所以會報錯。
登錄功能優化:
注銷功能:思路:移除session,返回登錄頁面
1 package com.mine.servlet.user; 2 3 import com.mine.util.Constants; 4 5 import javax.servlet.ServletException; 6 import javax.servlet.http.HttpServlet; 7 import javax.servlet.http.HttpServletRequest; 8 import javax.servlet.http.HttpServletResponse; 9 import java.io.IOException; 10 11 public class LogoutServlet extends HttpServlet { 12 @Override 13 protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { 14 // 移除用戶的session 15 req.getSession().removeAttribute(Constants.USER_SESSION); 16 // 回到登錄頁面 17 resp.sendRedirect("/login.jsp"); 18 } 19 20 @Override 21 protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { 22 doGet(req, resp); 23 } 24 }
注冊
1 <servlet> 2 <servlet-name>LogoutServlet</servlet-name> 3 <servlet-class>com.mine.servlet.user.LogoutServlet</servlet-class> 4 </servlet> 5 <servlet-mapping> 6 <servlet-name>LogoutServlet</servlet-name> 7 <url-pattern>/jsp/logout.do</url-pattern> 8 </servlet-mapping>
出現bug 404
解決方案:
登錄攔截優化:
編寫一個過濾器
1 package com.mine.filter; 2 3 import com.mine.pojo.User; 4 import com.mine.util.Constants; 5 6 import javax.servlet.*; 7 import javax.servlet.http.HttpServletRequest; 8 import javax.servlet.http.HttpServletResponse; 9 import java.io.IOException; 10 import java.net.HttpRetryException; 11 import java.net.http.HttpRequest; 12 import java.net.http.HttpResponse; 13 14 public class SysFilter implements Filter { 15 @Override 16 public void init(FilterConfig filterConfig) throws ServletException { 17 18 } 19 20 @Override 21 public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException { 22 HttpServletRequest request = (HttpServletRequest) req; // 這個為了獲取session 23 HttpServletResponse response = (HttpServletResponse) resp; // 這個為了重定向 24 25 // 過濾器從session中獲取用戶,如果把session移除掉,它一定獲取不到 26 User user = (User) request.getSession().getAttribute(Constants.USER_SESSION); 27 28 if (user == null) { // 如果用戶為空,說明session已經被移除或者注銷了或者未登錄,那就讓它走error.jsp 29 response.sendRedirect("/smbms/error.jsp"); 30 31 } else { 32 chain.doFilter(req, resp); 33 } 34 } 35 36 @Override 37 public void destroy() { 38 39 } 40 }
配置
1 <!-- 用戶登錄過濾器--> 2 <filter> 3 <filter-name>SysFilter</filter-name> 4 <filter-class>com.mine.filter.SysFilter</filter-class> 5 </filter> 6 <filter-mapping> 7 <filter-name>SysFilter</filter-name> 8 <url-pattern>/jsp/*</url-pattern> <!-- jsp下面的所有頁面 --> 9 </filter-mapping>
注:如果error.jsp訪問找不到資源,把error改個名即可訪問
bug: