smart-framework框架学习之DispatcherServlet分发机制
2015-06-18 00:00
489 查看
最近几天,工作之余在学习黄勇老师的Smart-Framework框架,希望自己可以借此机会,对于web开发能力可以更近一步。 本文对于DispatcherServlet分发机制进行细致化的分析解读,若有地方不妥,万望指出,谢谢。 # DispatcherServlet.java是Smart-Framework框架中的Controller,对应于web请求,DispatcherServlet.java将其分发到处理该请求的action去。
首先,DispatcherServlet.java在系统启动时,默认启动init(ServletConfig)方法,初始化相关配置。
在Action 分发机制实现原理一文中,曾经对init(ServletConfig)有所解释,将静态资源放到一个指定的目录下,就可以在初始化时,直接加载静态资源,之后只需要加载动态资源即可。
其次,在DispatcherSerlvet.java中,service()主要获取web的url动态请求,将请求分发到处理请求的相应的action类,进行处理。主要流程如下:
获取类加载器
获取urls资源,根据基础包名获取urls资源
遍历urls资源,获取协议名分为file和jar两种,根据协议进行获取项目基础包及其子包下的action类,并check是否有action注解标识
将获取到的action类和每个action中的方法以及注解中的requestPath封装成map对象,Requester是方法与注解的封装,Handler为类与方法的封装。
遍历action的映射,查找处理请求url资源的action类的Handler对象
初始化数据(目的:使用ThreadLocal,存放线程的局部变量让每个线程请求,访问的都是独立的数据),用于在action和service对象中获取request和response对象。
实例化Handler,获取action对象,创建action方法的参数列表。系统启动时,会将所有bean、service、action的类进行实例化,然后放到map集合中去。
根据反射机制,调用Method的invoke方法
对返回的数据类型进行判断,默认view和result两种,view用于页面跳转,result用于文件上传或者json数据请求。此处应该使用了约定优于配置的原则,返回值类型只有view和result两种。
首先,DispatcherServlet.java在系统启动时,默认启动init(ServletConfig)方法,初始化相关配置。
@WebServlet(urlPatterns = "/*", loadOnStartup = 0) public class DispatcherServlet extends HttpServlet { ... @Override public void init(ServletConfig config) throws ServletException { // 初始化相关配置 ServletContext servletContext = config.getServletContext(); UploadHelper.init(servletContext); }
在Action 分发机制实现原理一文中,曾经对init(ServletConfig)有所解释,将静态资源放到一个指定的目录下,就可以在初始化时,直接加载静态资源,之后只需要加载动态资源即可。
@WebServlet(urlPatterns = "/*", loadOnStartup = 0) public class DispatcherServlet extends HttpServlet { @Override public void init(ServletConfig config) throws ServletException { // 用 Default Servlet 来映射静态资源 ServletContext context = config.getServletContext(); ServletRegistration registration = context.getServletRegistration("default"); registration.addMapping("/favicon.ico", "/www/*"); }
其次,在DispatcherSerlvet.java中,service()主要获取web的url动态请求,将请求分发到处理请求的相应的action类,进行处理。主要流程如下:
获取类加载器
Thread.currentThread().getContextClassLoader();
获取urls资源,根据基础包名获取urls资源
classloader.getResources(packageName.replace(".","/"))
遍历urls资源,获取协议名分为file和jar两种,根据协议进行获取项目基础包及其子包下的action类,并check是否有action注解标识
//jar类型的部分处理 // 获取子包 String subPackagePath = fileName; if (StringUtil.isNotEmpty(packagePath)) { subPackagePath = packagePath + "/" + subPackagePath; } // 子包名 String subPackageName = fileName; if (StringUtil.isNotEmpty(packageName)) { subPackageName = packageName + "." + subPackageName; } //jar类型的部分处理 String className = jarEntryName.substring(0, jarEntryName.lastIndexOf(".")).replaceAll("/", "."); // 判断是否可以添加类 if (checkAddClass(cls)) { // 添加类 classList.add(cls); }
将获取到的action类和每个action中的方法以及注解中的requestPath封装成map对象,Requester是方法与注解的封装,Handler为类与方法的封装。
Map<Requester, Handler> Requester->actionMethod,requestPath; Handler-->actionclass,actionMethod.
遍历action的映射,查找处理请求url资源的action类的Handler对象
// 获取请求路径匹配器(使用正则表达式匹配请求路径并从中获取相应的请求参数) Matcher requestPathMatcher = Pattern.compile(requestPath).matcher(currentRequestPath); // 判断请求方法与请求路径是否同时匹配 if (requestMethod.equalsIgnoreCase(currentRequestMethod) && requestPathMatcher.matches()) { // 获取 Handler 及其相关属性 handler = actionEntry.getValue(); // 设置请求路径匹配器 if (handler != null) { handler.setRequestPathMatcher(requestPathMatcher); }
初始化数据(目的:使用ThreadLocal,存放线程的局部变量让每个线程请求,访问的都是独立的数据),用于在action和service对象中获取request和response对象。
DataContext.init(request, response); private static final ThreadLocal<DataContext> dataContextContainer = new ThreadLocal<DataContext>(); public static DataContext getInstance() { return dataContextContainer.get(); }
实例化Handler,获取action对象,创建action方法的参数列表。系统启动时,会将所有bean、service、action的类进行实例化,然后放到map集合中去。
Object beanInstance = cls.newInstance(); Map<Class<?>, Object> beanMap; beanMap.put(cls, beanInstance);
根据反射机制,调用Method的invoke方法
对返回的数据类型进行判断,默认view和result两种,view用于页面跳转,result用于文件上传或者json数据请求。此处应该使用了约定优于配置的原则,返回值类型只有view和result两种。
public class View extends BaseBean { private String path; // 视图路径 private Map<String, Object> data; // 相关数据 ... } public class Result extends BaseBean { private boolean success; // 成功标志 private int error; // 错误代码 private Object data; // 相关数据 }
相关文章推荐
- Oculus Rift游戏开发
- Bartender五大优势
- angularjs中ng-repeat里面ng-model的使用
- Nginx 服务器安装及配置文件详解
- subprocess
- Javascript下的urlencode编码解码方法decodeURIComponent()
- JavaScript 全半角转换
- 最简洁短小的 JavaScript 判定 IE 浏览器
- 中国石油化工股份有限公司浙江温州石油分公司签约广州润普
- jQuery中$.fn的用法示例介绍
- android json解析及简单例子
- 为什么我找不到工作?创优翼来告诉你原因!
- VIEWGOOD(远古)在线访谈系统解决方案
- 详解CorelDRAW打印设置中的布局选项卡
- 用CorelDRAW X7移除位图中的尘埃与刮痕标记
- maven POM.xml 标签详解
- 百度入股星美 BAT搅动影院市场
- 用shell比较2个文件的内容
- HP-UX下监控Oracle或者其他特定程序CPU使用率的脚本
- Oracle数据泵导入导出作业