整个项目的整体结构
1. 首先创建一张数据表,用于存储用户信息
create table tb_user(
id int(4) primary key auto_increment,
username varchar(50),
password varchar(50),
sex varchar(50),
question varchar(50),
answer varchar(50),
email varchar(50));
2. JavaBean设计
- 实体类设计(放在entity包下面)
public class User {
private int id;
private String username;
private String password;
private String sex;
private String question;
private String answer;
private String email;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public String getQuestion() {
return question;
}
public void setQuestion(String question) {
this.question = question;
}
public String getAnswer() {
return answer;
}
public void setAnswer(String answer) {
this.answer = answer;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
}
2.数据库连接工具类(放在util包下面)
public class DataBaseUtil {
//连接数据库
public static Connection getConn() {
Connection conn = null;
try {
//加载数据库驱动
Class.forName("com.mysql.jdbc.Driver");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
String url = "jdbc:mysql://localhost:3306/jdbcdemo?useUnicode=true&characterEncoding=UTF-8";
try {
conn = DriverManager.getConnection(url, "root", "root");
if (conn != null) {
System.out.println(1123);
}
} catch (SQLException e) {
e.printStackTrace();
}
return conn;
}
//关闭数据库
public static void closeConn(Connection conn){
if (conn != null) {
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
3.用户数据库操作
与用户相关的数据库操作方法被封装到UserDao类中,实现数据的添加与查询
public class UserDao {
//查询数据库信息
/**
* 在用户提交注册信息是,需要判断该用户名是否存在
*
* @param username
* @return
*/
public boolean userExist(String username) {
Connection conn = DataBaseUtil.getConn();
//根据指定的用户名查询信息
String sql = "select * from tb_user where username = ?";
try {
//获取PreparedStatement对象,用于执行数据库查询
PreparedStatement preparedStatement = conn.prepareStatement(sql);
preparedStatement.setString(1, username);
//执行查询获取结果集
ResultSet resultSet = preparedStatement.executeQuery();
while (!resultSet.next()) {
//如果没有此数据,证明该用户名可用
return true;
}
//释放资源,后创建的先销毁
resultSet.close();
preparedStatement.close();
} catch (SQLException e) {
e.printStackTrace();
} finally {
DataBaseUtil.closeConn(conn);
}
return true;
}
/**
* 在用户提交注册信息时,如果注册成功需要将,需要将用户注册的信息存入数据库
*/
public void saveUser(User user) {
//获取数据库连接
Connection conn = DataBaseUtil.getConn();
//插入信息的sql语句
String sql = "insert into tb_user(username,password,sex,question,answer,email) values(?,?,?,?,?,?)";
try {
PreparedStatement ps = conn.prepareStatement(sql);
ps.setString(1, user.getUsername());
ps.setString(2, user.getPassword());
ps.setString(3, user.getSex());
ps.setString(4, user.getQuestion());
ps.setString(5, user.getAnswer());
ps.setString(6, user.getEmail());
//执行更新操作
ps.executeUpdate();
//释放资源
ps.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
/**
* 注册成功后,用户既可通过注册的用户及密码进行登录,对于程序而言,此操作实质是根据
* 用户所提供的用户名及密码在数据库进行查询,如果查询成功,则登录成功
*/
public User login(String username, String password) {
//实例化一个用户对象
User user =null;
Connection conn = DataBaseUtil.getConn();
String sql = "select * from tb_user where username = ? and password = ?";
try {
PreparedStatement ps = conn.prepareStatement(sql);
ps.setString(1, username);
ps.setString(2, password);
//执行查询获取结果集
ResultSet rs = ps.executeQuery();
//判断结果集是否有效,如过有效,则对用户进行赋值
while (rs.next()) {
user = new User();
//对用户对象进行复制
user.setId(rs.getInt("id"));
user.setUsername(rs.getString("username"));
user.setPassword(rs.getString("password"));
user.setSex(rs.getString("sex"));
user.setQuestion(rs.getString("question"));
user.setAnswer(rs.getString("answer"));
user.setEmail(rs.getString("email"));
}
//释放资源
rs.close();
ps.close();
} catch (SQLException e) {
e.printStackTrace();
} finally {
DataBaseUtil.closeConn(conn);
}
return user;
}
}
3.实现过程
- 用户注册
(1)创建RegServlet的类,用于处理用户注册请求的servlet
public class RegServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doPost(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setContentType("text/html;charset=utf-8");
req.setCharacterEncoding("utf-8");
//获取用户注册信息
String username = req.getParameter("username");
String password = req.getParameter("password");
String sex = req.getParameter("sex");
String question = req.getParameter("question");
String answer = req.getParameter("answer");
String email = req.getParameter("email");
//实例化UserDao对象
UserDao userDao = new UserDao();
if (username != null) {
//实例化一个User对象
User user = new User();
//对用户对象的属性赋值
user.setUsername(username);
user.setPassword(password);
user.setSex(sex);
user.setQuestion(question);
user.setAnswer(answer);
user.setEmail(email);
userDao.saveUser(user);
req.setAttribute("info", "注册成功! <br>");
} else {
req.setAttribute("info", "此用户一存在!<br>");
}
//转发到message.jsp页面
req.getRequestDispatcher("message.jsp").forward(req, resp);
}
}
(2)创建注册页面
<%--
Created by IntelliJ IDEA.
User: pc
Date: 17-5-11
Time: 下午3:01
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>注册界面</title>
</head>
<body>
<form action="/RegServlet" method="post" onsubmit="return reg(this)">
<table align="center" border="0" width="500">
<tr>
<td align="right" width="30%">用户名:</td>
<td><input type="text" name="username" class="box"></td>
</tr>
<tr>
<td align="right" width="30%">密码:</td>
<td><input type="password" name="password" class="box"></td>
</tr>
<tr>
<td align="right" width="30%">确认密码:</td>
<td><input type="password" name="password" class="box"></td>
</tr>
<tr>
<td align="right" width="30%">性别:</td>
<td>
<input type="radio" name="sex" value="男" checked="checked">男
<input type="radio" name="sex" value="女">女
</td>
</tr>
<tr>
<td align="right" width="30%">密码找回问题:</td>
<td><input type="text" name="question" class="box"></td>
</tr>
<tr>
<td align="right" width="30%">密码找回答案:</td>
<td><input type="text" name="answer" class="box"></td>
</tr>
<tr>
<td align="right" width="30%">邮箱:</td>
<td><input type="text" name="email" class="box"></td>
</tr>
<tr>
<td colspan="2" align="center" height="40">
<input type="submit" value="注册">
<input type="reset" value="重置">
</td>
</tr>
</table>
</form>
</body>
</html>
2.用户登录
(1)创建LoginServlet,处理用户登录请求的servlet.
/**
* Created by pc on 17-5-11.
*/
@WebServlet("/LoginServlet")
public class LoginServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setContentType("text/html;charset=utf-8");
req.setCharacterEncoding("utf-8");
String username = req.getParameter("username");
String password = req.getParameter("password");
UserDao userDao = new UserDao();
//根据密码查询用户
User user = userDao.login(username, password);
//判断user是否为空
if (user != null) {
//将用户的对象放到session中
req.getSession().setAttribute("user", user);
//转发到result.jsp页面
req.getRequestDispatcher("message.jsp").forward(req, resp);
/**
response.sendRedirect(url)跳转到指定的URL地址,产生一个新的request,所以要传递参数只有在url后加参
数,如:
url?id=1.
request.getRequestDispatcher(url).forward(request,response)是直接将请求转发到指定URL,所以该请求
能够直接获得上一个请求的数据,也就是说采用请求转发,request对象始终存在,不会重新创建。而
sendRedirect()会新建request对象,所以上一个request中的数据会丢失。
*/
}else {
//登录失败
req.setAttribute("info","用户名或密码错误!");
req.getRequestDispatcher("message.jsp").forward(req, resp);
}
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doPost(req, resp);
}
}
(2)创建用户登录的页面
<%--
Created by IntelliJ IDEA.
User: pc
Date: 17-5-11
Time: 下午3:31
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>登录界面</title>
</head>
<body>
<form action="/LoginServlet" method="post" onsubmit="return login(this);">
<input type="text" name="username"><br>
<input type="password" name="password"><br>
<input type="submit" value="登录">
<input type="reset" value="重置">
</form>
</body>
</html>
3.用户退出
创建UserExitServlet类,用来处理用户推出请求
在处理过程中,需要将存放在session中的User清楚,达到用户退出的效果
/**
* Created by pc on 17-5-11.
*/
public class UserExitServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doPost(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.setCharacterEncoding("utf-8");
resp.setContentType("text/html;charset=utf-8");
//获取session
HttpSession session = req.getSession();
//获取用户对象
User user = (User) session.getAttribute("user");
//判断用户是否有效
if (user != null) {
//将用户对象逐出Session
session.removeAttribute("user");
//设置提示信息
req.setAttribute("info", user.getUsername() + "已成功退出!");
}
req.getRequestDispatcher("message.jsp").forward(req, resp);
}
}
4.提示页面信息
程序在处理业务请求后,需要告知用户处理结果,如用户注册成功,用户登录失败等信息,因此创建message.jsp页面,用于显示系统提示信息。
<%@ page import="model.User" %><%--
Created by IntelliJ IDEA.
User: pc
Date: 17-5-11
Time: 下午4:23
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>提示信息页面</title>
</head>
<body>
<%
//获取提示信息
String info = (String) request.getAttribute("info");
if (info != null) {
out.print(info);
}
/*获取用户的登录信息*/
User user = (User) session.getAttribute("user");
if (user != null) {
%>
<table align="center" width="600" border="1" height="550" bordercolor="#E8F4CC">
<tr>
<td align="center" colspan="2">
<span style="font-weight: bold;font-size: 18px;"><%=user.getUsername()%></span>登录成功!
</td>
</tr>
<tr>
<td align="center" colspan="2">性别:</td>
<td align="center" colspan="2"><%=user.getSex()%></td>
</tr>
<tr>
<td align="center" colspan="2">邮箱</td>
<td align="center" colspan="2"><%=user.getEmail()%></td>
</tr>
</table>
<%
}else {
out.print("<br>对不起您没有登录!");
}
%>
</body>
</html>
4. 一些容易混淆的知识点
-
session.setAttribute()和session.getAttribute()配对使用,作用域是整个会话期间,在所有的页面都使用这些数据的时候使用。
-
request.setAttribute()和request.getAttribute()配对使用,作用域是请求和被请求页面之间。request.setAttribute()是只在此action的下一个forward需要使用的时候使用;request.getAttribute()表示从request范围取得设置的属性,必须要先setAttribute设置属性,才能通过getAttribute来取得,设置与取得的为Object对象类型。其实表单控件中的Object的name与value是存放在一个哈希表中的,所以在这里给出Object的name会到哈希表中找出对应它value。setAttribute()的参数是String和Object。
-
request.getParameter()表示接收参数,参数为页面提交的参数。包括:表单提交的参数、URL重写(就是xxx?id=1中的id)传的参数等,因此这个并没有设置参数的方法(没有setParameter()),而且接收参数返回的不是Object,而是String类型。
-
request.getParameter() 和request.getAttribute() 区别
#######(1)request.getParameter()取得是通过容器的实现来取得通过类似post,get等式传入的数据,request.setAttribute()和getAttribute()只是在web容器内部流转,仅仅是请求处理阶段。
#######(2)request.getParameter()方法传递的数据,会从Web客户端传到Web服务器端,代表HTTP请求数据。request.getParameter()方法返回String类型的数据。request.setAttribute()和getAttribute()方法传递的数据只会存在于Web容器内部还有一点就是,HttpServletRequest类有setAttribute()方法,而没有setParameter()方法。
-
request.getAttribute()与request.setAttribute()
-
request.getAttribute("nameOfObj")可得到JSP页面一表单中控件的Value。其实表单控件中的Object的name与value是存放在一个哈希表中的,所以在这里给出Object的name会到哈希表中找出对应它的value。而不同页面间传值使用request.setAttribute(position, nameOfObj)时,只会从a.jsp到b.jsp一次传递,之后这个request就会失去它的作用范围,再传就要再设一个request.setAttribute()。而使用session.setAttribute()会在一个过程中始终保有这个值。
-
response.sendRedirect(url)与request.getRequestDispatcher(url).forward(request,response)的区别
- #######response.sendRedirect(url)跳转到指定的URL地址,产生一个新的request,所以要传递参数只有在url后加参数,如:url?id=1.
- #######request.getRequestDispatcher(url).forward(request,response)是直接将请求转发到指定URL,所以该请求能够直接获得上一个请求的数据,也就是说采用请求转发,request对象始终存在,不会重新创建。而sendRedirect()会新建request对象,所以上一个request中的数据会丢失。