JAVAWEB学习(12) - 实现一个简单的MVC框架

实现一个简单的MVC框架

1. 目标

SmartMVC核心是一个通用的控制器(DispatcherServlet)。利用SmartMVC,我们在开发一个web应用时,只需要添加相应的配置,通过该控制器就可以调用相应的模型或者视图。也就是说,只需要写模型和视图,不再需要写控制器了。

2. 架构

smartmvc

3. 开发步骤

1. 创建一个Maven工程(smartmvc)

项目结构如下:

目录

2. 导包

<dependencies>
	<dependency>
		<groupId>dom4j</groupId>
		<artifactId>dom4j</artifactId>
		<version>1.6.1</version>
	</dependency>
</dependencies>

3. 添加一个JSP(/WEB-INF/hello.jsp)

<%@ page pageEncoding="utf-8" 
contentType="text/html; charset=utf-8" %>
<html>
	<head></head>
	<body style="font-size:30px;">
		Hello SmartMVC!
	</body>
</html>

4. 在base.annotation包下添加一个java注解(@RequestMapping)

@Retention(RetentionPolicy.RUNTIME)
public @interface RequestMapping {
	public String value();
}

5. 在demo包下添加HelloController类(处理器)

//该类方法前添加@RequestMapping注解(指定请求路径)
//方法返回值是一个字符串(即视图名)
public class HelloController {

@RequestMapping("/hello.do")
public String hello(){
	System.out.println("HelloController的hello方法");
	return "hello";
 }
}

6. 在resources文件夹下添加smart-mvc.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans>
	<!-- 配置处理器:
			class属性用于指定处理器类名。
	 -->
	<bean class="demo.HelloController"/>
	<bean class="demo.LoginController"/>
</beans>

7. 在base.web包下添加DispatcherServlet

/**
在初始化方法里,读取配置文件中的处理器类名,将处理器实例化,
然后将处理器实例交给HandlerMapping来处理。
*/
public class DispatcherServlet extends HttpServlet {
private static final long serialVersionUID = 1L;

private HandlerMapping handlerMapping;

@Override
/**
 * 读取配置文件(smartmvc.xml)的内容,将所有
 * 处理器实例化,然后将这些处理器实例交给
 * HandlerMapping来处理。
 * 注:
 * 	  HandlerMapping负责建立请求路径与处理器的
 * 对应关系。
 */
public void init() throws ServletException {
	//读取配置文件位置及文件名
	String configLocation = getServletConfig().getInitParameter("configLocation");
	
	SAXReader sax = new SAXReader();
	
	InputStream in = getClass().getClassLoader().getResourceAsStream(configLocation);
	
	try {
		/*
		 * 利用dom4j读取配置文件的内容,
		 * SAXReader的read方法的返回值可以
		 * 想像一棵树,我们可以从根节点开始,
		 * 一层一层遍历。
		 */
		Document doc = sax.read(in);
		//找到根节点
		Element root = doc.getRootElement();
		//找出根节点的所有子节点
		List<Element> elements = root.elements();
		List beans = new ArrayList();
		//遍历子节点,读取处理器类名
		for(Element ele : elements){
			String className = ele.attributeValue("class");
			System.out.println("className:" + className);
			//将处理器实例化
			Object bean = Class.forName(className).newInstance();
			beans.add(bean);
		}
		System.out.println("beans:" + beans);
		
		//将处理器实例交给HandlerMapping来处理
		handlerMapping  = new HandlerMapping();
		handlerMapping.process(beans);
		
	} catch (Exception e) {
		e.printStackTrace();
		throw new ServletException(e);
	}
}

8. 配置web.xml文件

<servlet>
	<servlet-name>DispatcherServlet</servlet-name>
	<servlet-class>base.web.DispatcherServlet</servlet-class>
	<!--
		指定配置文件的位置及文件名 
 	-->
	<init-param>
		<param-name>configLocation</param-name>
		<param-value>smart-mvc.xml</param-value>
	</init-param>
	<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
	<servlet-name>DispatcherServlet</servlet-name>
	<url-pattern>*.do</url-pattern>
</servlet-mapping>

9. 在base.common包下添加Handler类

public class Handler {
	private Method method;
	private Object obj;
	
	public Handler(Method method, Object obj) {
		this.method = method;
		this.obj = obj;
	}
	
	public Method getMethod() {
		return method;
	}
	public void setMethod(Method method) {
		this.method = method;
	}
	public Object getObj() {
		return obj;
	}
	public void setObj(Object obj) {
		this.obj = obj;
	}
}

10. 在base.common包下添加HandlerMapping类(映射处理器)

public class HandlerMapping {

//mappings用于存放请求路径与处理器的对应关系
private Map<String,Handler> mappings = 
		new HashMap<String,Handler>();

/**
 * 依据请求路径返回Handler对象。
 * 注:
 *   Handler对象封装了处理器对象及方法对象,
 *  方便利用java反射来调用处理器的方法。
 */
public Handler getHandler(String path){
	return mappings.get(path);
}

public void process(List beans) {
	for(Object bean: beans){
		//获得Class对象
		Class clazz = bean.getClass();
		//获得所有方法
		Method[] methods = clazz.getDeclaredMethods();
		//遍历所有方法
		for(Method mh : methods){
			//获得@RequestMapping注解
			RequestMapping rm = mh.getDeclaredAnnotation(RequestMapping.class);
			//获得请求路径
			String path = rm.value();
			//存放请求路径与处理器的对应关系
			mappings.put(path, new Handler(mh,bean));
		}
		
	}
	System.out.println("mappings:" + mappings);
	}
}

至此,一个简单的MVC框架就设计完成了,最后附上设计图:

s1

猜你喜欢

转载自blog.csdn.net/yisany_Q/article/details/83626543
今日推荐