
前面我们实现了用户登录功能,当时我们要求用户登录成功后,跳转到success.html 页面
【相关博文:Html、Servlet、JDBC实现页面登录】
现在需要做需求迭代:
1.用户登录成功后,要求跳转到success.jsp 页面,这个页面展示登录成功后的用户姓名,格式为:欢迎您,XXX,退出
2. 当用户点击退出按钮时,清除 session,跳回到登录页面
实现上述功能后,需添加一个过滤器和监听器:
过滤器: 完成上述功能后项目中无论用户是否登录成功,都可以直接访问 success.jsp,因此使用过滤器实现用户在登录情况下才能访问 success.jsp 页面
监听器: 监听 session 的变化,如果 session 每存储一次用户信息到 session则调取监听器,监听session 的数据变化
编写登录界面并进行表单验证
实现将数据从客服端发送到服务器
通过java代码操作数据库,判断用户名和密码是否正确
创建过滤器和监听器
1、sql语言及基本操作
2、JDBC(Java数据库连接)
3、自定义工具类以及properties配置文件的使用
4、JDBC连接池
5、Servlet工作原理与生命周期
6、Servlet请求与响应
7、 JSP基础知识
创建数据库,保存用户名和密码
创建登录页面,要求用户输入用户名和密码
接收用户提交的用户名和密码,接收后将数据传递到数据库进行验证
根据验证结果,跳转到不同的结果页面(成功跳转到 success.html、失败
跳转到 false.html)
实现对文件的过滤
实现session监听
properties配置文件创建一个utils包,新建类DBUtils,新建配置文件db.properties
使用ResourceBundle访问本地资源,从里面读取我们需要的值
driver=com.mysql.cj.jdbc.Driver url=jdbc:mysql://localhost:3306/demo?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=GMT username=root password=123456DBUtils.java
JDBC工具类,封装了操作sql的方法,因此方法都推荐静态static
//定义需要的工具类对象(变量定义)
protected static Connection connection = null;
protected static PreparedStatement pps = null;//后续都是用预状态通道来实现
protected static ResultSet rs = null;//结果集
protected static int count = 0;//受影响的行数
//登录的用户名和密码
private static String username;
private static String password;
private static String url;
private static String driverName;
//Druid连接池
private static DruidDataSource druidDataSource = new DruidDataSource();
//加载驱动
static {
//Druid
ResourceBundle bundle = ResourceBundle.getBundle("db");//参数只写属性文件名,不需要写后缀
//加载属性文件
driverName = bundle.getString("driver");
url = bundle.getString("url");
username = bundle.getString("username");
password = bundle.getString("password");
druidDataSource.setUsername(username);
druidDataSource.setPassword(password);
druidDataSource.setUrl(url);
druidDataSource.setDriverClassName(driverName);
}
protected static Connection getConnection() {
try {
connection = druidDataSource.getConnection();
} catch (SQLException e) {
e.printStackTrace();
}
return connection;
}
//得到预状态通道
protected static PreparedStatement getPps(String sql) {
try {
getConnection();
pps = connection.prepareStatement(sql);
} catch (SQLException e) {
e.printStackTrace();
}
return pps;
}
//绑定参数,给占位符赋值,list中保存的是给占位符所赋的值
private static void setParams(List list) {
try {
if (list != null && list.size() > 0) {//集合中有内容
for (int i = 0; i < list.size(); i++) {
pps.setObject(i + 1, list.get(i));//赋值,位置从1开始所以为i+1
}
}
} catch (SQLException e) {
e.printStackTrace();
}
}
protected static int update(String sql, List list) {
try {
getPps(sql);//得到预状态通道
setParams(list);//绑定参数
count = pps.executeUpdate();//pps.executeUpdate()执行sql语句,返回受影响的行数
} catch (SQLException e) {
e.printStackTrace();
}
return count;//返回受影响的行数
}
protected static ResultSet query(String sql, List list) {
try {
getPps(sql);//得到预状态通道
setParams(list);//绑定参数
rs = pps.executeQuery();//pps.executeUpdate()执行sql语句,返回结果集
return rs;//返回结果集
} catch (SQLException e) {
e.printStackTrace();
}
return null;
}
protected static void closeAll() {
try {
if (rs != null) {
rs.close();
}
if (pps != null) {
pps.close();
}
if (connection != null) {
connection.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
创建数据库demo,建立表user,保存用户名和密码
创建一个pojo包,新建类User
User类对应的数据表user,因此类属性名 = 表字段名
User.java private String username;
private String userpassword;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getUserpassword() {
return userpassword;
}
public void setUserpassword(String userpassword) {
this.userpassword = userpassword;
}
public User() {
}
public User(String username, String userpassword) {
this.username = username;
this.userpassword = userpassword;
}
@Override
public String toString() {
return "User{" +
"username='" + username + ''' +
", userpassword='" + userpassword + ''' +
'}';
}
要求用户输入用户名和密码
用户登录
css样式参考文章
section {
position: relative;
overflow: hidden;
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
background: linear-gradient(to bottom, #f1f4f9, #dff1ff);
}
.box {
position: relative;
}
.color {
position: absolute;
filter: blur(200px);
}
.color:nth-child(1) {
top: -350px;
width: 600px;
height: 600px;
background:#FFC0CB;
}
.color:nth-child(2) {
bottom: -150px;
left: 100px;
width: 500px;
height: 500px;
background: #FFFFE0;
}
.color:nth-child(3) {
bottom: 50px;
right: 100px;
width: 500px;
height: 500px;
background:#DDA0DD;
}
.color:nth-child(4) {
bottom: 50px;
right: 100px;
width: 500px;
height: 500px;
background:#FFFFFF;
}
.container {
position: relative;
width: 400px;
min-height: 400px;
background: rgba(255, 255, 255, 0.1);
display: flex;
justify-content: center;
align-items: center;
backdrop-filter: blur(5px);
box-shadow: 0 25px 45px rgba(0, 0, 0, 0.1);
border: 1px solid rgba(255, 255, 255, 0.5);
border-right: 1px solid rgba(255, 255, 255, 0.2);
border-bottom: 1px solid rgba(255, 255, 255, 0.2);
}
.inputStyle{
width: 100%;
padding: 10px 20px;
margin-top: 20px;
background: rgba(255, 255, 255, 0.2);
outline: none;
border: none;
border-radius: 30px;
border: 1px solid rgba(255, 255, 255, 0.5);
border-right: 1px solid rgba(255, 255, 255, 0.2);
border-bottom: 1px solid rgba(255, 255, 255, 0.2);
font-size: 16px;
letter-spacing: 1px;
color: #000;
box-shadow: 0 5px 15px rgba(0, 0, 0, 0.05);
}
.buttomStyle{
width: 100%;
padding: 10px 20px;
max-width: 100px;
margin-top: 30px;
margin-left: 10px;
margin-bottom: 20px;
border-radius: 30px;
font-size: 16px;
letter-spacing: 1px;
background: #fff;
color: #666;
font-weight: 600;
cursor: pointer;
}
创建一个web包,新建 LoginServlet 类,继承HttpServlet,接收客户端输入的用户名和密码
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doPost(req, resp);//当method为get时,依旧执行doPost
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.setCharacterEncoding("utf-8");
//取值
String username = req.getParameter("username");
System.out.println("用户输入的用户名:"+username);
String userpassword = req.getParameter("userpassword");
System.out.println("用户输入的密码:"+userpassword);
if(dao.checkLogin(username,userpassword)){
System.out.println("登陆成功");
resp.sendRedirect("/Success.html");
//req.getRequestDispatcher("/Success.html").forward(req,resp);
}else{
System.out.println("登录失败");
resp.sendRedirect("/Fail.html");
//req.getRequestDispatcher("/fail.html").forward(req,resp);
}
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
super.doPost(req, resp);
req.getSession().invalidate();
Enumeration em = req.getSession().getAttributeNames();
while(em.hasMoreElements()){
req.getSession().removeAttribute(em.nextElement().toString());
}
// //req.getRequestDispatcher("index.jsp").forward(req,resp);
resp.sendRedirect("/login.jsp");//login.jsp
}
主要负责数据处理的模块
Dao.java创建一个dao包,新建 Dao类,继承DBUtils类,使用 JDBC 完成相应数据库操作
public static User login(String username, String password){
System.out.println("进入check in");
String sql = "select* from user where username = ? and userpassword = ?";
ArrayList param = new ArrayList();
param.add(username);
param.add(password);
ResultSet query = query(sql, param);
try {
if(!query.next()){
System.out.println("dao:false");
return null;
}else{
User user = new User();
user.setUsername(query.getString("username"));
user.setUserpassword(query.getString("userpassword"));
System.out.println("dao:true");
return user;
}
} catch (SQLException throwables) {
System.out.println(throwables.getMessage());
return null;
}finally {
closeAll();
}
}
<%--
Created by IntelliJ IDEA.
User: ss
Date: 2021/9/26
Time: 19:12
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%@taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
登陆成功
欢迎登录!
登录失败
LoginFilter.java在util中新建LoginFilter类,继承Filter类
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("init Filter");
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
//判断请求是否是 可以放过的某一个请求,或者在session中已经保存了登录状态的数据
//Login.jsp ,login请求 ,fail页面,session中持有了数据(在登陆成功的状态下存进去的)
HttpServletRequest req = (HttpServletRequest)servletRequest;
HttpServletResponse resp = (HttpServletResponse)servletResponse;
if(ignore(req) || req.getSession().getAttribute("username") != null){
filterChain.doFilter(req,resp);
}else {//跳转 重定向到登录页面
resp.sendRedirect("/login.jsp");//login.jsp
}
}
private boolean ignore(HttpServletRequest req){
String[] uris = {"login","login.jsp","fail.jsp","MyCSS.css","css","js"};
for (String u:uris) {
if(req.getRequestURI().endsWith(u)){
return true;
}
}
return false;
}
@Override
public void destroy() {
System.out.println("destroy Filter");
}
九、 监听器
MySessionListener.java在util中新建 MySessionListener类,继承HttpSessionListener类
@Override
public void sessionCreated(HttpSessionEvent httpSessionEvent) {
System.out.println("session created!");
httpSessionEvent.getSession().setMaxInactiveInterval(5);
}
@Override
public void sessionDestroyed(HttpSessionEvent httpSessionEvent) {
System.out.println("session distroyed");
}
driver=com.mysql.cj.jdbc.Driver url=jdbc:mysql://localhost:3306/demo?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=GMT username=root password=123456DBUtils.java
public class DBUtils {
//1.定义需要的工具类对象(变量定义)
protected static Connection connection = null;
protected static PreparedStatement pps = null;//后续都是用预状态通道来实现
protected static ResultSet rs = null;//结果集
protected static int count = 0;//受影响的行数
//登录的用户名和密码
private static String username;
private static String password;
private static String url;
private static String driverName;
//Druid
private static DruidDataSource druidDataSource = new DruidDataSource();
//2.加载驱动
static {
//Druid
ResourceBundle bundle = ResourceBundle.getBundle("db");//参数只写属性文件名,不需要写后缀
//加载属性文件
driverName = bundle.getString("driver");
url = bundle.getString("url");
username = bundle.getString("username");
password = bundle.getString("password");
druidDataSource.setUsername(username);
druidDataSource.setPassword(password);
druidDataSource.setUrl(url);
druidDataSource.setDriverClassName(driverName);
}
//3.获得连接
protected static Connection getConnection() {
try {
connection = druidDataSource.getConnection();
} catch (SQLException e) {
e.printStackTrace();
}
return connection;
}
//4.得到预状态通道
protected static PreparedStatement getPps(String sql) {
try {
getConnection();//insert into users values(?,?,?,?,)
pps = connection.prepareStatement(sql);
} catch (SQLException e) {
e.printStackTrace();
}
return pps;
}
//5.绑定参数,给占位符赋值,list中保存的是给占位符所赋的值
private static void setParams(List list) {
try {
if (list != null && list.size() > 0) {//集合中有内容
for (int i = 0; i < list.size(); i++) {
pps.setObject(i + 1, list.get(i));//赋值,位置从1开始所以为i+1
}
}
} catch (SQLException e) {
e.printStackTrace();
}
}
//6.增删改
protected static int update(String sql, List list) {
try {
getPps(sql);//得到预状态通道
setParams(list);//绑定参数
count = pps.executeUpdate();//pps.executeUpdate()执行sql语句,返回受影响的行数
} catch (SQLException e) {
e.printStackTrace();
}
return count;//返回受影响的行数
}
//7.查询
protected static ResultSet query(String sql, List list) {
try {
getPps(sql);//得到预状态通道
setParams(list);//绑定参数
rs = pps.executeQuery();//pps.executeUpdate()执行sql语句,返回结果集
return rs;//返回结果集
} catch (SQLException e) {
e.printStackTrace();
}
return null;
}
//8.关闭资源
protected static void closeAll() {
try {
if (rs != null) {
rs.close();
}
if (pps != null) {
pps.close();
}
if (connection != null) {
connection.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}
public class User {
private String username;
private String userpassword;
public User() {
}
public User(String username, String userpassword) {
this.username = username;
this.userpassword = userpassword;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getUserpassword() {
return userpassword;
}
public void setUserpassword(String userpassword) {
this.userpassword = userpassword;
}
@Override
public String toString() {
return "User{" +
"username='" + username + ''' +
", userpassword='" + userpassword + ''' +
'}';
}
}
<%--
Created by IntelliJ IDEA.
User: ss
Date: 2021/9/27
Time: 20:08
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
登录
用户登录
MyCss.css
section {
position: relative;
overflow: hidden;
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
background: linear-gradient(to bottom, #f1f4f9, #dff1ff);
}
.color {
position: absolute;
filter: blur(200px);
}
.color:nth-child(1) {
top: -350px;
width: 600px;
height: 600px;
background:#FFC0CB;
}
.color:nth-child(2) {
bottom: -150px;
left: 100px;
width: 500px;
height: 500px;
background: #FFFFE0;
}
.color:nth-child(3) {
bottom: 50px;
right: 100px;
width: 500px;
height: 500px;
background:#DDA0DD;
}
.color:nth-child(4) {
bottom: 50px;
right: 100px;
width: 500px;
height: 500px;
background:#FFFFFF;
}
.box {
position: relative;
}
.container {
position: relative;
width: 400px;
min-height: 400px;
background: rgba(255, 255, 255, 0.1);
display: flex;
justify-content: center;
align-items: center;
backdrop-filter: blur(5px);
box-shadow: 0 25px 45px rgba(0, 0, 0, 0.1);
border: 1px solid rgba(255, 255, 255, 0.5);
border-right: 1px solid rgba(255, 255, 255, 0.2);
border-bottom: 1px solid rgba(255, 255, 255, 0.2);
}
.inputStyle{
width: 100%;
padding: 10px 20px;
margin-top: 20px;
background: rgba(255, 255, 255, 0.2);
outline: none;
border: none;
border-radius: 30px;
border: 1px solid rgba(255, 255, 255, 0.5);
border-right: 1px solid rgba(255, 255, 255, 0.2);
border-bottom: 1px solid rgba(255, 255, 255, 0.2);
font-size: 16px;
letter-spacing: 1px;
color: #000;
box-shadow: 0 5px 15px rgba(0, 0, 0, 0.05);
}
.buttomStyle{
width: 100%;
padding: 10px 20px;
max-width: 100px;
margin-top: 30px;
margin-left: 10px;
margin-bottom: 20px;
border-radius: 30px;
font-size: 16px;
letter-spacing: 1px;
background: #fff;
color: #666;
font-weight: 600;
cursor: pointer;
}
@WebServlet("/login")//前端action与此对应
public class LoginServlet extends HttpServlet {
Dao dao = new Dao();
@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");
//取值
String username = req.getParameter("username");
System.out.println("用户输入的用户名:"+username);
String userpassword = req.getParameter("userpassword");
System.out.println("用户输入的密码:"+userpassword);
User user = dao.login(username,userpassword);
if( user != null){
System.out.println("登陆成功");
req.getSession().setAttribute("user",user);//登陆成功,session就有了一个凭证
req.getRequestDispatcher("/success.jsp").forward(req,resp);
}else{
System.out.println("登录失败");
resp.sendRedirect("/fail.jsp");
//req.getRequestDispatcher("/fail.html").forward(req,resp);
}
}
}
退出后返回登录界面LogoutServlet.java
@WebServlet("/logOut")
public class LogoutServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
super.doGet(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
super.doPost(req, resp);
req.getSession().invalidate();
Enumeration em = req.getSession().getAttributeNames();
while(em.hasMoreElements()){
req.getSession().removeAttribute(em.nextElement().toString());
}
// //req.getRequestDispatcher("index.jsp").forward(req,resp);
resp.sendRedirect("/login.jsp");//login.jsp
}
}
public class Dao extends DBUtil {
public static User login(String username, String password){
System.out.println("进入check in");
String sql = "select* from user where username = ? and userpassword = ?";
ArrayList param = new ArrayList();
param.add(username);
param.add(password);
ResultSet query = query(sql, param);
try {
if(!query.next()){
System.out.println("dao:false");
return null;
}else{
User user = new User();
user.setUsername(query.getString("username"));
user.setUserpassword(query.getString("userpassword"));
System.out.println("dao:true");
return user;
}
} catch (SQLException throwables) {
System.out.println(throwables.getMessage());
return null;
}finally {
closeAll();
}
}
}
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%@taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
登陆成功
欢迎登录!
Fail.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%@taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
登录失败
@WebFilter("*")
public class LoginFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("init Filter");
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
//判断请求是否是 可以放过的某一个请求,或者在session中已经保存了登录状态的数据
//Login.jsp ,login请求 ,fail页面,session中持有了数据(在登陆成功的状态下存进去的)
HttpServletRequest req = (HttpServletRequest)servletRequest;
HttpServletResponse resp = (HttpServletResponse)servletResponse;
if(ignore(req) || req.getSession().getAttribute("username") != null){
filterChain.doFilter(req,resp);
}else {//跳转 重定向到登录页面
resp.sendRedirect("/login.jsp");//login.jsp
}
}
private boolean ignore(HttpServletRequest req){
String[] uris = {"login","login.jsp","fail.jsp","MyCSS.css","css","js"};
for (String u:uris) {
if(req.getRequestURI().endsWith(u)){
return true;
}
}
return false;
}
@Override
public void destroy() {
System.out.println("destroy Filter");
}
}
public class MySessionListener implements HttpSessionListener {
@Override
public void sessionCreated(HttpSessionEvent httpSessionEvent) {
System.out.println("session created!");
httpSessionEvent.getSession().setMaxInactiveInterval(5);
}
@Override
public void sessionDestroyed(HttpSessionEvent httpSessionEvent) {
System.out.println("session distroyed");
}
}