用户注册登录案例
2017-06-16 13:17
393 查看
综合案例
实现用户注册、登录、列表显示的功能。符合MVC思想,使用javaee三层架构。如下图。需要用到数据库驱动包以及BeanUtils包。就是这些
commons-beanutils、commons-logging、mysql-connector-java。
整个流程如下
0. 数据库连接工具类
package utils; import java.io.FileInputStream; import java.io.InputStream; import java.sql.*; import java.util.Properties; public class JDBCUtil { private static String driver; private static String url; private static String user; private static String password; // 静态代码块,随着类的加载而加载,只加载一次 static { try { Properties prop = new Properties(); // 下面这个是本机使用的就填写项目所在位置,但是我们是要部署到服务器的,所以获取WEB-INF/classes目录下的,注意要加"/" // InputStream is = new FileInputStream("/example/src/jdbc_setting.properties"); InputStream is = JDBCUtil.class.getResourceAsStream("/jdbc_setting.properties"); // load()接收InputStream,所以向上转型 prop.load(is); driver = prop.getProperty("ClassName"); url = prop.getProperty("url"); user = prop.getProperty("user"); password = prop.getProperty("password"); Class.forName(driver); is.close(); } catch (Exception e) { e.printStackTrace(); } } public static Connection getConnection() { Connection connection = null; try { connection = DriverManager.getConnection(url, user, password); } catch (Exception e) { e.printStackTrace(); throw new RuntimeException("创建连接失败!"); } return connection; } // 释放资源 // 参数可能为空 // 调用close要抛出异常,即使出现异常也能关闭 public void close(Connection conn, Statement state, ResultSet result) { try { if (result != null) { result.close(); } } catch (SQLException e) { e.printStackTrace(); } finally { try { if (state != null) { state.close(); } } catch (SQLException e) { e.printStackTrace(); } finally { try { if (conn != null) { conn.close(); } } catch (SQLException e) { e.printStackTrace(); } } } } }
数据库配置文件
ClassName=com.mysql.jdbc.Driver url=jdbc\:mysql\://localhost\:3306/example user=root password=admin
1. 用一个bean来封装注册用户的信息
package domain; public class User { private int id; private String name; private String password; private String email; public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } @Override public String toString() { return "User [id=" + id + ", nameString=" + name + ", password=" + password + ", email=" + email + "]"; } }
2. 定义一个借口用来保存User
package dao; import domain.User; public interface UserDao { void save(User u); User getUserByName(String name); }
2. 实现上述接口
主要实现了插入和查询功能package dao.impl; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import dao.UserDao; import domain.User; import utils.JDBCUtil; public class UserDaoImple implements UserDao { @Override public void save(User u) { // 1. 获得连接 Connection connection = JDBCUtil.getConnection(); // 2. 准备sql语句 String sql = "INSERT INTO "+ "`example`.`t_user` (`name`, `password`, `email`) "+ "VALUES "+ "(?, ?, ?);"; // 3. 获得PreparedStatement对象,可防止sql注入 PreparedStatement preStatement = null; try { // 先运送sql语句过去预编译 preStatement = connection.prepareStatement(sql); // 4. 设置传送的参数,第一个参数是列数,从1开始 preStatement.setString(1, u.getName()); preStatement.setString(2, u.getPassword()); preStatement.setString(3, u.getEmail()); //5. 执行sql int result = preStatement.executeUpdate(); // 上面只对一行作用了,添加成功肯定是一行。若 != 1说明没有添加成功 if(result != 1 ){ throw new RuntimeException("保存用户失败!"); } } catch (SQLException e) { e.printStackTrace(); } finally { // 6. 关闭资源 JDBCUtil.close(connection, preStatement, null); } } @Override public User getUserByName(String name) { User user = null; // 1. 获得连接 Connection connection = JDBCUtil.getConnection(); // 2. 写sql语句 String sql = "SELECT * FROM t_user WHERE name = ?"; // 3. 获得PreparedStatement PreparedStatement preparedStatement = null; try { preparedStatement = connection.prepareStatement(sql); // 4. 设置参数 preparedStatement.setString(1, name); // 5. 执行查询 ResultSet set = preparedStatement.executeQuery(); // 因为用户名唯一,结果集里只有一条,直接用if就好,可以不用while // 6. 将结果集封装到User if (set.next()) { user = new User(); user.setId(set.getInt("id")); user.setName(set.getString("name")); user.setPassword(set.getString("password")); user.setEmail(set.getString("email")); } } catch (SQLException e) { e.printStackTrace(); throw new RuntimeException("查询用户失败"); } finally { // 7. 关闭连接,返回User JDBCUtil.close(connection, preparedStatement, null); } return user; } }
4. 用户注册
package service; import dao.UserDao; import dao.impl.UserDaoImple; import domain.User; public class UserService { private UserDao userDao = new UserDaoImple(); public void regist(User u) { // 检查用户名是否存在 User exitsUser = userDao.getUserByName(u.getName()); // 用户名已经被使用 if (exitsUser != null) { throw new RuntimeException("用户名已经存在!"); } else { // 如果这个名字没有使用,则保存 userDao.save(u); } } }
5. 检查用户名和密码
package utils; import java.util.HashMap; import java.util.Map; import domain.User; public class CheckUtils { public static Map<String, String> checkUser(User u) { Map<String, String> map = new HashMap<>(); // 验证用户名不为空,"".equals(u.getName())更好。,u.getName().equals("")如果u.getName()为null则不能调用.equals(); if (u.getName() == null || "".equals(u.getName().trim())) { map.put("name", "用户名不能为空!"); } // 验证密码不为空 if (u.getPassword() == null || "".equals(u.getPassword().trim())) { map.put("password", "密码不能为空!"); } return map; } }
6. 注册的servlet
package web; import java.io.IOException; import java.lang.reflect.InvocationTargetException; import java.util.Map; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.commons.beanutils.BeanUtils; import domain.User; import service.UserService; import utils.CheckUtils; @WebServlet("/RegistServlet") public class RegistServlet extends HttpServlet { private UserService us= new UserService(); protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //1 封装参数到User对象 User user = new User(); try { // 表单参数封装到user BeanUtils.populate(user, request.getParameterMap()); } catch (IllegalAccessException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (InvocationTargetException e) { // TODO Auto-generated catch block e.printStackTrace(); } // 检查有没有错误 Map<String, String> errors = CheckUtils.checkUser(user); // 如果有错误 if (! errors.isEmpty()) { request.setAttribute("errors", errors); // 注意是转发而不是重定向,转发过去是一次请求,还是刚才jsp页面。才能收到错误信息。 // 如果是重定向,重新加载jsp不会收到错误信息 request.getRequestDispatcher("/regist.jsp").forward(request, response); return; } // 3. 调用Service保存 try { // regist方法里面throw了很多异常,要捕获 us.regist(user); // 4 根据结果,跳转到对应页面,失败就转发到注册页面 } catch (Exception e) { e.printStackTrace(); request.setAttribute("error", e.getMessage()); request.getRequestDispatcher("/regist.jsp").forward(request, response); return; } // 成功重定向到登录页面。request.getContextPath()获得项目名/example response.sendRedirect(request.getContextPath()+"/login.jsp"); } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } }
7. 注册界面和登录界面
注册<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> <% String path = request.getContextPath(); String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/"; %> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <base href="<%=basePath%>"> <title>My JSP 'regist.jsp' starting page</title> <meta http-equiv="pragma" content="no-cache"> <meta http-equiv="cache-control" content="no-cache"> <meta http-equiv="expires" content="0"> <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"> <meta http-equiv="description" content="This is my page"> <!-- <link rel="stylesheet" type="text/css" href="styles.css"> --> </head> <body> <form action="/example/RegistServlet" method="post" name="form1"> <table border="1" width="30%" > <tr> <th colspan="2" align="center" > 用户注册 </th> </tr> <tr> <td>用户名:</td> <td><input type="text" name="name" /><font color="red" >${requestScope.errors.name }</font></td> </tr> <tr> <td>密码:</td> <td><input type="password" name="password" /><font color="red" >${requestScope.errors.password }</font></td> </tr> <tr> <td>邮箱:</td> <td><input type="text" name="email" /><font color="red" ></font></td> </tr> <tr> <td colspan="2" align="center" > <input type="submit" value="注册" /> </td> </tr> </table> </form> <font color="red">${requestScope.error }</font> </body> </html>
登录
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> <% String path = request.getContextPath(); String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/"; %> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <base href="<%=basePath%>"> <title>My JSP 'login.jsp' starting page</title> <meta http-equiv="pragma" content="no-cache"> <meta http-equiv="cache-control" content="no-cache"> <meta http-equiv="expires" content="0"> <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"> <meta http-equiv="description" content="This is my page"> <!-- <link rel="stylesheet" type="text/css" href="styles.css"> --> </head> <body> <form action="/example/LoginServlet" method="post" name="form2"> <table border="1" width="30%" > <tr> <th colspan="2" align="center" > 用户登录 </th> </tr> <tr> <td>用户名:</td> <td><input type="text" name="name" /><font color="red" >${requestScope.errors.name }</font></td> </tr> <tr> <td>密码:</td> <td><input type="password" name="password" /><font color="red" >${requestScope.errors.password }</font></td> </tr> <tr> <td colspan="2" align="center" > <input type="submit" value="登录" /> </td> </tr> </table> </form> <font color="red">${requestScope.error }</font> </body> </html>
8. 用户登录
UserService新增用户登录方法// 用户登录 public User login(User u){ //1 根据用户名,调用dao获得User对象 User existU = userDao.getUserByName(u.getName()); // 为空说明还没注册 if(existU==null){ //没获得到=> 用户名不存在=> 抛出异常 throw new RuntimeException("用户名不存在!"); } //2 和数据库的账户密码比对密码是否一致 if(!existU.getPassword().equals(u.getPassword())){ //不一致=>密码不正确=>抛出异常 throw new RuntimeException("密码不正确!"); } //3 能执行到这儿说明已经注册且登录成功。返回的是数据库中User对象 return existU; }
LoginServlet
package web; import java.io.IOException; import java.lang.reflect.InvocationTargetException; import java.util.Map; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.commons.beanutils.BeanUtils; import domain.User; import service.UserService; import utils.CheckUtils; @WebServlet("/LoginServlet") public class LoginServlet extends HttpServlet { private UserService us = new UserService(); protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 避免乱码 request.setCharacterEncoding("UTF-8"); User u = new User(); try { BeanUtils.populate(u, request.getParameterMap()); } catch (IllegalAccessException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (InvocationTargetException e) { // TODO Auto-generated catch block e.printStackTrace(); } // 2.非空校验 Map<String,String> errors = CheckUtils.checkUser(u); if(errors.size()>0){ request.setAttribute("errors", errors); request.getRequestDispatcher("/login.jsp").forward(request, response); return; } // 3.调用Service User existU = null; try { existU= us.login(u); } catch (Exception e) { e.printStackTrace(); request.setAttribute("error", e.getMessage()); request.getRequestDispatcher("/login.jsp").forward(request, response); return; } // 4.向session中加入登录标识, 登录用session可以保持用户的状态,不掉线 request.getSession().setAttribute("user", existU); // 5.重定向到列表显示servlet response.sendRedirect(request.getContextPath()+"/ListServlet"); } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } }
休息一下,看下
request.getRequestDispatcher和
response.sendRedirect为什么一个是request的方法,一个是response的方法?
转发是向服务器请求,然后服务器内部进行转发操作,因为是请求所以用request
重定向是浏览器的动作,响应新的页面给用户。所以用的是response
9. 登录后显示用户数据列表
UserDao里新增接口方法List<User> getAllUsers();
同时UserDaoImple去实现
@Override public List<User> getAllUsers() { List<User> users = new ArrayList<>(); // 1. 获得连接 Connection connection = JDBCUtil.getConnection(); // 2. 写sql语句 String sql = "SELECT * FROM t_user"; // 3. 获得PreparedStatement PreparedStatement preparedStatement = null; try { preparedStatement = connection.prepareStatement(sql); ResultSet set = preparedStatement.executeQuery(); // 因为用户名唯一,结果集里只有一条,直接用if就好,可以不用while // 6. 将结果集封装到User while (set.next()) { User user = new User(); user.setId(set.getInt("id")); user.setName(set.getString("name")); user.setPassword(set.getString("password")); user.setEmail(set.getString("email")); users.add(user); } } catch (SQLException e) { e.printStackTrace(); throw new RuntimeException("查询用户列表失败"); } finally { // 7. 关闭连接,返回User JDBCUtil.close(connection, preparedStatement, null); } return users; }
登录成功后的列表显示需要使用servlet从数据库取得用户数据,然后转发到list.jsp显示
package web; import java.io.IOException; import java.util.ArrayList; import java.util.List; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import domain.User; import service.UserService; @WebServlet("/ListServlet") public class ListServlet extends HttpServlet { private UserService userService = new UserService(); protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 1. 校验用户是否已经登录 User user = (User) request.getSession().getAttribute("user"); // 如果用户下线了, 重定向到登录界面。这里就不是转发了。因为login里面无需接收诸如错误等信息 if (user == null) { // response.sendRedirect(request.getContextPath()+"/login.jsp"); request.getRequestDispatcher("/login.jsp").forward(request, response); return; } // 调用Service获取所有用户 List<User> userList = userService.getAllUsers(); // 转发到jsp显示, 设置属性方便forEach遍历 request.setAttribute("list", userList); request.getRequestDispatcher("WEB-INF/page/list.jsp").forward(request, response);; return; } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } }
lsit.jsp
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> <%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <% String path = request.getContextPath(); String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/"; %> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <base href="<%=basePath%>"> <title>My JSP 'list.jsp' starting page</title> <meta http-equiv="pragma" content="no-cache"> <meta http-equiv="cache-control" content="no-cache"> <meta http-equiv="expires" content="0"> <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"> <meta http-equiv="description" content="This is my page"> <!-- <link rel="stylesheet" type="text/css" href="styles.css"> --> </head> <body> <h1>用户列表</h1> <div>欢迎回来!${sessionScope.user.name}</div> <br> <a href="/example/LoginoutServlet">退出登录</a> <table border="1"> <tr> <th>id</th> <th>用户名</th> <th>邮箱</th> </tr> <c:forEach items="${requestScope.list}" var="user" > <tr> <td>${pageScope.user.id }</td> <td>${pageScope.user.name }</td> <td>${pageScope.user.email }</td> </tr> </c:forEach> </table> </body> </html>
10. 用户退出登录
销毁当前的session重定向到登录界面
在list.jsp中加入一句
<a href="/example/LoginoutServlet">退出登录</a>
新增一个LoginoutServlet,用户点击上面的超链接后,跳转到这个servlet
package web; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @WebServlet("/LoginoutServlet") public class LoginoutServlet extends HttpServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 销毁session request.getSession().invalidate(); // 重定向到登录页面让其他用户进行登录 response.sendRedirect(request.getContextPath() + "/login.jsp"); } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } }
至此,小案例完成。
题外话,lsit.jsp为什么不放在WebRoot下?
放在根目录下,用户可以直接输入地址访问。而这时我们登录后才可以看到的界面。所以不能暴露出来让用户直接跳过登录步骤。
就算是放在根目录下,因为没有servlet传过来的userList属性。数据也是空的,毫无意义。
看下截图
用户没有输入账号和密码时用户注册一个已经存在的用户名时
账号和密码不对应时
成功登录时候
by @sunhaiyu
2017.4.12
相关文章推荐
- 案例——用户登录注册xml版
- 黑马程序员_用户登录注册案例
- 用户注册登录案例分析以及简单实现
- 集合框架_用户登录注册案例详细分析和分包的实现、用户基本描述类和用户操作接口的实现、用户操作类的具体实现、用户测试类的实现、加入猜数字小游戏
- 用户登录注册案例(集合版)
- 用户注册和登录案例(服务器端:数据控制,业务层,dao层)
- java基础学习_集合类03_用户登录注册案例(集合版)、Set集合、Collection集合总结_day17总结
- 用户注册登录案例
- 集合实现用户登录注册案例
- 用户登录注册案例
- 用户注册和登录案例
- 用户登录注册案例分析
- 【Android】用户登录注册界面开发及用户信息管理案例代码详解
- Redis用户添加、分页、登录、注册、加关注案例
- 【Android】用户登录注册界面开发及用户信息管理案例代码详解
- 集合框架_用户登录注册案例分析图解
- Android用户登录注册界面开发及用户信息管理案例代码详解
- 【Android】用户登录注册界面开发及用户信息管理案例代码详解
- Java实现--登录和注册案例(把用户信息存进集合)
- GUI_用户登录注册加入四则运算案例