零基础学Struts
上QQ阅读APP看书,第一时间看更新

1.1 MVC思想概述

下面通过一个登录案例概述一下MVC思想。

1.1.1 简单的登录案例

在学习框架之前必须很好地掌握Java Web的基础知识(如JSP、Servlet、JDBC),这样学习框架才不会吃力,才会觉得顺手。

下面来使用JSP编写一个简单的登录项目,判断用户是否合法,如果合法就显示登录成功,否则就显示登录失败。暂时不需要使用数据库,这里使用固定的用户名和密码。

步骤如下。

(1)首先新建Web项目,其实就是一个普通的文件夹,不过在这个文件夹中包含一个名为“WEBINF”的文件夹,并且在它之下有一个“web.xml”的文件。“web.xml”代码如下。

          <? xml version="1.0" encoding="UTF-8"? >
          <web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="
          http://www.w3.org/2001/XMLSchema-instance" version="2.5" xsi:schemaLocation="
          http://java.sun.com/xml/ns/javaee   http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
            <welcome-file-list>
              <welcome-file>index.jsp</welcome-file>
            </welcome-file-list>
          </web-app>

(2)分析该项目。项目中包含一个用户登录页、一个用来接收用户请求信息并判断用户信息合法语法的登录判断页、一个登录成功显示页、一个登录失败显示页。

用户登录页包含一个简单的表单,表单中包含两个文本域,分别用来接收用户输入的用户名和密码,还包括两个按钮,分别用来提交表单和重置表单。登录页“login.jsp”代码如下。

        <%@page contentType="text/html; charset=gb2312"%>
        <html>
        <head>
            <title>用户登录</title>
        </head>
        <body>
        <center>
            <h2>用户登录</h2>
            <%--登录表单--%>
            <form action="login_conf.jsp" method="post">
            <table>
                  <tr>
                        <td>用户名:</td>
                        <%--接收用户输入的用户名,其name属性为uname--%>
                        <td><input type="text" name="uname"></td>
                  </tr>
                  <tr>
                        <%--接收用户输入的密码,其name属性为upassword--%>
                        <td>&nbsp; &nbsp;码:</td>
                        <td><input type="password" name="upassword"></td>
                  </tr>
                  <tr>
                        <td colspan="2">
                        <%--登录按钮和重置按钮--%>
                        <input type="submit" value="登录">
                        <input type="reset" value="重置">
                        </td>
                  </tr>
            </table>
            </form>
        </center>
        </body>
        </html>

(3)登录判断页首先接受用户登录页传递的用户信息,并对用户信息进行判断。如果合法则跳转到用户登录成功页,如果非法则跳转到用户登录失败页。登录判断页“login_conf.jsp”代码如下。

        <%@page contentType="text/html; charset=gb2312"%>
        <html>
        <head>
            <title>登录判断</title>
        </head>
        <body>
            <%
              // 接收请求的内容
              String name = request.getParameter("uname") ;
              String password = request.getParameter("upassword") ;
        %>
        <%
              // 判断用户名及密码
              if("xiaoqiang".equals(name)&&"xiaoqiang".equals(password)){
                      // 合法用户
        %>
                      <jsp:forward page="login_success.jsp"/>
        <%
              } else {
                      // 非法用户
        %>
                      <jsp:forward page="login_failure.jsp"/>
        <%
              }
        %>
  </body>
  </html>

(4)登录成功页和登录失败页代码只是简单地显示信息,用来提示是否登录成功。其中登录成功页“login_success.jsp”代码如下。

        <%@page contentType="text/html; charset=gb2312"%>
        <html>
        <head>
            <title>登录成功</title>
        </head>
        <body>
        <center>
            <h2>登录成功</h2>
        </center>
        </body>
        </html>

登录失败页“login_failure.jsp”代码如下。

        <%@page contentType="text/html; charset=gb2312"%>
        <html>
        <head>
            <title>登录失败</title>
        </head>
        <body>
        <center>
            <h2>登录失败</h2>
        </center>
        </body>
        </html>

