MVC模式 2

本文详细介绍了MVC框架的增强方法,包括通过XML配置子控制器、利用结果码控制页面跳转、将一组相关操作整合到单个Action中、使用ModelDriver接口自动封装实体类以及使配置文件更具灵活性。

MVC框架

延续MVC框架1的实列,通过XML对自定义mvc框架进行增强
1、将Action的信息配置到xml(反射实例化)

在主控制器DispatcherServlet类中原来子控制器的来源是map集合,这样的话子控制器会被写死在map容器里,代码不够灵活 ,现在讲子控制器以配置的方式放在config.xml中,未来可以通过改变config.xml中的内容,随意给中央控制器添加子控制器;

/**
 * 主控制器
 */
public class DispatcherServlet extends HttpServlet{
	private static final long serialVersionUID = 6716422786850137569L;
	private ConfigModel configModel;
	//初始化方法
	public void init() {
//		//加法
//		actionMap.put("/addCal", new AddCalAction());
//		//减法
//		actionMap.put("/delCal", new DelCalAction());
//		//乘法
//		actionMap.put("/chengCal", new ChengCalAction());
//		//除法
//		actionMap.put("/chuCal", new ChuCalAction());
		try {
//			将原有的读取框架的默认配置文件转变成读取课配置路径的配置文件
			String xmlPath = this.getInitParameter("xmlPath");
			if(xmlPath == null || "".equals(xmlPath))
				configModel = ConfigModelFactory.build();
			else
				configModel = ConfigModelFactory.build(xmlPath);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			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 {
		init();
		String url = req.getRequestURI();//T224_mvc/xxx.action
		url = url.substring(url.lastIndexOf("/"), url.lastIndexOf("."));
		
		ActionModel actionModel = configModel.pop(url);
		if(actionModel == null) {
			throw new RuntimeException("你没有配置对应的子控制器Action!!!");
		}
		try {
			//原来子控制器的来源是map集合,这样的话子控制器会被写死在map容器里,代码不够灵活
//			现在讲子控制器以配置的方式放在config.xml中,未来可以通过改变config.xml中的内容
//			随意给中央控制器添加子控制器
			Action action = (Action)Class.forName(actionModel.getType()).newInstance();
		}
			//每个子控制器,都需要对结果进行对应的处理,也就是说要么转发,要么重定向,代码重复量较大
//			针对于这一现象,将其交给配置文件来处理
//			调用了增强版的子控制器来处理业务逻辑
			String code = action.execute(req, resp);
			ForwardModel forwardModel = actionModel.pop(code);
			if(forwardModel == null) {
				throw new RuntimeException("你没有配置对应的子控制器Action的处理方式Forward!!!");
			}
			String jspPath = forwardModel.getPath();
			if(forwardModel.isRedirect()) {
				resp.sendRedirect(req.getContextPath()+jspPath);
			}else {
				req.getRequestDispatcher(jspPath).forward(req, resp);
			}
		} catch (InstantiationException e) {
			e.printStackTrace();
		} 
	}
}
2、 通过结果码控制页面的跳转

每个子控制器,都需要对结果进行对应的处理,也就是说要么转发,要么重定向,代码重复量较大,针对于这一现象,将其交给配置文件来处理,调用了增强版的子控制器来处理业务逻辑;

/**
 * 主控制器
 */
public class DispatcherServlet extends HttpServlet{
	private static final long serialVersionUID = 6716422786850137569L;
	private ConfigModel configModel;
	//初始化方法
	public void init() {
//		//加法
//		actionMap.put("/addCal", new AddCalAction());
//		//减法
//		actionMap.put("/delCal", new DelCalAction());
//		//乘法
//		actionMap.put("/chengCal", new ChengCalAction());
//		//除法
//		actionMap.put("/chuCal", new ChuCalAction());
		try {
//			将原有的读取框架的默认配置文件转变成读取课配置路径的配置文件
			String xmlPath = this.getInitParameter("xmlPath");
			if(xmlPath == null || "".equals(xmlPath))
				configModel = ConfigModelFactory.build();
			else
				configModel = ConfigModelFactory.build(xmlPath);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			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 {
		init();
		String url = req.getRequestURI();//T224_mvc/xxx.action
		url = url.substring(url.lastIndexOf("/"), url.lastIndexOf("."));
//		Action action = new AddCalAction(); 
//		class Student extends Person
//		Person p = new Student();
//		Action action = actionMap.get(url);
//		req.setAttribute("uri", url);
		
		ActionModel actionModel = configModel.pop(url);
//		String type = actionModel.getType();
		if(actionModel == null) {
			throw new RuntimeException("你没有配置对应的子控制器Action!!!");
		}
		try {
			//每个子控制器,都需要对结果进行对应的处理,也就是说要么转发,要么重定向,代码重复量较大
//			针对于这一现象,将其交给配置文件来处理
//			调用了增强版的子控制器来处理业务逻辑
			String code = action.execute(req, resp);
			ForwardModel forwardModel = actionModel.pop(code);
			if(forwardModel == null) {
				throw new RuntimeException("你没有配置对应的子控制器Action的处理方式Forward!!!");
			}
			String jspPath = forwardModel.getPath();
			if(forwardModel.isRedirect()) {
				resp.sendRedirect(req.getContextPath()+jspPath);
			}else {
				req.getRequestDispatcher(jspPath).forward(req, resp);
			}
		} catch (InstantiationException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		} 
	}
}
------------------------------
/**
 * 子控制器
 *    专门用来处理业务逻辑的
 * @author shiyi
 *
 */
public interface Action {
	String execute(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException ;
}
--------------------------------
在xml中进行配置
<?xml version="1.0" encoding="UTF-8"?>
<config>
	<action path="/addCal" type="com.zking.web.AddCalAction">
		<forward name="calRes" path="/calRes.jsp" redirect="false" />
	</action>
	<action path="/delCal" type="com.zking.web.DelCalAction">
		<forward name="calRes" path="/calRes.jsp" redirect="false" />
	</action>
	<action path="/chengCal" type="com.zking.web.ChengCalAction">
		<forward name="calRes" path="/calRes.jsp" redirect="false" />
	</action>
	<action path="/chuCal" type="com.zking.web.ChuCalAction">
		<forward name="calRes" path="/calRes.jsp" redirect="false" />
	</action>
</config>

3 、将一组相关的操作放到一个Action中(反射调用方法)

之前的Action只能处理有关实体类的一个业务,现在这个是增强版的子控制器,凡是操作这个实体类的操作,对应方法都可以写在当前增强版的子控制器来完成;

public class ActionSupport implements Action {

	@Override
	public String execute(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		String methodName = req.getParameter("methodName");
		String code = null;
		try {
			Method method = this.getClass().getDeclaredMethod(methodName,
					HttpServletRequest.class,
					HttpServletResponse.class);
			method.setAccessible(true);
//			具体调用了你自己所写的子控制器中的方法来处理浏览器请求
			code = (String) method.invoke(this, req,resp);
		} catch (NoSuchMethodException e) {
			e.printStackTrace();
		} catch (SecurityException e) {
			e.printStackTrace();
		}catch (IllegalAccessException e) {
			e.printStackTrace();
		} catch (IllegalArgumentException e) {
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			e.printStackTrace();
		}
		return code;
	}
}
提供一组与execute方法的参数、返回值相同的方法,只有方法名不一样

public class CalActiona extends ActionSupport implements ModelDriven<Cal>{
	private Cal cal = new Cal();
	public String add(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		req.setAttribute("res", Integer.valueOf(cal.getNum1())+ Integer.valueOf(cal.getNum2()));
		return "calRes";
	}
	
	public String del(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		req.setAttribute("res", Integer.valueOf(cal.getNum1())- Integer.valueOf(cal.getNum2()));
		return "calRes";
	}
	
	public String cheng(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		req.setAttribute("res", Integer.valueOf(cal.getNum1())* Integer.valueOf(cal.getNum2()));
		return "calRes";
	}
	
	public String chu(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		req.setAttribute("res", Integer.valueOf(cal.getNum1())/ Integer.valueOf(cal.getNum2()));
		return "calRes";
	}
	@Override
	public Cal getModel() {
		return cal;
	}
}
---------------------
package com.shiyi.entity;
public class Cal {
	private String num1;
	private String num2;
	public String getNum1() {
		return num1;
	}
	public void setNum1(String num1) {
		this.num1 = num1;
	}
	public String getNum2() {
		return num2;
	}
	public void setNum2(String num2) {
		this.num2 = num2;
	}
	public Cal(String num1, String num2) {
		super();
		this.num1 = num1;
		this.num2 = num2;
	}
	public Cal() {
		super();
	}
}
--------------------------
在xml中进行配置
<?xml version="1.0" encoding="UTF-8"?>
<config>
	<action path="/cal" type="com.zking.web.CalActiona">
		<forward name="calRes" path="/calRes.jsp" redirect="false" />
	</action>
</config>
4、 利用ModelDriver接口对Java对象进行赋值(反射读写方法)

ModelDriver(模型驱动接口) 是用来处理jsp页面传递过来的参数,将所有的参数自动封装到实体类T中;

package com.shiyi.framework;
/**
 * 模型驱动接口
 * 	是用来处理jsp页面传递过来的参数,将所有的参数自动封装到实体类T中
 * @author shiyi
 *@param <T>
 */
public interface ModelDriven<T> {
	T getModel();
}
--------------------
public class CalActiona extends ActionSupport implements ModelDriven<Cal>{
	private Cal cal = new Cal();
	public String add(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		req.setAttribute("res", Integer.valueOf(cal.getNum1())+ Integer.valueOf(cal.getNum2()));
		return "calRes";
	}
	
	public String del(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		req.setAttribute("res", Integer.valueOf(cal.getNum1())- Integer.valueOf(cal.getNum2()));
		return "calRes";
	}
	
	public String cheng(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		req.setAttribute("res", Integer.valueOf(cal.getNum1())* Integer.valueOf(cal.getNum2()));
		return "calRes";
	}
	
	public String chu(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		req.setAttribute("res", Integer.valueOf(cal.getNum1())/ Integer.valueOf(cal.getNum2()));
		return "calRes";
	}
	@Override
	public Cal getModel() {
		return cal;
	}
}
-------------------
调用模型驱动接口,获取所要操作的实体类,然后将jsp传递过来的参数,封装到实体类中
			if(action instanceof ModelDriven) {
				ModelDriven modelDriven = (ModelDriven)action;
				Object model = modelDriven.getModel();				
//				Map<String, String[]> map = req.getParameterMap();
//				for(Map.Entry<String, String[]> entry:map.entrySet()) {
//					可以获取到类对应属性bname,获取到类所对应的属性值
//				}
				BeanUtils.populate(model, req.getParameterMap());	
			}
5 、使得框架的配置文件可变

将原有的读取框架的默认配置文件转变成读取课配置路径的配置文件

	//初始化方法
	public void init() {
//		//加法
//		actionMap.put("/addCal", new AddCalAction());
//		//减法
//		actionMap.put("/delCal", new DelCalAction());
//		//乘法
//		actionMap.put("/chengCal", new ChengCalAction());
//		//除法
//		actionMap.put("/chuCal", new ChuCalAction());
		try {
//			将原有的读取框架的默认配置文件转变成读取课配置路径的配置文件
			String xmlPath = this.getInitParameter("xmlPath");
			if(xmlPath == null || "".equals(xmlPath))
				configModel = ConfigModelFactory.build();
			else
				configModel = ConfigModelFactory.build(xmlPath);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
----------------------------
在web.xml中进行配置
 <servlet>
  	<servlet-name>dispatcherServlet</servlet-name>
  	<servlet-class>com.zking.framework.DispatcherServlet</servlet-class>
  	<init-param>
  		<param-name>xmlPath</param-name>
  		<param-value>/mvc.xml</param-value>
  	</init-param>
  </servlet>
  <servlet-mapping>
  	<servlet-name>dispatcherServlet</servlet-name>
  	<url-pattern>*.action</url-pattern>
  </servlet-mapping>	
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值