涉及知识点:
- slf4j
- java annotation如何定义
- 通过classloader获取java文件的路径等信息 – https://www.cnblogs.com/seven…
- map遍历 https://blog.csdn.net/tjcyjd/… 方法二
- class.forname实例化 https://www.cnblogs.com/shosk…
- java 反射中的调用方法 – https://www.cnblogs.com/qingc…
- java 获取项目路径的方式
第一部分, 工程基础配置
- 创建Dynamic web工程
- 为工程添加runtime librariy. 目的: 为了实现servlet功能 (主要需要其中的servlet-api等jar文件) 此为servlet基础知识.
- 创建DispatcherServlet并继承HttpServlet
-
web.xml中声明此dispatcherServlet, 目的: ①表示这是个会被tomcat容器识别的servlet, ②拦截所有请求
<?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, 指定需要被扫描的包
path=com.spring.sim
-
web.xml中将properties文件设置为启动时被load
⚠ 此步骤为可选, 在DispatcherServlet中声明也可以
此步完成后, web.xml不需要再改动
<?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>
-
声明要用到的Annotation
- 涉及到的annotation有: Autowired, Controller, RequestMapping, RequestParam, Service
- 涉及Annotation知识点
- 这一步骤
-
Annotation source code:
@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组件的功能
@SSService public class Service { public void get(String name) { System.out.println(name); } }
-
编写Action, 目的: 模拟Springmvc的action, 实际上模拟的Action已经和SpringMVC的相同了
@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
DispatcherServlet是整个工程的大脑, 它负责整个容器的的初始化, 资源读取管理和请求分发.
此工程中, dispatcherServlet分为以下几个部分:
-
初始化容器
-
接收并处理请求
- 根据请求路径., 找到记录中对应Action, 通过反射调用Action对应的方法
看起来似乎很简单, 但实现起来还是有一些麻烦的.
下面我们开始.
-
编写初始化方法 – 此方法名无法更改, 只能是init方法, 这是Servlet规范
而在init方法中, 第一步需要提取出所有的Java类型文件, 每一个文件都要对应一个或多个路径, 所以我们
- 新建一个全局map<String, Object>
private Map<String, Object> javaFiles = new HashMap<>();
- 遍历工程, 获取所有Java类, 此时我们新建一个方法, 将其从init方法中抽离出来
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); } } }
原文
https://segmentfault.com/a/1190000023310505
本站部分文章源于互联网,本着传播知识、有益学习和研究的目的进行的转载,为网友免费提供。如有著作权人或出版方提出异议,本站将立即删除。如果您对文章转载有任何疑问请告之我们,以便我们及时纠正。PS:推荐一个微信公众号: askHarries 或者qq群:474807195,里面会分享一些资深架构师录制的视频录像:有Spring,MyBatis,Netty源码分析,高并发、高性能、分布式、微服务架构的原理,JVM性能优化这些成为架构师必备的知识体系。还能领取免费的学习资源,目前受益良多

转载请注明原文出处:Harries Blog™ » [Spring MVC] 理解核心原理 – 实现轻量级Spring MVC框架