javaEE之自定义框架

简介: javaEE之自定义框架

1.什么是MVC

MVC全名是Model View Controller,是模型(model)-视图(view)-控制器(controller)的缩写,一种软件设计典范。用一种业务逻辑、数据、界面显示分离的方法,将业务逻辑聚集到一个部件里面,在改进和个性化定制界面及用户交互的同时,不需要重新编写业务逻辑。

MVC结构

  • Model:是应用程序中用于处理应用程序数据逻辑的部分,通常模型对象负责在数据库中存取数据。
  • View:是应用程序中处理数据显示的部分,通常视图是依据模型数据创建的。
  • Controller:是应用程序中处理用户交互的部分,通常控制器负责从视图读取数据,控制用户输入,并向模型发送数据。

MVC是一个框架模式,它强制性的使应用程序的输入、处理和输出分开。使用MVC应用程序被分成三个核心部件:模型、视图、控制器。它们各自处理自己的任务。最典型的MVC就是JSP + servlet + javabean的模式

  • Model:常用javabean去实现,通过各种类来对数据库的数据进行获取,并封装在对象当中。
  • View:常用JSP来实现,通过可直接观察的JSP页面来展示我们从数据库中获取的数据。
  • Controller:常用servlet来实现,通过servlet来获取经过javabean包装过的对象(已存入数据库中的数据),然后再发送数据传输到JSP界面。
  • 1)不能跨层调用; 2)只能由上往下进行调用:View -> Controller -> Model

MVC优化:

开始创建配置文件

<?xml version="1.0" encoding="UTF-8"?>
<config>
  <action path="/order" type="com.junlinyi.servlet.OrderAction">
    <!-- forward标签:没有子标签; name:字符串,同一action标签下的forward标签name值不能相同 ; path:以/开头的字符串 
      redirect:只能是false|true,允许空,默认值为false -->
    <forward name="failed" path="/reg.jsp" redirect="false" />
    <forward name="success" path="/login.jsp" redirect="true" />
  </action>
  <action path="/book" type="com.junlinyi.servlet.BookAction">
    <forward name="failed" path="/login.jsp" redirect="false" />
    <forward name="success" path="/main.jsp" redirect="true" />
  </action>
</config>

要将这个做成架包,所以里面的东西不能是死的,不然就会有新的就会改变,所以我们就用到了建模,将它变成活,到时候只要在配置文件里面添加即可 以前都是将子控制器放在Map集合中,现在要将其放在MVC.XML文件中

DispatherAction :

package com.zhanghao.framework;
import java.io.IOException;
import java.util.Map;
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;
/**
 * 对应图中的ActionServlet:中央控制器
 * 
 * @author jj
 *
 */
@WebServlet("*.action")
public class DispatherServlet extends HttpServlet {
  // public Map<String, Action> actionmap = new HashMap<String,Action>();//通过Map集合去拿到Action类
  // 以前所有的子控制器都是放到Map集合中,现在所有的子控制器在mvc.xml中,其实就是放到configModel
  private ConfigModel configModel;
  public void init() throws ServletException {// 通过Map集合去拿到Action类之后,写一个初始化的方法init(),把所有的action放进去。(案例只有一个BookAction)
    // actionmap.put("/book",new BookAction());
    // actionmap.put("/order", new OrderAction());
    try {
      // configModel包含了所有的子控制器
      configModel = ConfigModelFactory.build();// 初始化
    } catch (Exception e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }
  }
  @Override
  protected void doGet(HttpServletRequest request, HttpServletResponse response)
      throws ServletException, IOException {
    doPost(request, response);
  }
  @Override
  protected void doPost(HttpServletRequest request, HttpServletResponse response)
      throws ServletException, IOException {
    // book -> BookAction -> add
    String uri = request.getRequestURI();// 获取URL地址
    uri = uri.substring(uri.lastIndexOf("/"), uri.lastIndexOf("."));// 截取
    // Action action =
    // actionmap.get(uri);//把所有的action放进init()方法之后,就可以通过map拿到uri,在这里返回一个action对象后续要通过它去抓取add等方法去提供服务
    ActionModel actionModel = configModel.pop(uri);// 要通过uri=/book 在configModel对象中找值,而不是在Map里找
    if (actionModel == null)
      throw new RuntimeException("action not config");//抛异常
    // 返回的type值就是拿到com.Kissship.web.OrderAction路径
    String type = actionModel.getType();
//    BookAction bookaction = new BookAction();对象实例化
    Action action;
    try {
      action = (Action) Class.forName(type).newInstance();// 反射实例化
      //BookAction有没有实现ModelDriver接口  如果实现了才可向下转型
      if(action instanceof ModelDriver) {
        ModelDriver md = (ModelDriver) action;
        Object bean = md.getModel();//这时候这model对象里还是没有值的
        Map<String, String[]> map = request.getParameterMap();//所有参数值都在map里
        BeanUtils.populate(bean, map);//将参数值封装到表对应的对象中
      }     
      //具体业务代码执行后的返回值————add/upd/del/list的返回值-》list/toList
      String res = action.execute(request, response);// 通过实例化的返回值action拿到execute反射代码块
      //要通过返回值拿到,该方法结果是重定向还是转发,还是跳转哪个页面
      ForwardModel forwardModel = actionModel.pop(res);
      if(forwardModel != null) {
        boolean redirect = forwardModel.isRedirect();
        String path = forwardModel.getPath();
        if(redirect) {
          response.sendRedirect(request.getContextPath() + "/" + path); 
        }else {
          request.getRequestDispatcher(path).forward(request, response);
        }
      }
    } catch (Exception e) {
      e.printStackTrace();
    }
  }
}

