使用servlet实现用户登录
Posted faraway2004
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了使用servlet实现用户登录相关的知识,希望对你有一定的参考价值。
本文简单讲述使用servlet实现用户登录,包括用户登录、退出和注册等。
1.关于servlet
1.1概述
Servlet(Server Applet),全称Java Servlet,未有中文译文。是用Java编写的服务器端程序。其主要功能在于交互式地浏览和修改数据,生成动态Web内容。狭义的Servlet是指Java语言实现的一个接口,广义的Servlet是指任何实现了这个Servlet接口的类,一般情况下,人们将Servlet理解为后者。Servlet运行于支持Java的应用服务器中。从原理上讲,Servlet可以响应任何类型的请求,但绝大多数情况下Servlet只用来扩展基于HTTP协议的Web服务器。
最早支持Servlet标准的是JavaSoft的Java Web Server。此后,一些其它的基于Java的Web服务器开始支持标准的Servlet。
1.2实现过程
最早支持 Servlet 技术的是 JavaSoft 的 Java Web Server。此后,一些其它的基于 Java 的 Web Server 开始支持标准的 Servlet API。Servlet 的主要功能在于交互式地浏览和修改数据,生成动态 Web 内容。这个过程为:
1) 客户端发送请求至服务器端;
2) 服务器将请求信息发送至 Servlet;
3) Servlet 生成响应内容并将其传给服务器。响应内容动态生成,通常取决于客户端的请求;
4) 服务器将响应返回给客户端。
Servlet 看起来像是通常的 Java 程序。Servlet 导入特定的属于 Java Servlet API 的包。因为是对象字节码,可动态地从网络加载,可以说 Servlet 对 Server 就如同 Applet对 Client 一样,但是,由于 Servlet 运行于 Server 中,它们并不需要一个图形用户界面。从这个角度讲,Servlet 也被称为 FacelessObject。
一个 Servlet 就是 Java 编程语言中的一个类,它被用来扩展服务器的性能,服务器上驻留着可以通过“请求-响应”编程模型来访问的应用程序。虽然 Servlet 可以对任何类型的请求产生响应,但通常只用来扩展 Web 服务器的应用程序。
目前最新版本为 3.1。
1.3生命周期
1) 客户端请求该 Servlet;
2) 加载 Servlet 类到内存;
3) 实例化并调用init()方法初始化该 Servlet;
4) service()(根据请求方法不同调用doGet() 或者 doPost(),此外还有doHead()、doPut()、doTrace()、doDelete()、doOptions());
5) destroy()。
加载和实例化 Servlet。这项操作一般是动态执行的。然而,Server 通常会提供一个管理的选项,用于在 Server 启动时强制装载和初始化特定的 Servlet。
Server 创建一个 Servlet的实例
第一个客户端的请求到达 Server
Server 调用 Servlet 的 init() 方法(可配置为 Server 创建 Servlet 实例时调用,在 web.xml 中 <servlet> 标签下配置 <load-on-startup> 标签,配置的值为整型,值越小 Servlet 的启动优先级越高)
一个客户端的请求到达 Server
Server 创建一个请求对象,处理客户端请求
Server 创建一个响应对象,响应客户端请求
Server 激活 Servlet 的 service() 方法,传递请求和响应对象作为参数
service() 方法获得关于请求对象的信息,处理请求,访问其他资源,获得需要的信息
service() 方法使用响应对象的方法,将响应传回Server,最终到达客户端。service()方法可能激活其它方法以处理请求,如 doGet() 或 doPost() 或程序员自己开发的新的方法。
对于更多的客户端请求,Server 创建新的请求和响应对象,仍然激活此 Servlet 的 service() 方法,将这两个对象作为参数传递给它。如此重复以上的循环,但无需再次调用 init() 方法。一般 Servlet 只初始化一次(只有一个对象),当 Server 不再需要 Servlet 时(一般当 Server 关闭时),Server 调用 Servlet 的 destroy() 方法。
1.4编程接口
HTTPServlet 使用一个 html 表单来发送和接收数据。要创建一个 HTTPServlet,请扩展 HttpServlet 类, 该类是用专门的方法来处理 HTML 表单的 GenericServlet 的一个子类。 HTML 表单是由 <form> 和 </form> 标记定义的。表单中典型地包含输入字段(如文本输入字段、复选框、单选按钮和选择列表)和用于提交数据的按钮。当提交信息时,它们还指定服务器应执行哪一个Servlet(或其它的程序)。 HttpServlet 类包含 init()、destroy()、service() 等方法。其中 init() 和 destroy() 方法是继承的。
(1) init() 方法
在 Servlet 的生命期中,仅执行一次 init() 方法。它是在服务器装入 Servlet 时执行的。 可以配置服务器,以在启动服务器或客户机首次访问 Servlet 时装入 Servlet。 无论有多少客户机访问 Servlet,都不会重复执行 init() 。
缺省的 init() 方法通常是符合要求的,但也可以用定制 init() 方法来覆盖它,典型的是管理服务器端资源。 例如,可能编写一个定制 init() 来只用于一次装入 GIF 图像,改进 Servlet 返回 GIF 图像和含有多个客户机请求的性能。另一个示例是初始化数据库连接。缺省的 init() 方法设置了 Servlet 的初始化参数,并用它的 ServletConfig 对象参数来启动配置, 因此所有覆盖 init() 方法的 Servlet 应调用 super.init() 以确保仍然执行这些任务。在调用 service() 方法之前,应确保已完成了 init() 方法。
(2) service() 方法
service() 方法是 Servlet 的核心。每当一个客户请求一个HttpServlet 对象,该对象的service() 方法就要被调用,而且传递给这个方法一个"请求"(ServletRequest)对象和一个"响应"(ServletResponse)对象作为参数。 在 HttpServlet 中已存在 service() 方法。缺省的服务功能是调用与 HTTP 请求的方法相应的 do 功能。例如, 如果 HTTP 请求方法为 GET,则缺省情况下就调用 doGet() 。Servlet 应该为 Servlet 支持的 HTTP 方法覆盖 do 功能。因为 HttpServlet.service() 方法会检查请求方法是否调用了适当的处理方法,不必要覆盖 service() 方法。只需覆盖相应的 do 方法就可以了。
Servlet 的响应可以是下列几种类型:
一个输出流,浏览器根据它的内容类型(如 text/html)进行解释。
一个 HTTP 错误响应,重定向到另一个 URL、servlet、JSP。
(3) doGet() 方法
当一个客户通过 HTML 表单发出一个 HTTP GET 请求或直接请求一个 URL 时,doGet() 方法被调用。与 GET 请求相关的参数添加到 URL 的后面,并与这个请求一起发送。当不会修改服务器端的数据时,应该使用 doGet() 方法。
(4) doPost() 方法
当一个客户通过 HTML 表单发出一个 HTTP POST 请求时,doPost() 方法被调用。与 POST 请求相关的参数作为一个单独的 HTTP 请求从浏览器发送到服务器。当需要修改服务器端的数据时,应该使用 doPost() 方法。
(5) destroy() 方法
destroy() 方法仅执行一次,即在服务器停止且卸装 Servlet 时执行该方法。典型的,将 Servlet 作为服务器进程的一部分来关闭。缺省的 destroy() 方法通常是符合要求的,但也可以覆盖它,典型的是管理服务器端资源。例如,如果 Servlet 在运行时会累计统计数据,则可以编写一个 destroy() 方法,该方法用于在未装入 Servlet 时将统计数字保存在文件中。另一个示例是关闭数据库连接。
当服务器卸装 Servlet 时,将在所有 service() 方法调用完成后,或在指定的时间间隔过后调用 destroy() 方法。一个 Servlet 在运行 service() 方法时可能会产生其它的线程,因此请确认在调用 destroy() 方法时,这些线程已终止或完成。
(6) getServletConfig() 方法
getServletConfig() 方法返回一个 ServletConfig 对象,该对象用来返回初始化参数和 ServletContext。ServletContext 接口提供有关 servlet 的环境信息。
(7) getServletInfo() 方法
getServletInfo() 方法是一个可选的方法,它提供有关 servlet 的信息,如作者、版本、版权。
当服务器调用 sevlet 的 service()、doGet() 和 doPost() 这三个方法时,均需要 “请求”和“响应”对象作为参数。“请求”对象提供有关请求的信息,而“响应”对象提供了一个将响应信息返回给浏览器的一个通信途径。
javax.servlet 软件包中的相关类为 ServletResponse 和 ServletRequest,而 javax.servlet.http 软件包中的相关类为 HttpServletRequest 和 HttpServletResponse。Servlet 通过这些对象与服务器通信并最终与客户端通信。Servlet 能通过调用"请求"对象的方法获知客户端环境,服务器环境的信息和所有由客户机提供的信息。Servlet 可以调用“响应”对象的方法发送响应,该响应是准备发回客户端的。
2.系统架构
2.1登录用例图
2.2页面流程图
2.3系统架构图
2.4数据库设计
本例使用oracle数据库
用户表包括id,用户名,密码,email,共4个字段
-- Create table
create table P_USER
(
id VARCHAR2(50) not null,
username VARCHAR2(20),
password VARCHAR2(20),
email VARCHAR2(50)
)
tablespace USERS
pctfree 10
initrans 1
maxtrans 255
storage
(
initial 64
minextents 1
maxextents unlimited
);
-- Add comments to the table
comment on table P_USER
is '用户表';
-- Add comments to the columns
comment on column P_USER.id
is 'id';
comment on column P_USER.username
is '用户名';
comment on column P_USER.password
is '密码';
comment on column P_USER.email
is 'email';
3.servlet编写
3.1java类
UserServlet.java
package com.baosight.servlet;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.baosight.bean.UserBean;
/**
* <p>Title:UserServlet </p>
* <p>Description:TODO </p>
* <p>Company: </p>
* @author yuan
* @date 2016-5-23 下午10:50:57*/
public class UserServlet extends HttpServlet
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException
doPost(request,response);
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException
String method = request.getParameter("method");
if("login".equals(method))//登录
String username = request.getParameter("username");
String password = request.getParameter("password");
if(username==null||"".equals(username.trim())||password==null||"".equals(password.trim()))
System.out.println("用户名或密码不能为空!");
response.sendRedirect("login.jsp");
return;
UserBean userBean = new UserBean();
boolean isValid = userBean.valid(username,password);
if(isValid)
System.out.println("登录成功!");
request.getSession().setAttribute("username", username);
response.sendRedirect("welcome.jsp");
return;
else
System.out.println("用户名或密码错误,登录失败!");
response.sendRedirect("login.jsp");
return;
else if("logout".equals(method))//退出登录
System.out.println("退出登录!");
request.getSession().removeAttribute("username");
response.sendRedirect("login.jsp");
return;
else if("register".equals(method))//注册
String username = request.getParameter("username");
String password1 = request.getParameter("password1");
String password2 = request.getParameter("password2");
String email = request.getParameter("email");
if(username==null||"".equals(username.trim())||password1==null||"".equals(password1.trim())||password2==null||"".equals(password2.trim())||!password1.equals(password2))
System.out.println("用户名或密码不能为空!");
response.sendRedirect("register.jsp");
return;
UserBean userBean = new UserBean();
boolean isExit = userBean.isExist(username);
if(!isExit)
userBean.add(username, password1, email);
System.out.println("注册成功,请登录!");
response.sendRedirect("login.jsp");
return;
else
System.out.println("用户名已存在!");
response.sendRedirect("register.jsp");
return;
上面根据页面form提交的请求中的method参数来判断业务类型,并分别调用userbean中的方法进行处理
关于登录:
当用户名或密码为空时返回登录页面login.jsp
当登录成功后将用户信息保存到session,跳转到欢迎页面welcome.jsp
当登录失败时返回登录页面login.jsp
关于退出登录:
从session中移除用户信息,跳转到登录页面login.jsp
关于注册:
当用户名或密码为空时返回注册页面register.jsp
当注册用户名在数据库不存在时,新增用户
新增成功后跳转到登录页面login.jsp
当注册用户名在数据库存在时,返回注册页面register.jsp
这里servlet起到了控制器的作用,对不同类型的请求分别进行处理并做出各自的响应
上述servlet模型也是后来出现的各种框架比如struts的基本实现原理
3.2配置文件
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" version="2.5">
<display-name></display-name>
<servlet>
<description>This is the description of my J2EE component</description>
<display-name>This is the display name of my J2EE component</display-name>
<servlet-name>UserServlet</servlet-name>
<servlet-class>com.baosight.servlet.UserServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>UserServlet</servlet-name>
<url-pattern>/UserServlet</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
</web-app>
4.javabean的编写
4.1开发数据库底层处理javabean
DBAcess.java
package com.baosight.bean;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
/**数据库操作类
* <p>Title:DBAcess </p>
* <p>Description:TODO </p>
* <p>Company: </p>
* @author yuan
* @date 2016-5-22 下午12:40:24*/
public class DBAcess
private String driver = "oracle.jdbc.driver.OracleDriver";
private String url = "jdbc:oracle:" + "thin:@127.0.0.1:1521:orcl";
private String username = "scott";
private String password = "tiger";
private Connection conn;
private Statement stm;
private ResultSet rs;
//创建连接
public boolean createConn()
boolean b = false;
try
Class.forName(driver);// 加载Oracle驱动程序
conn = DriverManager.getConnection(url, username, password);
b = true;
catch (SQLException e)
// TODO Auto-generated catch block
e.printStackTrace();
// 获取连接
catch (ClassNotFoundException e)
// TODO Auto-generated catch block
e.printStackTrace();
return b;
//修改
public boolean update(String sql)
boolean b = false;
try
stm = conn.createStatement();
stm.execute(sql);
b = true;
catch (SQLException e)
// TODO Auto-generated catch block
e.printStackTrace();
return b;
//查询
public void query(String sql)
try
stm = conn.createStatement();
rs = stm.executeQuery(sql);
catch (SQLException e)
// TODO Auto-generated catch block
e.printStackTrace();
//判断有无数据
public boolean next()
boolean b = false;
try
if(rs.next())
b = true;
catch (SQLException e)
// TODO Auto-generated catch block
e.printStackTrace();
return b;
//获取表字段值
public String getValue(String field)
String value = null;
try
if (rs != null)
value = rs.getString(field);
catch (SQLException e)
// TODO Auto-generated catch block
e.printStackTrace();
return value;
//关闭连接
public void closeConn()
try
if (conn != null)
conn.close();
catch (SQLException e)
// TODO Auto-generated catch block
e.printStackTrace();
//关闭statement
public void closeStm()
try
if (stm != null)
stm.close();
catch (SQLException e)
// TODO Auto-generated catch block
e.printStackTrace();
//关闭ResultSet
public void closeRs()
try
if (rs != null)
rs.close();
catch (SQLException e)
// TODO Auto-generated catch block
e.printStackTrace();
public String getDriver()
return driver;
public void setDriver(String driver)
this.driver = driver;
public String getUrl()
return url;
public void setUrl(String url)
this.url = url;
public String getUsername()
return username;
public void setUsername(String username)
this.username = username;
public String getPassword()
return password;
public void setPassword(String password)
this.password = password;
public Statement getStm()
return stm;
public void setStm(Statement stm)
this.stm = stm;
public ResultSet getRs()
return rs;
public void setRs(ResultSet rs)
this.rs = rs;
public void setConn(Connection conn)
this.conn = conn;
public Connection getConn()
return conn;
上述数据库操作类使用JDBC连接数据库,并封装了连接数据库、查询、修改、关闭资源等方法。
4.2开发JavaBean业务逻辑组件
UserBean.javapackage com.baosight.bean;
import com.baosight.util.GenerateUUID;
/**
* <p>Title:UserBean </p>
* <p>Description:TODO </p>
* <p>Company: </p>
* @author yuan
* @date 2016-5-22 下午1:05:00*/
public class UserBean
//登录验证
public boolean valid(String username,String password)
boolean isValid = false;
DBAcess db = new DBAcess();
if(db.createConn())
String sql = "select * from p_user where username='"+username+"' and password='"+password+"'";
db.query(sql);
if(db.next())
isValid = true;
db.closeRs();
db.closeStm();
db.closeConn();
return isValid;
//注册验证
public boolean isExist(String username)
boolean isValid = false;
DBAcess db = new DBAcess();
if(db.createConn())
String sql = "select * from p_user where username='"+username+"'";
db.query(sql);
if(db.next())
isValid = true;
db.closeRs();
db.closeStm();
db.closeConn();
return isValid;
//注册用户
public boolean add(String username,String password,String email)
boolean isValid = false;
DBAcess db = new DBAcess();
if(db.createConn())
String sql = "insert into p_user(id,username,password,email) values('"+GenerateUUID.next()+"','"+username+"','"+password+"','"+email+"')";
isValid = db.update(sql);
db.closeStm();
db.closeConn();
return isValid;
上述业务逻辑javabean,定义了登录验证、注册验证和新增用户等方法
4.3关于生成唯一ID
上面在新增用户时需要插入ID,本例使用UUID来生成唯一IDGenerateUUID.java
package com.baosight.util;
import java.util.Date;
/**
* <p>Title:GenerateUUID </p>
* <p>Description:TODO </p>
* <p>Company: </p>
* @author yuan
* @date 2016-5-22 下午1:31:46*/
public class GenerateUUID
private static Date date = new Date();
// private static StringBuilder buf = new StringBuilder();
private static int seq = 0;
private static final int ROTATION = 99999;
public static synchronized long next()
if (seq > ROTATION) seq = 0;
// buf.delete(0, buf.length());
date.setTime(System.currentTimeMillis());
String str = String.format("%1$tY%1$tm%1$td%1$tk%1$tM%1$tS%2$05d", date, seq++);
return Long.parseLong(str);
public static void main(String[] args)
for(int i=0;i<100;i++)
System.out.println(next());
5.页面编写
5.1登录页面
login.jsp<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<base href="<%=basePath%>">
<title>登录页面</title>
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">
<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
<meta http-equiv="description" content="This is my page">
<!--
<link rel="stylesheet" type="text/css" href="styles.css">
-->
</head>
<body>
<form action="UserServlet?method=login" method="post">
<table>
<tr>
<td colspan="2">登录窗口</td>
</tr>
<tr>
<td>用户名:</td>
<td><input type="text" name="username" />
</td>
</tr>
<tr>
<td>密码:</td>
<td><input type="password" name="password" />
</td>
</tr>
<tr>
<td colspan="2"><input type="submit" value="登录" /> <a href="register.jsp">注册</a>
</td>
</tr>
</table>
</form>
</body>
</html>
注意:页面表单直接提交到servlet
<form action="UserServlet?method=login" method="post">
页面效果
5.2登录成功欢迎页面
welcome.jsp<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<base href="<%=basePath%>">
<title>My JSP 'welcom.jsp' starting page</title>
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">
<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
<meta http-equiv="description" content="This is my page">
<!--
<link rel="stylesheet" type="text/css" href="styles.css">
-->
</head>
<body>
<table>
<tr>
<td><img src="images/logo4.png" />
</td>
<td><img src="images/logo2.png" height="90" />
</td>
</tr>
<tr>
<td colspan="2"><hr />
</td>
</tr>
<tr>
<td>
<table>
<tr>
<td><a>Main</a>
</td>
</tr>
<tr>
<td><a>Menu1</a>
</td>
</tr>
<tr>
<td><a>Menu2</a>
</td>
</tr>
<tr>
<td><a>Menu3</a>
</td>
</tr>
<tr>
<td><a>Menu4</a>
</td>
</tr>
<tr>
<td><a>Menu5</a>
</td>
</tr>
<tr>
<td><a>Menu6</a>
</td>
</tr>
<tr>
<td><a>Menu7</a>
</td>
</tr>
<tr>
<td><a>Menu8</a>
</td>
</tr>
</table></td>
<td>
<form action="UserServlet?method=logout" method="post">
<table>
<tr>
<td colspan="2">登录成功!</td>
</tr>
<tr>
<td>欢迎你,</td>
<td>$username </td>
</tr>
<tr>
<td colspan="2"><input type="submit" value="退出" /></td>
</tr>
</table>
</form></td>
</tr>
</table>
</body>
</html>
注意:页面表单直接提交到servlet
<form action="UserServlet?method=logout" method="post">
页面效果
5.3用户注册页面
register.jsp<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<base href="<%=basePath%>">
<title>注册页面</title>
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">
<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
<meta http-equiv="description" content="This is my page">
<!--
<link rel="stylesheet" type="text/css" href="styles.css">
-->
</head>
<body>
<form action="UserServlet?method=register" method="post">
<table>
<tr>
<td colspan="2">注册窗口</td>
</tr>
<tr>
<td>用户名:</td>
<td><input type="text" name="username" /></td>
</tr>
<tr>
<td>密码:</td>
<td><input type="password" name="password1" /></td>
</tr>
<tr>
<td>确认密码:</td>
<td><input type="password" name="password2" /></td>
</tr>
<tr>
<td>email:</td>
<td><input type="text" name="email" /></td>
</tr>
<tr>
<td colspan="2"><input type="submit" value="注册" /> <a href="login.jsp">返回</a></td>
</tr>
</table>
</form>
</body>
</html>
注意:页面表单直接提交到servlet
<form action="UserServlet?method=register" method="post">
运行效果
6.总结
本例使用servlet作为控制器来处理页面的请求和做出响应,并使用javabean对数据库操作和业务逻辑处理进行了封装。
注意:页面表单直接提交到servlet
以上即为使用servlet实现用户登录的简单介绍,还需要不断完善。
以上是关于使用servlet实现用户登录的主要内容,如果未能解决你的问题,请参考以下文章