例1-4
用JSP、Servlet及JavaBeans构建一个简单的登陆系统。该系统的要求是,当用户在登陆录页面上填写用户名和密码并提交之后,系统将检查该用户是否已经注册;如果该用户已经注册,系统将进入主页面,否则就进入注册页面。我们将按照以下步骤构建这个系统:
1.数据库设计:使用MS Access作为数据库,构建数据表T_UserInfo;
2.构建视图组件:登录页面login.jsp,主页面main.jsp,以及注册页面register.jsp;
3.构建控制层组件:一个Servlet,取名为loginServlet.java;
4.构建业务逻辑层组件(Model组件):一个JavaBean,取名为loginHandler.java;
5.构建数据访问层组件:一个数据访问类,取名为dbPool,java;
6.编译、打包程序;
7.部署该程序到Web服务器Tomcat中,然后运行。
该系统的工作流程如图:
1.数据库设计
用户登录是一个涉及数据库操作的用例。登录涉及的数据表名为test,结构如下:
字段名:username 字段类型:nvarchar(50) 字段描述:用户名,主键
字段名:password 字段类型:nvarchar(50) 字段描述:密码
2.构建视图组件
本例有3个视图组件,分别是登录页面login.jsp,主页面main.jsp及注册页面register.jsp。它们之间的关系是,当用户在登录页面login.jsp填上用户名和密码后并提交后,系统将检查用户是否已经注册,如果该用户已经注册,系统将进入主页面main.jsp,否则就进入注册页面register.jsp。
当用户按下login.jsp页面上的“登录”按钮后,系统就把请求传给一个叫做loginServlet的Servlet。以做进一步处理。
login.jsp:
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<body>
<FORM name="form" action="loginservlet" method="get">
<P> 用户名:
<INPUT type="text" name="username" size="15">
</P><P> 密 码: <INPUT type="password" name="password" size="15">
</P><P>
<INPUT type="submit" name="submit" value="登录"></P><P>
</P>
</FORM>
</body>
</html>
当用户登录成功后,系统转入main.jsp,告诉用户已经登录成功,现已进入主页面。
main.jsp:
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>My JSP 'main.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">
</head>
<body>
<h1>
<%=session.getAttribute("username")%>,你成功登录,现已进入主页面!
</h1>
</body>
</html>
当用户登录失败后,系统转入register.jsp,告诉用户登录失败,现已进入注册页面,请注册用户信息。
register.jsp:
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>My JSP 'register.jsp' starting page</title>
</head>
<body>
<H1>
<%=session.getAttribute("username")%>,你未能成功登录,现进入注册页面,请注册你的信息!
</H1>
</body>
</html>
本例的控制器组件是一个Servlet,叫做loginServlet,该组件先处理HTTP POST请求,然后调用模型组件或业务逻辑组件loginHandler检查该用户是否已注册,如果已注册,系统转入主页面main.jsp,否则进入注册页面register.jsp,要求用户注册自己的信息。另外,Servlet都要在web.xml中声明。
loginServlet.java:
package chap1;
import javax.servlet.*;
import javax.servlet.http.*;
import java.io.*;
import java.util.*;
public class LoginServlet extends HttpServlet{
private static final long serialVersionUID = 2674925070582791853L;
//初始化Servlet
public void init() throws ServletException{
}
//处理HTTP POST请求
public void doPost(HttpServletRequest request,HttpServletResponse response)
throws ServletException,IOException{
//从请求中取出用户名和密码的值
String username=request.getParameter("username");
String password=request.getParameter("password");
//生成一个ArrayList对象,并把用户名和密码的值存入该对象中
ArrayList arr=new ArrayList();
arr.add(username);
arr.add(password);
//生成一个Session对象
HttpSession session=request.getSession(true);
session.removeAttribute("username");
session.setAttribute("username",username);
//调用模型组件loginHandler,检查该用户是否已注册
LoginHandler login=new LoginHandler();
boolean mark=login.checkLogin(arr);
//如果已经注册,进入主页面
if(mark) response.sendRedirect("main.jsp");
//如果未注册,进入注册页面
else response.sendRedirect("register.jsp");
}
//处理HTTP GET请求
public void doGet(HttpServletRequest request,HttpServletResponse response)
throws ServletException,IOException{
doPost(request,response);
}
//销毁Servlet
public void destroy(){
}
}
web.xml:
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
<servlet>
<servlet-name>loginservlet</servlet-name>
<servlet-class>chap1.LoginServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>loginservlet</servlet-name>
<url-pattern>/loginservlet</url-pattern>
</servlet-mapping>
</web-app>
本例的模型组件(或称为业务逻辑组件)是loginHandler,它先从数据访问组件dbPool取得数据库连接,然后检查数据库中是否已有该用户的记录,即检查还用户是否已经注册。如果已注册,返回true,否则返回false。
loginHandler.java:
package chap1;
import java.sql.*;
import java.util.*;
public class LoginHandler {
public LoginHandler() { }
Connection conn;
PreparedStatement ps;
ResultSet rs;
//检查是否已注册
public boolean checkLogin(ArrayList arr)
{
//从数据访问组件dbPool中取得连接
try{
conn=DbPool.getConnection();
String name=(String)arr.get(0);
String password=(String)arr.get(1);
String sql="select * from test where username=? and password=?";
ps=conn.prepareStatement(sql);
ps.setString(1,name);
ps.setString(2,password);
rs=ps.executeQuery();
if(rs.next()){
DbPool.dbClose(conn,ps,rs); //释放资源
return true;
}
else{
DbPool.dbClose(conn,ps,rs);
return false;
}
}catch(SQLException e){
System.out.print("SQLException"+e.getMessage());
return false;
}
}
}
本例的数据库访问组件是dbPool,dbPool从一个属性文件db.properties中获得数据库驱动程序,URL,用户名和密码,然后利用这些信息连接一数据库,取得连接。因为所用数据库是SQL Server,数据库驱动程序采用com.microsoft.jdbc.sqlserver.SQLServerDriver,数据库URL为jdbc:microsoft:sqlserver://localhost:1433;DatabaseName=test;本例需要把数据库驱动程序(3个jar包)放在lib目录下。
DbPool.java:
package chap1;
import java.io.*;
import java.util.*;
import java.sql.*;
public class DbPool {
private static DbPool instance=null;
//取得连接
public static synchronized Connection getConnection(){ //多线程.
if(instance == null){
instance = new DbPool();
}
return instance._getConnection();
}
private DbPool()
{
super();
}
private Connection _getConnection(){
try{
String sDBDriver=null;
String sConnection=null;
String sUser=null;
String sPassword=null;
Properties p=new Properties();
InputStream is=getClass().getResourceAsStream("/db.properties");
p.load(is);
sDBDriver=p.getProperty("DBDriver",sDBDriver);
sConnection=p.getProperty("Connection",sConnection);
sUser=p.getProperty("User",sUser);
sPassword=p.getProperty("Password",sPassword);
Properties pr=new Properties();
pr.put("user",sUser);
pr.put("password",sPassword);
pr.put("characterEncoding","GB2312");
pr.put("userUnicode","TRUE");
Class.forName(sDBDriver).newInstance();
return DriverManager.getConnection(sConnection, pr);
}
catch(Exception se){
System.out.println(se.getMessage());
return null;
}
}
//释放资源
public static void dbClose(Connection conn,PreparedStatement ps,ResultSet rs)
throws SQLException
{
rs.close();
ps.close();
conn.close();
}
}
db.properties:
DBDriver=com.microsoft.jdbc.sqlserver.SQLServerDriver
Connection=jdbc:microsoft:sqlserver://localhost:1433;DatabaseName=test;
User=sa
Password=sa
编译loginServlet.java时,需要引用javax.servlet和javax.servlet.http两个软件包。Sun的JDK一般不包含这两个软件包。这两个软件包包含在servlet.jar中。因此在编译servlet时,需要引用servlet.jar。假如servlet.jar放在d:\library目录中,servlet程序放在d:\login目录中,要用javac编译servlet程序,则编译命令如下:
D:\javac -classpath "d:\library\servlet.jar" login\*.java
在实际的运行中,有一些细节是需要注意的,我将jsp文件放在了一个文件夹jsp中,所以遇到了一些问题:
1.jsp页面中action属性是与url-pattern对应的,程序首先与url-pattern对应,然后通过映射找到实际的servlet类。
2.jsp页面中action属性内容中如果含有“/”,例如:action="/login",则系统将在webapps目录下开始查找对应的servlet类,如果不含有,则从本工程目录下查找servlet类。