文档章节

JFinal 源码解析系列二

yiguangtia
 yiguangtia
发布于 2015/07/16 18:45
字数 957
阅读 26
收藏 0

1 当访问某个链接之后JFinal便会调用doFilter()进行处理。

public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest)req;
HttpServletResponse response = (HttpServletResponse)res;
request.setCharacterEncoding(encoding);//设置编码
String target = request.getRequestURI();//获取URI如访问 /app/login
if (contextPathLength != 0)
target = target.substring(contextPathLength);//去除weapp name
boolean[] isHandled = {false};//是否处理标识符
try {
handler.handle(target, request, response, isHandled);//处理请求,之后进行详细解析
}
catch (Exception e) {
if (log.isErrorEnabled()) {
String qs = request.getQueryString();
log.error(qs == null ? target : target + "?" + qs, e);
}
}
if (isHandled[0] == false)
chain.doFilter(request, response);//继续处理chain上其他操作
}
handler.handle(target, request, response, isHandled);

handler中的方法handle方法为抽象方法,由于为加载其他插件,先分析ActionHandler中的handle方法

final class ActionHandler extends Handler {
	
	private final boolean devMode;
	private final ActionMapping actionMapping;
	private static final RenderFactory renderFactory = RenderFactory.me();
	private static final Logger log = Logger.getLogger(ActionHandler.class);
	
	public ActionHandler(ActionMapping actionMapping, Constants constants) {
		this.actionMapping = actionMapping;
		this.devMode = constants.getDevMode();
	}
	
	/**
	 * handle
	 * 1: Action action = actionMapping.getAction(target)
	 * 2: new Invocation(...).invoke()
	 * 3: render(...)
	 */
	public final void handle(String target, HttpServletRequest request, HttpServletResponse response, boolean[] isHandled) {
		if (target.indexOf('.') != -1) {//urk中存在.则跳过
			return ;
		}
		
		isHandled[0] = true;//标识为true
		String[] urlPara = {null};//url参数数组
		Action action = actionMapping.getAction(target, urlPara);//从actionMAp中获取处理的action对象
		
		if (action == null) {//为空则返回404
			if (log.isWarnEnabled()) {
				String qs = request.getQueryString();
				log.warn("404 Action Not Found: " + (qs == null ? target : target + "?" + qs));
			}
			renderFactory.getErrorRender(404).setContext(request, response).render();
			return ;
		}
		
		try {
			Controller controller = action.getControllerClass().newInstance();//获取action的具体Controller的名字并实例化,高并发和访问估计会带来问题
			controller.init(request, response, urlPara[0]);//初始化request,response,以及url参数
			
			if (devMode) {
				boolean isMultipartRequest = ActionReporter.reportCommonRequest(controller, action);//判断是否需要打印相关信息到控制台
				new Invocation(action, controller).invoke();//调用invoke方法进行处理,此为核心代码。
				if (isMultipartRequest) ActionReporter.reportMultipartRequest(controller, action);
			}
			else {
				new Invocation(action, controller).invoke();
			}
			
			Render render = controller.getRender();//get the render
			if (render instanceof ActionRender) {
				String actionUrl = ((ActionRender)render).getActionUrl();//获取actionURl
				if (target.equals(actionUrl))
					throw new RuntimeException("The forward action url is the same as before.");
				else
					handle(actionUrl, request, response, isHandled);
				return ;
			}
			//不涉及渲染的操作render为null
			if (render == null)
				render = renderFactory.getDefaultRender(action.getViewPath() + action.getMethodName());
			render.setContext(request, response, action.getViewPath()).render();
		}
		catch (RenderException e) {
			if (log.isErrorEnabled()) {
				String qs = request.getQueryString();
				log.error(qs == null ? target : target + "?" + qs, e);
			}
		}
		catch (ActionException e) {
			int errorCode = e.getErrorCode();
			if (errorCode == 404 && log.isWarnEnabled()) {
				String qs = request.getQueryString();
				log.warn("404 Not Found: " + (qs == null ? target : target + "?" + qs));
			}
			else if (errorCode == 401 && log.isWarnEnabled()) {
				String qs = request.getQueryString();
				log.warn("401 Unauthorized: " + (qs == null ? target : target + "?" + qs));
			}
			else if (errorCode == 403 && log.isWarnEnabled()) {
				String qs = request.getQueryString();
				log.warn("403 Forbidden: " + (qs == null ? target : target + "?" + qs));
			}
			else if (log.isErrorEnabled()) {
				String qs = request.getQueryString();
				log.error(qs == null ? target : target + "?" + qs, e);
			}
			e.getErrorRender().setContext(request, response, action.getViewPath()).render();
		}
		catch (Throwable t) {
			if (log.isErrorEnabled()) {
				String qs = request.getQueryString();
				log.error(qs == null ? target : target + "?" + qs, t);
			}
			renderFactory.getErrorRender(500).setContext(request, response, action.getViewPath()).render();
		}
	}
}

以下为核心处理代码

