当前位置: 首页 > news >正文

思途JSP学习 0801

继上篇0731,本文将实现主页显示、登录功能、验证码功能(会话域session)、登录检测拦截功能(过滤器)、监听器

一、主页显示

新建main.jsp、main.css、main.js

<%@ page contentType="text/html;charset=UTF-8" %>
<%@ taglib prefix="c" uri="jakarta.tags.core"%>
<c:set var="ctx" value="${pageContext.request.contextPath}"/>
<html>
<head><base href="${ctx}/"><title>后台管理系统-首页</title><script src="assets/lib/jquery/jquery-3.7.1.min.js"></script><%--自定义css及js--%><link rel="stylesheet" href="assets/modules/main/main.css"><script>const ctx = "${ctx}";</script><script src="assets/modules/main/main.js"></script>
</head>
<body>
<header><h1>尊敬的用户&nbsp;<b>admin0</b>&nbsp;您好,欢迎使用本系统。<a class="logout-btn" href="admin/logout">注销</a></h1>
</header>
<div class="body"><aside><ul class="nav"><li><a href="/student/list">学生管理</a></li><li><a href="/admin/student/class">班级管理</a></li><li><a href="/admin/student/majon">专业管理</a></li><li><a href="/admin/student/course">课程管理</a></li><li><a href="/admin/student/exam">考试管理</a></li><li><a href="/admin/student/score">成绩管理</a></li></ul></aside><div class="main"><iframe></iframe></div>
</div>
</body>
</html>
$(() => {const $nav = $(".nav");//导航菜单单击$nav.on("click", ">li", function () {let url = $(this).children("a").attr("href");$(".main>iframe").attr("src", ctx + url);});$nav.on("click", ">li>a", function (e) {e.preventDefault();});
});
@charset "UTF-8";* {font-size: 14px;
}html, body {height: 100%;
}body {margin: 0;display: flex;flex-direction: column;
}header {width: 100%;height: 78px;background: #aad7f6 url("./header.png") no-repeat left center/auto 100%;flex-shrink: 0;box-sizing: border-box;border-bottom: 1px solid #ccc;position: relative;
}header > h1 {position: absolute;top: 50px;left: 128px;font-weight: normal;
}.body {flex-grow: 1;display: flex;
}aside {background-color: #3f3f3f;height: 100%;width: 180px;
}.main {flex-grow: 1;
}.nav {list-style-type: none;margin: 0;padding: 0;
}.nav > li {padding: 10px 0;cursor: pointer;text-align: center;
}.nav > li:hover {background-color: #16b777;
}.nav > li > a {text-decoration: none;color: #fff;
}.main > iframe {outline: none;border: none;width: 100%;height: 100%;
}header a.logout-btn {background-color: #16b777;padding: 4px 15px;border-radius: 5px;font-size: 12px;color: #fff;
}

2.给main设置servlet响应,将访问页面显示在主页中

package com.situ.servlet;import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;import java.io.IOException;@WebServlet({"", "/admin", "/admin/main"})
public class MainServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {req.getRequestDispatcher("/WEB-INF/jsp/main.jsp").forward(req, resp);}
}

二.登录页面实现

1.新建login.jsp、login.js、login.css