(5)部署该项目。打开Tomcat安装目录下的conf文件夹,打开其中的“server.xml”文件。在文件的最下面的“</host>”标签之前添加如下代码。

        <Context path="/01"docBase="E:\BookDemo\ch01\01"reloadable="true"crossContext="true">
        </Context>

其中docBase属性用来指定项目所在目录,path属性用来指定虚拟路径,也就是通过浏览器访问时的路径地址。

1.1.2 测试案例

下面一起运行这个程序,看是否实现了项目的要求。

步骤如下。

(1)运行Tomcat服务器,启动Tomcat服务(如果Tomcat为安装版本),或者打开Tomcat的安装目录下的bin目录,找到“startup.bat”,双击运行该批处理来运行Tomcat服务器。

(2)打开浏览器,访问登录页地址“http://localhost:8080/01/login.jsp”,页面显示效果如图1.1所示。

(3)在表单中填写用户信息,这里是随意填写的一个用户信息。单击“登录”按钮进行提交。页面提交到登录判断页。

因为用户信息是随意填写的,所以登录判断页判断该用户为非法用户。登录判断页会执行下面这段代码。

        <jsp:forward page="login_failure.jsp"/>

因此将执行服务器端跳转到登录失败页(如图1.2所示)。

(4)输入正确的用户信息,单击“登录”按钮进行提交。页面提交到登录判断页,页面显示效果如图1.3所示。

图1.1 用户登录页

图1.2 登录失败页

图1.3 登录成功页

输入的是正确的用户信息,所以登录判断页判断该用户为合法用户。因此登录判断页会执行下面这段代码。

        <jsp:forward page="login_success.jsp"/>

因此将执行服务器端跳转到登录成功页。但是这里发现一个问题,直接浏览“login_success.jsp”页面就可以显示成功,根本就不用登录,因此必须在登录成功页加上判断。

修改代码步骤如下。

(1)修改登录判断页“login_conf.jsp”。如果判断为合法用户,则将在request范围中添加属性login,并将属性值设置为true,修改代码如下所示。

        <%@page contentType=”text/html; charset=gb2312”%>
        <html>
        <head>
            <title>登录判断</title>
        </head>
        <body>
            <%
                    // 接收请求的内容
                    String name = request.getParameter("uname") ;
                    String password = request.getParameter("upassword") ;
            %>
            <%
                    // 判断用户名及密码
                    if("xiaoqiang".equals(name)&&"xiaoqiang".equals(password)){
                            // 合法用户
                            //request范围中添加属性login,其属性值为true
                            request.setAttribute("login", "true");
            %>
                            <jsp:forward page="login_success.jsp"/>
            <%
                    } else {
                            // 非法用户
            %>
                            <jsp:forward page="login_failure.jsp"/>
            <%
                    }
            %>
        </body>
        </html>

(2)修改登录成功页“login_success.jsp”。在该页面中添加对request范围内login属性的判断,如果该属性存在并且其属性值为true才显示用户登录成功,否则将跳转到登录页,代码如下所示。

        <%@page contentType="text/html; charset=gb2312"%>
        <html>
        <head>
            <title>登录成功</title>
        </head>
        <body>
        <center>
            <%
                    if(request.getAttribute("login") ! = null && request.getAttribute("login").equals("true")){
            %>
            <h2>登录成功</h2>
            <%
                    } else {
            %>
                    <jsp:forward page="login.jsp"></jsp:forward>
            <%
                    }
              %>
          </center>
          </body>
          </html>

打开浏览器,直接访问登录成功页“http://localhost:8080/01/login_success.jsp”。这时页面并没有显示登录成功,而是直接跳转回了“login.jsp”用户登录页。这样就能够避免用户直接进入成功页。不过代码中还有很多地方需要改进,如直接通过JSP来进行业务逻辑的判断,其实这样是非常不好的。“login_conf.jsp”页面完成的是判断和跳转功能,完全可以使用Servlet来进行操作,而不是使用JSP。下面讲解MVC设计模式,并通过使用MVC设计模式来改进这个项目。

