分享
 
 
 

开源技术——体验Struts

王朝other·作者佚名  2008-05-31
窄屏简体版  字體: |||超大  

用户登陆的实现

看到题目,您一定觉得很土,Struts早已风靡,而关于Stuts的文章也早已遍地都是,假如你觉得土那你就别看了,我只是把我这段时间学到的一些比较肤浅知识在这里记录一下,假如您真在这些连载文章中获得了您想要的知识,那么我就会很欣慰了。

这不快毕业了吗?我选的题目就和Struts有关,做一个关于学校的毕业设计选题系统,就是B/S结构,访问数据库的一些俗套的东西,为了巩固我这段时间学习Struts,我把这个系统竟往难里做,这样对我这个动手能力差的人,实际工作经验少的人来说,会有点帮助吧?

当初就是这样想的,所以就开始了我的Struts之旅。

那我就从我的第一页讲起吧,当然第一页一般都是登陆,至于怎么配置Struts,您还是参考一些别人的文章吧,我觉得写这些就够土的了,写怎么配置,怎么实现就更土!

这句是生成验证登陆表单所需要的js代码

用户名:

密码:

onclick="window.location='ajax.do?method=register'" value="注册"/>

把控制格式的HTML删除掉,应该剩下这些就是主干了,对于这个毕业设计选题系统,有三种角色,治理员(Admin),教师(Teacher),学生(Student)而我把他们的登陆都做到了一起,在后台这三种角色也是都放在了一个表中,对于他们这三种对象,都是继续于Person的类,所以在登陆时可以忽视他们的具体角色,用多态来实现登陆。

action="/ajax.do?method=login" :将一些关于登陆啊,注册的一些乱七八糟的操作我都放到了一个DispatchAction,之后可以用method的不同来分别调用不同的功能。

onsubmit="return validateLoginForm(this)":这个是用来实现Struts自带的validate验证

:是用来显示在登陆时的错误信息

在这里需要的Struts相关配置会有如下的几个方面:

首先是要对配置文件进行配置我们登陆时需要的FormBean和Action

(1)struts-config.XML:

对于登陆失败,我们预备返回到这里

(2)validation.xml:

user

^[0-9a-zA-Z]*$

这里是常量配置,因为我们还会需要到用户名的验证,所以把他设置为了常量

下面是对这个bean的具体严整手段了,按字段field分别来写他们所依靠depaends的检验手段,常用的有必须填required,正则表达式验证mask,最大maxlength和最小minlength

从application.properties里读取input.user.mask

从application.properties里读取input.user

以上三部分构成了js的一条错误提示,以下是具体的严整规则了

mask

${user}

minlength

1

maxlength

16

depends="required,mask,minlength,maxlength">

resource="false" />

resource="false" />

mask

${password}

minlength

1

maxlength

16

对于我们需要的FormBean是这样写的:

package com.boya.subject.view;

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( " " );

}

}

加上点ajax

你问我什么叫ajax,我也不太了解,我了解的是那支培养了无数荷兰足球精华的Ajax,谁知道怎么有人用几个单词的头字母也能凑出这个单词来,不过感觉用它来做东西,应该会挺有意思的

比如当用户在注册的时候,用户点一个按纽不用刷新界面就可以获得一句提示,是有这人还是没有这人啊?这次我尝试了用ajax技术来做一个三级要害的下拉列表,而这是我要讲的要害。

其实现在一般的ajax都是向Servlet发出请求,之后服务器响应,再偷摸的把结果传给它,之后显示出来,而换到Struts,有人会发甍,也一样,Action是Servlet,DispatchAction也是,只要把代码往这里写,让它往.do那里请求就行了。

在接下来我就向大家介绍我是怎样实现上述功能的

因为大学里面的结构是这里的

学院-专业-班级-学生

在学生注册的时候他是依靠于上述对象的,所以用户注册就需要一个三级的下拉选择

而ajax就能象变魔术一样,从服务器那里偷摸弄来您需要的列表

下面我先给大家展示一下第一个功能是怎么实现的吧?

当用户在注册的时候,点一个按纽,之后会弹出一个alert来告诉你这个用户是否有人用了,下面就让我们来看看这个功能是怎么实现的吧?

这里定义了按纽,用来测试老师是否已经存在了

大体的ajax的JS代码都上面这四部分,