<%@ page contentType="text/html;charset=UTF-8" %>
<%@ taglib prefix="c" uri="jakarta.tags.core"%>
<c:set var="ctx" value="${pageContext.request.contextPath}"/>
<html>
<head><base href="${ctx}/"><title>后台管理系统-登录</title><script src="assets/lib/jquery/jquery-3.7.1.min.js"></script><%--引入layui--%><link rel="stylesheet" href="assets/lib/layui/css/layui.css"><script src="assets/lib/layui/layui.js"></script><%--自定义css及js--%><link rel="stylesheet" href="assets/modules/login/login.css"><script>const ctx = "${ctx}";</script><script src="assets/modules/login/login.js"></script>
</head>
<body>
<div class="login"><div class="header"><h1>教学教务管理系统</h1></div><div class="body"><form id="login-form" action=""><div class="row"><label for="username">用户名:</label><input id="username" name="username" type="text" placeholder="请输入用户名" autocomplete="off" value="admin0"></div><div class="row"><label for="password">密码:</label><input id="password" name="password" type="password" placeholder="请输入密码" autocomplete="off" value="123456"></div><div class="row"><label for="captcha">验证码:</label><div><input id="captcha" name="captcha" type="text" placeholder="请输入验证码" autocomplete="off"><img id="captcha-img" src="admin/captcha" alt="captcha"></div></div></form><button id="login-btn">登录</button></div>
</div>
</body>
</html>
$(() => {//刷新验证码$("#captcha-img").click(function () {$(this).attr("src", ctx + "/admin/captcha?t=" + Math.random());});//登录$("#login-btn").click(function () {let username = $("#username").val();let password = $("#password").val();let captcha = $("#captcha").val();//校验if (!username) {layer.msg("用户名不可为空");return;}if (!password) {layer.msg("密码不可为空");return;}if (!captcha) {layer.msg("验证码不可为空");return;}$.ajax({url: ctx + "/admin/login",method: "post",data: {username,password,captcha},success(resp) {$("#captcha-img").trigger("click");//刷新验证码if (resp.success) {location.href = ctx + "/admin/main";//跳转到后台首页} else {layer.msg(resp.error || "认证失败,请检查后重试");}}});});
});
@charset "UTF-8";
* {font-size: 16px;
}html,
body {height: 100%;
}body {background-color: #ebeeef;display: flex;justify-content: center;align-items: center;
}.login {width: 670px;height: 500px;background-color: #fff;border-radius: 10px;overflow: hidden;display: flex;flex-direction: column;
}.login > .header {height: 180px;background: url(./bg-01.jpg) no-repeat center center/cover;position: relative;display: flex;justify-content: center;align-items: center;
}.login > .header::after {content: "";display: block;position: absolute;top: 0;left: 0;width: 100%;height: 100%;background-color: rgba(54, 84, 99, 0.7);
}.login > .header > h1 {color: #fff;z-index: 1000;font-size: 30px;
}.login > .body {flex-grow: 1;display: flex;justify-content: center;align-items: center;
}#login-form {width: 400px;
}#login-btn {height: 240px;width: 120px;outline: none;border: none;background-color: #1e9fff;color: #fff;border-radius: 10px;cursor: pointer;transition: opacity 0.5s;
}#login-btn:hover {opacity: 0.7;
}#login-form label {display: block;margin-bottom: 5px;
}#login-form .row {margin-bottom: 15px;
}#login-form .row:last-child > div {display: flex;align-items: center;
}input {outline: none;border: 1px solid #ccc;width: 360px;padding: 12px 0 12px 8px;
}#captcha {width: 220px;
}#captcha-img {width: 130px;height: 44px;border: 1px solid #ccc;margin-left: 10px;
}

3.实现LoginServlet,完善后台功能,访问数据库指定用户信息,新建模型user用于存储用户数据,用户名和密码以及验证码全部正确就给js返回true,

