posts - 14, comments - 22, trackbacks - 0, articles - 4
  BlogJava :: 首页 ::  :: 联系 :: 聚合  :: 管理

体验Struts(5)---从分页体会MVC

Posted on 2006-05-26 00:29 誰伴我闖蕩 阅读(2250) 评论(0)  编辑  收藏

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

    public Page( Vector<E> 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<E> getNextPage()
    {
        current = current + 1;
        if ( (current - 1) > 0 )
        {
            previous = true;
        }
        else
        {
            previous = false;
        }
        if ( current >= pages )
        {
            next = false;
        }
        else
        {
            next = true;
        }
        Vector<E> os = gets();
        return os;
    }

 //获取上一页

    public Vector<E> 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<E> os = gets();
        return os;
    }

 //一开始获取的

    public Vector<E> gets()
    {
        if ( current * each < total )
        {
            end = current * each;
            start = end - each;
        }
        else
        {
            end = total;
            start = each * (pages - 1);
        }
        Vector<E> gets = new Vector<E>();
        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<Student> ss; //用来装结果的容器
    private Page<Student> 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<Student> 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<Student>( 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<LabelValueBean> studentSearch()
    {
        Vector<LabelValueBean> s = new Vector<LabelValueBean>();
        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后,还是看看视图吧,


先放个查询表单:

<html:javascript dynamicJavascript="true" staticJavascript="true" formName="SearchForm" />
<html:form action="/adminUser.do?search=true" onsubmit="return validateSearchForm(this)">

<html:select property="from" >
<html:options collection="search" property="value" labelProperty="label" />
</html:select>

<html:text property="key" size="16" maxlength="16"/>

<html:image src="images/search.gif"/>

</html:form>

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

<logic:iterate id="student" name="students">

<nested:root name="student">

<nested:nest property="schoolClass"><nested:write property="schoolClass"/></nested:nest>//寻找了student的schoolClass属性对象的schoolClass嵌套

<nested:write property="name"/>      //student的名字

<nested:link page="/adminActions.do?method=deleteStudent" paramId="id" paramProperty="id" onclick="return window.confirm('您真的要删除吗?')">删除</nested:link>

</nested:root>

这里是显示分页对象的:

第<bean:write name="page" property="current" />页
共<bean:write name="page" property="pages" />页
        //上一页是否存在
        <logic:equal name="page" property="previous" value="true">
               <html:link page="/adminUser.do?part=student&op=previous">
                <font color="6795b4">上一页</font>
               </html:link>&nbsp;&nbsp; 
        </logic:equal>
        <logic:notEqual name="page" property="previous" value="true">上一页&nbsp;&nbsp;  </logic:notEqual>
        
       //下一页是否存在
         <logic:equal name="page" property="next" value="true">
         <html:link page="/adminUser.do?part=student&op=next">
          <font color="6795b4">下一页</font>
         </html:link>&nbsp;&nbsp;  </logic:equal>
        <logic:notEqual name="page" property="next" value="true">下一页&nbsp;&nbsp;  </logic:notEqual>
        

共有<bean:write name="page" property="total" />条数据

</logic:iterate>

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


只有注册用户登录后才能发表评论。


网站导航:
 
有事在这里给我留言噢!