二. 手寫SpringMVC框架

 

1.1 新建DispatcherServlet

 

1.2 在src目錄下,新建applicationContext.xml

 

<?xml version=”1.0″ encoding=”UTF-8″?>

 

<beans id=”b1″>
<bean id=”emp” class=”xxx.controller.EmpController”/>
<bean id=”dept” class=”xxx.controller.DeptController”/>
</beans>

1.3 DispatcherServlet的構造方法中解析applicationContext.xml配置文件

import java.io.IOException;

import java.io.InputStream;

import java.util.Map;

import java.util.concurrent.ConcurrentHashMap;

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 javax.xml.parsers.DocumentBuilder;

import javax.xml.parsers.DocumentBuilderFactory;

import javax.xml.parsers.ParserConfigurationException;

import org.w3c.dom.Document;

import org.w3c.dom.Element;

import org.w3c.dom.Node;

import org.w3c.dom.NodeList;

import org.xml.sax.SAXException;

 

@WebServlet(“*.do”)

public class DispatcherServlet extends HttpServlet {

private Map<String, Object> map = new ConcurrentHashMap<>();

public DispatcherServlet() {

try {

InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream(“applicationContext.xml”);

// 1,通過工廠模式,創建documentBuilderFactory工廠對象

DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();

 

// 2,創建DocumentBuilder對象

DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();

 

// 3,得到Document對象( 注意導入org.w3c.dom包中的)

Document document = documentBuilder.parse(inputStream);

 

// 4,獲得所有的bean標籤

NodeList nodeList = document.getElementsByTagName(“bean”);

for (int i = 0; i < nodeList.getLength(); i++) {

    Node node = nodeList.item(i);

 

if(node.getNodeType() == Node.ELEMENT_NODE) {

     //(注意導入org.w3c.dom包中的)

//強轉成Element類的對象,裡面有比Node類更方便的方法

Element element = (Element)node;

 

String id = element.getAttribute(“id”);

String className = element.getAttribute(“class”);

boolean flag = map.containsKey(id);

if(flag == true)

return;

Object o = Class.forName(className).newInstance();

map.put(id, o);

}

}

} catch (ParserConfigurationException | SAXException | IOException | ClassNotFoundException | InstantiationException | IllegalAccessException e) {

e.printStackTrace();

}

}

 

@Override

protected void service(HttpServletRequest request, HttpServletResponse response)

throws ServletException, IOException {

// 設置編碼

request.setCharacterEncoding(“UTF-8”);

response.setCharacterEncoding(“UTF-8”);

response.setContentType(“text/html;charset=UTF-8”);

 

// 假設url是: //localhost:8080/mymvc2/hello.do

// ServletPathServlet的訪問路徑: /hello.do

// 思路是:

// 1步: /hello.do -> hello 或者 /book.do -> book

// 2步: hello -> HelloController 或者 book -> BookController

String servletPath = request.getServletPath(); // /hello.do

int lastDotIndex = servletPath.lastIndexOf(“.do”);

servletPath = servletPath.substring(1, lastDotIndex); // hello

}

}

1.4 在DispatcherServlet的service方法中,通過ServletPath獲取對應的Controller對象,優化反射的程式碼

@Override

protected void service(HttpServletRequest request, HttpServletResponse response)

throws ServletException, IOException {

// 設置編碼

request.setCharacterEncoding(“UTF-8”);

response.setCharacterEncoding(“UTF-8”);

response.setContentType(“text/html;charset=UTF-8”);

 

// 假設url是: //localhost:8080/mymvc2/hello.do

// ServletPathServlet的訪問路徑: /hello.do

// 思路是:

// 1步: /hello.do -> hello 或者 /book.do -> book

// 2步: hello -> HelloController 或者 book -> BookController

String servletPath = request.getServletPath(); // /hello.do

int lastDotIndex = servletPath.lastIndexOf(“.do”);

servletPath = servletPath.substring(1, lastDotIndex); // hello

 

// 通過ServletPath獲取對應的Controller對象

Object xxxController = map.get(servletPath);

 

String ac = request.getParameter(“ac”);

System.out.println(“=======” + ac + “======”);

if (StringUtil.isEmpty(ac))

ac = “index”;

 

try {

// 這裡只能try…catch異常,因為在重寫的方法里,不能拋出比父類更大的異常

Method method = xxxController.getClass().getDeclaredMethod(ac, HttpServletRequest.class,HttpServletResponse.class);

if (method != null) {

method.invoke(xxxController, request, response);

} else {

throw new RuntimeException(“ac值違法);

}

} catch (NoSuchMethodException | SecurityException | IllegalAccessException | IllegalArgumentException

| InvocationTargetException e) {

e.printStackTrace();

}

}

1.5 寫一個簡單的EmpController

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

 

public class EmpController {

public void index(HttpServletRequest request,HttpServletResponse response) {

System.out.println(“EmpController…index”);

}

}

2. 第二次改進,每一個方法中都有獲取參數的程式碼, 或者都有請求轉發或是重定向的程式碼。解決跳轉問題

(程式碼格式問題各位大佬別吐槽,複製過來的有時間改)