package com.situ.model;import lombok.Getter;
import lombok.Setter;@Setter
@Getter
public class User {private Integer id;private String username;private String password;
}
package com.situ.servlet;import com.situ.common.LoginFilter;
import com.situ.model.User;
import com.situ.service.UserService;
import com.situ.service.impl.UserServiceImpl;
import com.situ.util.BeanFactory;
import com.situ.util.ServletUtils;
import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpSession;
import org.springframework.util.DigestUtils;
import org.springframework.util.StringUtils;import java.io.IOException;
import java.util.Map;@WebServlet("/admin/login")
public class LoginServlet extends HttpServlet {private final UserService userService = BeanFactory.getBean(UserServiceImpl.class);@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {req.getRequestDispatcher("/WEB-INF/jsp/login.jsp").forward(req, resp);}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//身份认证String username = req.getParameter("username");String password = req.getParameter("password");String captcha = req.getParameter("captcha");//验证码//参数有效性验证if (!StringUtils.hasText(username)) {ServletUtils.renderJson(resp, Map.of("success", false, "error", "用户名不可为空"));return;}if (!StringUtils.hasText(password)) {ServletUtils.renderJson(resp, Map.of("success", false, "error", "密码不可为空"));return;}if (!StringUtils.hasText(captcha)) {ServletUtils.renderJson(resp, Map.of("success", false, "error", "验证码不可为空"));return;}//获取会话域对象HttpSession session = req.getSession();String answer = (String) session.getAttribute("captcha");if (!captcha.equals(answer)) {ServletUtils.renderJson(resp, Map.of("success", false, "error", "验证码不匹配"));return;}//判断此用户在数据库中是否存在User dbUser = userService.findByUsername(username);if (dbUser == null) {ServletUtils.renderJson(resp, Map.of("success", false, "error", "不存在此用户"));return;}//对密码进行加密String encrypt = password + "{" + username + "}";encrypt = DigestUtils.md5DigestAsHex(encrypt.getBytes());// 且密码是否正确if (!encrypt.equals(dbUser.getPassword())) {ServletUtils.renderJson(resp, Map.of("success", false, "error", "密码不正确"));return;}//登录成功,将用户信息保存到会话域对象中session.setAttribute(LoginFilter.LOGIN_USER_KEY, dbUser);ServletUtils.renderJson(resp, Map.of("success", true));}
}
package com.situ.service;import com.situ.model.User;public interface UserService {User findByUsername(String username);
}package com.situ.service.impl;import com.situ.dao.UserDao;
import com.situ.dao.impl.UserDaoImpl;
import com.situ.model.User;
import com.situ.service.UserService;public class UserServiceImpl implements UserService {private UserDao userDao = new UserDaoImpl();@Overridepublic User findByUsername(String username) {return userDao.findByUsername(username);}
}
package com.situ.dao;import com.situ.model.User;public interface UserDao {public User findByUsername(String userName);
}package com.situ.dao.impl;import com.situ.common.Global;
import com.situ.dao.UserDao;
import com.situ.model.User;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;import java.util.List;public class UserDaoImpl implements UserDao {private final RowMapper<User> rowMapper = new BeanPropertyRowMapper<>(User.class);@Overridepublic User findByUsername(String userName) {JdbcTemplate jdbcTemplate = Global.getTemplate();String sql = "select id, username, password from t_security_user where username = ?";// User user = jdbcTemplate.queryForObject(sql, rowMapper, userName);List<User> users = jdbcTemplate.query(sql, rowMapper, userName);return users.isEmpty() ? null : users.get(0);}
}

三、验证码功能实现

新建CaptchaServlet用于实现验证码的显示,并将验证码内容通过会话域session传递给loginServlet进行验证是否正确。

package com.situ.servlet;import com.wf.captcha.SpecCaptcha;
import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpSession;import java.io.IOException;@WebServlet("/admin/captcha")
public class CaptchaServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//响应验证码SpecCaptcha captcha = new SpecCaptcha(130, 44, 4);//设置响应头,响应内容类型resp.setContentType("image/gif");//设置不保留缓存resp.setHeader("Pragma", "No-cache");resp.setHeader("Cache-Control", "no-cache");resp.setDateHeader("Expires", 0);//将验证码答案在服务器端保存//获取一个会话对象,会话域HttpSession session = req.getSession();session.setAttribute("captcha", captcha.text().toLowerCase());captcha.out(resp.getOutputStream());}
}

四、过滤器功能实现

通过session将LoginServlet中成功登录的用户记录,如果没有登录则强制跳转到login页面,如果有登录信息则不强制进行跳转

package com.situ.common;import com.situ.model.User;
import jakarta.servlet.*;
import jakarta.servlet.annotation.WebFilter;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpSession;
import org.springframework.util.AntPathMatcher;
import org.springframework.util.PathMatcher;import java.io.IOException;@WebFilter("/*")
public class LoginFilter implements Filter {public static final String LOGIN_USER_KEY = "@#login_user";public static final String[] WHITE = { "/assets/**", "/admin/login/**", "/admin/captcha/**"};@Overridepublic void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {HttpServletRequest req = (HttpServletRequest) servletRequest;HttpServletResponse resp = (HttpServletResponse) servletResponse;System.out.println(req.getRequestURL());String uri = req.getRequestURI();uri = uri.replace(req.getContextPath(),"");//路径匹配器PathMatcher matcher = new AntPathMatcher();for (String s : WHITE) {if (matcher.match(s, uri)) {filterChain.doFilter(servletRequest, servletResponse);return;}}//会话域HttpSession session = req.getSession();System.out.println(session.getId());//全局域ServletContext ctx = req.getServletContext();User user = (User)session.getAttribute(LOGIN_USER_KEY);if (user == null) {resp.sendRedirect(req.getContextPath() + "/admin/login");}else{filterChain.doFilter(servletRequest, servletResponse);}}
}

五、监听器案例

