自定义MVC【2】
这篇文章主要写的是对上一篇博客的自定义mvc进行加强,也就是进行代码的简化
不知道的可以去看看我的上一篇博客
首先来看咱们的中央控制器:
package com.wt.framework;
import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.beanutils.BeanUtils;
import com.wt.web.AddCalAction;
import com.wt.web.DelCalAction;
import com.wt.web.cCalAction;
import com.wt.web.xCalAction;
/**
* 主控制器
*
* @author MRCHENIKE
*
*/
public class DispatcherServlet extends HttpServlet{
private static final long serialVersionUID = 7986425427339711656L;
// private Map<String, Action> actionMap = new HashMap<>();
private ConfigModel configModel = null;
public void init() {
// actionMap.put("/addCal", new AddCalAction());
// actionMap.put("/delCal", new DelCalAction());
// actionMap.put("/cCal", new cCalAction());
// actionMap.put("/xCal", new xCalAction());
try {
// 将原有的读取框架的默认配置文件变成可读取可配置路径的配置文件
String xmlPath = this.getInitParameter("xmlPath");
if(xmlPath == null || "".equals(xmlPath)) {
configModel = ConfigModelFactory.build();
}
else {
configModel = ConfigModelFactory.build(xmlPath);
}
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 {
init();
String url = req.getRequestURI(); //mvc/xxx.action
url = url.substring(url.lastIndexOf("/"), url.lastIndexOf("."));
// Action action = actionMap.get(url);
// action.execute(req, resp);
ActionModel actionModel = configModel.pop(url);
if(actionModel ==null) {
throw new RuntimeException("你没有配置对对应的子控制器");
}
try {
//将原来子控制器的来源是map集合,这样的话子控制器会被写死在map容器中
// 代码不够灵活,现在讲子控制器以配置的方式存放在config.xml,未来可以通过改变config.xml的内容
// 随意给中央控制器添加子控制器
Action action = (Action)Class.forName(actionModel.getType()).newInstance();
//调用模型驱动接口获取所要操作的实体类,然后将jsp传递过来的参数封装到实体类中
if(action instanceof ModelDrive) {
ModelDrive modelDrive = (ModelDrive)action;
Object model = modelDrive.getModel();
// 将所有的参数自动封装到实体类T中
BeanUtils.populate(model, req.getParameterMap());
}
//每个子控制器,都需要对结果集进行对应的处理,
// 也就是说要么转发,要么重定向,代码重复量较大
// 针对于这一现象,将其交给配置文件处理
// 调用了增强版的子控制器来处理业务逻辑
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();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
}
}
}
然后通过将Action的信息配置到xml(反射实例化),也就是增强版的子控制器
package com.wt.framework;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* 之前的action只能处理一个实体类的一个业务
* 现在这个是增强版的子控制器
* 凡是这个实体例题的操作,
* 对应的方法都可以写在当前增强版的子控制器来完成
*
*
* @author MRCHENIKE
*
*/
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;
}
}
其次咱们创建一个模型驱动接口:
package com.wt.framework;
/**
* 模型驱动接口
* 是用来处理jsp页面传递过来的参数,
* 将所有的参数自动封装到实体类T中
* @author MRCHENIKE
*
* @param <T>
*/
public interface ModelDrive<T> {
T getModel();
}
因为咱们上一篇博客的demo是计算器,并且加减乘除都要一个实体类的话,显得代码非常的臃肿,然后特地写了个类来封装这些方法,而且将参数封装起来
package com.wt.web;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.wt.entity.Cal;
import com.wt.framework.ActionSupport;
import com.wt.framework.ModelDrive;
public class CalAction extends ActionSupport implements ModelDrive<Cal>{
private Cal cal = new Cal();
public String add(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//加
// String num1 = req.getParameter("num1");
// String num2 = req.getParameter("num2");
//负责运算
req.setAttribute("res", Integer.parseInt(cal.getNum1())+Integer.parseInt(cal.getNum2()));
// req.getRequestDispatcher("calRes.jsp").forward(req, resp);
return "calRes";
}
public String del(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//减
// String num1 = req.getParameter("num1");
// String num2 = req.getParameter("num2");
req.setAttribute("res", Integer.parseInt(cal.getNum1())-Integer.parseInt(cal.getNum2()));
// req.getRequestDispatcher("calRes.jsp").forward(req, resp);
return "calRes";
}
public String c(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//乘
// String num1 = req.getParameter("num1");
// String num2 = req.getParameter("num2");
req.setAttribute("res", Integer.parseInt(cal.getNum1())*Integer.parseInt(cal.getNum2()));
// req.getRequestDispatcher("calRes.jsp").forward(req, resp);
return "calRes";
}
public String chu(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//除
// String num1 = req.getParameter("num1");
// String num2 = req.getParameter("num2");
req.setAttribute("res", Integer.parseInt(cal.getNum1())/Integer.parseInt(cal.getNum2()));
// req.getRequestDispatcher("calRes.jsp").forward(req, resp);
return "calRes";
}
@Override
public Cal getModel() {
return cal;
}
}
然后咱们的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>
<script type="text/javascript">
function doSub(val){
if(val==1){
//calForm.action = "${pageContext.request.contextPath }/addCal.action";
calForm.methodName.value = "add"
}
else if(val==2){
//calForm.action = "${pageContext.request.contextPath }/delCal.action";
calForm.methodName.value = "del"
}
else if(val==3){
//calForm.action = "${pageContext.request.contextPath }/cCal.action";
calForm.methodName.value = "c"
}
else if(val==4){
//calForm.action = "${pageContext.request.contextPath }/xCal.action";
calForm.methodName.value = "chu"
}
calForm.submit();
}
</script>
</head>
<body>
<form id="calForm" name="calForm" action="${pageContext.request.contextPath }/cal.action">
num1:<input type="text" name="num1"><br>
num2:<input type="text" name="num2"><br>
<input type="hidden" name="methodName">
<button onclick="doSub(1)">+</button>
<button onclick="doSub(2)">-</button>
<button onclick="doSub(3)">*</button>
<button onclick="doSub(4)">/</button>
</form>
</body>
</html>
比如我有另一个的mvc.xml文件
<?xml version="1.0" encoding="UTF-8"?>
<config>
<action path="/cal" type="com.wt.web.CalAction">
<forward name="calRes" path="/calRes.jsp" redirect="false" />
</action>
</config>
使得框架的配置文件可变:
<?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>dispatcherServlet</servlet-name>
<servlet-class>com.wt.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>
</web-app>
我们看
下输入的
结果: