例1-4
用JSP、Servlet及JavaBeans構(gòu)建一個簡單的登陸系統(tǒng)。該系統(tǒng)的要求是,當用戶在登陸錄頁面上填寫用戶名和密碼并提交之后,系統(tǒng)將檢查該用戶是否已經(jīng)注冊;如果該用戶已經(jīng)注冊,系統(tǒng)將進入主頁面,否則就進入注冊頁面。我們將按照以下步驟構(gòu)建這個系統(tǒng):
1.數(shù)據(jù)庫設計:使用MS Access作為數(shù)據(jù)庫,構(gòu)建數(shù)據(jù)表T_UserInfo;
2.構(gòu)建視圖組件:登錄頁面login.jsp,主頁面main.jsp,以及注冊頁面register.jsp;
3.構(gòu)建控制層組件:一個Servlet,取名為loginServlet.java;
4.構(gòu)建業(yè)務邏輯層組件(Model組件):一個JavaBean,取名為loginHandler.java;
5.構(gòu)建數(shù)據(jù)訪問層組件:一個數(shù)據(jù)訪問類,取名為dbPool,java;
6.編譯、打包程序;
7.部署該程序到Web服務器Tomcat中,然后運行。
該系統(tǒng)的工作流程如圖:
1.數(shù)據(jù)庫設計
用戶登錄是一個涉及數(shù)據(jù)庫操作的用例。登錄涉及的數(shù)據(jù)表名為test,結(jié)構(gòu)如下:
字段名:username 字段類型:nvarchar(50) 字段描述:用戶名,主鍵
字段名:password 字段類型:nvarchar(50) 字段描述:密碼
2.構(gòu)建視圖組件
本例有3個視圖組件,分別是登錄頁面login.jsp,主頁面main.jsp及注冊頁面register.jsp。它們之間的關系是,當用戶在登錄頁面login.jsp填上用戶名和密碼后并提交后,系統(tǒng)將檢查用戶是否已經(jīng)注冊,如果該用戶已經(jīng)注冊,系統(tǒng)將進入主頁面main.jsp,否則就進入注冊頁面register.jsp。
當用戶按下login.jsp頁面上的“登錄”按鈕后,系統(tǒng)就把請求傳給一個叫做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>
當用戶登錄成功后,系統(tǒng)轉(zhuǎn)入main.jsp,告訴用戶已經(jīng)登錄成功,現(xiàn)已進入主頁面。
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")%>,你成功登錄,現(xiàn)已進入主頁面!
</h1>
</body>
</html>
當用戶登錄失敗后,系統(tǒng)轉(zhuǎn)入register.jsp,告訴用戶登錄失敗,現(xiàn)已進入注冊頁面,請注冊用戶信息。
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")%>,你未能成功登錄,現(xiàn)進入注冊頁面,請注冊你的信息!
</H1>
</body>
</html>
本例的控制器組件是一個Servlet,叫做loginServlet,該組件先處理HTTP POST請求,然后調(diào)用模型組件或業(yè)務邏輯組件loginHandler檢查該用戶是否已注冊,如果已注冊,系統(tǒng)轉(zhuǎn)入主頁面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);
//調(diào)用模型組件loginHandler,檢查該用戶是否已注冊
LoginHandler login=new LoginHandler();
boolean mark=login.checkLogin(arr);
//如果已經(jīng)注冊,進入主頁面
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 <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>
本例的模型組件(或稱為業(yè)務邏輯組件)是loginHandler,它先從數(shù)據(jù)訪問組件dbPool取得數(shù)據(jù)庫連接,然后檢查數(shù)據(jù)庫中是否已有該用戶的記錄,即檢查還用戶是否已經(jīng)注冊。如果已注冊,返回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)
{
//從數(shù)據(jù)訪問組件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;
}
}
}
本例的數(shù)據(jù)庫訪問組件是dbPool,dbPool從一個屬性文件db.properties中獲得數(shù)據(jù)庫驅(qū)動程序,URL,用戶名和密碼,然后利用這些信息連接一數(shù)據(jù)庫,取得連接。因為所用數(shù)據(jù)庫是SQL Server,數(shù)據(jù)庫驅(qū)動程序采用com.microsoft.jdbc.sqlserver.SQLServerDriver,數(shù)據(jù)庫URL為jdbc:microsoft:sqlserver://localhost:1433;DatabaseName=test;本例需要把數(shù)據(jù)庫驅(qū)動程序(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
在實際的運行中,有一些細節(jié)是需要注意的,我將jsp文件放在了一個文件夾jsp中,所以遇到了一些問題:
1.jsp頁面中action屬性是與url-pattern對應的,程序首先與url-pattern對應,然后通過映射找到實際的servlet類。
2.jsp頁面中action屬性內(nèi)容中如果含有“/”,例如:action="/login",則系統(tǒng)將在webapps目錄下開始查找對應的servlet類,如果不含有,則從本工程目錄下查找servlet類。