自定义MVC二
1. 什么是MVC
MVC全名是Model View Controller,是模型(model)-视图(view)-控制器(controller)的缩写,
它是一种软件设计典范,用一种业务逻辑、数据、界面显示分离的方法组织代码
我们需要导入四个包
还有5个工具类
ActionModel
package com.zjj.beike; import java.io.Serializable; import java.util.HashMap; import java.util.Map; /** * 用来描述action标签 * @author Administrator * */ public class ActionModel implements Serializable{ private static final long serialVersionUID = 6145949994701469663L; private Map<String, ForwardModel> forwardModels = new HashMap<String, ForwardModel>(); private String path; private String type; public String getPath() { return path; } public void setPath(String path) { this.path = path; } public String getType() { return type; } public void setType(String type) { this.type = type; } public void put(ForwardModel forwardModel){ forwardModels.put(forwardModel.getName(), forwardModel); } public ForwardModel get(String name){ return forwardModels.get(name); } }
ConfigModel
package com.zjj.beike; import java.io.Serializable; import java.util.HashMap; import java.util.Map; /** * 用来描述config标签 * @author Administrator * */ public class ConfigModel implements Serializable{ private static final long serialVersionUID = -2334963138078250952L; private Map<String, ActionModel> actionModels = new HashMap<String, ActionModel>(); public void put(ActionModel actionModel){ actionModels.put(actionModel.getPath(), actionModel); } public ActionModel get(String name){ return actionModels.get(name); } }
ConfigModelFactory
package com.zjj.beike; import java.io.InputStream; import java.util.List; import org.dom4j.Document; import org.dom4j.Element; import org.dom4j.io.SAXReader; public class ConfigModelFactory { private ConfigModelFactory() { } private static ConfigModel configModel = null; public static ConfigModel newInstance() throws Exception { return newInstance("config.xml"); } /** * 工厂模式创建config建模对象 * * @param path * @return * @throws Exception */ public static ConfigModel newInstance(String path) throws Exception { if (null != configModel) { return configModel; } ConfigModel configModel = new ConfigModel(); InputStream is = ConfigModelFactory.class.getResourceAsStream(path); SAXReader saxReader = new SAXReader(); Document doc = saxReader.read(is); List<Element> actionEleList = doc.selectNodes("/config/action"); ActionModel actionModel = null; ForwardModel forwardModel = null; for (Element actionEle : actionEleList) { actionModel = new ActionModel(); actionModel.setPath(actionEle.attributeValue("path")); actionModel.setType(actionEle.attributeValue("type")); List<Element> forwordEleList = actionEle.selectNodes("forward"); for (Element forwordEle : forwordEleList) { forwardModel = new ForwardModel(); forwardModel.setName(forwordEle.attributeValue("name")); forwardModel.setPath(forwordEle.attributeValue("path")); forwardModel.setRedirect(forwordEle.attributeValue("redirect")); actionModel.put(forwardModel); } configModel.put(actionModel); } return configModel; } public static void main(String[] args) { try { ConfigModel configModel = ConfigModelFactory.newInstance(); ActionModel actionModel = configModel.get("/loginAction"); ForwardModel forwardModel = actionModel.get("failed"); System.out.println(actionModel.getType()); System.out.println(forwardModel.getPath()); } catch (Exception e) { e.printStackTrace(); } } }
ForwardModel
package com.zjj.beike; import java.io.Serializable; /** * 用来描述forward标签 * @author Administrator * */ public class ForwardModel implements Serializable { private static final long serialVersionUID = -8587690587750366756L; private String name; private String path; private String redirect; public String getName() { return name; } public void setName(String name) { this.name = name; } public String getPath() { return path; } public void setPath(String path) { this.path = path; } public String getRedirect() { return redirect; } public void setRedirect(String redirect) { this.redirect = redirect; } }
mvc.xml
<?xml version="1.0" encoding="UTF-8"?> <!-- config标签:可以包含0~N个action标签 --> <config> <!-- action标签:可以饱含0~N个forward标签 path:以/开头的字符串,并且值必须唯一 非空 type:字符串,非空 --> <action path="/Cal" type="com.web.AddCalAction"> <forward name="res" path="/res.jsp" redirect="false" /> </action> </config>
下面来看下我们的中央控制器
private static final long serialVersionUID = 1L; //private Map<String , IAction> actionMap = new HashMap<>(); //在configModel对象包含了所有的子控制信息 private ConfigModel configModel; public void init() { // actionMap.put("/addCal", new AddCalAction()); try { String xmlPath=this.getInitParameter("xmlPath"); if(xmlPath==null|| "".equals(xmlPath)) { configModel=ConfigModelFactory.newInstance(); }else { configModel=ConfigModelFactory.newInstance(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 request, HttpServletResponse response) throws ServletException, IOException { init(); String url= request.getRequestURI(); // /***/addCal.action url = url.substring(url.lastIndexOf("/"), url.lastIndexOf(".")); // IAction action = actionMap.get(url); ActionModel actionModel = configModel.get(url); // if(actionModel ==null) { // throw new RuntimeException("你没有配置action标签,找不到对应的子控制器处理浏览器发送的请求"); // } try { Action action=(Action) Class.forName(actionModel.getType()).newInstance(); //action就是com.zking.web.CalAction if(action instanceof ModelDrivern) { ModelDrivern modelDrivern=(ModelDrivern)action; //此时的model的所有属性值都是null的 Object model = modelDrivern.getModel(); BeanUtils.populate(model, request.getParameterMap()); } //返回码 String code = action.execute(request, response); ForwardModel forwardModel = actionModel.get(code); if(forwardModel!=null) { String jspPath = forwardModel.getPath(); if("false".equals(forwardModel.getRedirect())) { //做转发的处理 request.getRequestDispatcher(jspPath).forward(request, response); } else { response.sendRedirect(request.getContextPath()+jspPath); } } } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } // try { // action.execute(req, resp); // } catch (Exception e) { // // TODO Auto-generated catch block // e.printStackTrace(); // } }
以及我们的xml的配置
<?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.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>
还有一个子控制器
作用:用来直接处理浏览器发送过来的请求。
public interface Action { String execute(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException, Exception; }
现在再来看下增强版的
原来的子控制器只能处理一个用户请求
作用:将一组相关的操作放到一个Action中
public class ActionSupport implements Action{ @Override public final String execute(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException, Exception { String menthodName=request.getParameter("menthodName"); //this值的是CalAction它的一个类实例 String code=null; Method m=this.getClass().getDeclaredMethod(menthodName,HttpServletRequest.class,HttpServletResponse.class); m.setAccessible(true); code = (String) m.invoke(this,request,response); return code; } }
利用ModelDrivern接口对Java对象进行赋值(反射读写属性)
public interface ModelDrivern<T> { T getModel(); }
接下来就是实现业务逻辑的类CalAction
public class CalAction extends ActionSupport implements ModelDrivern<Cal>{ private Cal cal=new Cal(); public String add(HttpServletRequest request, HttpServletResponse response) throws Exception, Exception { request.setAttribute("res", cal.getNum1()+cal.getNum2()); return "res"; } public String reduce(HttpServletRequest request, HttpServletResponse response) throws Exception, Exception { request.setAttribute("res", cal.getNum1()-cal.getNum2()); return "res"; } public String ride(HttpServletRequest request, HttpServletResponse response) throws Exception, Exception { request.setAttribute("res", cal.getNum1()*cal.getNum2()); return "res"; } public String except(HttpServletRequest request, HttpServletResponse response) throws Exception, Exception { request.setAttribute("res", cal.getNum1()/cal.getNum2()); return "res"; } @Override public Cal getModel() { // TODO Auto-generated method stub 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(num){ if(num == 1){ calForm.action="${pageContext.request.contextPath}/Cal.action?menthodName=add"; } else if(num==2){ calForm.action="${pageContext.request.contextPath}/Cal.action?menthodName=reduce"; } else if(num==3){ calForm.action="${pageContext.request.contextPath}/Cal.action?menthodName=ride"; } else if(num==4){ calForm.action="${pageContext.request.contextPath}/Cal.action?menthodName=except"; } calForm.submit(); } </script> </head> <body> <form name="calForm" method="post" action=""> num1:<input type="text" name="num1" ><br> num2:<input type="text" name="num2" ><br> <button onclick="doSub(1)">+</button> <button onclick="doSub(2)">-</button> <button onclick="doSub(3)">*</button> <button onclick="doSub(4)">/</button> </form> </body> </html>
我选乘把
结果