Java EE轻量级解决方案:S2SH
上QQ阅读APP看本书,新人免费读10天
设备和账号都新为新人

1.2 自定义MVC框架

Java EE领域的MVC框架有很多,本书首先会设计一个简单的自定义MVC框架,以此帮助读者体会MVC框架的含义和实现过程,以及在MVC设计模式中控制器(Controller)的作用。通过此框架的实现还可以帮助读者理解Struts2的原理。

使用自定义MVC框架开发加法器程序的结构图如图1-6所示。

图1-6 加法器的MVC结构图

此加法器程序首先需要用户在add.jsp页面中输入两个数,单击“加”按钮进行计算,计算的结果在add_result.jsp页面中显示,如图1-7所示。

图1-7 加法器运行效果

下述内容用于实现任务描述1.D.1,使用自定义的MVC框架完成加法计算器。

1.2.1 实现控制器

自定义的MVC框架的核心是控制器的实现:定义Action接口,实现Controller类。

首先在com.haiersoft.ch01.framework包中创建Action接口,代码如下。

【描述1.D.1】Action.java

    public interface Action {
    //定义该接口的实现类必须实现的execute方法
    String execute(HttpServletRequest request,HttpServletResponse response);
    }

上述Action接口中定义了一个execute()方法,该方法有请求对象request和响应对象response两个参数;该方法返回一个字符串类型的值,表示执行完操作后转发到的页面。Action接口对各种动作的执行方法进行统一,便于在控制器中进行调用和访问。

然后在com.haiersoft.ch01.framework包中创建一个名为Controller的Servlet,代码如下。

【描述1.D.1】Controller.java

/**
* 自定义MVC框架:基于Servlet实现的控制器
*/
public class Controller extends HttpServlet {
    //声明由控制器Controller维护的Action映射,其中保存所有的Action实例
    private HashMap actionMap;
    /**
    * Servlet初始化方法
    */
    @SuppressWarnings("unchecked")
    public void init() throws ServletException {
        // 初始化actionMap
        actionMap = new HashMap();
        // 将AddAction对象放入到actionMap 中
        actionMap.put("add", new AddAction());
    }
    /**
    * 根据path判断由哪个action执行操作
    */
    private Action determinActionByPath(String path) {
        //如:从http://localhost:8080/ch01/add.action中得到add
        String actionName =
            path.substring(path.lastIndexOf('/') + 1, path.length() - 7);
        // 获得该请求对应的action对象
        Action ret = (Action)actionMap.get(actionName);
        return ret;
    }
    /**
      * 处理页面以get方式提交的请求
      */
    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        // 得到path,诸如:http://localhost:8080/ch01/ShowBaby.action
        String path = request.getServletPath();
        // 找出Action
        Action action = (Action)this.determinActionByPath(path);
        // 执行操作
        String resultView = action.execute(request,response);
        // 控制页面转向
        if (null!=resultView){
            request.getRequestDispatcher(resultView).forward(request,
            response);
        }
    }
    public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        // 执行doGet方法
        this.doGet(request, response);
    }
}

上述的Controller类是基于Servlet技术实现的一个控制器,在处理每次请求时,首先根据请求路径找到将要被执行的Action对象,然后调用Action对象中的execute()方法,最后根据execute()方法返回的路径转发到相应的页面。

Controller类是一个Servlet,因此在web.xml中需要对其进行如下配置。

【描述1.D.1】web.xml

    <servlet>
        <!-- 使用自定义的控制器 -->
        <servlet-name>Controller</servlet-name>
        <servlet-class>com.haiersoft.ch01.framework.Controller</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>Controller</servlet-name>
        <!-- 请求匹配类型 -->
        <url-pattern>*.action</url-pattern>
    </servlet-mapping>

在上述Servlet配置中,所有以“.action”结尾的请求全部派发到Controller类进行处理。因此Action接口和Controller类组成了自定义MVC框架中核心的控制器部分。

注意 在许多框架结构中(例如Struts2)已经提供类似Action接口和Controller类的控制器,无须自己定义。

1.2.2 实现加法器功能

框架提供了控制器,也规定了模型和视图的集成方式,这样在此自定义框架上开发加法器可以按照如下4个步骤进行。

01 创建add.jsp页面,用于接收用户输入数据;

