自定义MVC详解

J2EE

目录

J2EE

1、什么是mvc

2、mvc组成部分

3、搭建mvc(代码)

1、中央控制器:DispathServlet

2、模型驱动:ModelDriver

3、子控制器接口:Action

4、增强子控制器:ActionSupport

5、具体子控制器案例BookServlet

6、Dao层

7、XML配置文件

8、web.xml

4、界面效果图

5、mvc的执行流程

1、简单流程,首先大致感受一下他的流程

2、详细流程,建议按照这个流程图来理解每个类之间的关系和作用,是如何构成mvc的。

6、总结:


1、什么是mvc

全名Model View Controller,模型视图控制器,是一种软件设计的典范。

用业务逻辑、数据和界面显示分离的方法来组织代码,在需要程序进行改动时不需要重新修改代

码,达到减少代码的作用。

我的理解:不适用mvc我们会创建很多个servlet分别来实现增加,删除...操作,各司其职。mvc就

像是一个通用的servlet,其中组成有一个中央控制器,根据我们的请求不同来实现不同的业务逻

辑。前端的请求进入mvc进过一系列处理(取数据并不和中央控制器产生联系)之后将结果反馈给

界面。很明显的诠释了业务逻辑,数据和显示界面分离这句话。

2、mvc组成部分

①XML模型ConfigModelFactory:面对对象的思想操作我们的XML文件,修改XML来实现不同的逻辑。

②中央控制器DispathServlet:处理所有请求,分配给具体的子控制器实现业务。

③子控制器Action(接口):对子控制器的一种约束。

④增强子控制器ActionSupport:所有具体子控制器的父类,实现Action接口。

⑤模型驱动ModelDriver(泛型接口):具体的子控制器实现后实现返回子控制指定类型的对象,在中央控制器

中使用BeanUtils类对具体的子控制器类中定义的对象通过请求对象req进行初始化。

3、搭建mvc(代码)

1、中央控制器:DispathServlet

package com.zwf.mvc;

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;

/**
 * 中央控制器
 * 作用:可以解决所有类型的请求,和浏览器直接关联
 * @author zjjt 隔壁程序员老张
 *
 */
@WebServlet("*.action")
public class DispathServlet extends HttpServlet{
	
	/**
	 * XML配置文件模型
	 */
	private ConfigModel configModel=null;
	
