目录
一,自定义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());//映射到该方法中 键值对形式
}
泛型指定子控制器实体类。最后在子控制器中实现模型驱动接口并实现其中的方法即可