目录
一、登录功能
1、实现登录页面
①新建一张登录表:login
②插入一条测试数据
③新建一个login.jsp登录界面
④此表的实体Teacher类:
⑤ 然后在写一个dao方法,需要根据用户名查询登录表中的用户信息
⑥业务层中我们直接调用dao层方法
⑦在Servlet中新建分支login.do
⑧CheckCode.class
⑨ 写完了这个Servlet不要忘了修改部署文件
⑩下面进行测试:编辑
2、实现登录验证
① 创建一个过滤器
②SessionFilter.class
③ 在web.xml中添加过滤器
④功能与原理:
二、注册功能
①搭建一个前端页面(这个页面先搭后搭建都可以,没有顺序要求)
②Dao层实现如何在数据库中插入数据
③业务层
④Servlet层
⑤思路与测试:
项目资源链接:
一、登录功能
1、实现登录页面
①新建一张登录表:login
②插入一条测试数据
③新建一个login.jsp登录界面
<%@ page language="java" contentType="text/html; charset=utf-8" import="java.util.*,sams.ck.entity.*,java.text.*"
pageEncoding="utf-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>login</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<%@ include file="head.jsp" %>
</head>
<body>
<div>
<h3>
登录
</h3>
<form action="login.do" method="post">
<table cellpadding="0" cellspacing="0" border="0" class="form_table">
<tr>
<td valign="middle" align="right">
用户名:
</td>
<td valign="middle" align="left">
<input type="text" class="inputgri" name="uname" placeholder="请输入您的用户名" value="<%=request.getAttribute("uname")==null?"":request.getAttribute("uname") %>" />
<span style="color:red">
<%=request.getAttribute("umsg")==null?"":request.getAttribute("umsg") %>
</span>
</td>
</tr>
<tr>
<td valign="middle" align="right">
密码:
</td>
<td valign="middle" align="left">
<input type="password" class="inputgri" name="pwd" placeholder="请输入您的密码"/>
<span style="color:red">
<%=request.getAttribute("pmsg")==null?"":request.getAttribute("pmsg") %>
</span>
</td>
</tr>
<tr>
<td valign="middle" align="right">
验证码:
<a href="javascript:;" onclick="document.getElementById('num').src = 'checkCode.do?'+(new Date()).getTime()">
<img id="num" src="checkCode.do" />
</a>
</td>
<td valign="middle" align="left">
<input type="text" class="inputgri" name="number" placeholder="请输入您的验证码"/>
<span style="color:red">
<%=request.getAttribute("ckmsg")==null?"":request.getAttribute("ckmsg") %>
</span>
</td>
</tr>
</table>
<p>
<input type="submit" class="button" value="登录" />
<input type="button" class="button" value="注册" onclick="location='register.jsp'"/>
</p>
</form>
</div>
</body>
</html>
因为我们的登录用户不是学生而是老师或者管理员,所以我们需要建一张新的数据表,然后在创建
④此表的实体Teacher类:
package sams.ck.entity;
import java.util.Objects;
public class Teacher {
//定义属性,要与登录表的内容对应
private int uid;//用户id
private String uname;//用户名
private String pwd;//密码
private String rname;//真实姓名
private String tel;//电话号码
//为学生实体类型添加无参构造方法
public Teacher() {}
public int getUid() {
return uid;
}
public void setUid(int uid) {
this.uid = uid;
}
public String getUname() {
return uname;
}
public void setUname(String uname) {
this.uname = uname;
}
public String getPwd() {
return pwd;
}
public void setPwd(String pwd) {
this.pwd = pwd;
}
public String getRname() {
return rname;
}
public void setRname(String rname) {
this.rname = rname;
}
public String getTel() {
return tel;
}
public void setTel(String tel) {
this.tel = tel;
}
@Override
public int hashCode() {
return Objects.hash(uid);
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Teacher other = (Teacher) obj;
return uid == other.uid;
}
@Override
public String toString() {
return "Teacher [uid=" + uid + ", uname=" + uname + ", pwd=" + pwd + ", rname=" + rname + ", tel=" + tel + "]";
}
}
⑤ 然后在写一个dao方法,需要根据用户名查询登录表中的用户信息
package sams.ck.dao;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import sams.ck.entity.Student;
import sams.ck.entity.Teacher;
import sams.ck.util.DBUtil;
public class userDao {
//根据用户名查询用户信息
public Teacher findByUserName(String uname){
Teacher tea=null;
try {
//获取数据库链接
Connection con=DBUtil.getConnection();
//定义sql
String sql="select * from login where uname=?";
//获取PreparedStatement对象
PreparedStatement prep=con.prepareStatement(sql);
//注入占位符参数
prep.setString(1, uname);
//执行sql获取结果集对象
ResultSet rs=prep.executeQuery();
while(rs.next()){
tea=new Teacher();
tea.setUid(rs.getInt("id"));
tea.setUname(rs.getString("uname"));
tea.setRname(rs.getString("realname"));
tea.setPwd(rs.getString("pwd"));
tea.setTel(rs.getString("telephone"));
}
} catch (SQLException e) {
e.printStackTrace();
}
return tea;
}
}
⑥业务层中我们直接调用dao层方法
package sams.ck.service;
import sams.ck.dao.userDao;
import sams.ck.entity.Teacher;
public class userService {
private userDao dao = new userDao();
//登录方法
public Teacher login(String uname){
return dao.findByUserName(uname);
}
}
然后来到Servlet层,这里我没有新建一个关于登录的Servlet服务,我把原来的stuServlet改为了Servlet,这样就可以把登录和前面学生的相关服务放在一起,当然也可以分开来写,只不过在新写了一个Servlet后还有对应修改部署文件(web.xml),后面我会用验证码举例。
⑦在Servlet中新建分支login.do
(.do是一种合并Servlet的写法,可以将多个页面集中管理
更过详细请查阅——Servlet合并:
Servlet请求方式:
精确匹配 /a
通配匹配 /*
后缀匹配 *.do
)
else if (path.equals("/login")) {
String uname = request.getParameter("uname");
String pwd = request.getParameter("pwd");
String ck = request.getParameter("number");
Teacher tea = uservice.login(uname);
request.setAttribute("uname", uname);
if (tea == null) {
// 说明数据库中没有与该用户名对应的数据用户名错误
request.setAttribute("umsg", "用户名错误");
request.getRequestDispatcher("login.jsp").forward(request, response);
return;
}
if (!tea.getPwd().equals(pwd)) {
// 说明密码错误
request.setAttribute("pmsg", "密码错误");
request.getRequestDispatcher("login.jsp").forward(request, response);
return;
}
// 从session当中将CheckCodeServlet中绑定的验证码取出
String ck2 = (String) session.getAttribute("ck");
// 将前端页面传递过来的验证码与后台生成的验证码进行比较
if (!ck.equals(ck2)) {
// 说明验证码错误
request.setAttribute("ckmsg", "验证码错误");
request.getRequestDispatcher("login.jsp").forward(request, response);
return;
}
// 用户名和密码验证都没有问题后,将登录对象的数据绑定到session对象中
session.setAttribute("e", tea);
// 如果上述两个条件都没有触发 说明用户名和密码正确
response.sendRedirect("stuList.do");
}
实现验证码功能时,我们单独写了一个Servlet(也可以和上面的写在一起,以CheckCode.do的方式)但是代码有点多,就单拿出来了。
⑧CheckCode.class
package sams.ck.servlet;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Random;
import javax.imageio.ImageIO;
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;
public class CheckcodeServlet extends HttpServlet {
//生成验证码图片和验证码的
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//设置响应消息头 告诉浏览器 服务器给你返回的是一个jpeg格式的图片
response.setContentType("image/jpeg");
//画图
//通过BufferedImage 内存映像对象 来完成图片的绘制
BufferedImage image=new BufferedImage(60,20,BufferedImage.TYPE_INT_RGB);
//获取画笔对象
Graphics g=image.getGraphics();
//设置画笔的颜色
g.setColor(new Color(255,255,255));
//填充背景色
g.fillRect(0, 0, 60, 20);
//设置前景色
g.setColor(new Color(0,0,0));
//生成随机数
Random rad=new Random();
String number=rad.nextInt(99999)+"";
//将生成的验证码绑定到Session对象当中
HttpSession session=request.getSession();
session.setAttribute("ck",number);
//将生成的验证码(纯数字版) 画到图片上
g.drawString(number, 5, 15);
//为验证码添加干扰线
for(int i=0;i<6;i++){
//随机设定画笔的颜色
g.setColor(new Color(rad.nextInt(255),rad.nextInt(255),rad.nextInt(255)));
g.drawLine(rad.nextInt(60), rad.nextInt(20), rad.nextInt(60), rad.nextInt(20));
}
//将画好的验证码压缩并输出
//获取服务器向浏览器输出数据的输出流
OutputStream os=response.getOutputStream();
//将图片压缩 输出
ImageIO.write(image, "JPEG", os);
}
}
⑨ 写完了这个Servlet不要忘了修改部署文件
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" id="WebApp_ID" version="3.1">
<servlet>
<servlet-name>student</servlet-name>
<servlet-class>sams.ck.servlet.Servlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>student</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>checkCode</servlet-name>
<servlet-class>sams.ck.servlet.CheckcodeServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>checkCode</servlet-name>
<url-pattern>/checkCode.do</url-pattern>
</servlet-mapping>
</web-app>
这样就完成了。
⑩下面进行测试:
测试成功,但是还有一个小问题,就是当我们的用户即使没有登录通过网址也能访问到我们的页面内容,因为我们没有对登录进行验证,下面我们会通过session验证的方法,加强网站的安全性。
2、实现登录验证
① 创建一个过滤器
②SessionFilter.class
package sams.ck.filter;
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
public class SessionFilter implements Filter {
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletRequest req=(HttpServletRequest)request;
HttpServletResponse res=(HttpServletResponse)response;
String uri=req.getRequestURI();
//将获取的请求资源路径uri进行字符串切割处理
String path=uri.substring(uri.lastIndexOf("/"),uri.lastIndexOf("."));
//System.out.println(path);
if(path.equals("/login")||path.equals("/style")||path.equals("/checkCode")||path.equals("/register")){
chain.doFilter(request, response);
return;
}
//获取session对象
HttpSession session=req.getSession();
//进行session验证
Object obj=session.getAttribute("e");
if(obj==null){
//跳转回登录页面
res.sendRedirect("login.jsp");
return;
}
chain.doFilter(request, response);
}
}
③ 在web.xml中添加过滤器
<filter>
<filter-name>s</filter-name>
<filter-class>sams.ck.filter.SessionFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>s</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
④功能与原理:
实现对所有访问路径的拦截,只对login、style、checkcode路径放行,必须从login页面跳转到list页面否则其他路径都不予通行,原理是登录时会在session中留下记录,所以session不为空,判断后可以继续向下访问,如果session为空,也就是没有完成登录,就会跳转到login.jsp,直到完成登录才能进行继续访问。
二、注册功能
①搭建一个前端页面(这个页面先搭后搭建都可以,没有顺序要求)
register.jsp
<%@ page language="java" contentType="text/html; charset=utf-8" import="java.util.*,sams.ck.entity.*,java.text.*"
pageEncoding="utf-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>login</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<%@ include file="head.jsp" %>
</head>
<body>
<div>
<h3>
注册
</h3>
<form action="register.do" method="post">
<table cellpadding="0" cellspacing="0" border="0" class="form_table">
<tr>
<td valign="middle" align="right">
用户名:
</td>
<td valign="middle" align="left">
<input type="text" class="inputgri" name="uname" placeholder="请输入您的用户名"/>
</td>
</tr>
<tr>
<td valign="middle" align="right">
密码:
</td>
<td valign="middle" align="left">
<input type="password" class="inputgri" name="pwd" placeholder="请输入您的用户密码"/>
</td>
</tr>
<td valign="middle" align="right">
密码:
</td>
<td valign="middle" align="left">
<input type="password" class="inputgri" name="repwd" placeholder="请再次输入您的密码"/>
<span style="color:red">
<%=request.getAttribute("remsg")==null?"":request.getAttribute("remsg") %>
</span>
</td>
<tr>
<td valign="middle" align="right">
真实姓名:
</td>
<td valign="middle" align="left">
<input type="text" class="inputgri" name="realname" placeholder="请输入您的真实姓名"/>
</td>
</tr>
<tr>
<td valign="middle" align="right">
手机号码:
</td>
<td valign="middle" align="left">
<input type="text" class="inputgri" name="telephone" placeholder="请输入您的手机号码"/>
</td>
</tr>
</table>
<p>
<input type="submit" class="button" value="完成" />
<input type="button" class="button" value="返回" onclick="location='login.jsp'"/>
</p>
</form>
</div>
</body>
</html>
②Dao层实现如何在数据库中插入数据
//实现注册功能
public void register(Teacher teacher) {
try {
//建立数据库连接
Connection conn = DBUtil.getConnection();
//定义sql语句
String sql = "insert into login(uname,pwd,realname,telephone)values(?,?,?,?)";
//获取PreparedStatement对象
PreparedStatement prep = conn.prepareStatement(sql);
//添加占位符参数
prep.setString(1, teacher.getUname());
prep.setString(2, teacher.getPwd());
prep.setString(3, teacher.getRname());
prep.setString(4, teacher.getTel());
//执行SQL
prep.executeUpdate();
} catch (SQLException e) {
e.printStackTrace();
}
}
③业务层
package sams.ck.service;
import sams.ck.dao.userDao;
import sams.ck.entity.Teacher;
public class userService {
private userDao dao = new userDao();
//登录方法
public Teacher login(String uname){
return dao.findByUserName(uname);
}
//注册方法
public void register(Teacher teacher) {
dao.register(teacher);
}
}
④Servlet层
else if (path.equals("/register")) {
// 获取前端浏览器传递过来的用户信息
String uname = request.getParameter("uname");
String pwd = request.getParameter("pwd");
String repwd = request.getParameter("repwd");
String rname = request.getParameter("realname");
String tel = request.getParameter("telephone");
if(!pwd.equals(repwd)) {
//两次密码不一致,重定向回到注册页面重新输入
request.setAttribute("remsg", "两次密码输入不一致,请重新输入。");
request.getRequestDispatcher("register.jsp").forward(request, response);
return;
}
// 将获取的前端传递的参数封装到teacher对象当中
Teacher teacher = new Teacher();
teacher.setPwd(repwd);
teacher.setUname(uname);
teacher.setRname(rname);
teacher.setTel(tel);
uservice.register(teacher);
// 添加成功后将页面重定向会 信息展示页
response.sendRedirect("login.jsp");
}
⑤思路与测试:
思路:
注册和添加非常相似,sql都是insert语句。然后实现逻辑上就是在前端提交表单,在后端接收表单中的数据,对数据进行处理,封装在实体对象中,在通过业务层提交给dao层,最后进入数据库。唯一需要注意的一点是,注册时需要对密码进行判断,我们要用两个密码变量,比较参数是否一致,若不一致,需要重新输入,并给出提示信息,这里提示信息用setAttribute传递后端变量,再用转发功能交给前端页面。
request.setAttribute("remsg", "两次密码输入不一致,请重新输入。");
request.getRequestDispatcher("register.jsp").forward(request, response);
前端从request中获取到参数并进行判断是否输出提示。
<%=request.getAttribute("remsg")==null?"":request.getAttribute("remsg") %>
当两次密码一致时,就不需要提示错误信息。直接提交表单,并回到登录界面即可。
测试:
本次课设所有基本功能:增删改查、分页、搜索、登录、注册已经全部实现,项目源代码如下,如有问题请评论区留言或者私信问我。
项目资源链接:
https://download.csdn.net/download/qq_51701007/87263900https://download.csdn.net/download/qq_51701007/87263900