1.1.3 Model 1和Model 2

首先来看什么是Model 1模式。前面编写的那个登录项目为例就是用典型的基于Model 1模式来开发的,整个Web项目都是由JSP页面构成的。其中登录判断页“login_conf.jsp”既要接受客户端的请求,还必须对其用户信息判断进行跳转。JSP页面既要负责显示还要负责控制,将控制逻辑和表现逻辑混在一起了。

使用Model 1模式开发代码重用性非常低,对于功能相似的代码只能选择复制的方式,而不是直接调用。这样使得整个JSP页面充斥着功能类似的代码。

使用Model 1模式开发程序扩展性也非常差,如果以后想要给程序扩展功能是非常困难的。假如在一个JSP页面添加了某一功能,那么可能其他的很多页面都需要变动,甚至整个Web应用都要修改。这种牵一发而动全身的应用,会使得后期工作异常的困难和烦琐。

JSP页面中大量充斥着Java脚本,这使得后期的维护非常困难。有时候一个地方出现错误就要到处去找。还有代码重用性,笔者就是经常在使用复制、粘贴,已经成了一种习惯。

不过使用Model 1模式来开发比较简单和方便。因此如果是小型的Web站点,后期的更新和维护工作不是很大,就可以采用Model 1模式来开发。

Model 2是基于MVC架构的设计模式。MVC包含3个基本部分,分别是Model(模型)、View(视图)和Controller(控制器)。JSP只负责显示,而控制器则由Servlet充当,模型由JavaBean充当。为了更好地明白Model 1和Model 2的区别,下面给出Model 1以及Model 2的程序流程图,如图1.4和图1.5所示。

图1.4 Model 1的程序流程图

图1.5 Model 2的程序流程图

Model 1的程序流程比较容易理解。用户提交信息给JSP页面,JSP接受用户提交的值,通过JavaBean连接数据库并操作数据库,然后将结果返回给用户。

Model 2将JSP的功能简化了,在Model 1中JSP负责的东西过多了。在Model 2中使用Servlet来充当控制器,而JSP只是充当显示。至于为什么会这样设计,是因为在JSP中进行接受参数和判断还有跳转等功能会用到大量的Java脚本代码。过多的Java脚本代码会使得页面维护起来非常困难,而Servlet本来就是一个Java文件,这样使用Servlet来接受参数和判断还有跳转等功能是非常合适的。用户可以把Servlet看成是一个大管家,它负责所有的业务逻辑并通过JavaBean来操作数据库以及决定显示页面。

通过分层的思想使得程序执行更加清晰,各层都只负责自己的功能,不会出现混乱。而且如果程序后期需要增加功能或者进行维护都是非常方便的,下面来演示如何使用MVC设计模式来改进前面的登录案例。

1.1.4 使用MVC设计模式改进代码

如果要使用MVC设计模式,那么控制器就要使用Servlet。具体的逻辑判断则交给业务逻辑组件来判断,而业务逻辑组件判断的结果则返回交给Servlet来判断并实现跳转。

步骤如下。

(1)新建一个Web项目,把上个项目中的“login.jsp”、“login_success.jsp”以及“login_failure.jsp”复制到本项目中。

(2)新建业务逻辑组件类,类名为LoginCheck,包含一个isLogin方法,用来判断用户是否合法,代码如下所示。

        public class LoginCheck {
              //判断是否为合法用户
              public boolean isLogin(String name, String password){
                    if("xiaoqiang".equals(name)&&"xiaoqiang".equals(password)){
                            return true;
                    }else{
                            return false;
                    }
              }
        }