先是创建XMLHttpRequest,

var xmlHttp;

function createXMLHttpRequest()

{

if (window.XMLHttpRequest)

{

xmlHttp = new XMLHttpRequest();

}

else if (window.ActiveXObject)

{

xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");

}

}

之后是客户响应部分的代码

function teacherCheck()

{

var f = document.TeacherRegisterForm 从表单里读字段

var user = f.user.value

if(user=="")

{

window.alert("用户名不能为空!")

f.user.focus()

return false

}

else

{

createXMLHttpRequest() 这里都是精华了

var url = "ajax.do?method=checkUserIsExist&user="+user 定义响应地址

xmlHttp.open("GET",url, true) 发出响应

xmlHttp.onreadystatechange = checkUser 把从服务器得到的响应再传给另个函数

xmlHttp.send(null)

}

}

function checkUser()

{

if (xmlHttp.readyState == 4)

{

if (xmlHttp.status == 200)

{

alert(xmlHttp.responseText) 这里是对响应结果的操作,在这里我们是滩出对话框,并把服务器发来的信息显示出来

}

}

}

我把所有乱七八糟的操作都放到了一个DispatchAction里,所以它也不例外的在这个DA中了

public ActionForward checkUserIsExist( ActionMapping mapping,

ActionForm form, HttpServletRequest req, HttpServletResponse res )

throws Exception

{

Service service = getService();

res.getWriter().write(service.checkUserIsExistForAjax( req.getParameter( "user" ) ) );

return null;

}

它仅仅是把业务逻辑部分的结果发送回去,而真正的判定是在业务逻辑那里实现的,

public String checkUserIsExistForAjax( String user )把结果弄成String的形式传回去

{

Connection connection = null;

PreparedStatement pstmt1 = null;

ResultSet rs = null;

try

{

connection = getConnection();

pstmt1 = connection

.prepareStatement( "select * from user where user=?" );

pstmt1.setString( 1, user );

rs = pstmt1.executeQuery();

rs.last();

if ( rs.getRow() > 0 )

{

return ID.M_EXIST; 用户存在

}

}

catch ( Exception e )

{

e.printStackTrace();

}

finally

{

close( rs );

close( pstmt1 );

close( connection );

}

return ID.M_NOEXIST;用户不存在

}

用ajax实现三级下拉列表

接着上次的话题,下面的就是学生注册时需要的学院,专业,班级,三层列表,

学院:

专业:

班级:

学院是上来就应该有的,我们把他放到了LabelValueBean里

public Vector getInstitutes()

{

Connection connection = null;

PreparedStatement pstmt = null;

ResultSet rs = null;

try

{

connection = getConnection();

pstmt = connection.prepareStatement( "select * from institute" );

rs = pstmt.executeQuery();

Vector institutes = new 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"), "请选择所在班级");

}

}

}

从分页体会MVC

大家都知道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 v = null; //存放查询结果的容器

public Page( Vector v ,int per)

{

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;

end = total;

}

else

{

start = 0;

end = each;

}

}

public int getCurrent()

{

return current;

}

public void setCurrent( int current )

{

this.current = current;

}

public int getEach()

{

return each;

}

public void setEach( int each )

{

this.each = each;

}

public boolean isNext()

{

return next;

}

public void setNext( boolean next )

{

this.next = next;

}

public boolean isPrevious()

{

return previous;

}

public void setPrevious( boolean previous )

{

this.previous = previous;

}

public int getEnd()

{

return end;

}

public int getPages()

{

return pages;

}

public int getStart()

{

return start;

}

public int getTotal()

{

return total;

}

//获取下一页的对象们

public Vector getNextPage()

{

current = current + 1;

if ( (current - 1) > 0 )

{

previous = true;

}

else

{

previous = false;

}

if ( current >= pages )

{

next = false;

}

else

{

next = true;

}

Vector os = gets();

return os;

}

//获取上一页

public Vector getPreviouspage()

{

current = current - 1;

if ( current == 0 )

{

current = 1;

}

if ( current >= pages )

{

next = false;

}

else

{

next = true;

}

if ( (current - 1) > 0 )

{

previous = true;

}

else

{

previous = false;

}

Vector os = gets();

return os;

}

//一开始获取的

public Vector gets()

