用戶登陸的實現
看到題目,您一定覺得很土,Struts早已風靡,而關於Stuts的文章也早已遍地都是,假如你覺得土那你就別看了,我只是把我這段時間學到的一些比較膚淺知識在這裡記錄一下,假如您真在這些連載文章中獲得了您想要的知識,那麼我就會很欣慰了。import javax.servlet.http.HttpServletRequest;
import org.apache.struts.action.*;
public class LoginForm extends ActionForm
{
private static final long serialVersionUID = 1L;
private String user = null;
private String password = null;
public String getPassword()
{
return password;
}
public void setPassword( String password )
{
this.password = password;
}
public String getUser()
{
return user;
}
public void setUser( String user )
{
this.user = user;
}
public void reset(ActionMapping mapping,HttpServletRequest request)
{
this.password = null;這裡很重要,當用戶輸入有錯時,需要返回登陸界面給用戶,為了用戶填寫方便我們可以設置返回給用戶的哪部分信息設置為空
}
}
我用來實現登陸的DispatchAction代碼如下:
public ActionForward login( ActionMapping mapping, ActionForm form,
HttpServletRequest req, HttpServletResponse res ) throws Exception
{
Service service = getService();調用業務邏輯
LoginForm loginForm = (LoginForm) form;獲取formbean
String user = loginForm.getUser();提取用戶名
Person person = service.getUser( user );從業務邏輯中查找用戶
ActionMessages messages = new ActionMessages();
ActionMessage am;
if ( person == null )假如用戶不存在,我們就返回
{
am = new ActionMessage( "index.jsp.fail.user", user );參數的意義:第一個是主串,而後面的作為arg數組
messages.add( "user", am );把錯誤信息放到errors 屬性為user那裡去顯示
saveErrors( req, messages );
form.reset( mapping, req );假如出現錯誤,調用formbean的重置功能
return mapping.findForward( ID.FAIL );
}
if ( !person.getPassword().equals( loginForm.getPassword() ) )假如密碼不一致
{
am = new ActionMessage( "index.jsp.fail.password", user );
messages.add( "password", am );
saveErrors( req, messages );
form.reset( mapping, req );
return mapping.findForward( ID.FAIL );
}
setSessionObject( req, person.getType(), person );把用戶放到session裡
return new ActionForward( person.getType() + ".do", true );我在每個類型用戶的類中加入了一個getType來在這裡調用,之後動態的去對應的admin.do,student.do,teacher.do的主頁面,並且這裡實現的不是請求轉發,而是請求從定向
}
整體結構
為了讓大家更方便的了解我這個設計,我先把我的一些整體的規劃都說出來吧,由於我是初學,難免會參照本書籍來看,我買的是那本孫某女的書《精通:*****》,看了看她前面的介紹,我一看了不得,能出書,寫的還都不錯,這女的可不得了,漸漸迷惑的地方非常多,比如例子裡面注釋都拽上了英語,搞不懂,而當我從網上下到電子盜版jakarta struts(我已安下栽說明要求的那樣在24小時後刪除了)這本書的時候我才恍然大悟,原來是抄襲啊?至於是誰抄的誰,口說無憑,不能亂誹謗,不過大家心裡都該有桿稱!
下面就是代碼了:
package com.boya.subject.model;
public interface Person
{
public Long getId();
public void setId( Long id );
public String getName();
public void setName( String name );
public String getPassword();
public void setPassword( String password );
public String getTelphone();
public void setTelphone( String telphone );
public String getUser();
public void setUser( String user );
public String getType();
}
package com.boya.subject.model;
public abstract class User implements Person
{
private Long id;數據庫id
private String user;用戶名
private String password;密碼
private String name;姓名
private String telphone;電話
public Long getId()
{
return id;
}
public void setId( Long id )
{
this.id = id;
}
public String getName()
{
return name;
}
public void setName( String name )
{
this.name = name;
}
public String getPassword()
{
return password;
}
public void setPassword( String password )
{
this.password = password;
}
public String getTelphone()
{
return telphone;
}
public void setTelphone( String telphone )
{
this.telphone = telphone;
}
public String getUser()
{
return user;
}
public void setUser( String user )
{
this.user = user;
}
}
package com.boya.subject.model;
public class Admin extends User
{
private String grade = null; 治理員權限
public String getGrade()
{
return grade;
}
public void setGrade( String grade )
{
this.grade = grade;
}
public String getType()
{
return "admin";
}
}
package com.boya.subject.model;
public class Teacher extends User
{
private String level; 教師職稱
public String getLevel()
{
return level;
}
public void setLevel( String level )
{
this.level = level;
}
public String getType()
{
return "teacher";
}
}
package com.boya.subject.model;
public class Student extends User
{
private String sn;學生學號
private SchoolClass schoolClass; 班級
public SchoolClass getSchoolClass()
{
return schoolClass;
}
public void setSchoolClass( SchoolClass schoolClass )
{
this.schoolClass = schoolClass;
}
public String getSn()
{
return sn;
}
public void setSn( String sn )
{
this.sn = sn;
}
public String getType()
{
return "student";
}
}
而對於Action我分別做了一個抽象類,之後別的從這裡繼續
先是Action的
package com.boya.subject.controller;
import java.io.IOException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.apache.struts.action.Action;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;
import com.boya.subject.frame.ID;
import com.boya.subject.frame.ServiceFactory;
import com.boya.subject.model.Person;
import com.boya.subject.service.Service;
import com.boya.subject.util.HtmlUtil;
public abstract class BaseAction extends Action
{
/**
* 由服務工廠方法創建服務
* @return 數據庫操作的服務
* 2006-5-16 18:10:04
*/
public Service getService()
{
ServiceFactory factory = (ServiceFactory) getAppObject( ID.SF );
Service service = null;
try
{
service = factory.createService();
}
catch ( Exception e )
{
}
return service;
}
/**
* 判定用戶是否合法登陸
* @param req
* @return 用戶是否登陸
* 2006-5-16 18:11:26
*/
public boolean isLogin( HttpServletRequest req )
{
if ( getPerson( req ) != null ) return true;
else
return false;
}
/**
* 抽象方法,子類實現
* @param mapping
* @param form
* @param req
* @param res
* @return
* @throws Exception
* 2006-5-16 18:12:54
*/
protected abstract ActionForward executeAction( ActionMapping mapping,
ActionForm form, HttpServletRequest req, HttpServletResponse res )
throws Exception;
/**
* 獲取session范圍的用戶
* @param req
* @return 當前用戶
* 2006-5-16 18:13:35
*/
public abstract Person getPerson( HttpServletRequest req );
/**
* 父類的執行Action
* @see org.apache.struts.action.Action#execute(org.apache.struts.action.ActionMapping, org.apache.struts.action.ActionForm, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
*/
public ActionForward execute( ActionMapping mapping, ActionForm form,
HttpServletRequest req, HttpServletResponse res ) throws Exception
{
if ( !isLogin( req ) )
{
HtmlUtil.callParentGo( res.getWriter(), ID.M_UNLOGIN, ID.P_INDEX );
return null;
}
return executeAction( mapping, form, req, res );
}
/**
* 刪除session中屬性為attribute的對象
* @param req
* @param attribute 對象屬性
* 2006-5-16 18:16:59
*/
public void removeSessionObject( HttpServletRequest req, String attribute )
{
HttpSession session = req.getSession();
session.removeAttribute( attribute );
}
/**
* 設置session中屬性為attribute的對象
* @param req
* @param attribute 設置屬性
* @param o 設置對象
* 2006-5-16 18:17:50
*/
public void setSessionObject( HttpServletRequest req, String attribute,
Object o )
{
req.getSession().setAttribute( attribute, o );
}
/**
* 設置application中屬性為attribute的對象
* @param req
* @param attribute 設置屬性
* @param o 設置對象
* 2006-5-16 18:17:50
*/
public void setAppObject( String attribute, Object o )
{
servlet.getServletContext().setAttribute( attribute, o );
}
public Object getSessionObject( HttpServletRequest req, String attribute )
{
Object obj = null;
HttpSession session = req.getSession( false );
if ( session != null ) obj = session.getAttribute( attribute );
return obj;
}
public Object getAppObject( String attribute )
{
return servlet.getServletContext().getAttribute( attribute );
}
public void callParentGo( HttpServletResponse res, String msg, String url )
throws IOException
{
HtmlUtil.callParentGo( res.getWriter(), msg, url );
}
public void callMeGo( HttpServletResponse res, String msg, String url )
throws IOException
{
HtmlUtil.callMeGo( res.getWriter(), msg, url );
}
public void callBack( HttpServletResponse res, String msg )
throws IOException
{
HtmlUtil.callBack( res.getWriter(), msg );
}
public void callMeConfirm( HttpServletResponse res, String msg, String ok,
String no ) throws IOException
{
HtmlUtil.callMeConfirm( res.getWriter(), msg, ok, no );
}
}
再是DispatchAction的
package com.boya.subject.controller;
import java.io.IOException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;
import org.apache.struts.actions.DispatchAction;
import com.boya.subject.frame.ID;
import com.boya.subject.frame.ServiceFactory;
import com.boya.subject.model.Person;
import com.boya.subject.service.Service;
import com.boya.subject.util.HtmlUtil;
public abstract class BaseDispatchAction extends DispatchAction
{
/**
* 由服務工廠方法創建服務
* @return 數據庫操作的服務
* 2006-5-16 18:10:04
*/
public Service getService()
{
ServiceFactory factory = (ServiceFactory) getAppObject( ID.SF );
Service service = null;
try
{
service = factory.createService();
}
catch ( Exception e )
{
}
return service;
}
/**
* 判定用戶是否合法登陸
* @param req
* @return 用戶是否登陸
* 2006-5-16 18:11:26
*/
public boolean isLogin( HttpServletRequest req )
{
if ( getPerson( req ) != null ) return true;
else
return false;
}
/**
* 獲取session范圍的用戶
* @param req
* @return 當前用戶
* 2006-5-16 18:13:35
*/
public abstract Person getPerson( HttpServletRequest req );
/**
* 父類的執行DispatchAction
* @see org.apache.struts.action.Action#execute(org.apache.struts.action.ActionMapping, org.apache.struts.action.ActionForm, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
*/
public ActionForward execute( ActionMapping mapping, ActionForm form,
HttpServletRequest req, HttpServletResponse res ) throws Exception
{
try
{
if ( !isLogin( req ) )
{
callParentGo( res, ID.M_UNLOGIN, ID.P_INDEX );
return null;
}
return super.execute( mapping, form, req, res );
}
catch ( NoSUChMethodException e )
{
callBack( res, ID.M_NOMETHOD );
return null;
}
}
/**
* 刪除session中屬性為attribute的對象
* @param req
* @param attribute 對象屬性
* 2006-5-16 18:16:59
*/
public void removeSessionObject( HttpServletRequest req, String attribute )
{
HttpSession session = req.getSession();
session.removeAttribute( attribute );
}
/**
* 設置session中屬性為attribute的對象
* @param req
* @param attribute 設置屬性
* @param o 設置對象
* 2006-5-16 18:17:50
*/
public void setSessionObject( HttpServletRequest req, String attribute,
Object o )
{
req.getSession().setAttribute( attribute, o );
}
/**
* 設置application中屬性為attribute的對象
* @param req
* @param attribute 設置屬性
* @param o 設置對象
* 2006-5-16 18:17:50
*/
public void setAppObject( String attribute, Object o )
{
servlet.getServletContext().setAttribute( attribute, o );
}
public Object getSessionObject( HttpServletRequest req, String attribute )
{
Object obj = null;
HttpSession session = req.getSession( false );
if ( session != null ) obj = session.getAttribute( attribute );
return obj;
}
public Object getAppObject( String attribute )
{
return servlet.getServletContext().getAttribute( attribute );
}
public void callParentGo( HttpServletResponse res, String msg, String url )
throws IOException
{
HtmlUtil.callParentGo( res.getWriter(), msg, url );
}
public void callMeGo( HttpServletResponse res, String msg, String url )
throws IOException
{
HtmlUtil.callMeGo( res.getWriter(), msg, url );
}
public void callBack( HttpServletResponse res, String msg )
throws IOException
{
HtmlUtil.callBack( res.getWriter(), msg );
}
public void callMeConfirm( HttpServletResponse res, String msg, String ok,
String no ) throws IOException
{
HtmlUtil.callMeConfirm( res.getWriter(), msg, ok, no );
}
}
對於程序中的一些提示信息,我比較喜歡用JS來寫,所以我把這些都放到了一個類中
import java.io.IOException;
import java.io.Writer;
public class HtmlUtil
{
public static void callParentGo( Writer out, String msg, String url )
throws IOException
{
out.write( " " );
}
public static void callMeGo( Writer out, String msg, String url )
throws IOException
{
out.write( " " );
}
public static void callMeConfirm( Writer out, String msg ,String ok, String no )
throws IOException
{
out.write( " " );
}
public static void callBack( Writer out, String msg ) throws IOException
{
out.write( " " );
}
}
接著上次的話題,下面的就是學生注冊時需要的學院,專業,班級,三層列表,
學院:
專業:
班級:
學院是上來就應該有的,我們把他放到了LabelValueBean裡
public Vector
{
Connection connection = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
try
{
connection = getConnection();
pstmt = connection.prepareStatement( "select * from institute" );
rs = pstmt.executeQuery();
Vector
institutes.add( new LabelValueBean( "請選擇所在學院", "" ) );
while ( rs.next() )
{
institutes.add( new LabelValueBean(
rs.getString( "institute" ), rs.getString( "id" ) ) );
}
return institutes;
}
catch ( Exception e )
{
e.printStackTrace();
}
finally
{
close( rs );
close( pstmt );
close( connection );
}
return null;
}
而當它選擇了一個學院後,相應的getDepartments(this.value)的js腳本就該工作了,還是四步
var xmlHttp;
function createXMLHttpRequest()
{
if (window.XMLHttpRequest)
{
xmlHttp = new XMLHttpRequest();
}
else if (window.ActiveXObject)
{
xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
}
}
發出請求
function getDepartments(institute)
{
createXMLHttpRequest()
var url = "ajax.do?institute="+institute+"&method=getDepartments"
xmlHttp.open("GET",url, true)
xmlHttp.onreadystatechange = departments
xmlHttp.send(null)
}
處理響應
function departments()
{
if (xmlHttp.readyState == 4)
{
if (xmlHttp.status == 200)
{
resText = xmlHttp.responseText
each = resText.split("")
buildSelect( each, document.getElementById("departmentId"), "請選擇所在專業");
}
}
}
function buildSelect(str,sel,label)
{
sel.options.length=0;
sel.options[sel.options.length]=new Option(label,"")
for(var i=0;i
each=str[i].split(",")
sel.options[sel.options.length]=new Option(each[0],each[1])
}
}
我把從數據庫中得到的各個專業進行了編碼,之後再這裡再回歸回去,下面的是編碼過程
public StringBuffer getDepartmentsByInstituteIdForAjax( Long instituteId )
{
Connection connection = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
try
{
connection = getConnection();
pstmt = connection
.prepareStatement( "select * from department where instituteID=?" );
pstmt.setLong( 1, instituteId );
rs = pstmt.executeQuery();
StringBuffer sb = new StringBuffer();
while ( rs.next() )
{
sb.append( rs.getString( "department" ) + ","
+ rs.getLong( "id" ) );
if ( !rs.isLast() ) sb.append( "" );
}
return sb;
}
catch ( Exception e )
{
e.printStackTrace();
}
finally
{
close( rs );
close( pstmt );
close( connection );
}
return null;
}
當然這些都是由
public ActionForward getDepartments( ActionMapping mapping,
ActionForm form, HttpServletRequest req, HttpServletResponse res )
throws Exception
{
Service service = getService();
res.getWriter().write(
service.getDepartmentsByInstituteIdForAjax(
Long.parseLong( req.getParameter( "institute" ) ) )
.toString() );
return null;
}
來控制
===========班級的再這裡
public ActionForward getClasses( ActionMapping mapping, ActionForm form,
HttpServletRequest req, HttpServletResponse res ) throws Exception
{
Service service = getService();
res.getWriter().write(
service.getClassesByDepartmentIdForAjax(
Long.parseLong( req.getParameter( "department" ) ) )
.toString() );
return null;
}
public StringBuffer getClassesByDepartmentIdForAjax( Long departmentId )
{
Connection connection = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
try
{
connection = getConnection();
pstmt = connection
.prepareStatement( "select * from class where departmentID=?" );
pstmt.setLong( 1, departmentId );
rs = pstmt.executeQuery();
StringBuffer sb = new StringBuffer();
while ( rs.next() )
{
sb.append( rs.getString( "class" ) + "," + rs.getLong( "id" ) );
if ( !rs.isLast() ) sb.append( "" );
}
return sb;
}
catch ( Exception e )
{
e.printStackTrace();
}
finally
{
close( rs );
close( pstmt );
close( connection );
}
return null;
}
function getClasses(department)
{
createXMLHttpRequest()
var url = "ajax.do?department="+department+"&method=getClasses"
xmlHttp.open("GET",url, true)
xmlHttp.onreadystatechange = classes
xmlHttp.send(null)
}
function classes()
{
if (xmlHttp.readyState == 4)
{
if (xmlHttp.status == 200)
{
resText = xmlHttp.responseText
each = resText.split("")
buildSelect( each, document.getElementById("classid"), "請選擇所在班級");
}
}
}
大家都知道Struts是一種基於MVC的結構,而這個MVC又怎麼樣理解呢?書上闡述的一般都很具體,而我的理解很直白,我們可以把業務邏輯放到每個JSP頁面中,當你訪問一個JSP頁面的時候,就可以看到業務邏輯得到的結果,而把這些業務邏輯與HTML代碼夾雜到了一起,一定會造成一些不必要的麻煩,可以不可以不讓我們的業務邏輯和那些HTML代碼夾雜到一起呢?多少得攙雜一些,那干脆,盡量少的吧,於是我們可以嘗試著把業務邏輯的運算過程放到一個Action裡,我們訪問這個Action,之後Action執行業務邏輯,最後把業務邏輯的結果放到request中,並將頁面請求轉發給一個用於顯示結果的jsp頁面,這樣,這個頁面就可以少去很多的業務邏輯,而只是單純的去顯示一些業務邏輯計算結果的頁面而已。這時的Action稱為控制器,JSP頁可以叫做視圖了,而控制器操作的業務對象,無非就應該叫模型了!
從上面的話,我們來分析一下當我們要做一個分頁時所需要的部分,而在這之前,我們先看看他們的執行過程吧,首先我們第一次請求訪問一個頁面,它會把所有記錄的前N條顯示給我們,之後計算是否有下一頁,等類似的信息,當我們點下一頁的時候,就獲取下一頁的信息,我們還可以添加一個搜索,比如我們用於顯示學生的,可以安學生姓名查找,學號查找,班級查找。而對於顯示的對象,我們一般也都會封裝為javabean,所以用於放置查詢結果的容器是不定的,而這時,我們就需要用泛型來提升我們的代碼效率!
首先我們寫一個用於分頁顯示的javabean:
package com.boya.subject.model;
import java.util.Vector;
public class Page
{
private int current = 1; //當前頁
private int total = 0; //總記錄數
private int pages = 0; //總頁數
private int each = 5; //每頁顯示
private int start = 0; //每頁顯示的開始記錄數
private int end = 0; //每頁顯示的結束記錄數
private boolean next = false; //是否有下一頁
private boolean previous = false; //是否有上一頁
private Vector
public Page( Vector
{
this.v = v;
each = per;
total = v.size(); //容器的大小就是總的記錄數
if ( total % each == 0 )
pages = total / each; //計算總頁數
else
pages = total / each + 1;
if ( current >= pages )
{
next = false;
}
else
{
next = true;
}
if ( total < each )
{
start = 0;