J2EE 快速入门之第十三章 自定义mvc_2

目录

一:博客重点

二:反射增强第一步:

   1.config.xml建模

     2.获取Action配置信息

     3.反射机制实例化Action子控制器

     4.将请求委托给子控制器处理并返回结果码

     5.根据返回结果码进行页面跳转(重定向/转发)

三:反射增强第二步:

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

     1.创建DispatcherAction类

DispatcherAction extends Action

          2.根据请求参数获取方法名,利用反射机制调用方法

参数名:methodName:add/minus/mul/div 

     3.创建CalAction类(CalAction提供一组加减乘除的方法)

CalAction extends DispatcherAction

提供一组与execute方法的参数、返回值相同的方法,只有方法名不一样

四、反射增强第三步:

     1.利用反射机制对Java对象进行属性赋值

 简化调用:BeanUtils.populate(calBean, parameterMap);

     2.ModelDriver接口返回的对象不能为空


一:博客重点

            通过XML对自定义MVC框架进行3步增强

二:反射增强第一步:

   1.config.xml建模

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE config>
<!--config标签:可以包含0~N个action标签 -->
<config>
<action path="/helloAction" type="com.zking.mvc.action.HelloAction"/>
<action path="/addAction" type="com.zking.mvc.action.AddAction">
<forward path="/rs.jsp" redirect="false" name="success"/>
</action>
<action path="/calAction" type="com.zking.mvc.action.CalAction">
<forward path="/rs.jsp" redirect="false" name="success"/>
</action>
</config>

     2.获取Action配置信息

//获取请求路径*.action 例如:/helloAction.action
String requestURL = req.getServletPath();
//获取请求路径名 * 例如:/helloAction
int start = requestURL.indexOf("/");
int end = requestURL.lastIndexOf(".");
String requestName = requestURL.substring(start, end);
//根据请求路径名获取对应的ActionModel建模对象(path和type)
ActionModel actionModel = this.findAction(requestName);
/**
	 * 根据请求路径名获取对应的ActionModel建模对象(path和type)
	 * path:请求路径名,例如:/helloAction
	 * type:对应子控制器类Action的全路径名,Class.forName
	 * @param requestName 请求路径名
	 * @return
	 */
	private ActionModel findAction(String requestName) {
		ActionModel actionModel = configModel.get(requestName);
		if(null==actionModel)
			throw new RuntimeException("ActionModel不存在!!!");
		return actionModel;
	}

 

     3.反射机制实例化Action子控制器

//根据ActionModel中的type属性实现子控制器类Action反射机制实例化
Action action = this.createAction(actionModel.getType());
/**
	 * 根据ActionModel中的type属性实现子控制器类Action反射机制实例化
	 * @param type 类的全路径名,例如:com.zking.xxx.action.HelloAction
	 * @return
	 */
	private Action createAction(String type) {
		try {
			//获取类对象(3种),此处使用Class.forName
			Class cls = Class.forName(type);
			//直接反射机制实例化子控制器类
			return (Action) cls.newInstance();
		} catch (Exception e) {
			throw new RuntimeException("反射机制实例化Action子控制器类失败!");
		}
	}

     4.将请求委托给子控制器处理并返回结果码

//将请求委托给具体的子控制器类Action去处理并返回请求结果码
 String code = action.execute(req, resp);

     5.根据返回结果码进行页面跳转(重定向/转发)

//根据请求结果码跳转页面(重定向和转发)
this.gotoPage(req, resp, code, actionModel);
/**
	 * 跳转页面(转发或者重定向)
	 * @param req
	 * @param resp
	 * @param code 请求结果码,对应config.xml中forward标签的name属性
	 * @param actionModel config.xml中action标签对应的建模实体类,其中包含了0~N个forward标签的建模实体类ForwardModel
	 * @throws ServletException
	 * @throws IOException
	 */
	private void gotoPage(HttpServletRequest req,HttpServletResponse resp,
			String code,ActionModel actionModel) throws ServletException,IOException{
		//判断结果码是否为空
		if(null==code)
			return;
		//根据请求结果码获取对应的ForwardModel
		ForwardModel forwardModel = actionModel.get(code);
		//判断forwardModel是否为空
		if(null==forwardModel)
			throw new RuntimeException("ForwardModel不存在!!!");
		//post和get的区别?
		//重定向和转发的区别?
		//1) 重定向地址栏改变,转发不变
		//2) 重定向能重定向到外部资源,转发只能转发项目内部资源
		//3) 重定向二次请求,转发一次请求
		//4) 重定向一般存储到session或者application(不推荐);转发保存到request(推荐)
		//根据forwardModel中的redirect属性判断跳转方式(重定向或者转发)
		if(forwardModel.isRedirect())
			resp.sendRedirect(req.getContextPath()+forwardModel.getPath());
		else
			req.getRequestDispatcher(forwardModel.getPath()).forward(req, resp);
	}
	


三:反射增强第二步:

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

     1.创建DispatcherAction类

  • DispatcherAction extends Action

     
     2.根据请求参数获取方法名,利用反射机制调用方法

  • 参数名:methodName:add/minus/mul/div 

package com.zking.mvc.framework;

import java.io.IOException;
import java.lang.reflect.Method;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

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

/**
 * 反射调用方法,不做具体的核心业务逻辑处理
 * @author Administrator
 *
 */
public class DispatcherAction extends Action {