        1.会话域监听MySessionListener
package com.situ.common;import jakarta.servlet.annotation.WebListener;
import jakarta.servlet.http.HttpSessionAttributeListener;
import jakarta.servlet.http.HttpSessionEvent;
import jakarta.servlet.http.HttpSessionListener;@WebListener
public class MySessionListenerimplements HttpSessionListener, HttpSessionAttributeListener {@Overridepublic void sessionCreated(HttpSessionEvent se) {System.out.println("session created:" + se.getSession().getId());}@Overridepublic void sessionDestroyed(HttpSessionEvent se) {System.out.println("session destroyed");}
}
2.全局域监听MyServletContextListener

这里将我们的驱动配置设置到了resources中,只在全局域生成时调用一次

package com.situ.common;import jakarta.servlet.ServletContextEvent;
import jakarta.servlet.ServletContextListener;
import jakarta.servlet.annotation.WebListener;import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;@WebListener
public class MyServletContextListener implements ServletContextListener {@Overridepublic void contextInitialized(ServletContextEvent sce) {System.out.println("contextInitialized");InputStream is = Thread.currentThread().getContextClassLoader().getResourceAsStream("jdbc.properties");Properties prop = new Properties();try {prop.load(is);String driver = prop.getProperty("jdbc.driver");String url = prop.getProperty("jdbc.url");String username = prop.getProperty("jdbc.user");String password = prop.getProperty("jdbc.password");Global.driver = driver;Global.jdbcUrl = url;Global.username = username;Global.password = password;} catch (IOException e) {throw new RuntimeException(e);}}
}

jdbc.properties

jdbc.driver=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://127.0.0.1:3306/student2025?serverTimezone=Asia/Shanghai&characterEncoding=utf8&useSSL=false&allowPublicKeyRetrieval=true
jdbc.user=root
jdbc.password=123456
http://www.dtcms.com/a/310728.html

相关文章:

  • 函数 dirfd 详解
  • 26考研|高等代数:欧几里得空间
  • TwinCAT3示例项目1
  • Redis学习18-分布式锁
  • 深拷贝与浅拷贝的定义
  • 机器学习特征工程----常见的特征构建与转换方法
  • dify 升级1.7.1 插件无法下载依赖
  • 分区管控与高效协同:EtherCAT转EtherCAT网关赋能纺织生产
  • c++-reverse_iterator
  • 什么是 Redis?从基础概念到技术本质的全面解析
  • 微信小程序页面间通信的实现方式
  • 升级的MS1836C HD转CVBS/S-Video转换器
  • WooCommerce 与 ERP 系统集成解决方案
  • Agents-SDK智能体开发[1]之入门
  • 智能客服系统实战:多轮对话与知识库检索完整实现
  • DL环境捉虫
  • Python从入门到精通——第四章 程序流程控制
  • 第五届智能通信与计算国际学术会议(ICICC 2025)
  • 电子合同管理台账功能详解
  • Dify API接口上传文件 postman配置
  • Param关键字的使用
  • Pycaita二次开发基础代码解析:几何体重命名与参数提取技术
  • 如何使用Postman做接口测试
  • VS Code 插件开发教程
  • 麻醉深度监护系统市场规模从 857 百万美元向 1244 百万美元跨越,2031 年将形成更大的市场
  • 机试01——C++基础语法与库函数
  • Luckysheet 打印终极指南(预览视图+打印功能) : 2025 最新实现
  • Codeforces Educational 181(ABCD)
  • c++--格式化/clang-format
  • 亚像素级精度的二维图像配准方法