如果你没有配置文件就会报错,下列是展示图:报action not config 就是没有配置文件

Action类:

下面我们这个Action类中所写的是我们改变了的返回参数

package com.zhanghao.framework;
import java.io.IOException;
import java.lang.reflect.Method;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
 * 子控制器
 * 真正做事,处理浏览器发送的请求的类
 * @author jj
 *
 */
public class Action {
  protected String execute(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    String methodName = request.getParameter("methodName");
    String res = "";
    try {
      Method m = this.getClass().getDeclaredMethod(methodName, HttpServletRequest.class, HttpServletResponse.class);
      m.setAccessible(true);
      res = (String) m.invoke(this, request, response);
    } catch (Exception e) {
      e.printStackTrace();
    }
    return res;
  }
}

  ConfigModelFactory:

package com.zhanghao.utils;
import java.io.InputStream;
import java.util.Iterator;
import java.util.List;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.Node;
import org.dom4j.io.SAXReader;
//工厂模式
public class ConfigModelFactory {
  //常量的定义
  private static final String DEFAULT_PATH="/config.xml";
  private ConfigModelFactory() {}
  public static ConfigModel createConfigModel() {
    return createConfigModel(DEFAULT_PATH);
  }
  public static ConfigModel createConfigModel(String path) {
    ConfigModel configModel=null;
    try {
      configModel=new ConfigModel();
      //获取config.xml配置文件,并返回InputStream输入流
      InputStream is=ConfigModelFactory.class.getResourceAsStream(DEFAULT_PATH);
      //创建SAXReader对象,读取InputStream输入流
      SAXReader saxReader=new SAXReader();
      Document doc=saxReader.read(is);
      //获取Xml文件中的元素信息进行建模
      List<Node> lstNodes=doc.selectNodes("/config/action");
      Element actionElement=null;
      String actionPath=null;
      String actionType=null;
      ActionModel actionModel=null;
      List<Node> forwardLstNodes=null;
      Element forwardElement=null;
      String forwardName=null;
      String forwardPath=null;
      String forwardRedirect=null;
      ForwardModel forwardModel=null;
      for (Node node : lstNodes) {
        //获取Action元素节点的属性信息
        actionElement=(Element)node;
        actionPath=actionElement.attributeValue("path");
        actionType=actionElement.attributeValue("type");
        actionModel=new ActionModel();
        actionModel.setPath(actionPath);
        actionModel.setType(actionType);
        configModel.push(actionModel);
        //获取Action元素节点下的Forward元素节点信息
        forwardLstNodes=actionElement.selectNodes("forward");
        for (Node forwardNode : forwardLstNodes) {
          forwardElement=(Element)forwardNode;
          forwardName=forwardElement.attributeValue("name");
          forwardPath=forwardElement.attributeValue("path");
          forwardRedirect=forwardElement.attributeValue("redirect");
          //将属性值封装到实体对象
          forwardModel=new ForwardModel();
          forwardModel.setName(forwardName);
          forwardModel.setPath(forwardPath);
          forwardModel.setRedirect(forwardRedirect);
          actionModel.push(forwardModel);
        }
      }
    } catch (Exception e) {
      e.printStackTrace();
    }
    return configModel;
  }
  public static void main(String[] args) {
    //XML建模,将XML配置文件中的元素信息转换成对象
    ConfigModel configModel=ConfigModelFactory.createConfigModel();
    System.out.println("OK");
    //获取第一个Action中name为success的对象信息
    ActionModel actionModel=configModel.get("/regAction");
    ForwardModel forwardModel=actionModel.get("success");
    System.out.println(forwardModel.getName());
    System.out.println(forwardModel.getPath());
    System.out.println(forwardModel.isRedirect());
  }
}