	/**
	 * XML配置文件模型的初始化
	 * ②
	 */
	@Override
	public void init() throws ServletException {
		String configurationlocation = this.getInitParameter("configurationlocation");
		try {
			if(configurationlocation != null && !configurationlocation.equals("")) {
				configModel = ConfigModelFactory.build(configurationlocation);
			}else {
				configModel = ConfigModelFactory.build();
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		doPost(req, resp);
	}
	
	@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //①
		String URL = req.getRequestURI();//获取请求路径
		URL = URL.substring(URL.lastIndexOf("/"),URL.lastIndexOf("."));//截取子控制器名称
		ActionModel actionModel = configModel.pop(URL);//模型中获取子控制器模型
		String type = actionModel.getType();//获得子控制器全路径名
		ActionSupport action = null;//定义子控制器父类
		try {
            //③
			action = (ActionSupport) Class.forName(type).newInstance();//强转
			if(action instanceof ModelDriver) {//如果该子控制器实现了模型驱动接口
				ModelDriver m = (ModelDriver) action;//强转
				Object bean = m.getModel();//获得子控制器传入的对象
                //请求的所有参数对对象进行初始化
				BeanUtils.populate(bean, req.getParameterMap());
			}
            //④
			String res = action.execute(req, resp);//执行方法并且获得ForwardModel名称
            //⑤
			ForwardModel forwardModel = actionModel.pop(res);//获取ForwardModel
			String path = forwardModel.getPath();//获得跳转路径
			boolean isRedirect = forwardModel.isRedirect();
            //⑥
			if(isRedirect) {//重定向
				resp.sendRedirect(req.getContextPath()+path);
			}else {//转发
				req.getRequestDispatcher(path).forward(req, resp);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}

2、模型驱动:ModelDriver

package com.zwf.mvc;

/**
 * 模型驱动,由具体的子控制器实现,在中央控制器中来对具体的子控制器中的对象初始化。
 * @author zjjt 隔壁程序员老张
 *
 * @param <T>
 */
public interface ModelDriver <T> {
	T getModel();	
}

3、子控制器接口:Action

package com.zwf.mvc;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * 子控制器接口,对子控制器的行为约束。也是属于mvc中的一个规范
 * @author zjjt 隔壁程序员老张
 *
 */
public interface Action {
	String execute(HttpServletRequest req,HttpServletResponse res);
}

4、增强子控制器:ActionSupport

package com.zwf.mvc;

import java.lang.reflect.Method;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * 所有子控制器的父类
 * 实现子控制器接口Action,表示所有的子控制器必须具备execute方法,是对子控制器的行为约束
 * 具体子控制器与Dao层相关
 * @author zjjt 隔壁程序员老张
 *
 */
public class ActionSupport implements Action{
	
	/**
	 * 获得请求参数方法名称methodName,然后反射动态调用具体子类的methodName方法
	 */
	@Override
	public String execute(HttpServletRequest req, HttpServletResponse resp) {
		String methodName = req.getParameter("methodName");
		String res = null;
		try {
			Method m = this.getClass().getDeclaredMethod(methodName, HttpServletRequest.class, HttpServletResponse.class);
			m.setAccessible(true);
			res =(String) m.invoke(this, req, resp);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return res;
}

中央控制器中通过反射实例化具体子对象,由于不知道会是哪一个子控制器,所以创建一个父类接收,事实上是子控制器本身。因此在Actionsupport类中反射调用方法是调用反射调用具体子控制器的方法。XML模型类就不列出来了,在XML建模有相关的模型类。

5、具体子控制器案例BookServlet

package com.servlet.zwf;

import java.util.List;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.dao.zwf.BookDao;
import com.entity.zwf.Book;
import com.util.zwf.PageBean;
import com.zwf.mvc.ActionSupport;
import com.zwf.mvc.ModelDriver;

/**
 * 书籍控制器
 * @author zjjt  隔壁程序员老张
 *
 */
public class BookServlet extends ActionSupport implements ModelDriver<Book>{
	/**
	 * 需要通过请求进行初始化的书籍对象,一下的业务逻辑都将使用该对象进行处理。因为是来自用户请求进行初始化的对象。
	 */
	private Book b=new Book();
	
	/**
	 * 书籍Dao层对象
	 */
	BookDao bd=new BookDao();
	
	/**
	 * 实现模型驱动接口重写的方法,返回对象b在中央控制器中有请求进行初始化
	 */
	@Override
	public Book getModel() {
		return b;
	}
	
	/**
	 * 增加书籍方法
	 * @param req 前端请求对象
	 * @param resp 前端响应对象
	 * @return XML文件中forward标签名,决定后续的转发或者重定向的地址
	 */
	public String add(HttpServletRequest req, HttpServletResponse resp) {
		try {
			bd.add(b);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return "toList";
	}
	
	/**
	 * 修改书籍方法,调用单个查询方法
	 * @param req
	 * @param resp
	 * @return
	 */
	public String toEdit(HttpServletRequest req, HttpServletResponse resp){
		try {
			b = bd.getOne(b);
		} catch (Exception e) {
			e.printStackTrace();
		}
		req.setAttribute("b", b);
		return "toEdit";
	}
	
	/**
	 * 查询方法,将数据都放入请求中再根据XML决定跳转地址然后进行数据显示
	 * @param req
	 * @param resp
	 * @return
	 */
	public String list(HttpServletRequest req, HttpServletResponse resp){
		PageBean p=new PageBean();//创建PageBean对象
		p.init(req);//初始化PageBean
		List<Book> all=null;//数据容器
		try {
			all = bd.getAll(Book.class, p, b);//调用方法
		} catch (Exception e) {
			e.printStackTrace();
		}
		req.setAttribute("books", all);//将数据放入请求中
		req.setAttribute("pageBean", p);
		return "list";
	}
	
	/**
	 * 修改方法
	 * @param req
	 * @param resp
	 * @return
	 */
	public String edit(HttpServletRequest req, HttpServletResponse resp) {
		try {
			bd.edit(b);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return "toList";
	}
	
	/**
	 * 删除方法
	 * @param req
	 * @param resp
	 * @return
	 */
	public String del(HttpServletRequest req, HttpServletResponse resp) {
		try {
			bd.del(b);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return "toList";
	}
	
}

6、Dao层

package com.dao.zwf;

import java.util.List;

import com.entity.zwf.Book;
import com.util.zwf.PageBean;

/**
 *  书籍Dao层
 * @author zjjt  隔壁程序员老张
 *
 */
public class BookDao extends BookBase<Book>{
	
	public List<Book> getAll(Class<Book> clz, PageBean p ,Book b) throws Exception {
		String sql="select * from t_mvc_book";
		String key = "";
		String bname=b.getBname();
		if(bname != null) {
			sql+=" where bname like ?";
			key=bname;
		}
		return super.getAll(sql, clz, p, key);
	}
	
	public void add(Book b) throws Exception {
		String sql="insert into t_mvc_book values(?,?,?)";
		String attr[]= {"bid","bname","price"};
		super.executeUpdate(sql, b, attr);
	}
	
	public void del(Book b) throws Exception {
		String sql="delete from t_mvc_book where bid="+b.getBid();
		System.out.println(sql);
		super.executeUpdate(sql, b, null);
	}
	
	public Book getOne(Book b) throws Exception {
		String sql="select * from t_mvc_book where bid="+b.getBid();
		return super.getAll(sql, Book.class, null, "").get(0);
	}
	
	public void edit(Book b) throws Exception {
		String sql="update t_mvc_book set bname=?,price=? where bid="+b.getBid();
		String attr[]= {"bname","price"};
		super.executeUpdate(sql, b, attr);
	}
}

7、XML配置文件

<?xml version="1.0" encoding="UTF-8"?>
<config>
	<!-- 
		在这里每加一个配置,就相当于actions.put("/goods", new GoodsAction());
		这样就解决了代码灵活性的问题
	 -->
	<action path="/book" type="com.servlet.zwf.BookServlet">
		<forward name="list" path="/index.jsp" redirect="false" />
		<forward name="toEdit" path="/bookEdit.jsp" redirect="false" />
		<forward name="toList" path="/book.action?methodName=list" redirect="true" />
	</action>
	
	<action path="/goods" type="com.zking.web.GoodsAction">
		<forward name="failed" path="/login.jsp" redirect="false" />
		<forward name="success" path="/main.jsp" redirect="true" />
	</action>
	
	<action path="/order" type="com.zking.web.OrderAction">
		<forward name="failed" path="/login.jsp" redirect="false" />
		<forward name="success" path="/main.jsp" redirect="true" />
	</action>
</config>

8、web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" id="WebApp_ID" version="3.1">
  <display-name>MVC</display-name>
  <servlet>
    <servlet-name>DispathServlet</servlet-name>
    <servlet-class>com.zwf.mvc.DispathServlet</servlet-class>
    <init-param>
      <param-name>configurationlocation</param-name>
      <param-value>/mvc.xml</param-value>
    </init-param>
  </servlet>
  <servlet-mapping>
    <servlet-name>DispathServlet</servlet-name>
    <url-pattern>*.action</url-pattern>
  </servlet-mapping>
</web-app>

4、界面效果图

具体的操作和之前的增删改查无异,但是底层发生了变化,mvc版本。

5、mvc的执行流程

1、简单流程,首先大致感受一下他的流程

2、详细流程,建议按照这个流程图来理解每个类之间的关系和作用,是如何构成mvc的。

强烈推荐图和代码结合学习,跟着这个流程来理解学习上面的代码。

流程讲解

首先是用户进入主界面需要看到所有的数据,用户请求会被中央控制器拦截然后进行处理。

首先截取请求路径中的 /book,拿到对应的action模型,得到对应的子控制器的全路径名,反

射实例,使用增强子控制器说明实例化。调用execute()方法,子控制器调用Dao层进行数据

操作。如果BookServlet执行的是list(),返回“list”,然后通过该字符串得到对应的forward模

型,拿到path,和redirect的值,再进行转发或者重定向处理。

6、总结:

再反过来想,以前每需要一个add或者del操作等都需要定义一个servlet,而且每一个servlet中都有

获取请求参数然后实例化成对象再进入Dao层进行处理数据,还要定义转发或者重定向。学习了

mvc之后,之前每写一个servlet都需要写一次获得请求参数然后构建具体对象(mvc由模型确定进

行一次性赋值创建,该对象在子控制器中已经定义好),然后用该对象进行Dao层方面的操作

(mvc由子控制器进行方法调用,由增强子控制器截取请求参数决定反射调用哪个方法),再将需

要的数据设置在请求对象中(mvc中由具体的子控制器完成),最后转发或者重定向到要跳转的对

象(mvc由中央控制器通过xml文件配置判断转发还是重定向)。如果有100个servlet,就要编写

100次上述操作,但是拥有mvc之后,我们仅仅只需要编写我们的xml文件来完成不同的业务逻辑。

通用分页是PageBean为核心点,从头到尾都有它在,自定义mvc则是req请求对象全程都在。

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小张同学_java

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值