	/**
	 * 反射调用具体的子控制器类Action中的方法
	 */
	@Override
	public final String execute(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		try {
			//1.获取请求方法名(要调用哪一个方法去完成具体的核心业务)
			String methodName = req.getParameter("methodName");
			//判断methodName是否为空
			if(null==methodName) {
				//获取请求参数集合Map
				Map<String, String[]> params = req.getParameterMap();
				//获取请求参数集合的键值对
				Set<Entry<String,String[]>> entrySet = params.entrySet();
				//循环遍历键值对
				for (Entry<String, String[]> entry : entrySet) {
					//获取Key,对应表单元素中的name属性
					String key = entry.getKey();
					//判断key中是否包含methodName:的请求参数名
					if(key.indexOf("methodName:")==0) {
						methodName=key.replace("methodName:", "");
						break;
					}
				}
			}
			//2.获取类对象
			Class cls = this.getClass();
			//3.反射调用方法
			Method method=cls.getDeclaredMethod(methodName, HttpServletRequest.class,HttpServletResponse.class);
			//4.设置访问权限
			method.setAccessible(true);
			//5.执行方法并返回结果码
			Object code = method.invoke(this, req,resp);
			
			return null==code?null:code.toString();
		} catch (Exception e) {
			e.printStackTrace();
			throw new RuntimeException("反射调用方法异常!");
		}
	}

}

     3.创建CalAction类(CalAction提供一组加减乘除的方法)

  • CalAction extends DispatcherAction

  • 提供一组与execute方法的参数、返回值相同的方法,只有方法名不一样

package com.zking.mvc.action;

import java.io.IOException;

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

import com.zking.mvc.entity.CalBean;
import com.zking.mvc.framework.DispatcherAction;
import com.zking.mvc.framework.DriverModel;

/**
 * 做一件事情:XxxAction extends Action  -> execute
 * 做多件事情:XxxAction extends DispatcherAction 
 * 必须要传递一个参数叫做methodName
 * 注:只要继承了DispatcherAction,则提供一组与execute相同的参数和返回值的方法,只有方法名不同
 * @author Administrator
 *
 */
public class CalAction extends DispatcherAction implements DriverModel<CalBean> {

	//必须要在返回之前先完成实例化操作
	private CalBean calBean=new CalBean();
	@Override
	public CalBean getModel() {
		// TODO Auto-generated method stub
		return calBean;
	}
	
	
	/**
	 * 加法
	 * @param req
	 * @param resp
	 * @return
	 * @throws ServletException
	 * @throws IOException
	 */
	public String add(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {
		System.out.println(calBean);
		/*int num1=Integer.parseInt(req.getParameter("num1"));
		int num2=Integer.parseInt(req.getParameter("num2"));*/
		int rs=calBean.getNum1()+calBean.getNum2();
		req.setAttribute("rs", rs);
		//req.getRequestDispatcher("/rs.jsp").forward(req, resp);
		return "success";
	}

	/**
	 * 减法
	 * @param req
	 * @param resp
	 * @return
	 * @throws ServletException
	 * @throws IOException
	 */
	public String minus(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {
		/*int num1=Integer.parseInt(req.getParameter("num1"));
		int num2=Integer.parseInt(req.getParameter("num2"));*/
		int rs=calBean.getNum1()-calBean.getNum2();
		req.setAttribute("rs", rs);
		//req.getRequestDispatcher("/rs.jsp").forward(req, resp);
		return "success";
	}
	
	/**
	 * 乘法
	 * @param req
	 * @param resp
	 * @return
	 * @throws ServletException
	 * @throws IOException
	 */
	public String div(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {
		/*int num1=Integer.parseInt(req.getParameter("num1"));
		int num2=Integer.parseInt(req.getParameter("num2"));*/
		int rs=calBean.getNum1()*calBean.getNum2();
		req.setAttribute("rs", rs);
		//req.getRequestDispatcher("/rs.jsp").forward(req, resp);
		return "success";
	}
	
	/**
	 * 除法
	 * @param req
	 * @param resp
	 * @return
	 * @throws ServletException
	 * @throws IOException
	 */
	public String mod(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {
		/*int num1=Integer.parseInt(req.getParameter("num1"));
		int num2=Integer.parseInt(req.getParameter("num2"));*/
		int rs=calBean.getNum1()/calBean.getNum2();
		req.setAttribute("rs", rs);
		//req.getRequestDispatcher("/rs.jsp").forward(req, resp);
		return "success";
	}

	
	
	
}


四、反射增强第三步:

       利用ModelDriver接口对Java对象进行赋值(反射读写方法)

     1.利用反射机制对Java对象进行属性赋值

  •  简化调用:BeanUtils.populate(calBean, parameterMap);

//反射参数赋值
this.setParameters(req, action);
/**
	 * 反射参数赋值
	 * @param req
	 * @param action
	 */
	private void setParameters(HttpServletRequest req,Action action) {
		//判断action子控制器类是否实现了DriverModel接口
		if(action instanceof DriverModel) {
			//强转
			DriverModel dm=(DriverModel) action;
			//获取DriverModel接口对应方法的返回值
			Object model = dm.getModel();
			//获取请求参数集合
			Map<String, String[]> params = req.getParameterMap();
			//通过第三方工具类完成反射参数赋值工作
			try {
				BeanUtils.populate(model, params);
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}

     2.ModelDriver接口返回的对象不能为空

package com.zking.mvc.framework;

public interface DriverModel<T> {
	
	public T getModel();
}

 注:Action多例模式?因为Action的属性要用来接收参数

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值