ForwardModel:

package com.zhanghao.utils;
import java.io.Serializable;
public class ForwardModel implements Serializable {
  private static final long serialVersionUID = 1L;
  private String name;
  private String path;
  private boolean redirect;
  public ForwardModel() {
    super();
  }
  public String getName() {
    return name;
  }
  public void setName(String name) {
    this.name = name;
  }
  public String getPath() {
    return path;
  }
  public void setPath(String path) {
    this.path = path;
  }
  public boolean isRedirect() {
    return redirect;
  }
  public void setRedirect(boolean redirect) {
    this.redirect = redirect;
  }
  public void setRedirect(String redirect) {
    this.redirect = Boolean.parseBoolean(redirect);
  }
}

BookAction:

package com.zhanghao.dao;
import java.io.IOException;
import java.util.Map;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.zhanghao.entity.Book;
import com.zhanghao.framework.Action;
import com.zhanghao.framework.ModelDriver;
public class BookAction extends Action implements ModelDriver<Book>{
  private Book book = new Book();
  public String add(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    Map<String, String[]> parameterMap = request.getParameterMap();
//    String bid = request.getParameter("bid");
//    String bname = request.getParameter("bname");
//    String price = request.getParameter("price");
//    Book book = new Book();
//    book.setBid(Integer.valueOf(bid));
//    book.setBname(bname);
//    book.setPrice(Float.valueOf(price));
    System.out.println(book);
    System.out.println("BookAction.add...");
    request.setAttribute("content", "Kissship");
//    response.sendRedirect("res.jsp");
    return "toList";
  }
  public String del(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    System.out.println("BookAction.del...");
    request.setAttribute("content", "Kissship");
//    response.sendRedirect("res.jsp");
    return "toList";
  }
  public String upd(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    System.out.println("BookAction.upd...");
    request.setAttribute("content", "Kissship");
//    response.sendRedirect("res.jsp");
    return "toList";
  }
  public String list(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    System.out.println("BookAction.list...");
    request.setAttribute("content", "Kissship");
//    request.getRequestDispatcher("res.jsp").forward(request, response);
    return "list";
  }
  @Override
  public Book getModel() {
    return book;
  }
}

到这我们就可以开始写jsp文件