{

if ( current * each < total )

{

end = current * each;

start = end - each;

}

else

{

end = total;

start = each * (pages - 1);

}

Vector gets = new Vector();

for ( int i = start; i < end; i++ )

{

E o = v.get( i );

gets.add( o );

}

return gets;

}

}

而对于按不同搜索,我们需要一个FormBean,一般的搜索,都是模糊搜索,搜索个大概,而且输入的信息中文的比重也会很大,所以,我把对中文字符的转换放到了这个BEAN里,在进行select * from * where like这样的查询时,假如是like ''这样就可以得到所有的记录了,我便用这个来对付没有输入查询要害字的情况,而like '%*%'可以匹配要害字,而%%也在这里添加上了!

package com.boya.subject.view;

import java.io.UnsupportedEncodingException;

import javax.servlet.http.HttpServletRequest;

import org.apache.struts.action.ActionForm;

import org.apache.struts.action.ActionMapping;

public class SearchForm extends ActionForm

{

private static final long serialVersionUID = 1L;

private String key;

private String from;

public String getFrom()

{

return from;

}

public void setFrom( String from )

{

this.from = from;

}

public void reset( ActionMapping mapping, HttpServletRequest req )

{

this.key = null;

}

public String getKey()

{

return key;

}

public void setKey( String key )

{

try

{

key = new String( key.getBytes( "iso-8859-1" ), "gb2312" );

}

catch ( UnsupportedEncodingException e )

{

e.printStackTrace();

}

this.key = "%" + key + "%";

}

public String getAny(){

return "%%";

}

}

前期都做好了,我现在就要开始访问这个Action了,可是这个控制器还没写呢!这里是代码

public class AdminUserAction extends AdminAction

{

private Vector ss; //用来装结果的容器

private Page ps; //分页显示的PAGE对象

protected ActionForward executeAction( ActionMapping mapping,

ActionForm form, HttpServletRequest req, HttpServletResponse res )

throws Exception

{

if ( !isSupper( req ) )

{

return notSupper( res );//假如不是超级治理员怎么办?

}

Service service = getService();//获取业务逻辑

SearchForm sf = (SearchForm) form;//获取搜索FORM

String op = req.getParameter( "op" );//获取用户对页面的操作

String search = req.getParameter( "search" );//是否执行了搜索

Vector temp = null; //用于存放临时反馈给用户的结果容器

if ( op == null )//假如用户没有执行上/下一页的操作

{

if ( search != null )//用户假如执行了搜索

{

if ( sf.getFrom().equalsIgnoreCase( "class" ) )//假如是按班级查找

{

ss = service.getAllStudentBySchoolClassForAdmin( sf

.getKey() );//获取from的要害字

}

else if ( sf.getFrom().equalsIgnoreCase( "name" ) )//假如是按姓名查找

{

ss = service.getAllStudentByNameForAdmin( sf

.getKey() );

}

else if ( sf.getFrom().equalsIgnoreCase( "user" ) )//假如是按用户名查找

{

ss = service.getAllStudentByUserForAdmin( sf

.getKey() );

}

else

{

ss = service.getAllStudentBySnForAdmin( sf.getKey() );//按学号查找

}

form.reset( mapping, req );//重置搜索表单

}

else

{

ss = service.getAllStudentForAdmin( sf.getAny() ); //用户未执行查找就显示全部,

}

if ( ss != null && ss.size() != 0 )//假如查找不为空,有记录,那就创建一个分页对象

{

ps = new Page( ss, 10 );//将查询结果和每页显示记录数作为参数构件对象

temp = ps.gets();//并获取第一页

}

}

else//假如用户执行了操作

{

if ( op.equals( "next" ) )//操作是下一页

{

temp = ps.getNextPage();

}

if ( op.equals( "previous" ) )//操作是上一页

{

temp = ps.getPreviouspage();

}

}

req.setAttribute( "search", SelectUtil.studentSearch() );//把搜索用到的表单放到request中

req.setAttribute( "students", temp );//该页显示的学生

req.setAttribute( "page", ps );//分页对象

return mapping.findForward( "student" );//请求转发

}

}

用到SelectUtil中的代码如下:

/**

* 获取学生查找类别的select

* @return 学生查找类别

* 2006-5-17 9:06:12

*/

public static Vector studentSearch()

