JFinal 源码导读第四天(1) initActionMapping核心介绍

本文深入剖析了一个Java Web框架的工作原理,特别是如何通过拦截器管理请求处理流程,包括默认拦截器、控制器级拦截器及方法级拦截器的组合使用。
1.接上一篇代码 Method[] methods = controllerClass.getMethods();
for (Method method : methods) {
				String methodName = method.getName();
				if (!excludedMethodName.contains(methodName) && method.getParameterTypes().length == 0) {
					Interceptor[] methodInters = interceptorBuilder.buildMethodInterceptors(method);
					Interceptor[] actionInters = interceptorBuilder.buildActionInterceptors(defaultInters, controllerInters, controllerClass, methodInters, method);
					String controllerKey = entry.getKey();
					
					ActionKey ak = method.getAnnotation(ActionKey.class);
					if (ak != null) {
						String actionKey = ak.value().trim();
						if ("".equals(actionKey))
							throw new IllegalArgumentException(controllerClass.getName() + "." + methodName + "(): The argument of ActionKey can not be blank.");
						
						if (!actionKey.startsWith(SLASH))
							actionKey = SLASH + actionKey;
						
						if (mapping.containsKey(actionKey)) {
							warnning(actionKey, controllerClass, method);
							continue;
						}
						
						Action action = new Action(controllerKey, actionKey, controllerClass, method, methodName, actionInters, routes.getViewPath(controllerKey));
						mapping.put(actionKey, action);
					}
					else if (methodName.equals("index")) {
						String actionKey = controllerKey;
						
						Action action = new Action(controllerKey, actionKey, controllerClass, method, methodName, actionInters, routes.getViewPath(controllerKey));
						action = mapping.put(actionKey, action);
						
						if (action != null) {
							warnning(action.getActionKey(), action.getControllerClass(), action.getMethod());
						}
					}
					else {
						String actionKey = controllerKey.equals(SLASH) ? SLASH + methodName : controllerKey + SLASH + methodName;
						
						if (mapping.containsKey(actionKey)) {
							warnning(actionKey, controllerClass, method);
							continue;
						}
						
						Action action = new Action(controllerKey, actionKey, controllerClass, method, methodName, actionInters, routes.getViewPath(controllerKey));
						mapping.put(actionKey, action);
					}
				}
			}
2.if (!excludedMethodName.contains(methodName) && method.getParameterTypes().length == 0)
其实这句代码很简单, excludedMethodName是父类中的Controller无参数的方法,这里主要是获取我们自定义的方法入口
3.如果是我们定义的BlogController.java,这里就是让BlogController.java中的方法进入,而不让其父类的方法进入,例如下面的index(),add(),save(),edit(),delete()可以满足条件
public void index() {
		setAttr("blogPage", Blog.dao.paginate(getParaToInt(0, 1), 10, "select *", "from blog order by id asc"));
		render("blog.html");
	}
	
	public void add() {
	}
	
	@Before(BlogValidator.class)
	public void save() {
		getModel(Blog.class).save();
		redirect("/blog");
	}
	
	public void edit() {
		setAttr("blog", Blog.dao.findById(getParaToInt()));
	}
	
	@Before(BlogValidator.class)
	public void update() {
		getModel(Blog.class).update();
		redirect("/blog");
	}
	
	public void delete() {
		Blog.dao.deleteById(getParaToInt());
		redirect("/blog");
	}

3.假如进入的是save()方法,
Interceptor[] methodInters = interceptorBuilder.buildMethodInterceptors(method);

