下面指定了 jar 包的打包设置,首先使用 manifest 设置主类,否则生成的 jar 包找不到主类清单,会无法运行。还使用了 from 语句来设置打包范围,这是固定句式,用来收集所有的 java 类文件。
framework 实现流程如下图:
这里看代码注释,结合下面这张 tomcat 架构图就可以理解了。
图片来自
如果暂时不理解也没关系,不影响框架学习,我只是为了玩一玩内嵌 tomcat,完全可以自己实现一个乞丐版的网络服务器的。
这里使用的是我们自定义的 Servlet 子类 DispatcherServlet 对象,该类重写了 service() 方法,代码如下:
@Override public void service(ServletRequest req, ServletResponse res) throws IOException { for (MappingHandler mappingHandler : HandlerManager.mappingHandlerList) { // 从所有的 MappingHandler 中逐一尝试处理请求, // 如果某个 handler 可以处理(返回true),则返回即可 try { if (mappingHandler.handle(req, res)) { return; } } catch (IllegalAccessException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } } res.getWriter().println("failed!"); }HandlerManager 和 MappingHandler 处理器后面会讲,这里先不展开。至此,tomcat 服务器启动完成;
扫描类扫描类是通过这句代码完成的:
// 扫描类 List<Class<?>> classList = ClassScanner.scannerCLasses(cls.getPackage().getName());ClassScanner.scannerCLasses 方法实现如下:
public static List<Class<?>> scannerCLasses(String packageName) throws IOException, ClassNotFoundException { List<Class<?>> classList = new ArrayList<>(); String path = packageName.replace(".", "http://www.likecs.com/"); // 线程上下文类加载器默认是应用类加载器,即 ClassLoader.getSystemClassLoader(); ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); // 使用类加载器对象的 getResources(ResourceName) 方法获取资源集 // Enumeration 是古老的迭代器版本,可当成 Iterator 使用 Enumeration<URL> resources = classLoader.getResources(path); while (resources.hasMoreElements()) { URL url = resources.nextElement(); // 获取协议类型,判断是否为 jar 包 if (url.getProtocol().contains("jar")) { // 将打开的 url 返回的 URLConnection 转换成其子类 JarURLConnection 包连接 JarURLConnection jarURLConnection = (JarURLConnection) url.openConnection(); String jarFilePath = jarURLConnection.getJarFile().getName(); // getClassesFromJar 工具类获取指定 Jar 包中指定资源名的类; classList.addAll(getClassesFromJar(jarFilePath, path)); } else { // 简单起见,我们暂时仅实现扫描 jar 包中的类 // todo } } return classList; } private static List<Class<?>> getClassesFromJar(String jarFilePath, String path) throws IOException, ClassNotFoundException { // 为减少篇幅,这里完整代码就不放出来了 }注释很详细,就不多废话了。
初始化Bean工厂这部分是最重要的,IOC 和 AOP 都在这里实现。
代码请到在 BeanFactory 类中查看,GitHub 在线查看 BeanFactory
注释已经写的非常详细。这里简单说下处理逻辑。