自定义MVC---引用XML

简介: 自定义MVC---引用XML

1.什么是MVC?

MVC是三个单词的首字母缩写,它们是Model(模型)、View(视图)和Controller(控制)

   1.1视图

        视图(View)代表用户交互界面,对于Web应用来说,可以概括为HTML界面,但有可能为XHTML、XML和Applet。随着应用的复杂性和规模性,界面的处理也变得具有挑战性。一个应用可能有很多不同的视图,MVC设计模式对于视图的处理仅限于视图上数据的采集和处理,以及用户的请求,而不包括在视图上的业务流程的处理。业务流程的处理交予模型(Model)处理。比如一个订单的视图只接受来自模型的数据并显示给用户,以及将用户界面的输入数据和请求传递给控制和模型。

   1.2模型

        模型(Model):就是业务流程/状态的处理以及业务规则的制定。业务流程的处理过程对其它层来说是黑箱操作,模型接受视图请求的数据,并返回最终的处理结果。业务模型的设计可以说是MVC最主要的核心。目前流行的EJB模型就是一个典型的应用例子,它从应用技术实现的角度对模型做了进一步的划分,以便充分利用现有的组件,但它不能作为应用设计模型的框架。它仅仅告诉你按这种模型设计就可以利用某些技术组件,从而减少了技术上的困难。对一个开发者来说,就可以专注于业务模型的设计。MVC设计模式告诉我们,把应用的模型按一定的规则抽取出来,抽取的层次很重要,这也是判断开发人员是否优秀的设计依据。抽象与具体不能隔得太远,也不能太近。MVC并没有提供模型的设计方法,而只告诉你应该组织管理这些模型,以便于模型的重构和提高重用性。我们可以用对象编程来做比喻,MVC定义了一个顶级类,告诉它的子类你只能做这些,但没法限制你能做这些。这点对编程的开发人员非常重要。

      业务模型还有一个很重要的模型那就是数据模型。数据模型主要指实体对象的数据 保存(持续化)。比如将一张订单保存到数据库,从数据库获取订单。我们可以将这个模型单独列出,所有有关数据库的操作只限制在该模型中。

1.3控制

       控制(Controller)可以理解为从用户接收请求, 将模型与视图匹配在一起,共同完成用户的请求。划分控制层的作用也很明显,它清楚地告诉你,它就是一个分发器,选择什么样的模型,选择什么样的视图,可以完成什么样的用户请求。控制层并不做任何的数据处理。例如,用户点击一个连接,控制层接受请求后, 并不处理业务信息,它只把用户的信息传递给模型,告诉模型做什么,选择符合要求的视图返回给用户。因此,一个模型可能对应多个视图,一个视图可能对应多个模型。

       模型、视图与控制器的分离,使得一个模型可以具有多个显示视图。如果用户通过某个视图的控制器改变了模型的数据,所有其它依赖于这些数据的视图都应反映到这些变化。因此,无论何时发生了何种数据变化,控制器都会将变化通知所有的视图,导致显示的更新。这实际上是一种模型的变化-传播机制。模型、视图、控制器三者之间的关系和各自的主要功能

  1)最上面的一层,是直接面向最终用户的"视图层"(View)。它是提供给用户的操作界面,是程序的外壳。

  2)最底下的一层,是核心的"数据层"(Model),也就是程序需要操作的数据或信息。

  3)中间的一层,就是"控制层"(Controller),它负责根据用户从"视图层"输入的指令,选取"数据层"中的数据,然后对其进行相应的操作,产生最终结果。

这三层是紧密联系在一起的,但又是互相独立的,每一层内部的变化不影响其他层。每一层都对外提供接口(Interface),供上面一层调用。这样一来,软件就可以实现模块化,修改外观或者变更数据都不用修改其他层,大大方便了维护和升级。

 

2.实列演化

2.1实体类

Book(书籍)类

package com.xuyahui.entity;
public class Book {
  private int bid;
  private String bname;
  public Book() {
    // TODO Auto-generated constructor stub
  }
  public int getBid() {
    return bid;
  }
  public void setBid(int bid) {
    this.bid = bid;
  }
  public String getBname() {
    return bname;
  }
  public void setBname(String bname) {
    this.bname = bname;
  }
  @Override
  public String toString() {
    return "Book [bid=" + bid + ", bname=" + bname + "]";
  }
}

2.2模型驱动

ModelDriven 模型驱动接口

public interface ModelDriven<T> {
  T getmodel();
}

2.3 配置文件

mvc.xml配置文件

