MVC框架工作原理图
1.什么是MVC?
MVC全名:Model View Controller,其中Model(模型层)、View(视图层)、Controller(控制层)
它是一种软件设计典范,用于业务逻辑处理、数据、界面显示分离,
常用模式:
model1:jsp+jdbc
model2:mvc
三层架构和MVC的区别?
三层架构是一个经典的分层思想,将开发模式分为三层,每个人专注自己擅长模块即可
MVC是一种设计模式,其目的是让html和业务逻辑分开
2.MVC结构?
V(视图层)--》 JSP
C(控制层)--》 Servlet/Action
M(模型层)--》 Dao、Entity
1)实体域模型(entity层)
2)过程域模型(dao层)
注:1)不能跨层调用;
2)只能由上往下进行调用;View -> Controller -> Model
3.自定义MVC工作原理图
*.action 调度 截取*(请求路径名) 处理具体业务逻辑
JSP -----------> Servlet(中央控制器)--------------------->Action(子控制器)—>Model(Dao、DB)
通过XML对自定义MVC框架进行3步增强
一、反射增强第一步:
1)config.xml建模
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE config[
<!ELEMENT config (action*)>
<!ELEMENT action (forward*)>
<!ELEMENT forward EMPTY>
<!ATTLIST action
path CDATA #REQUIRED
type CDATA #REQUIRED
>
<!ATTLIST forward
name CDATA #REQUIRED
path CDATA #REQUIRED
redirect (true|false) "false"
>
]>
<!--
config标签:可以包含0~N个action标签
-->
<config>
<!--
action标签:可以饱含0~N个forward标签
path:以/开头的字符串,并且值必须唯一 非空
type:字符串,非空
-->
<!-- <action path="/regAction" type="test.RegAction">
forward标签:没有子标签;
name:字符串,同一action标签下的forward标签name值不能相同 ;
path:以/开头的字符串
redirect:只能是false|true,允许空,默认值为false
<forward name="failed" path="/reg.jsp" redirect="false" />
<forward name="success" path="/login.jsp" redirect="true" />
</action>
<action path="/loginAction" type="test.LoginAction">
<forward name="failed" path="/login.jsp" redirect="false" />
<forward name="success" path="/main.jsp" redirect="true" />
</action> -->
<action type="com.zhouzhuolin.mvc.action.AddAction" path="/addAction">
<forward name="rs" path="/rs.jsp" redirect="false"/>
</action>
<action type="com.zhouzhuolin.mvc.action.CalAction" path="/calAction">
<forward name="rs" path="/rs.jsp" redirect="false"/>
</action>
</config>
2)获取Action配置信息
3)反射机制实例化Action子控制器
4)将请求委托给子控制器处理并返回结果码
5)根据返回结果码进行页面跳转
重定向/转发
package com.zhouzhuolin.mvc.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.zhouzhuolin.mvc.action.AddAction;
import com.zhouzhuolin.mvc.action.HelloAction;
import com.zhouzhuolin.mvc.util.ActionModel;
import com.zhouzhuolin.mvc.util.ConfigModel;
import com.zhouzhuolin.mvc.util.ConfigModelFactory;
import com.zhouzhuolin.mvc.util.ForwardModel;
/**
* 核心控制器(根据不同的请求路径名调用action下的子控制器)
* @author LinGod
*
*/
public class ActionServlet extends HttpServlet {
private Map<String, Action> map=null;
private ConfigModel configModel;
@Override
public void init() throws ServletException {
// TODO Auto-generated method stub
super.init();
// map=new HashMap<String, Action>();
// map.put("/helloAction", new HelloAction());
// map.put("/addAction", new AddAction());
try {
configModel = ConfigModelFactory.createConfigModel();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
/**
*
*/
private static final long serialVersionUID = 8941367292695204397L;
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doPost(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 获取请求路径
String uri=req.getRequestURI();
// 截取请求路径名
int start=uri.lastIndexOf("/");
int end=uri.lastIndexOf(".");
// 获取请求路径名
String actionName=uri.substring(start, end);
// 根据请求路径名获取action子控制器
// Action action = map.get(actionName);
// System.out.println(action.getClass().getName());
ActionModel actionModel = configModel.get(actionName);
if (actionModel == null) {
throw new RuntimeException("没action中的path");
}
try {
Action action = (Action) Class.forName(actionModel.getType()).newInstance();
// 将请求委托给action子控制器处理
String coda=action.execute(req, resp);
ForwardModel forwardModel = actionModel.get(coda);
if (null==forwardModel) {
throw new RuntimeException("forwardModel不存在");
}
if (forwardModel.isRedirect()) {
resp.sendRedirect(req.getContextPath()+forwardModel.getPath());
}else {
req.getRequestDispatcher(forwardModel.getPath()).forward(req, resp);
}
} catch (InstantiationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
二、反射增强第二步: 将一组相关的操作放到一个Action中(反射调用方法)
1)创建DispatcherAction类
DispatcherAction extends Action
2)根据请求参数获取方法名,利用反射机制调用方法
参数名:methodName:add/minus/mul/div
package com.zhouzhuolin.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;
public class DispatcherAction extends Action {
@Override
public final String execute(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
try {
String methodName=getReqMethodName(req);
Class cla=this.getClass();
Method method = cla.getDeclaredMethod(methodName, HttpServletRequest.class,HttpServletResponse.class);
String code=(String) method.invoke(this, req,resp);
return code;
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
private String getReqMethodName(HttpServletRequest req) {
String methodName = req.getParameter("methodName");
Map<String, String[]> map = req.getParameterMap();
Set<Entry<String, String[]>> entrySet = map.entrySet();
for (Entry<String, String[]> entry : entrySet) {
String name=entry.getKey();
if (-1!=name.indexOf("methodName:")) {
methodName=name.replace("methodName:", "");
break;
}
}
return methodName;
}
}
3)创建CalAction类(CalAction提供一组加减乘除的方法)
CalAction extends DispatcherAction
提供一组与execute方法的参数、返回值相同的方法,只有方法名不一样
package com.zhouzhuolin.mvc.action;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.zhouzhuolin.mvc.framework.DispatcherAction;
public class CalAction extends DispatcherAction {
// +
public String add(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
int a=Integer.parseInt(req.getParameter("a"));
int b=Integer.parseInt(req.getParameter("b"));
int rs=a+b;
req.getSession().setAttribute("rs", rs);
return "rs";
}
// -
public String minus(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
int a=Integer.parseInt(req.getParameter("a"));
int b=Integer.parseInt(req.getParameter("b"));
int rs=a-b;
req.getSession().setAttribute("rs", rs);
return "rs";
}
// *
public String mod(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
int a=Integer.parseInt(req.getParameter("a"));
int b=Integer.parseInt(req.getParameter("b"));
int rs=a*b;
req.getSession().setAttribute("rs", rs);
return "rs";
}
// /
public String div(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
int a=Integer.parseInt(req.getParameter("a"));
int b=Integer.parseInt(req.getParameter("b"));
int rs=a/b;
req.getSession().setAttribute("rs", rs);
return "rs";
}
}
三、反射增强第三步:利用ModelDriver接口对Java对象进行赋值
1)利用反射机制对Java对象进行属性赋值
简化调用:BeanUtils.populate(calBean, parameterMap);
private void setReqCal(Action action,HttpServletRequest req) throws IllegalAccessException, InvocationTargetException {
if (action instanceof DriverModel) {
DriverModel driverModel=(DriverModel) action;
Object model = driverModel.getModel();
Map<String, String[]> parameterMap = req.getParameterMap();
BeanUtils.populate(model, parameterMap);
System.out.println(model);
}
}
2)ModelDriver接口返回的对象不能为空
package com.zhouzhuolin.mvc.framework;
public interface DriverModel<T> {
public T getModel();
}
注1:Action多例模式?因为Action的属性要用来接收参数
CalBean
package com.zhouzhuolin.mvc.entity;
public class CalBean {
private int a;
private int b;
public int getA() {
return a;
}
public void setA(int a) {
this.a = a;
}
public int getB() {
return b;
}
public void setB(int b) {
this.b = b;
}
public CalBean() {
super();
// TODO Auto-generated constructor stub
}
@Override
public String toString() {
return "CalBean [a=" + a + ", b=" + b + "]";
}
}
增强CalAction
package com.zhouzhuolin.mvc.action;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.zhouzhuolin.mvc.entity.CalBean;
import com.zhouzhuolin.mvc.framework.DispatcherAction;
import com.zhouzhuolin.mvc.framework.DriverModel;
public class CalAction extends DispatcherAction implements DriverModel<CalBean> {
private CalBean calBean = new CalBean();
@Override
public CalBean getModel() {
return calBean;
}
// +
public String add(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// int a=Integer.parseInt(req.getParameter("a"));
// int b=Integer.parseInt(req.getParameter("b"));
int rs=calBean.getA()+calBean.getB();
req.getSession().setAttribute("rs", rs);
return "rs";
}
// -
public String minus(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// int a=Integer.parseInt(req.getParameter("a"));
// int b=Integer.parseInt(req.getParameter("b"));
int rs=calBean.getA()-calBean.getB();
req.getSession().setAttribute("rs", rs);
return "rs";
}
// *
public String mod(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// int a=Integer.parseInt(req.getParameter("a"));
// int b=Integer.parseInt(req.getParameter("b"));
int rs=calBean.getA()*calBean.getB();
req.getSession().setAttribute("rs", rs);
return "rs";
}
// /
public String div(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// int a=Integer.parseInt(req.getParameter("a"));
// int b=Integer.parseInt(req.getParameter("b"));
int rs=calBean.getA()/calBean.getB();
req.getSession().setAttribute("rs", rs);
return "rs";
}
}
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>
</head>
<body>
<form action="calAction.action" method="post">
<label>a:</label><input type="text" name="a"><br>
<label>b:</label><input type="text" name="b"><br>
<input type="submit" name="methodName:add" value="+">
<input type="submit" name="methodName:minus" value="-">
<input type="submit" name="methodName:mod" value="*">
<input type="submit" name="methodName:div" value="/">
</form>
</body>
</html>
测试结果