index.jsp:
<%@ 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>
<p>版本1</p>
弊端:每一张表对应的每一个操作,都要写一个servlet类来处理<hr>
<a href="bookAdd.action">增加</a>
<a href="bookDel.action">删除</a>
<a href="bookUpd.action">修改</a>
<a href="bookList.action">查询</a>
<hr><hr>
<p>版本2</p>
弊端:每一张表对应的每一个操作,只要写一个servlet类来处理,但是每增加一个操作,都需要改变原有代码,换句话说要增加条件分支<hr>
<a href="book.action?methodName=add">增加</a>
<a href="book.action?methodName=del">删除</a>
<a href="book.action?methodName=upd">修改</a>
<a href="book.action?methodName=list">查询</a>
<hr><hr>
<p>版本3</p>
弊端:虽然解决了代码冗余的问题,但是放到项目范围,反射的代码是重复的<hr>
<a href="book.action?methodName=add">增加</a>
<a href="book.action?methodName=del">删除</a>
<a href="book.action?methodName=upd">修改</a>
<a href="book.action?methodName=list">查询</a>
<hr><hr>
<p>版本4</p>
弊端:中央控制器的action容器加载不可以灵活配置<hr>
<a href="order.action?methodName=add">增加</a>
<a href="order.action?methodName=del">删除</a>
<a href="order.action?methodName=upd">修改</a>
<a href="order.action?methodName=list">查询</a>
<a href="goods.action?methodName=list">检验异常</a>
<hr><hr>
<p>版本5</p>
常识:查询必然转发,增删改使用重定向
弊端:中央控制器的action容器加载不可以灵活配置  <hr>
<a href="book.action?methodName=add">增加</a>
<a href="book.action?methodName=del">删除</a>
<a href="book.action?methodName=upd">修改</a>
<a href="book.action?methodName=list">查询</a>
<hr><hr>
<p>版本6</p>
弊端:jsp传递到后台,封装到实体类的代码过多<hr>
<a href="book.action?methodName=add&bid=1&bname=Kissship&price=9.9">增加</a>
<a href="book.action?methodName=del">删除</a>
<a href="book.action?methodName=upd">修改</a>
<a href="book.action?methodName=list">查询</a>
<hr><hr>
<p>版本7</p>
解决了版本6的问题<hr>
<a href="book.action?methodName=add&bid=2&bname=Kissship&price=99.9">增加</a>
<a href="book.action?methodName=del">删除</a>
<a href="book.action?methodName=upd">修改</a>
<a href="book.action?methodName=list">查询</a>
</body>
</html>

在我们运行之前我们可以先写一个res.jsp文件用来测试

<%@ 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>
跳转成功:携带数据${content };
</body>
</html>

请看结果如图:


目录
相关文章
|
11天前
|
JavaScript 前端开发
JSf中ilter的使用方法
JSf中ilter的使用方法
|
19天前
|
JSON 前端开发 API
Apache HttpClient调用Spring3 MVC Restful Web API演示
Apache HttpClient调用Spring3 MVC Restful Web API演示
18 1
|
8天前
|
IDE Java API
如何使用Java和Spring Boot来开发一个基本的RESTful API
如何使用Java和Spring Boot来开发一个基本的RESTful API
10 0
|
1月前
|
Java API Maven
使用Java和Spring Boot构建RESTful API
使用Java和Spring Boot构建RESTful API
23 0
|
1月前
|
XML Java 数据格式
JAVAEE框架之Spring注解
JAVAEE框架之Spring注解
43 0
|
10月前
|
前端开发 Java 开发者
深入解析Java中的 @Controller 注解:构建灵活的Web应用
在现代的Java Web开发中,控制层是连接用户界面和后端逻辑的关键环节。Spring框架为我们提供了丰富的注解来构建控制层,其中 @Controller 注解在MVC架构中扮演着重要的角色。本文将带您深入了解 @Controller 注解,探讨其特点、用法、实现方式以及在实际应用中的优势。
|
Java
【JavaWeb】Java Web三大组件之Filter过滤器
JavaWeb中的过滤器:当浏览器访问服务器资源时,过滤器就会拦截浏览器发过来的请求,实现一些特别的功能。 作用:一般用于完成通用的操作,如登录验证,身份验证,统一字符编码和敏感字过滤等。
152 1
|
前端开发 Java API
Spring MVC框架:第二章:视图解析器和@RequestMapping注解使用在类级别及获取原生Servlet API对象
Spring MVC框架:第二章:视图解析器和@RequestMapping注解使用在类级别及获取原生Servlet API对象
254 0
|
Dubbo Java 应用服务中间件
SpringBoot整合Dubbo的第二种方式——API(自定义Configuration配置类)
SpringBoot整合Dubbo的第二种方式——API(自定义Configuration配置类)
SpringBoot整合Dubbo的第二种方式——API(自定义Configuration配置类)
|
JSON Java 应用服务中间件
【SpringBoot 2】(九)异常处理 web原生组件的注入
【SpringBoot 2】(九)异常处理 web原生组件的注入
643 0
【SpringBoot 2】(九)异常处理 web原生组件的注入