<?xml version="1.0" encoding="UTF-8"?>
<config>
  <action path="/regAction" type="test.RegAction">
    <forward name="failed" path="/reg.jsp" redirect="false" />
    <forward name="success" path="/login.jsp" redirect="true" />
  </action>
  <action path="/loginAction" type="test.LoginAction">
    <forward name="failed" path="/login.jsp" redirect="false" />
    <forward name="success" path="/main.jsp" redirect="true" />
  </action>
</config>

2.4实体的方法类

BookAction

public String See(HttpServletRequest request, HttpServletResponse response) {
    //参数传递
    request.setAttribute("String", "ikun的小黑子");
    System.out.println("book(书籍)Action的查看(See)方法");
    //返回值(是重定向还是转发)forward:转发,redirect:重定向
    return "forward";
  }
  public String Upda(HttpServletRequest request, HttpServletResponse response) {
    //参数传递
    request.setAttribute("String", "ikun的小黑子");
    System.out.println("book(书籍)Action的修改(Upda)方法");
    //返回值(是重定向还是转发)forward:转发,redirect:重定向
    return "redirect";
  }
  public String Del(HttpServletRequest request, HttpServletResponse response) {
    request.setAttribute("String", "ikun的小黑子");
    System.out.println("book(书籍)Action的删除(Del)方法");
    //返回值(是重定向还是转发)forward:转发,redirect:重定向
    return "redirect";
  }
  public String Add(HttpServletRequest request, HttpServletResponse response) {
    request.setAttribute("String", "ikun的小黑子");
    System.out.println("book(书籍)Action的增加(Add)方法");
    //返回值(是重定向还是转发)forward:转发,redirect:重定向
    return "redirect";
  }
  @Override
  public Book getModel() {
    return book;
  }
}

获取参数反射后调用方法

package com.Xuyahui.Servlet;
import java.io.IOException;
import java.lang.reflect.Method;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@WebServlet("/BookServlet.do")
public class BookServlet extends HttpServlet {
  private static final long serialVersionUID = 1L;
  protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
      doPost(request, response);
  }
  protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    //根据JSP页面传递的值
    String method = request.getParameter("method");
    //通过反射类类方法的方法进行增删改查
    try {
      Method m = this.getClass().getDeclaredMethod(method, HttpServletRequest.class,HttpServletResponse.class);
      m.setAccessible(true);
      m.invoke(this,request,response);
    } catch (Exception e) {
      e.printStackTrace();
    } 
  }
  private void See(HttpServletRequest request, HttpServletResponse response) {
    System.out.println("book(书籍)Servlet的查看(See)方法");
  }
  private void Upda(HttpServletRequest request, HttpServletResponse response) {
    System.out.println("book(书籍)Servlet的修改(Upda)方法");
  }
  private void Del(HttpServletRequest request, HttpServletResponse response) {
    System.out.println("book(书籍)Servlet的删除(Del)方法");
  }
  private void Add(HttpServletRequest request, HttpServletResponse response) {
    System.out.println("book(书籍)Servlet的增加(Add)方法");
  }
}

2.5控制器

package com.Xuyahui.framework;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.beanutils.BeanUtils;
import com.Xuyahui.framework.model.ActionModel;
import com.Xuyahui.framework.model.ConfigModel;
import com.Xuyahui.framework.model.ConfigModelFactory;
import com.Xuyahui.framework.model.ForwardModel;
@WebServlet("*.do")
public class ControllerServlet extends HttpServlet {
  private static final long serialVersionUID = 1L;
  // Map<String, Action> actionMap = new HashMap<String, Action>();
  // 以前所有的子控制器是放到map集合中,现在所有的子控制器在mvc.xml中,其实就是放到configModel对象中
  private ConfigModel configModel;
  @Override
  public void init() throws ServletException {
    // actionMap.put("/Book", new BookAction());
    try {
      // configModel包含了所有的子控制器
      configModel = ConfigModelFactory.build();
    } catch (Exception e) {
      e.printStackTrace();
    }
  }
  protected void doGet(HttpServletRequest request, HttpServletResponse response)
      throws ServletException, IOException {
    doPost(request, response);
  }
  protected void doPost(HttpServletRequest request, HttpServletResponse response)
      throws ServletException, IOException {
    String uri = request.getRequestURI();
    uri = uri.substring(uri.lastIndexOf("/"), uri.lastIndexOf("."));
    // Action action = actionMap.get(uri);
    // 要通过uri找到/book,在configModel对象中找
    ActionModel actionModel = configModel.pop(uri);
    // 判断如果为空在页面给与异常提示
    if (actionModel == null)
      throw new RuntimeException("action not config");
    // 获取类路径
    String type = actionModel.getType();
    Action action = null;
    try {
      action = (Action) Class.forName(type).newInstance();
      // bookAction有没有实现ModelDriver接口
      if (action instanceof ModelDriver) {
        ModelDriver md = (ModelDriver) action;
        Object bean = md.getModel();
        BeanUtils.populate(bean, request.getParameterMap());
      }
      //具体业务代码执行后的返回值 forward:转发,redirect:重定向
      String execut = action.execut(request, response);
            //要通过返回值拿到,该方法结果是重定向还是转发,还是跳转哪个页面
      ForwardModel forwardModel = actionModel.pop(execut);
      if(forwardModel != null) {
        //获取返回值true后false
        boolean redirect = forwardModel.isRedirect();
        String path = forwardModel.getPath();
        if(redirect) {
          //getContextPath()加载时防止页面丢失
          response.sendRedirect(request.getContextPath() + "/" + path);
        }else {
          request.getRequestDispatcher(path).forward(request, response);
        }
      }
    } catch (Exception e) {
      e.printStackTrace();
    }
  }
}