/**
	 * Build interceptors of Method
	 */
	Interceptor[] buildMethodInterceptors(Method method) {
		Before before = method.getAnnotation(Before.class);
		return before != null ? createInterceptors(before) : NULL_INTERCEPTOR_ARRAY;
	}
	/**
	 * Create interceptors with Annotation of Before. Singleton version.
	 */
	private Interceptor[] createInterceptors(Before beforeAnnotation) {
		Interceptor[] result = null;
		@SuppressWarnings("unchecked")
		Class<Interceptor>[] interceptorClasses = (Class<Interceptor>[]) beforeAnnotation.value();
		if (interceptorClasses != null && interceptorClasses.length > 0) {
			result = new Interceptor[interceptorClasses.length];
			for (int i=0; i<result.length; i++) {
				result[i] = intersMap.get(interceptorClasses[i]);
				if (result[i] != null)
					continue;
				
				try {
					result[i] = (Interceptor)interceptorClasses[i].newInstance();
					intersMap.put(interceptorClasses[i], result[i]);
				} catch (Exception e) {
					throw new RuntimeException(e);
				}
			}
		}
		return result;
	}
methodInters相当于获取BlogValidator接口,validate验证这块,我后面会详细介绍其原理,现在就不要深究啦
@Before(BlogValidator.class)
	public void save() {
		getModel(Blog.class).save();
		redirect("/blog");
	}
4.Interceptor[] actionInters = interceptorBuilder.buildActionInterceptors(defaultInters, controllerInters, controllerClass, methodInters, method);
该方法就是讲Global和Controller和Method上面的拦截器信息,如果有collerClearType,去除相应的拦截器,最后整合在一起 放入到actionInters中
Interceptor[] buildActionInterceptors(Interceptor[] defaultInters, Interceptor[] controllerInters, Class<? extends Controller> controllerClass, Interceptor[] methodInters, Method method) {
		ClearLayer controllerClearType = getControllerClearType(controllerClass);
		if (controllerClearType != null) {
			defaultInters = NULL_INTERCEPTOR_ARRAY;
		}
		
		ClearLayer methodClearType = getMethodClearType(method);
		if (methodClearType != null) {
			controllerInters = NULL_INTERCEPTOR_ARRAY;
			if (methodClearType == ClearLayer.ALL) {
				defaultInters = NULL_INTERCEPTOR_ARRAY;
			}
		}
		
		int size = defaultInters.length + controllerInters.length + methodInters.length;
		Interceptor[] result = (size == 0 ? NULL_INTERCEPTOR_ARRAY : new Interceptor[size]);
		
		int index = 0;
		for (int i=0; i<defaultInters.length; i++) {
			result[index++] = defaultInters[i];
		}
		for (int i=0; i<controllerInters.length; i++) {
			result[index++] = controllerInters[i];
		}
		for (int i=0; i<methodInters.length; i++) {
			result[index++] = methodInters[i];
		}
		
		return result;
	}
5.String controllerKey = entry.getKey();在我们的例子中为=/blog
ActionKey ak = method.getAnnotation(ActionKey.class); 我们这里没有用到目前,不管他,很简单,自己看看就能明白啦
actonInters就是上面所说的拦截器
Action action = new Action(controllerKey, actionKey, controllerClass, method, methodName, actionInters, routes.getViewPath(controllerKey));
mapping.put(actionKey, action);
routes.getViewPath(controllerKey)的值为= /blog/,actonInters就是上面所说的拦截器
如果是save方法:
controllerKey = /blog ,actionKey = /blog/save,controllerClass = BlogController.class,methodName = save,
同理如果是index()方法:
controllerKey=/blog,actionKey=/blog,controllerClass=BlogController.class,methodName =index
同理如果是add()方法:
controllerKey=/blog,actionKey=/blog/add,controllerClass=BlogController.class,methodName=add
同理如果是edit()方法:
controllerKey=/blog,actionKey=/blog/edit,controllerClass= BlogController.class,methodName=edit
同理如果是update()方法:
controllerKey=/blog,actionKey=/blog/update,controllerClass= BlogController.class,methodName=update
同理如果是delete()方法:
controllerKey=/blog,actionKey=/blog/delete,controllerClass= BlogController.class,methodName=delete
6. String controllerKey =entry.getKey();还有在我们中的例子为CommonController中的/
只有1个index方法
controllcontrollerKey=/,actionKey=/,controllerClass=CommonController.class,methodName =index
最后一个注意的地方,看看就明白啦
Action actoin = mapping.get("/");
if (actoin != null)
mapping.put("", actoin);





转载于:https://my.oschina.net/skyim/blog/138383

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值