web.xml中聲明此dispatcherServlet, 目的: ①表示這是個會被tomcat容器識別的servlet, ②攔截全部請求html
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0"> <display-name>SpringSim2</display-name> <servlet> <servlet-name>springsim2</servlet-name> <servlet-class>com.spring.sim.DispatcherServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>springsim2</servlet-name> <url-pattern>/*</url-pattern> </servlet-mapping> </web-app>
src下建立application.properties, 指定須要被掃描的包java
path=com.spring.sim
web.xml中將properties文件設置爲啓動時被load web
⚠ 此步驟爲可選, 在DispatcherServlet中聲明也能夠spring
此步完成後, web.xml不須要再改動api
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0"> <display-name>SpringSimv1</display-name> <servlet> <servlet-name>springsim</servlet-name> <servlet-class>pro.yizheng.DispatcherServlet</servlet-class> <!-- 指定配置文件 --> <init-param> <param-name>webXmlInitParam-properties</param-name> <param-value>application.properties</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>springsim</servlet-name> <url-pattern>/*</url-pattern> </servlet-mapping> </web-app>
聲明要用到的Annotationtomcat
Annotation source code:mvc
@Documented @Retention(RUNTIME) @Target(FIELD) public @interface SSAutowired { String value() default ""; } @Documented @Retention(RUNTIME) @Target({ TYPE}) public @interface SSController { String value() default ""; } @Documented @Retention(RUNTIME) @Target({TYPE,METHOD}) public @interface SSRequestMapping { String value() default ""; } @Documented @Retention(RUNTIME) @Target(PARAMETER) public @interface SSRequestParam { String value() default ""; } @Documented @Retention(RUNTIME) @Target(TYPE) public @interface SSService { String value() default ""; }
編寫service類, 目的: 模擬spring組件的功能app
@SSService public class Service { public void get(String name) { System.out.println(name); } }
編寫Action, 目的: 模擬Springmvc的action, 實際上模擬的Action已經和SpringMVC的相同了this
@SSController @SSRequestMapping("/demo") public class DemoAction { @SSAutowired private SSDemoService service; @SSRequestMapping("/query") public void query(HttpServletRequest requeust, HttpServletResponse response, @SSRequestParam("name") String name) { String reString = service.get(name); try { response.getWriter().write(reString); } catch (Exception e) { e.printStackTrace(); } } @SSRequestMapping("/add") public void add(HttpServletRequest requeust, HttpServletResponse response, @SSRequestParam("name") String name) { try { response.getWriter().write("this is add"); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }
DispatcherServlet是整個工程的大腦, 它負責整個容器的的初始化, 資源讀取管理和請求分發. url
此工程中, dispatcherServlet分爲如下幾個部分:
初始化容器
接收並處理請求
看起來彷佛很簡單, 但實現起來仍是有一些麻煩的.
下面咱們開始.
而在init方法中, 第一步須要提取出全部的Java類型文件, 每個文件都要對應一個或多個路徑, 因此咱們先完成遍歷類的方法
private Map<String, Object> javaFiles = new HashMap<>();
// 遍歷全部class文件 private void scanJavaFiles(String path) { // 經過application.properties中設定的包名, 找到其下全部的java class文件 File pathDir = new File(this.getClass().getResource(path).getPath()); String[] pathList = pathDir.list(); for (String temFile : pathList) { File tempFile = new File(pathDir+ "/" + temFile); // 若是是目錄的話, 即遞歸操做 if (tempFile.isDirectory()) { scanJavaFiles(path + "/" + temFile); } // 非目錄, 獲得子節點,將其放到全局變量中 if (temFile.endsWith(".class")) { javaFiles.put(path+ "/" + temFile.replace(".class", ""), null); } } }
編寫初始化方法 - 此方法名沒法更改, 只能是init方法, 這是Servlet規範
public void init(ServletConfig config) throws ServletException { System.out.println("init"); // 獲取配置文件中的scan package InputStream is = this.getClass().getClassLoader().getResourceAsStream(config.getInitParameter("param1")); Properties configContext = new Properties(); try { configContext.load(is); } catch (IOException e) { e.printStackTrace(); } String scanPackage = configContext.getProperty("path"); // 獲取路徑下的java文件 scanJavaFiles(scanPackage); // 第二部分完成 }