1.自定义MVC
自定义MVC就是去了解每个标签后的底层原理逻辑,也可以根据自己的开发需求去开发一架包来使用,这个对于架构师来说是需要掌握的
-------它的好处和用途:
- 分离关注点:MVC架构将应用程序的不同方面(数据、展示、控制逻辑)分离开来,使得代码更易于理解和维护。开发人员可以专注于特定领域的开发,提高开发效率。
- 可扩展性和可重用性:通过将应用程序分为模型、视图和控制器,可以更容易地添加新功能或修改现有功能,而不会影响其他部分的代码。这种模块化的结构使得代码更易于重用,可以更高效地开发和维护应用程序。
- 并行开发:MVC架构允许开发人员在不同的模块上并行工作,提高开发效率和团队协作能力。例如,模型开发人员可以同时开发数据存储和处理逻辑,视图开发人员可以同时进行用户界面设计,控制器开发人员可以编写业务逻辑。
- 测试和调试:MVC架构使得单元测试和调试更加容易。由于模型、视图和控制器是相互独立的,可以更容易地对每个部分进行测试和调试,确保代码的质量和
- 代码复用:MVC架构中的组件可以根据需要进行重用,提高开发效率。例如,可以使用相同的模型和控制器来支持不同的视图,或者可以使用相同的视图来展示不同的模型数据
2.优化版
注意:查询必然转发,增删改必然重定向
下面这个是优化版需要用到的配置文件,要添加什么页面,就只需要改这个配置文件就可以了
DispatherAction
--------因为要将这个做成架包,所以里面的东西不能是死的,不然就会有新的就会改变,
所以我们就用到了建模,将它变成活,到时候只要在配置文件里面添加即可
以前都是将子控制器放在Map集合中,现在要将其放在MVC.XML文件中
package com.sy.framwork; import java.io.IOException; import javax.servlet.ServletConfig; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.commons.beanutils.BeanUtils; import com.sy.framwork.model.ActionModel; import com.sy.framwork.model.ConfigModel; import com.sy.framwork.model.ConfigModelFactory; import com.sy.framwork.model.ForwardModel; /** * 中央控制器 * * @author W * */ @WebServlet("*.action") public class DispatherAction extends HttpServlet { private ConfigModel configmodel;//配置文件中最大的模型 @Override public void init(ServletConfig config) throws ServletException { try { configmodel = ConfigModelFactory.build();//调用获取配置文件数据的方法 System.out.println(configmodel); } 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 { String url = req.getRequestURI(); url = url.substring(url.lastIndexOf("/"), url.lastIndexOf(".")); ActionModel actionModel = configmodel.pop(url);//通过请求路径拿到action标签 if(actionModel==null) {//如果配置出现错误,那么就抛出一个异常 new RuntimeException("not config error"); } String type = actionModel.getType();//全路径 try { Action action = (Action) Class.forName(type).newInstance();//动态实例化处理操作的类 if(action instanceof ModelDriver) {//如果这个类实现了ModelDriver接口 ModelDriver md = (ModelDriver)action;//那么就将它转型成ModelDriver Object model = md.getModel();//调用方法(返回需要封装的实体) BeanUtils.populate(model, req.getParameterMap());//利用工具类将获取到的参数封装到实体中 } String execute = action.execute(req, resp);//调用操作的方法 ForwardModel forwardModel = actionModel.pop(execute);//通过name值拿到action中的forward if(forwardModel!=null) { boolean redirect = forwardModel.isRedirect();//是否重定向 String path = forwardModel.getPath();//拿到跳转的路径 if(redirect) {//重定向 resp.sendRedirect(req.getContextPath()+path); }else {//转发 req.getRequestDispatcher(path).forward(req, resp); } } } catch (Exception e) { e.printStackTrace(); } } }
这个类主要是获取路径,从配置文件中获取,通过截取的获取路径进行执行浏览器传来的请求。这里面因为有些要带参数,所以要进行判断,是否为重定向,否则为转发
package com.sy.framwork; import java.lang.reflect.Method; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class Action { public String execute(HttpServletRequest request, HttpServletResponse response) { //反射的代码 String methodname = request.getParameter("methodname"); String result=""; try { Method m=this.getClass().getDeclaredMethod(methodname, HttpServletRequest.class,HttpServletResponse.class); m.setAccessible(true); result=(String) m.invoke(this, request,response); } catch (Exception e) { e.printStackTrace(); } return result; } }
Servlet方法类(演示一遍)
package com.sy.servlet; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import com.sy.entity.Book; import com.sy.framwork.Action; import com.sy.framwork.ModelDriver; /** * book类需要进行的业务操作 * @author W * */ public class BookAction extends Action implements ModelDriver<Book>{ private Book book=new Book(); public String List(HttpServletRequest request, HttpServletResponse response) { System.out.println("BookAction..查询."); return "redirect"; } public String upd(HttpServletRequest request, HttpServletResponse response) { System.out.println("BookAction..修改."); return "forward"; } public String del(HttpServletRequest request, HttpServletResponse response) { System.out.println("BookAction..删除."); return "forward"; } public String add(HttpServletRequest request, HttpServletResponse response) { System.out.println("BookAction..增加."); return "forward"; } @Override public Book getModel() { return book; } }
3.Model
3.1ConfigModel类
package com.sy.framwork.model; import java.util.HashMap; import java.util.Map; public class ConfigModel { // config // actionModel在configModel中是唯一的,那么就会有一个容器(也就是属性),能够一对一的去存储actionModel private Map<String, ActionModel> actionMap=new HashMap<String, ActionModel>(); // 在configModel中能够添加actionModel public void push(ActionModel actionModel) { actionMap.put(actionModel.getPath(), actionModel); } //通过path在config里面拿到action public ActionModel pop(String path) { return actionMap.get(path); } public static void main(String[] args) throws Exception { //获取第二个action中第二个forward的path // ConfigModel configModel = new ConfigModel(); // ActionModel actionModel = configModel.pop("/loginAction"); // ForwardModel forwardModel = actionModel.pop("success"); // System.out.println(forwardModel.getPath()); //在这里,我们需要用到设计模式中的工厂模式去获取xml中的内容 ConfigModel build = ConfigModelFactory.build();//实例ConfigModelFactory,调用build方法 ActionModel pop = build.pop("/loginAction");//第二个action的path属性值 String path1 = pop.getPath(); System.out.println(path1); ForwardModel pop2 = pop.pop("success");//第二个forward的name属性值 String path2 = pop2.getPath(); System.out.println(path2); } }
3.2ConfigFactoryModel (工厂模型)
这里面的逻辑是比较强的,需要好好去理解,我们看到那个配置文件,有三个标签config,action,forword,这三者是层层包裹的,所以当config里面需要东西时,需要保证action里面有东西,那么就需要保证forword里面有东西。获取里面的属性
package com.sy.framwork.model; import java.io.InputStream; import java.util.List; import org.dom4j.Document; import org.dom4j.DocumentException; import org.dom4j.Element; import org.dom4j.Node; import org.dom4j.io.SAXReader; public class ConfigModelFactory { public static ConfigModel build() throws Exception { ConfigModel configModel = new ConfigModel();//示例ConfigModel InputStream in = ConfigModelFactory.class.getResourceAsStream("/mvc.xml");//获取流 SAXReader sr = new SAXReader(); Document read = sr.read(in);//读流 List<Element> actionEles = read.selectNodes("/config/action");//获取节点 //填充内容到ActionModel for (Element actionEle : actionEles) { ActionModel actionModel = new ActionModel();//实例 actionModel.setPath(actionEle.attributeValue("path"));//path actionModel.setType(actionEle.attributeValue("type"));//type //填充内容到ForwardModel List<Element> forwardEles = actionEle.selectNodes("forward"); for (Element forwardEle : forwardEles) { ForwardModel forwardModel = new ForwardModel();//实例 forwardModel.setName(forwardEle.attributeValue("name"));//name forwardModel.setPath(forwardEle.attributeValue("path"));//path //因为redirect是Boolean类型,所以与上述操作有些许不一样 forwardModel.setRedirect(!"false".equals(forwardEle.attribute("redirect"))); actionModel.push(forwardModel);//把forwardModel的内容加到actionModel中 } configModel.push(actionModel);//把actionModel的内容加到configModel中 } return configModel; } public static void main(String[] args) throws Exception { ConfigModel build = ConfigModelFactory.build(); System.out.println(build); // ActionModel actionModel = configModel.pop("/loginAction"); // ForwardModel forwardModel = actionModel.pop("success"); // System.out.println(forwardModel.getPath()); ActionModel pop = build.pop("/loginAction"); System.out.println(pop.getType()); } }
3.3ActionModel
package com.sy.framwork.model; import java.util.HashMap; import java.util.Map; public class ActionModel { // action // forwardModel在actionModel中是唯一的,那么在actionModel中会有一个容器(属性),可以一对一存储forwardModel // actionModel中还有两个属性:path和type private String path; private String type; private Map<String, ForwardModel> forwardMap = new HashMap<>(); public ActionModel() { // TODO Auto-generated constructor stub } 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; } // 在actionModel中能够添加forwardModel public void push(ForwardModel forwardModel) { forwardMap.put(forwardModel.getName(), forwardModel); } // 通过name值在action中拿到forward public ForwardModel pop(String name) { return forwardMap.get(name); } }
3.4ForwordModel
package com.sy.framwork.model; public class ForwardModel { // forwardModel中有属性:name,path,redirect private String name; private String path; private boolean redirect; public ForwardModel() { // TODO Auto-generated constructor stub } public ForwardModel(String name, String path, boolean redirect) { super(); this.name = name; this.path = path; this.redirect = 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 boolean isRedirect() { return redirect; } public void setRedirect(boolean redirect) { this.redirect = redirect; } @Override public String toString() { return "ForwardModel [name=" + name + ", path=" + path + ", redirect=" + redirect + "]"; } }
以上就是配置文件需要的Model
4.输出结果: