JAVAWEB學習(12) - 實現一個簡單的MVC框架
阿新 • • 發佈:2018-11-24
實現一個簡單的MVC框架
1. 目標
SmartMVC核心是一個通用的控制器(DispatcherServlet)。利用SmartMVC,我們在開發一個web應用時,只需要新增相應的配置,通過該控制器就可以呼叫相應的模型或者檢視。也就是說,只需要寫模型和檢視,不再需要寫控制器了。
2. 架構
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框架就設計完成了,最後附上設計圖: