您的位置:首页 > 其它

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)方法,初始化相关配置。

@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;     // 相关数据
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  smart4j smart-framework