02 创建业务逻辑类Calculator,实现数据的算术运算;

03 创建AddAction类,该类实现Action接口。在execute()方法中获取add.jsp页面中的表单数据,并调用Calculator进行计算;

04 创建add_result.jsp页面,用于显示计算结果。

下述内容对实现加法器功能的4个步骤进行详细介绍。

1. 实现add.jsp页面

在WebContent目录中创建add.jsp页面,用于接收两个数值,页面代码如下。

【描述1.D.1】add.jsp

<%@ page contentType="text/html; charset=GBK"%>
<html>
<head>
<title>计算器</title>
</head>
<body bgcolor="#ffffc0">
<h1>算术计算器</h1>
<form id="calcForm" method="post" action="add.action">
<table>
    <tbody>
        <tr>
            <td>第一个数</td>
            <td><input type="text" name="num1" /></td>
        </tr>
        <tr>
            <td>第二个数</td>
            <td><input type="text" name="num2" /></td>
        </tr>
        <tr>
            <td><input type="submit" value="加" /></td>
      </tr>
    </tbody>
</table>
</form>
</body>
</html>

在add.jsp页面中,表单的action属性值为“add.action”,即表单提交给“add.action”处理。同时因为在web.xml中已经配置了将所有以“.action”结尾的请求全部派发到Controller进行处理,所以此表单会提交给Controller类处理。

2. 实现Calculator类

在com.haiersoft.ch01.biz包中创建Calculator类,进行加减乘除运算,代码如下。

【描述1.D.1】Calculator.java

public class Calculator {
    /**
    * 实现算术加法
    */
    public double add(double a, double b) {
        return a + b;
    }
    /**
    * 实现算术减法
    */
    public double subtract(double a, double b) {
        return a - b;
    }
    /**
    * 实现算术乘法
    */
    public double multiply(double a, double b) {
        return a * b;
    }
    /**
    * 实现算术除法
    */
    public double divide(double a, double b) {
        // 注意:此处未判断除数不能为零,即b!=0,页面输入的第二个数不可为0,否则报错
        return a / b;
    }
}

3. 实现AddAction类

在com.haiersoft.ch01.action包中创建AddAction类,该类实现Action接口,代码如下。

【描述1.D.1】AddAction.java

    public class AddAction implements Action {
        // 业务逻辑对象
        private Calculator biz = new Calculator();
        public String execute(HttpServletRequest request,
                HttpServletResponse response) {
            // 获得页面输入
            double num1 = Double.parseDouble(request.getParameter("num1"));
            double num2 = Double.parseDouble(request.getParameter("num2"));
            // 调用业务逻辑方法,获得返回值
            double result = biz.add(num1, num2);
            // 将结果保存在request中,以便在页面中得到
            request.setAttribute("result", result);
            // 返回将要转发到的页面路径
            return "add_result.jsp";
        }
    }

在上述AddAction类的execute()方法中,首先从request中获取表单数据并转换成double类型,然后调用Calculator类的对象“biz”中的add()方法进行计算,再将结果保存到request对象的属性中,最后返回将要转发的页面add_result.jsp。

4. 实现add_result.jsp页面

在WebContent目录中创建add_result.jsp页面,显示计算结果值,代码如下。

【描述1.D.1】add_result.jsp

<%@ page contentType="text/html; charset=GBK" pageEncoding="GBK"%>
<html>
<head>
<title>计算器</title>
</head>
<body bgcolor="#ffffc0">
<h1>算术计算器</h1>
<table>
    <tbody>
        <tr>
            <td>第一个数</td>
            <td>${param.num1}</td>
        </tr>
        <tr>
            <td>第二个数</td>
            <td>${param.num2}</td>
        </tr>
        <tr>
            <td>结果</td>
            <!-- 使用EL表达式显示结果 -->
            <td>${requestScope.result}</td>
        </tr>
    </tbody>
</table>
<button onclick="history.go(-1);">返回</button>
</body>
</html>

上述add_result.jsp页面中使用EL表达式显示结果。程序的运行结果如图1-7所示。

通过在此自定义MVC框架然后用其开发加法器的过程,读者可以体会到在开发过程中使用框架所带来的便利和限制,初步了解框架的功能及作用,为学习Struts2做好充分的准备。