{

Vector s = new Vector();

s.add( new LabelValueBean( "按学号查找", "sn" ) );

s.add( new LabelValueBean( "按班级查找", "class" ) );

s.add( new LabelValueBean( "按姓名查找", "name" ) );

s.add( new LabelValueBean( "按用户查找", "user" ) );

return s;

}

在看页面视图前先让我们看看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";

}

}

在了解了model后,还是看看视图吧,

先放个查询表单:

由于模型中有嵌套,那么我们就将用到Nested标签,其实没有嵌套也可以使用这个标签,下面的是用于显示信息的,用迭迨器进行遍历request范围的students,你不安排范围,他会自动找到的,并把每次遍历的对象起名叫student,并作为层次的根元素,

//寻找了student的schoolClass属性对象的schoolClass嵌套

//student的名字

删除

这里是显示分页对象的:

第页

共页

//上一页是否存在

上一页

上一页

//下一页是否存在

下一页

下一页

共有条数据

到这里不知道您看明白了多少,在我的这个JSP页里几乎没有任何的业务逻辑,这样的设计就比把HTML和JAVA搀杂在一起好了很多。

阻止非法的登陆方式

假如用户直接输入了地址,不也可以直接访问吗?理论上是,我们可以加入session进行跟踪,以杜绝此类型事件发生,我们是不是要把每次对session的判定依次拷到每个页里呢,之后下次需要验证的SESSION换了,我们再换?太浪费了,我的做法是做了一个自定义标签,来解决这个问题。

import javax.servlet.jsp.JspException;

import javax.servlet.jsp.tagext.TagSupport;

public class CheckTag extends TagSupport

{

private static final long serialVersionUID = 879137944441282895L;

private String check = "";//用来验证的变量

private String url = "index.jsp";//出现错误要去的页面

private String msg = "";//错误的提示

private String scope = "";//要严整变量的范围

private String to = "go"; //假如验证失败,是将页面后退,还是定位到哪里?

public String getTo()

{

return to;

}

public void setTo( String to )

{

this.to = to;

}

public String getMsg()

{

return msg;

}

public void setMsg( String msg )

{

this.msg = msg;

}

public String getScope()

{

return scope;

}

public void setScope( String scope )

{

this.scope = scope;

}

public String getCheck()

{

return check;

}

public void setCheck( String check )

{

this.check = check;

}

public String getUrl()

{

return url;

}

public void setUrl( String url )

{

this.url = url;

}

public int doStsrtTag() throws JspException

{

return SKIP_BODY;

}

public int doEndTag() throws JspException

{

boolean valid = false;//先设为不可用

if ( scope.equalsIgnoreCase( "request" ) )//假如要检查request范围

{

valid = CheckUtil.checkRequestAttribute( pageContext.getRequest(),

check );

}

else if ( scope.equalsIgnoreCase( "session" ) )

{

valid = CheckUtil.checkSession( pageContext.getSession(), check );

}

else if ( scope.equalsIgnoreCase( "parameter" ) )

{

valid = CheckUtil.checkParameter( pageContext.getRequest(), check );

}

else if ( scope.equalsIgnoreCase( "application" ) )

{

valid = CheckUtil.checkApp( pageContext.getServletContext(), check );

}

if ( valid ) return EVAL_PAGE;//假如可用就继续执行此页的其余部分

else

{//否则,哈哈

try

{

if ( to.equalsIgnoreCase( "go" ) ) //现在失败了,就看怎么回到你该到的地方

HtmlUtil.callParentGo(

pageContext.getOut(), msg, url );//将浏览器定位到URL

else

HtmlUtil.callBack( pageContext.getOut(), msg );//后退一下页面来阻止

return SKIP_PAGE;//跳过页面的其余部分,不执行

}

catch ( Exception e )

{

throw new JspException( e.toString() );

}

}

}

public void release()

{

super.release();

check = "";

url = "";

msg = "";

scope = "";

}

}

下面是用到的htmlUtil部分:

public static void callParentGo( Writer out, String msg, String url )

throws IOException

{

out.write( " " );

}

public static void callBack( Writer out, String msg ) throws IOException

{

out.write( " " );

}

写个check.tld部署吧,

1.0

1.1

check

com.boya.subject.util.CheckTag

check

true

url

false

msg

true

scope

true

to

false

你 只要在每个页面里写下这个就可以判定用户是否登陆了

假如没有登陆那么,会自动提示到首页登陆,不错,很完美吧?

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有