自定义mvc框架
前言
又一次写到了自定义mvc框架,也是因为对开源框架学习和理解比较重要,话不多说,和小编一起来了解…
自定义mvc概念
那么什么是自定义mvc呢?打个比方,我是一个施工人员,有施工证才能进行施工,那么我要进行施工,每次都要经过施工点的门禁,门禁则根据施工证进行存档,通过了才能到达施工点,听从安排进行具体任务施工.
那么这里的的施工人员就是一个个子控制器子类,必须要继承实现父类子控制器的执行方法,才有资格进行操作,而我们子控制器子类真正要实现功能,要每次都经过主控制器的控制过滤,才能到指定子类进行施工,分发任务的就是子控制器了.
子控制器(分发任务):
package com.xiaoyang.framework;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public abstract class Action {
public abstract String execute(HttpServletRequest req,HttpServletResponse resp);
}
子控制器子类(施工员):
package com.xiaoyang.action;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.xiaoyang.framework.Action;
public class TestAction extends Action{
@Override
public String execute(HttpServletRequest req, HttpServletResponse resp) {
req.setAttribute("test","hello,测试成功");
try {
req.getRequestDispatcher("index.jsp").forward(req, resp);
} catch (ServletException | IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
}
施工证就是:public class TestAction extends Action
,如果我没有继承Action父类子控制器,我是没有这个方法的,那么势必就不能进行施工操作…
那么门禁就是这个主控制器了:
主控制器(门禁):
package com.xiaoyang.framework;
import java.io.IOException;
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 com.xiaoyang.action.CalcAction;
import com.xiaoyang.action.TestAction;
public class ActionServlet extends HttpServlet{
public Map<String, Action> map;
@Override
public void init() throws ServletException {
// TODO Auto-generated method stub
map=new HashMap<String,Action>();
map.put("/calc",new CalcAction());
map.put("/test",new TestAction());
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// TODO Auto-generated method stub
doPost(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// TODO Auto-generated method stub
//获取请求路径
String url = req.getRequestURI();
int start = url.lastIndexOf("/");
int end=url.lastIndexOf(".");
url=url.substring(start, end);
Action action = map.get(url);
action.execute(req, resp);
}
}
那么我在初始化方法里进行的初始化存值就是给每个施工员根据施工证进行存档:
public void init() throws ServletException {
// TODO Auto-generated method stub
//实例化map集合
map=new HashMap<String,Action>();
//将案例的两个类进行存储
map.put("/calc",new CalcAction());
map.put("/test",new TestAction());
}
最后我要进行施工,那就要通过门禁了:
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// TODO Auto-generated method stub
//获取请求路径
String url = req.getRequestURI();
//获取最后一个/
int start = url.lastIndexOf("/");
//获取最后一个.
int end=url.lastIndexOf(".");
//进行路径截取
url=url.substring(start, end);
//通过截取后的key(url)在map集合中找到指定的类进行处理
Action action = map.get(url);
action.execute(req, resp);
}
如果没有施工证,门禁就没有存档,那么请求进入,也进入不了:
Action action = map.get(url);
action.execute(req, resp);
为什么学习自定义mvc
了解完自定义mvc后,相信很多人和小编一样,有着一个疑问,为什么要去学习自定义mvc?
我们在没有用框架解决时,如果处理一个增加方法,就要建一个增加处理类,如果要处理删除,就要建一个删除处理类…
就像这样:
而我们用了自定义mvc的框架,一个类的所有增删改查操作都可以在相对应的子控制器子类实现:
package com.xiaoyang.action;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.xiaoyang.framework.Action;
public class JobAction extends Action{
/**
* 子控制器安排任务
*/
@Override
public String execute(HttpServletRequest req, HttpServletResponse resp) {
// TODO Auto-generated method stub
return null;
}
/**
* 增加方法
* @param req
* @param resp
* @return
*/
public String add(HttpServletRequest req,HttpServletResponse resp) {
return null;
}
/**
* 删除方法
* @param req
* @param resp
* @return
*/
public String del(HttpServletRequest req,HttpServletResponse resp) {
return null;
}
/**
* 修改方法
* @param req
* @param resp
* @return
*/
public String edit(HttpServletRequest req,HttpServletResponse resp) {
return null;
}
/**
* 查询方法
* @param req
* @param resp
* @return
*/
public String select(HttpServletRequest req,HttpServletResponse resp) {
return null;
}
/**
* 加载单个方法
* @param req
* @param resp
* @return
*/
public String load(HttpServletRequest req,HttpServletResponse resp) {
return null;
}
}
可以看到,除了子控制器之外,我们还可以增加很多方法,可以通俗这样想:除了指定下发下来的任务,我还可以帮忙做其他的事…
不止这些,基本像很多框架的套路都是mvc这种这种高内聚,低耦合的特点、流程和原理…比如struts2,自定义mvc也是一种设计模式…
自定义mvc工作流程
通过上面小编的举例解释,相信大家有个大概了解了,那么接下来给大家分析一下自定义mvc的一个运行工作流程:
1.请求进行测试
<a href="test.action">测试一下</a>
根据配置文件,会跳转至主控制器进行处理:
<servlet>
<servlet-name>ActionServlet</servlet-name>
<servlet-class>com.xiaoyang.framework.ActionServlet</servlet-class>
</servlet>
<!-- -->
<servlet-mapping>
<servlet-name>ActionServlet</servlet-name>
<url-pattern>*.action</url-pattern>
</servlet-mapping>
2.主控制器根据存储的请求对象,找到具体子类:
存储请求路径:
public Map<String, Action> map;
@Override
public void init() throws ServletException {
// TODO Auto-generated method stub
map=new HashMap<String,Action>();
map.put("/calc",new CalcAction());
map.put("/test",new TestAction());
}
根据存储的key(请求路径名),找到具体子控制器子类:
//获取请求路径
String url = req.getRequestURI();
int start = url.lastIndexOf("/");//截取最后一个/
int end=url.lastIndexOf(".");//截取最后一个.
url=url.substring(start, end);//进行截取
Action action = map.get(url);
这里是定的固定路径值,后面会更新优化…
3.进行任务执行:
Action action = map.get(url);
action.execute(req, resp);
4.子控制器的子类进行执行:
public class TestAction extends Action{
@Override
public String execute(HttpServletRequest req, HttpServletResponse resp) {
req.setAttribute("test","hello,测试成功");
try {
req.getRequestDispatcher("index.jsp").forward(req, resp);
} catch (ServletException | IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
5.功能完成,跳转至界面显示:
<%@ 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>
</head>
<body>
${test }
</body>
</html>
附上图片供大家理解:
自定义mvc的案例
最后结合一个案例更好的去理解:
主页进行加减乘除操作:
<%@ 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>
</head>
<body>
<form action="calc.action" method="post" id="iform">
<input type="text" name="name1"><br>
<input type="text" name="name2"><br>
<input type="submit" value="+" name="num">
<input type="submit" value="-" name="num">
<input type="submit" value="*" name="num">
<input type="submit" value="/" name="num">
</form>
</body>
</html>
主控制器存储请求路径名:
public Map<String, Action> map;
@Override
public void init() throws ServletException {
// TODO Auto-generated method stub
map=new HashMap<String,Action>();
map.put("/calc",new CalcAction());
}
在dopost里获取到请求路径对应的子控制器子类:
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// TODO Auto-generated method stub
//获取请求路径
String url = req.getRequestURI();
int start = url.lastIndexOf("/");
int end=url.lastIndexOf(".");
url=url.substring(start, end);
Action action = map.get(url);
action.execute(req, resp);
}
最后在子控制器子类里实现加减乘除操作:
package com.xiaoyang.action;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.xiaoyang.framework.Action;
import com.xiaoyang.util.Result;
public class CalcAction extends Action{
@Override
public String execute(HttpServletRequest req, HttpServletResponse resp) {
// TODO Auto-generated method stub
//获取两个计算的文本框的值
String name1 = req.getParameter("name1");
String name2 = req.getParameter("name2");
//获取提交按钮中的value
String result=req.getParameter("num");
Result res=new Result();
//调用封装好的方法判断是 + - * /并进行计算返回结果
int resultCalc = res.ResultCalc(name1, name2, result);
//将返回结果存入请求中,并跳转界面
req.setAttribute("result", resultCalc);
try {
req.getRequestDispatcher("result.jsp").forward(req, resp);
} catch (ServletException | IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
}
加减乘除方法助手类:
package com.xiaoyang.util;
public class Result {
public int ResultCalc(String name1,String name2,String result) {
int n=0;
switch (result) {
case "+":
n=Integer.parseInt(name1)+Integer.parseInt(name2);
break;
case "-":
n=Integer.parseInt(name1)-Integer.parseInt(name2);
break;
case "*":
n=Integer.parseInt(name1)*Integer.parseInt(name2);
break;
case "/":
n=Integer.parseInt(name1)/Integer.parseInt(name2);
break;
default:
break;
}
return n;
}
}
输出结果:
加:
减:
乘:
除:
尾言
自定义mvc框架的初步准备和案例就到这了,其实好好理解并不复杂,后续会分享优化自定义mvc的步骤,先到这了,有错误的地方欢迎大家指出…