一、cookie 与 session
1)cookie 与 session 的定义
2)相关的servlet中的 方法
二、代码实现 登录页面
1)先用 vscode 编写登录页面
注意文件的路径 在webapp路径下
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<!-- 使用form表单,实现登录效果 -->
<div>
<h1 style="text-align: center;">登录页面</h1>
<form action="login" method="post" style="width: 300px; margin:0 auto">
<table>
<tr>
<td>用户名:</td>
<td><input type="text" name="username"></td>
</tr>
<tr>
<td>密码:</td>
<td><input type="password" name="password"></td>
</tr>
</table>
<input type="submit" value="登录" style="width: 100px; height: 30px; margin-left:100px;">
</form>
</div>
</body>
</html>
打开smart tomcat 登录网址
2)编写登录 验证form表单逻辑
在maven项目里java目录下,创建LoginServlet的包,用于区分其他的代码
在包里创建 LoginServlet 的类,继承HttpServlet这个类
登录逻辑
package LoginServlet;
import sun.security.jgss.HttpCaller;
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 javax.servlet.http.HttpSession;
import java.io.IOException;
@WebServlet("/login")
public class LoginServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//1.获取http请求(由于post请求是form表单格式,所以可以直接用getParameter获取里面的内容)
//在读取请求的时候,最好设置字符编码集(否则,如果用户名是中文,那么读取的时候就是乱码)
req.setCharacterEncoding("utf8");
String username = req.getParameter("username");//获取用户名
String password = req.getParameter("password");//获取密码
//2.验证用户名和密码(一般来说是要从数据库中验证密码)
//此时为了简单验证,把正确的用户名和密码规定为:zhangsan 和 123456
//字符串.equals(变量) 这样的写法,可以用于处理 变量为 null的情况,如果用户名或着密码为空,也是登录失败的
resp.setContentType("text/html;charset=utf8");
if ("zhangsan".equals(username) && "123456".equals(password)){
resp.getWriter().write("欢迎" + username + "登录使用!");
}else{
//登陆失败
//给用户返回一个提示
resp.getWriter().write("登陆失败:用户名或密码错误!");
return;
}
//3.登录成功,会给用户创建一个会话
// 可以给会话中保存一些自定义的数据,通过Attribute的方式来存储
HttpSession session = req.getSession(true);//获取不到会自动创建 则如果“当前用户的会话对象”为空(第一次访问时)则创建一个新的会话对象返回
//此处 Attribute 存储的一些程序员自定义的属性,以 键值对 方式存储
//存储好了数据后,后续跳转到其他的页面,也随时可以把这个数据从会话中取出来
session.setAttribute("username",username);
session.setAttribute("loginTime",System.currentTimeMillis());//获取的是当前的时间戳
//4.此时登录成功后的相关数据已经存储好,可以跳转到网站页面了
resp.sendRedirect("index");//重定向到index页面上
}
}
3)登录后的页面index 的逻辑
package LoginServlet;
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 javax.servlet.http.HttpSession;
import java.io.IOException;
import java.util.Date;
@WebServlet("/index")
public class IndexServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//1.获取到用户对应的会话对象,生成的页面要根据用户信息来构成的
HttpSession session = req.getSession(false);//获取不到session不会自动创建
if (session == null){
//sessionId 不存在,或者 sessionid 没有在hash 表中查到
resp.setContentType("text/html;charset=utf8");
resp.getWriter().write("您当前尚未登录!");
return;
}
//2.从会话中拿到之前存储的用户信息
//getAttribute的返回值是一个Object对象,所以程序员需要手动 强制类型转换
String username = (String)session.getAttribute("username");
Long loginTime = (Long) session.getAttribute("loginTime");//时间戳 是一个很长的数 用 long长整型保存
Date date = new Date(loginTime);//时间戳对于用户来说不容易理解,所以将时间戳转换为 具体的时间,更直观
//3.生成一个页面,把上述数据显示到页面上
resp.setContentType("text/html;charset=utf8");
String respBody = "欢迎您" + username + "!上次登录时间为" + date;
resp.getWriter().write(respBody);
}
}
4)抓包验证
三、整个代码逻辑
四、优化
将写死的用户名和密码,使用数据库存储
建表建库,并且插入了三个数据
使用JDBC
package LoginServlet;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.mysql.jdbc.jdbc2.optional.MysqlDataSource;
import sun.security.jgss.HttpCaller;
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 javax.servlet.http.HttpSession;
import javax.sql.DataSource;
import java.io.IOException;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.function.LongToIntFunction;
class Login{
String username;
String password;
}
@WebServlet("/login")
public class LoginServlet extends HttpServlet {
private ObjectMapper objectMapper = new ObjectMapper();
//1.创建数据库 数据源
private DataSource dataSource = new MysqlDataSource();
@Override
public void init() throws ServletException {
//1.数据源 初始化
((MysqlDataSource)dataSource).setURL("jdbc:mysql://127.0.0.1:3306/login?characterEncoding=utf8&useSSL=false");
((MysqlDataSource)dataSource).setUser("root");
((MysqlDataSource)dataSource).setPassword("123456");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//1.获取http请求(由于post请求是form表单格式,所以可以直接用getParameter获取里面的内容)
//在读取请求的时候,最好设置字符编码集(否则,如果用户名是中文,那么读取的时候就是乱码)
req.setCharacterEncoding("utf8");
String username = req.getParameter("username");//获取用户名
String password = req.getParameter("password");//获取密码
//2.验证用户名和密码(一般来说是要从数据库中验证密码)
//此时为了简单验证,把正确的用户名和密码规定为:zhangsan 和 123456
//字符串.equals(变量) 这样的写法,可以用于处理 变量为 null的情况,如果用户名或着密码为空,也是登录失败的
resp.setContentType("text/html;charset=utf8");
//TODO 使用数据库
if (!findLogin(username,password,resp)){
resp.getWriter().write("登陆失败:用户名或密码错误!");
return;
}
// if ("zhangsan".equals(username) && "123456".equals(password)){
// resp.getWriter().write("欢迎" + username + "登录使用!");
// }else{
// //登陆失败
// //给用户返回一个提示
// resp.getWriter().write("登陆失败:用户名或密码错误!");
// return;
// }
//3.登录成功,会给用户创建一个会话
// 可以给会话中保存一些自定义的数据,通过Attribute的方式来存储
HttpSession session = req.getSession(true);//获取不到会自动创建 则如果“当前用户的会话对象”为空(第一次访问时)则创建一个新的会话对象返回
//此处 Attribute 存储的一些程序员自定义的属性,以 键值对 方式存储
//存储好了数据后,后续跳转到其他的页面,也随时可以把这个数据从会话中取出来
session.setAttribute("username",username);
session.setAttribute("loginTime",System.currentTimeMillis());//获取的是当前的时间戳
//4.此时登录成功后的相关数据已经存储好,可以跳转到网站页面了
resp.sendRedirect("index");//重定向到index页面上
}
private boolean findLogin(String username,String password,HttpServletResponse resp) throws IOException {
List<Login> loginList = new ArrayList<>();
try {
loginList = load();
} catch (SQLException e) {
throw new RuntimeException(e);
}
for(Login x:loginList){
if (x.username.equals(username) && x.password.equals(password)){
resp.getWriter().write("欢迎" + username + "登录使用!");
return true;
}
}
//登陆失败
// //给用户返回一个提示
return false;
}
private List<Login> load() throws SQLException {
//1.创建数据库 数据源(前面写了初始化数据源的方法)
//2.建立连接(connection是java.sql里的对象)
Connection connection = dataSource.getConnection();
//3.构造sql请求
String sql = "select * from login";
PreparedStatement statement = connection.prepareStatement(sql);
//4.执行sql语句
ResultSet resultSet = statement.executeQuery();
//5.遍历集合结果
List<Login> loginList = new ArrayList<>();
while (resultSet.next()){
Login login = new Login();
login.username = resultSet.getString("username");
login.password = resultSet.getString("password");
loginList.add(login);
}
//6.回收资源
connection.close();
statement.close();
resultSet.close();
//7.返回loginList
return loginList;
}
}