大家都知道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搀杂在一起好了很多。