2.6子控制器

package com.Xuyahui.framework;
import java.lang.reflect.Method;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class Action {
  public String execut(HttpServletRequest request, HttpServletResponse response) throws Exception {
    //根据JSP页面传递的值
    String method = request.getParameter("method");
    //定义返回值确定是重定向还是转发
    String res = "";
    //通过反射类类方法的方法进行增删改查
    try {
      Method m = this.getClass().getDeclaredMethod(method, HttpServletRequest.class,HttpServletResponse.class);
      m.setAccessible(true);
      res = (String) m.invoke(this,request,response);
    } catch (Exception e) {
      e.printStackTrace();
    } 
    return res;
  }
}

2.7测试及效果

测试代码

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<h3>书籍的方法功能--优化为配置文件及获取参数和跳转方法</h3><hr>
<a href="Book.do?method=Add&bid=1&bname=ikun&price=999">增加</a>
<a href="Book.do?method=Del&bid=1">删除</a>
<a href="Book.do?method=Upda&bid=1&bname=小黑子&price=666">修改</a>
<a href="Book.do?method=See&bid=1">查询</a>
</body>
</html>

结果显示:

增删改的的测试是重定向,不会带参数

查询是转发,所以带参数

 


目录
相关文章
|
1月前
|
前端开发 Java 数据库
springBoot:template engine&自定义一个mvc&后端给前端传数据&增删改查 (三)
本文介绍了如何自定义一个 MVC 框架,包括后端向前端传递数据、前后端代理配置、实现增删改查功能以及分页查询。详细展示了代码示例,从配置文件到控制器、服务层和数据访问层的实现,帮助开发者快速理解和应用。
|
4月前
|
XML 开发工具 数据格式
自定义 DSL 流程图(含XML 描述邮件,XML 描述流程图)
自定义 DSL 流程图(含XML 描述邮件,XML 描述流程图)
37 0
自定义 DSL 流程图(含XML 描述邮件,XML 描述流程图)
|
6月前
ssm(Spring+Spring mvc+mybatis)——web.xml
ssm(Spring+Spring mvc+mybatis)——web.xml
|
6月前
|
Java Spring
ssm(Spring+Spring mvc+mybatis)Spring配置文件——applicationContext.xml
ssm(Spring+Spring mvc+mybatis)Spring配置文件——applicationContext.xml
|
6月前
|
网络安全
ssh(Spring+Spring mvc+hibernate)——applicationContext.xml
ssh(Spring+Spring mvc+hibernate)——applicationContext.xml
|
6月前
|
XML Java Apache
Apache Flink自定义 logback xml配置
Apache Flink自定义 logback xml配置
346 0
|
6月前
|
XML 前端开发 定位技术
C#(NET Core3.1 MVC)生成站点地图(sitemap.xml)
C#(NET Core3.1 MVC)生成站点地图(sitemap.xml)
98 0
|
6月前
|
前端开发 Java
自定义mvc的增删改查
自定义mvc的增删改查
63 0
|
6月前
|
XML 前端开发 数据格式
自定义MVC引用XML配置文件实现
自定义MVC引用XML配置文件实现
63 0
|
6月前
|
设计模式 前端开发 搜索推荐
自定义mvc框架
自定义mvc框架
67 0