一,自定义mvc的流程
- 用户发送请求到指定的 URL。
- 应用程序的路由器(Router)根据 URL 分发请求给对应的控制器。
- 控制器解析用户的输入,调用相应的模型和视图,并获取处理结果。
- 视图负责生成用户界面,并将处理结果展示给用户。
- 用户与视图进行交互,发送新的请求。
- 控制器再次处理新的请求,并返回结果给用户。
二,XML建模进行反射优化
2.1常见的优化方法
- 定义路由配置:将路由规则和URL与控制器的映射关系配置在XML文件中。这样可以避免在代码中硬编码路由规则,提高了代码的可维护性和灵活性。
- 定义视图配置:将视图相关的配置信息,如视图路径、模板引擎的配置等,放在XML文件中。这样可以使视图的配置更加集中和可配置化,方便扩展和管理。
- 定义模型配置:将模型的相关配置信息,如数据库连接、数据表映射等配置在XML文件中。这样可以使模型的配置更加灵活和易于管理,同时也降低了与数据库相关的代码依赖。
- 自定义注入配置:将依赖注入(DI)容器的配置信息放在XML文件中。通过配置XML文件中的依赖注入关系,可以实现灵活的控制器、模型和视图的注入,减少耦合度,提高代码的可测试性和可维护性。
- 定义拦截器配置:将拦截器的配置信息,如拦截的URL规则、拦截器的顺序等,放在XML文件中。这样可以方便地定义和管理拦截器链,实现各种应用场景下的权限控制、日志记录等功能。
2.2 xml建模反射优化案例:
首先定义一个xml配置文件
注意:该xml配置文件需要放到到跟目录中(如下图)包--New--Shurce Folder
本案例需要操作的XML文件:
本XML各属性名含义:
action:
path=""前端操作类名称
type=""该类的路径名
forward:
name:方法返回名
path:跳转的路径
redirect:该结果集是否进行重定向
<?xml version="1.0" encoding="UTF-8"?> <config> <action path="/Order" type="com.LiuBing.framework.OrderAction"> <forward name="failed" path="/reg.jsp" redirect="false" /> <forward name="success" path="/login.jsp" redirect="true" /> </action> <action path="/Book" type="com.LiuBing.framework.BookAction"> <forward name="list" path="/res.jsp" redirect="false" /> <forward name="tolist" path="/res.jsp" redirect="true" /> </action> </config>
中央控制器代码:
前言:获取建模xml文件总容器ConFigModel,获取子容器actionmodel进行判断,判断xml配置文件中是否有前端所操作的类及对象,如果没有将会报出自定义异常action not config
如:
package com.LiuBing.framework; /** * 中央控制器 */ import java.io.IOException; import java.util.HashMap; import java.util.Map; 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.LiuBing.framework.model.ActionModel; import com.LiuBing.framework.model.ConFigModel; import com.LiuBing.framework.model.ConfigModelFactory; import com.LiuBing.framework.model.ForwardModel; @WebServlet("*.action") public class DispatherServlet extends HttpServlet { // 定义一个map集合 // public Map<String, Action> actionmap= new HashMap<String, Action>(); private ConFigModel conFigModel; @Override public void init(ServletConfig config) throws ServletException { // actionmap.put("/Book",new BookAction()); // actionmap.put("/Order",new OrderAction()); try { // conFigModel包含所有子控制器 conFigModel = ConfigModelFactory.build(); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doPost(req, resp); } @SuppressWarnings("rawtypes") @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { String uri = req.getRequestURI();// 地址方法 // 获取到相关的地址信息并过滤 uri = uri.substring(uri.lastIndexOf("/"), uri.lastIndexOf(".")); // 将地址保存到action // Action action = actionmap.get(uri); // 获取配置文件中action ActionModel actionmodel = conFigModel.pop(uri); // 判断action是否为空 if (actionmodel == null) // 为空提示语句 throw new RuntimeException("action not config"); // 不为空就获取到type路径(想进行哪个的业务操作路径) String type = actionmodel.getType(); Action action; try { // 获取反射需要操作的类类 action = (Action) Class.forName(type).newInstance(); //判断子容器BookAction有无实现ModelDriver 模型驱动接口接口 if(action instanceof ModelDriver) {//默认实现了该接口 ModelDriver md = (ModelDriver) action; Object bean = md.getModel(); BeanUtils.populate(bean, req.getParameterMap()); } // Action的res返回值 String res = action.execut(req, resp); //根据Action的返回值 该方法是重定向还是转发 ForwardModel forwardmodel = actionmodel.pop(res); //判断如果forwardmodel模型中有数据 if(forwardmodel!=null) { //前端操作数据是转发还是重定向 true false boolean redirect = forwardmodel.isRedirect(); //转发的页面 String path = forwardmodel.getPath(); //转发 if(redirect) { resp.sendRedirect(path); }else { //重定向 req.getRequestDispatcher(path).forward(req, resp); } } } catch (Exception e) { e.printStackTrace(); } } }
三,优化方法结果集调用跳转
3.1大概步骤:
在子类对象相对应的操作返回类型例如BookAction返回类型定义为String类型,并在中央控制器中接受子类的方法返回值,中央控制器中判断redirect重定向,最后进行xml文件的相对应的配置
子控制器代码:
package com.LiuBing.framework; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import com.LiuBing.entity.Book; public class BookAction extends Action implements ModelDriver<Book> { Book book = new Book(); public String add(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { System.out.println("进入的是增加BookaddServlet...."); request.setAttribute("content", "崽崽"); response.sendRedirect("res.jsp"); return "tolist"; } public String del(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { System.out.println("进入的是删除BookadelServlet...."); request.setAttribute("content", "崽崽"); response.sendRedirect("res.jsp"); return "tolist"; } public String upd(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { System.out.println("进入的是修改BookupdServlet...."); request.setAttribute("content", "崽崽"); response.sendRedirect("res.jsp"); return "tolist"; } public String list(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { System.out.println("进入的是查询BooklistServlet...."); request.setAttribute("content", "崽崽"); return "list"; } @Override public Book getModel() { return book; } }
中央控制器代码:
// Action的res返回值 String res = action.execut(req, resp); //根据Action的返回值 该方法是重定向还是转发 ForwardModel forwardmodel = actionmodel.pop(res); //判断如果forwardmodel模型中有数据 if(forwardmodel!=null) { //前端操作数据是转发还是重定向 true false boolean redirect = forwardmodel.isRedirect(); //转发的页面 String path = forwardmodel.getPath(); //转发 if(redirect) { resp.sendRedirect(path); }else { //重定向 req.getRequestDispatcher(path).forward(req, resp); } }
配置文件代码按本案例配置文件操作即可
最后运行结果:
进行增删改操作只会显示跳转成功,而查询所有会显示相对应的内容,这是因为增删改是重定向而查询是转发
四,优化参数的封装
4.1 前言:
在我们进行接受前端带过来的参数,往往会带很多参数在子控制器中进行遍历及封装加到实体中,这样会很麻烦的大大降低了代码效率,那有什么办法在进行这一步进行一个改善呢?有!模型驱动接口---连接模型和其他系统或应用程序的接口。它允许使用模型的输出来驱动和控制其他系统的行为。
定义一个模型驱动接口:
在中央控制器中,进行判断子控制器是否继承了模型驱动接口,并 BeanUtils.populate方法以键值对形式存储该被反射的类
模型驱动接口:
package com.LiuBing.framework; /** * 模型驱动接口 * @param <T> */ public interface ModelDriver<T> { T getModel(); }
中央控制器判断代码:
Action action; try { // 获取反射需要操作的类类 action = (Action) Class.forName(type).newInstance(); //判断子容器BookAction有无实现ModelDriver 模型驱动接口接口 if(action instanceof ModelDriver) {//默认实现了该接口 ModelDriver md = (ModelDriver) action; Object bean = md.getModel();//哪个继承了模型驱动接口 BeanUtils.populate(bean, req.getParameterMap());//映射到该方法中 键值对形式 }
泛型指定子控制器实体类。最后在子控制器中实现模型驱动接口并实现其中的方法即可