SmartMVC 自定义框架

MVC模式:解决用户界面问题的标准模式(套路)

  1. M:Model 模型,封装业务逻辑
  2. V:View 视图,代表显示界面
  3. C:Controller 控制器,用于连接整合M与V

Sun公司给web用户的的建议:

  1. 使用 Java Bean 作为Model,除处理业务逻辑;
  2. 使用 JSP作为视图显示数据
  3. 使用 Servlet作为控制器,整合JSP和JavaBean

     一般情况,将如上情况封装为框架,减少后续编程量。

SmartMVC 自定义框架_第1张图片

框架演化:

前端控制器:封装与WEB编程有关的功能,转发处理,重定向处理,异常处理等。
SmartMVC 自定义框架_第2张图片
该框架使前端控制器成为可复用的代码,主要完成转发动作,子控制器(其中含有少量代码)封装具体业务逻辑。
DispatchServlet:核心前端控制器,处理任何 *.do的请求,前端控制器处理全部 Web 功能。

前端处理器如何实现转发

  1. Java 5 提供了一种代码标注功能。
  2. 利用注解可以实现动态代码执行功能。
  3. 在软件运行期间动态解析注解动态执行方法。
  4. 使用注解:利用反射API解析使用注解。

     如何创建注解?

@Retention(RUNTIME) //注解一值保留到运行期
@Target(METHOD) //此注解只能写在方法上
public @interface RequestMapping {
	String value(); //利用value()可以给注解添加默认参数
}

     如何标注注解?

/**
 * 子控制器方法
 * @param request 用于在控制器和JSP直接传递数据
 * @return 转发的目标JSP页面
 * @throws Exception
 */
@RequestMapping("/list.do") 
public String execute(HttpServletRequest request) 
				throws Exception {
	UserDAO dao = new UserDAO();
	List users = dao.findAll();
	//将users数据传递到JSP
	request.setAttribute("users", users); 
	return "list";
}

MVC框架中常用注解:RequestMapping 与 Controller

代码实现(核心类):

前端处理器(DispatchServlet):

/**
 * 核心前端控制器,处理任何的 *.do 请求 前端控制器处理全部的Web功能
 * 该servlet启动参数设置为1,容器启动即创建对象,执行init方法。
 * init方法封装解析URL与控制器方法之间的映射。
 **/
public class DispatchServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;
	private HandlerMapping handlerMapping;

	public void init() throws ServletException {
		handlerMapping = new HandlerMapping();
		try {
			//读取配置文件参数
			String file = getInitParameter("config");
			//dom4j形式解析配置文件
			SAXReader read = new SAXReader();
			InputStream in = getClass()
                            .getClassLoader().getResourceAsStream(file);
			Document doc = read.read(in);
			Element root = doc.getRootElement();
			System.out.println("root:" + root.getName());
			List beans = root.elements("bean");
			for (Element bean : beans) {
				String controllerName = bean.attributeValue("class");
				handlerMapping.parseController(controllerName);
			}
		} catch (DocumentException e) {
			e.printStackTrace();
		}
	}
	
	protected void service(
            HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		// 创建子控制器
		// 执行子控制器方法
		// 根据子控制器的返回值,转发到JSP页面
		request.setCharacterEncoding("UTF-8");
		try {
			//获取请求url
			String reqUrl = request.getRequestURI();
			String contextPath = request.getContextPath();
			String url = reqUrl.substring(contextPath.length());
			// 创建子控制器
			// 调用子控制器的方法(封装业务逻辑)
			HandlerMapping mapping = new HandlerMapping();
			Handler handler = mapping.get(url);
			String path = handler.execute(request);
			path = "/WEB-INF/jsp/" + path + ".jsp";
			request.getRequestDispatcher(path).forward(request, response);
		} catch (Exception e) {
			e.printStackTrace();
			response.setContentType("text/html; charset=UTF-8");
			PrintWriter out = response.getWriter();
			out.println("系统故障:" + e.getMessage());
		}
	}
}

控制器(Controller)

public class Controller {
	/**
	 * 子控制器方法
	 * @param request 用于在控制器和JSP直接传递数据
	 * @return 转发的目标JSP页面
	 * @throws Exception
	 */
	@RequestMapping("/list.do") 
	public String execute(HttpServletRequest request) throws Exception {
		UserDAO dao = new UserDAO();
		List users = dao.findAll();
		//将users数据传递到JSP
		request.setAttribute("users", users); 
		return "list";
	}
	
	@RequestMapping("/add.do") 
	public String add(HttpServletRequest request) 
			throws Exception {
		return "add";
	}
}

HandlerMapping:

/**
 * 用于管理URL与子控制器方法的映射关系 
 * 如: 
 * 		list.do - > Handler(controller,execute()) 
 * 		add.do - >Handler(controller,add())
 */
public class HandlerMapping {

	private Map mapping = new HashMap();

	public HandlerMapping() {
		super();
	}

	/**
	 * 将一个控制器类解析并添加到map中 
         *   1.动态加载类到内存 
         *   2.找到全部的方法,并且查找方法上是否由RequestMapping注解
	 *   3.如果有,将注解URL何控制器方法添加到map中
	 */
	public void parseController(String className) {
		// 加载类到内存中
		Class cls;
		try {
			cls = Class.forName(className);
			// 创建子控制器对象
			Object controller = cls.newInstance();
			// 找到全部方法
			Method[] methods = cls.getDeclaredMethods();

			for (Method method : methods) {
				// 在方法上查找RequestMapping注解
				RequestMapping ann = method.getAnnotation(RequestMapping.class);
				// 如果ann为null,则该方法上没有该注解,否则
				if (ann != null) {
					// 将找到的方法添加到mapping中
					mapping.put(url, new Handler(controller, method));
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
    //定义方法,便于获取Handler对象
	public Handler get(String url) {
		return mapping.get(url);
	}		
	
}

Handler:处理者,处理器

public class Handler {
	//子控制器对象
	private Object controller;
	//子控制器方法
	private Method method;

	public Handler(Object controller, Method method) {
		this.controller = controller;
		this.method = method;
	} 
	public String execute(HttpServletRequest req) throws Exception {
		return (String)method.invoke(controller, req);
	}
}

Smart-MVC处理流程图:
SmartMVC 自定义框架_第3张图片

你可能感兴趣的:(技术专区)