new Invocation(action, controller).invoke();
public void invoke() { 
// inters为此action的拦截器栈,依次执行此action的拦截器,由初始化过程可知,拦截器顺序依次为 全局,controller,method
//此方法是个递归方法 拦截器01_before->拦截器02_before->xx_before->action.getMethod.invoke(controller,NULL_ARGS)->xx_after->拦截器02_after->拦截器01_after
//作者原话:inters是一个拦截器数组,index变量是指向这个数组当前正在执行的拦截器的下标。ActionInvocation.invoke()方法是一个递归调用,此递归属于间接递归,即:ActionInvocation.invoke()中调用了Interceptor.intercepte(ActionInvocation ai),而Interceptor.intercepte(ai)方法中开发者又调用了ai.invoke(),形成间接递归关系。每次递归index变量值会加一,直到index==inters.length递归终止,此时会调用Controller中的方法。这个设计构成了拦截器对action的环绕型拦截,是一种精巧、简洁、高效的设计。
//作者原话:
if (index < inters.length) {
inters[index++].intercept(this);//逐个处理拦截
}
//拦截器执行完则开始执行controller中的方法
else if (index++ == inters.length) {// index++ ensure invoke action only one time
try {
// Invoke the action
if (action != null) {
returnValue = action.getMethod().invoke(target, args);//调用该controller中的方法
}
// Invoke the method
else {
// if (!Modifier.isAbstract(method.getModifiers()))
// returnValue = methodProxy.invokeSuper(target, args);
if (useInjectTarget)//判断method是否为抽象方法
returnValue = methodProxy.invoke(target, args);
else
returnValue = methodProxy.invokeSuper(target, args);//利用cglib的代理调用父类方法
}
}
catch (InvocationTargetException e) {
Throwable t = e.getTargetException();
throw t instanceof RuntimeException ? (RuntimeException)t : new RuntimeException(e);
}
catch (RuntimeException e) {
throw e;
}
catch (Throwable t) {
throw new RuntimeException(t);
}
}
}


© 著作权归作者所有

yiguangtia
粉丝 5
博文 39
码字总数 29778
作品 0
深圳
私信 提问
建议以依赖的方式,而非copy的方式使用jfinal代码

Springblade 的技术组合是 spring+springmvc+beetl+beetlsql+shiro,刚看了一下源码,其中大量直接 copy 的 jfinal 源码,例如 render 模块、json 模块相当于整模块原封不动地 copy 使用。项...

JFinal
2016/09/05
1K
14
JFinal Weixin 1.9 发布,微信极速 SDK

JFinal Weixin 1.9 正式发布!离上一次 JFinal weixin 1.8 发布,已经过去 10 个月。在过去的 10 个月时间里 JFinal Weixin 紧随微信公众平台的演化,不断增加了新的 API,同时也在不断完善原...

JFinal
2017/05/22
10.1K
54
JFinal 1.5 发布,JAVA极速WEB+ORM框架

JFinal 爱好者一直都在问 JFinal 何时再次升级?JFinal 1.5 何时发布?以往升级都保持在每月近两次的频率,为何本次五个月过去了新版本还不出?由于作者暂时阔别码坛已有半年时间,一直无暇顾...

JFinal
2013/10/08
7.2K
101
OSC上关于Jfinal的提问整理(二)

1.【问】:Db.tx(new IAtom())事务不起作用? 【jfinal答】:1:如果使用的mysql,确保引擎为 InnoDB 2:这行代码改一下Db.save(c3p0Plugin.getDataSource(), "tbtest", "PKID", record);去掉......

木川瓦兹
2013/04/25
0
2
微信公众号极速 SDK - JFinal Weixin

JFinal Weixin 是基于 JFinal 的微信公众号极速 SDK,只需参考 Demo 代码即可进行极速开发。自 JFinal Weixin 1.2 版本开始已添加对多公众号支持 0、Maven 坐标 1、WeixinConfig public cla...

JFinal
2014/10/21
0
54

没有更多内容

加载失败,请刷新页面

加载更多

Linux输入法fcitx的安装问题

Fcitx 总共要安装的包如下 fcitxfcitx-binfcitx-config-commonfcitx-config-gtk | fcitx-config-gtk2fcitx-datafcitx-frontend-allfcitx-frontend-gtk2fcitx-frontend-gtk3......

CHONGCHEN
47分钟前
4
0
网络基础

前言: 最近整理一些以前的学习笔记(有部分缺失,会有些乱,日后再补)。 过去都是存储在本地,此次传到网络留待备用。 计算机网络的功能: 1.数据通信; 2.资源共享; 3.增加数据可靠性; 4....

迷失De挣扎
47分钟前
3
0
spring boot升级到spring cloud

1、先升级spring boot 版本到2.1.3 <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-dependencies</artifactId> <version>2.1.3.RELEAS......

moon888
51分钟前
10
0
从蓝鲸视角谈DevOps

DevOps源于Development和Operations的组合 常见的定义 DevOps是一种重视“软件开发人员(Dev)”和“IT运维技术人员(Ops)”之间沟通合作的文化、运动或惯例。透过自动化“软件交付”和“架构变...

嘉为科技
53分钟前
1
0
微服务设计 笔记

微服务设计 一、微服务架构理论 1.六边形架构 1)六边形架构(Hexagonal Architecture),又称为端口和适配器架构风格;使用适配器与外界进行交互,外界通过应用层API与内部进行交互。 2)经典...

啃不动地大坚果
今天
2
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部