小项目(servelt+jsp+mysql+EL+JSTL)完成一个登录功能的Servlet,具有增删改查的操作。实现登录身份验证,防止非法登录,防止多点登录,记住用户名密码功能。
项目框架
1.创建数据库表
login表
create table emp(
empid int(8) auto_increment primary key,
empname varchar(32),
job varchar(255),
salary float(9,2),
tel varchar(11) unique
);
insert into emp
values
(default,'tom','程序员',10000.5,'13553126224'),
(default,'jack','程序员',9000,'13553156224'),
(default,'张良','销售员',15000,'13553123456'),
(default,'王丽丽','销售员',15000,'18253123456');
在数据库中存储密码时,要进行加密。加密使用MD5算 法进行加密,MD5算法的特点是,一个字符串通过MD5算法加密后,会得到一个唯一对应的字符串;MD5算法加 密后获得的字符串是不可逆的;通过加盐的方式,让加密的密码更安全。
2.创建Users类
package com.hyxy.emp.vo;
public class Users {
private String loginname;
private String passwd;
private String username;
public String getLoginname() {
return loginname;
}
public void setLoginname(String loginname) {
this.loginname = loginname;
}
public String getPasswd() {
return passwd;
}
public void setPasswd(String passwd) {
this.passwd = passwd;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
}
3.Emp.java
package com.hyxy.emp.vo;
public class Emp {
//属性名要和表中的列名相同,可忽略大小写
private int empid;
private String empname;
private String job;
private double salary;
private String tel;
public int getEmpid() {
return empid;
}
public void setEmpid(int empid) {
this.empid = empid;
}
public String getEmpname() {
return empname;
}
public void setEmpname(String empname) {
this.empname = empname;
}
public String getJob() {
return job;
}
public void setJob(String job) {
this.job = job;
}
public double getSalary() {
return salary;
}
public void setSalary(double salary) {
this.salary = salary;
}
public String getTel() {
return tel;
}
public void setTel(String tel) {
this.tel = tel;
}
}
4.EmpServlet.java
package com.hyxy.emp.servlet;
import com.hyxy.emp.vo.Emp;
import com.oracle.jdbc.util.Dao;
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.io.PrintWriter;
import java.util.List;
@WebServlet("/emp.do")//用.do区分servlet的路径
public class EmpServlet extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.setCharacterEncoding("UTF-8");
resp.setContentType("text/html;charset=UTF-8");//设置客户端浏览器解码字符集
//resp.setCharacterEncoding("UTF-8"); //设置传输内容的编码字符集,浏览器使用相同的字符集才能解码
//System.out.println("调用Dao,获得数据,拼html发给浏览器");
//获得请求的操作标志值
//判断session中是否有key是user的对象,如果没有则向登陆界面进行重定向跳转
HttpSession session=req.getSession();
if(session.getAttribute("user")==null){
PrintWriter pw= resp.getWriter();
pw.println("<script>");
pw.println("window.parent.location.href='"+req.getContextPath()+"/index'");//执行js跳转
//pw.println("window.parent.location.href='${pageContext.request.contextPath}/index'");//执行js跳转
pw.println("</script>");
return;
//resp.sendRedirect();
}
String op=req.getParameter("op");
if("query".equals(op)){
//查询请求的处理
query(req,resp);
}else if("add".equals(op)){
add(req,resp);
}else if("save".equals(op)){
save(req,resp);
}else if("delete".equals(op)){
delete(req,resp);
}else if("edit".equals(op)){
edit(req,resp);
}else if("update".equals(op)){
update(req,resp);
}else if("back".equals(op)){
back(req,resp);
}
}
/**
* 将方法封装
* @param req
* @param resp
*/
protected void query(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//查询
String sql="select * from emp";
List<Emp> list = Dao.query(sql,Emp.class);
//使用JSP便于代码维护
req.setAttribute("list",list);
req.getRequestDispatcher("/view/emp/query.jsp").forward(req,resp);
}
protected void add(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.getRequestDispatcher("/view/emp/add.jsp").forward(req,resp);
}
protected void save(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//接收请求的参数,也就是要保存的数据
String empname= req.getParameter("empname");
String job= req.getParameter("job");
String salary= req.getParameter("salary");
String tel= req.getParameter("tel");//注意电话号码是唯一约束,不能相同,否则报错
//向数据库插入数据
String sql ="insert into emp values(default,?,?,?,?)";
Dao.executeSql(sql,empname,job,salary,tel);
//向浏览器返回插入后的查询数据,调用query,显示查询页面的数据
query(req, resp);
}
protected void delete(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String empid =req.getParameter("id");
String sql="delete from emp where empid=?";
Dao.executeSql(sql,empid);
query(req, resp);
}
protected void edit(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String empid = req.getParameter("id");
String sql = "select * from emp where empid = ?";
Emp e = Dao.queryOne(sql,Emp.class,empid);
req.setAttribute("emp",e);
req.getRequestDispatcher("/view/emp/edit.jsp").forward(req,resp);
}
protected void update(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String empname= req.getParameter("empname");
String job= req.getParameter("job");
String salary= req.getParameter("salary");
String tel= req.getParameter("tel");
String empid = req.getParameter("empid");//用表单隐藏
String sql ="update emp set empname=?,job=?,salary=?,tel=? where empid=?";
Dao.executeSql(sql,empname,job,salary,tel,empid);
//向浏览器返回插入后的查询数据,调用query,显示查询页面的数据
query(req, resp);
}
protected void back(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
}
}
框架页面设计
index.html
<!doctype html>
<html lang="en">
<head>
</head>
<frameset rows="100,*">
<frame src="/emp/view/frame/top.html">
<frameset cols="120,*">
<frameset rows="50%,50%">
<frame src="/emp/view/frame/catalog.html" name="left">
</frameset>
<frame src="/emp/view/frame/main.html" name="mainFrame">
</frameset>
</frameset>
</html>
catalog.html 框架左侧目录
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>目录</title>
</head>
<body>
<h2 align='center'>目录</h2>
<table align='center'>
<tr align='center'>
<td align='center'>
<a href="/emp/emp.do?op=query" target="mainFrame">员工管理</a><br>
</td><!--将内容1⽂件的内容指定显⽰给名为rightdown的框架-->
</tr>
<tr align='center'>
<td align='center'>
<a href="/emp/dept.do?op=query" target="mainFrame">部门管理</a><br>
</td>
</tr>
</table>
</body><!--上边的target为指定-->
</html>
一、实现登录身份验证功能
1.设计登录界面 IndexServlet.java处理访问登录页面的请求
package com.hyxy.emp.servlet;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
@WebServlet("/index")
public class IndexServlet extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//输入http://localhost:8080/emp/index访问登录页面
req.setCharacterEncoding("GBK");
resp.setCharacterEncoding("GBK");
Cookie[] cookies=req.getCookies();//获得一个cookie数组
String loginname="";
String passwd="";
String rememberMe="";
for(Cookie cookie:cookies){
if("rememberMe".equals(cookie.getName())){
rememberMe=cookie.getValue();
}
}
if("1".equals(rememberMe)){
for(Cookie cookie:cookies){
if("loginname".equals(cookie.getName())){
loginname=cookie.getValue();
}
if("passwd".equals(cookie.getName())){
passwd=cookie.getValue();
}
}
}
PrintWriter pw= resp.getWriter();
pw.println("<!doctype html>");
pw.println("<html>");
pw.println(" <head>");
pw.println(" <script>");
if(req.getAttribute("msg")!=null){
pw.println("alert('"+req.getAttribute("msg")+"');");
}
pw.println(" function login(){");
pw.println(" var loginname = document.getElementById('loginname');");
pw.println(" var passwd = document.getElementById('passwd');");
pw.println(" if(loginname.value==''){");
pw.println(" alert('请输入用户名');");
pw.println(" return;");
pw.println(" }");
pw.println(" if(passwd.value==''){");
pw.println(" alert('请输入密码');");
pw.println(" return;");
pw.println(" }");
pw.println(" loginForm.submit();");
pw.println(" }");
pw.println(" </script>");
pw.println(" </head>");
pw.println(" <body>");
pw.println(" <form name='loginForm' method='post' action='"+req.getContextPath()+"/login'>");
pw.println(" <table width='60%' align='center'>");
pw.println(" <tr>");
pw.println(" <td align='right'>用户名:</td>");
pw.println(" <td align='left'><input type='text' id='loginname' name='loginname' value='"+loginname+"'></td>");
pw.println(" </tr>");
pw.println(" <tr>");
pw.println(" <td align='right'>密 码:</td>");
pw.println(" <td align='left'><input type='password' id='passwd' name='passwd' value='"+passwd+"'></td>");
pw.println(" </tr>");
pw.println(" <tr>");
pw.println(" <td align='right'><input type='button' value='登录' onclick='login();'></td>");
pw.println(" <td align='left'><input type='checkbox' "+("1".equals(rememberMe)?"checked":"")+" name='rememberMe' value='1'>记住用户名密码</td>");
pw.println(" </tr>");
pw.println(" </table>");
pw.println(" </form>");
pw.println(" </body>");
pw.println("</html>");
}
}
2.LoginServlet.java处理登录身份认证请求
package com.hyxy.emp.servlet;
import com.hyxy.emp.vo.Users;
import com.oracle.jdbc.util.Dao;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.*;
import java.io.IOException;
import java.util.List;
@WebServlet("/login")
public class LoginServlet extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.setCharacterEncoding("GBK");
resp.setCharacterEncoding("GBK");
//功能一:登录身份认证
String loginname=req.getParameter("loginname");
String passwd=req.getParameter("passwd");
String rememberMe=req.getParameter("rememberMe");
//如果选中记住用户名密码勾选框,rememberMe的值是1
//将用户输入的登录名和密码在数据库中进行查找
String sql="select * from users where loginname=? and passwd=md5(?)";//第二个?是用户名加密码
List<Users> list = Dao.query(sql,Users.class,loginname,loginname+passwd);
if(list==null||list.size()==0){
//未找到,登录失败
//显示登陆页面,调用IndexServlet对象的service方法(无法实现),使用跳转
// 给出提示
//向IndexServlet进行跳转,使用请求转发跳转
req.setAttribute("msg","登录失败!");//存到Map中,msg是key,后面是value
req.getRequestDispatcher("/index").forward(req,resp);
}else{
//登录成功,重定向跳转
//显示主页面,LoginServlet
// resp.sendRedirect(req.getContextPath()+"/view/index.html");
//功能二:防止非法登录
//例如直接在浏览器输入链接http://localhost:8080/emp/emp.do?op=edit&id=2就能修改表中信息,不需要经过登陆界面
//实现方法,在每个页面都添加session进行判断,否则返回登陆界面
HttpSession session=req.getSession();
session.setAttribute("user",list.get(0));
ServletContext servletContext=this.getServletContext();
if(servletContext.getAttribute(loginname)!=null){
HttpSession otherSession=(HttpSession)servletContext.getAttribute(loginname);
if(!session.getId().equals(otherSession.getId())){//防止当前同一个用户登录多次时,自己将自己踢出
otherSession.invalidate();
}
}
servletContext.setAttribute(loginname,session);
if(rememberMe!=null){
Cookie cookie=new Cookie("loginname",loginname);
cookie.setMaxAge(60*60*24*30);
resp.addCookie(cookie);
cookie=new Cookie("passwd",passwd);
cookie.setMaxAge(60*60*24*30);
resp.addCookie(cookie);
}
Cookie cookie=new Cookie("rememberMe",rememberMe);
cookie.setMaxAge(60*60*24*30);
resp.addCookie(cookie);
//显示主页面
resp.sendRedirect(req.getContextPath()+"/view/index.html");
/*
功能三:防止多点登录
使别人的session失效,即可实现让对方下线
当登陆成功时,将登陆的用户名作为key,当前用户的session作为value存储到ServletContext容器中
登录成功时,判断Servlet Context中 是否有登陆用户的key-value,
如果有,则将Servlet Context中存储的session失效,将登陆用户的session存到Servlet Context中
无论Servlet Context中是否有别人登录的session,都要将新登陆的用户的session存到其中,以便实现相互踢出功能
*/
/*
功能四:记住用户名密码
勾选框选中,写Cookie
*/
}
}
}
3.点击登录按钮,用输入的用户名和密码与数据库的用户名密码 进行校验
IndexServlet:
pw.println(" <form name='loginForm' method='post' action='"+request.getContextPath()+"/login'>");
LoginServlet.java
List<Users> list = Dao.query(sql, Users.class,loginname,loginname+passwd);
if(list==null||list.size()==0){
//登录失败
//显示登录页面,给出提示
//调用 IndexServlet对象的service方法 无法实现
// 向IndexServlet进行跳转,需要传数据(登录失败的消息)
request.setAttribute("msg","登录失败!");
//请求转发跳转自动加上下文路径,因为调用的是request的方法
request.getRequestDispatcher("/index").forward(request,response);
}else{
//登录成功
//显示主页面
response.sendRedirect(request.getContextPath()+"/view/index.html");
}
IndexServlet中获得request的Attribute值判断是否提示 登录失败
pw.println(" <script>");
if(request.getAttribute("msg")!=null){
pw.println("alert('"+request.getAttribute("msg")+"');");
}
二、实现防止非法登录功能
访问系统功能时,只能先从登录页面进行,登录成功后,再能使用其他的功能。
LoginServlet中
//登录成功,向session中存储Users对象
HttpSession session = request.getSession();
session.setAttribute("user",list.get(0));
EmpServlet中
if(session.getAttribute("user")==null){
PrintWriter pw = response.getWriter();
pw.println("<script>");
pw.println("window.parent.location.href='"+request.getContextPath()+"/index'");
pw.println("</script>");
return;
//response.sendRedirect(request.getContextPath()+"/index");
}
三、实现防止多点登录功能
LoginServlet中:
else{
//登录成功,向session中存储Users对象
HttpSession session = request.getSession();
session.setAttribute("user",list.get(0));
//判断ServletContext中是否有登录的用户名key的value
ServletContext servletContext = this.getServletContext();
if(servletContext.getAttribute(loginname)!=null){
HttpSession otherSession = (HttpSession)servletContext.getAttribute(loginname);
//if(session!=otherSession)
if(!session.getId().equals(otherSession.getId()))
otherSession.invalidate();
}
//存入当前的Session对象
servletContext.setAttribute(loginname,session);
//显示主页面
response.sendRedirect(request.getContextPath()+"/view/index.html");
}
四、记住用户名密码功能
1. 如果勾选了 rememberMe的勾选框并登录成功时,向客户端发送用户名、密码、勾选框是否选中的Cookie;
pw.println("<td align='left'><input type='checkbox' "+("1".equals(rememberMe)?"checked":"")+" name='rememberMe' value='1'>记住用户名密码</td>");
LoginServlet.java
else{
//登录成功,向session中存储Users对象
HttpSession session = request.getSession();
session.setAttribute("user",list.get(0));
//判断ServletContext中是否有登录的用户名key的value
ServletContext servletContext = this.getServletContext();
if(servletContext.getAttribute(loginname)!=null){
HttpSession otherSession =(HttpSession)servletContext.getAttribute(loginname);
//if(session!=otherSession)
if(!session.getId().equals(otherSession.getId()))
otherSession.invalidate();
}
//存入当前的Session对象
servletContext.setAttribute(loginname,session);
if(rememberMe!=null){
//向客户端响应Cookie
Cookie cookie = new Cookie("loginname",loginname);
cookie.setMaxAge(60*60*24*30);
response.addCookie(cookie);
cookie = new Cookie("passwd",passwd);
cookie.setMaxAge(60*60*24*30);
response.addCookie(cookie);
}
Cookie cookie = new Cookie("rememberMe",rememberMe);
cookie.setMaxAge(60*60*24*30);
response.addCookie(cookie);
//显示主页面
response.sendRedirect(request.getContextPath()+"/view/index.html");
}
2. 进入到登录页面先访问IndexServlet,在IndexServlet中可以获得三个Cookie,如果勾选框是选中状态,就将 用户名、密码、勾选状态写到html中,IndexServlet发回浏览器
运行效果:
浏览器访问 http://localhost:8080/emp/index 为登录界面
2.勾选记住用户名密码,点击登录按钮,进入到主页
3.点击左侧目录中的“员工管理”
4. 点击新增按钮,填写信息,保存
5.点击“修改”,修改信息,保存