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>