(3)新建Servlet, Servlet类名为LoginConf。该Servlet接受用户提交的参数,并通过实例化一个业务逻辑组件,然后通过调用业务逻辑组件中的isLogin返回值来分别对合法用户和非法用户执行跳转,代码如下所示。

        import java.io.IOException;
        import java.io.PrintWriter;
        import javax.servlet.ServletException;
        import javax.servlet.http.HttpServlet;
        import javax.servlet.http.HttpServletRequest;
        import javax.servlet.http.HttpServletResponse;
        public class LoginConf extends HttpServlet {
              public void doGet(HttpServletRequest request, HttpServletResponse response)
                          throws ServletException, IOException {
                    //接受用户参数
                    String name = request.getParameter("uname");
                    String password = request.getParameter("upassword");
                    //new一个LoginCheck对象
                    LoginCheck lc = new LoginCheck();
                    //调用业务逻辑组件的判断功能
                    if(lc.isLogin(name, password)){
                          //如果为合法用户,在request范围中添加属性login,其属性值为true,并跳转到登录成功页
                          request.setAttribute("login", "true");
                          request.getRequestDispatcher("login_success.jsp").forward(request, response);
                    }else{
                          //如果为非法用户则跳转到登录失败页
                          request.getRequestDispatcher("login_failure.jsp").forward(request, response);
                    }
              }
              public void doPost(HttpServletRequest request, HttpServletResponse response)
                          throws ServletException, IOException {
                    doGet(request, response);
              }
        }

(4)分别编译LoginCheck类和LoginConf类,并将编译后的class文件放入项目的WEB-INF文件夹下的classes文件夹中。

(5)配置Servlet,修改“web.xml”文件,代码如下所示。

        <? xml version="1.0" encoding="UTF-8"? >
        <web-app version="2.5"
            xmlns="http://java.sun.com/xml/ns/javaee"
            xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
            xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
            http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
          <servlet>
            <servlet-name>LoginConf</servlet-name>
            <servlet-class>LoginConf</servlet-class>
          </servlet>
          <servlet-mapping>
            <servlet-name>LoginConf</servlet-name>
            <url-pattern>/LoginConf</url-pattern>
          </servlet-mapping>
        </web-app>

(6)修改“login.jsp”,即页面提交页,使页面跳转到LoginConf,代码如下所示。

        <form action="LoginConf"method="post">

(7)部署该项目。打开Tomcat安装目录下的conf文件夹,打开其中的“server.xml”文件。在文件的最下面的“</host>”标签之前添加如下代码。

        <Context path="/02"docBase="E:\BookDemo\ch01\02"reloadable="true"crossContext="true">
        </Context>

1.1.5 测试MVC改进代码

下面运行这个程序,看是否实现了项目的要求(本实例参照第1.1.2节进行了改进)。

步骤如下。

(1)启动Tomcat服务(如果Tomcat为安装版本),或者打开Tomcat安装目录下的bin目录,找到“startup.bat”,双击运行该批处理来运行Tomcat服务器。

(2)打开浏览器,访问登录页地址“http://localhost:8080/02/login.jsp”,页面显示效果如图1.6所示。

(3)在表单中填写用户信息,这里随意地填写一个用户信息。单击“登录”按钮进行提交。页面提交到登录判断页,页面显示效果如图1.7所示。

因为用户信息是随意填写的,所以登录判断页判断该用户为非法用户。在LoginConf的Servlet中调用业务逻辑组件LoginCheck的isLogin方法,返回的是“false”。在LoginConf中会执行下列代码。

          request.getRequestDispatcher("login_failure.jsp").forward(request, response);

因此将执行服务器端跳转到登录失败页。

(4)输入正确的用户信息,用户名和密码都填写“xiaoqiang”,单击“登录”按钮进行提交。页面提交到登录判断页,页面显示效果如图1.8所示。

图1.6 用户登录页

图1.7 登录失败页

图1.8 登录成功页

输入的是正确的用户信息,所以登录判断页判断该用户为合法用户。在LoginConf的Servlet中调用业务逻辑组件LoginCheck的isLogin方法,返回的是“true”。在LoginConf中会执行下列代码。

          request.getRequestDispatcher("login_success.jsp").forward(request, response);

因此将执行服务器端跳转到登录成功页。

(5)直接访问登录成功页地址“http://localhost:8080/02/login_success.jsp”,这时页面将自动跳转回登录页。