自动以ActionHandler实现,多多指教
内部CPI调用(感谢波总指导,省去反射代码)
import com.jfinal.aop.Invocation;
import com.jfinal.core.*;
import com.jfinal.log.Log;
import com.jfinal.render.Render;
import com.jfinal.render.RenderException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class MyActionHandler extends ActionHandler {
private static final Log log = Log.getLog(ActionHandler.class);
/**
* handle
* 1: Action action = actionMapping.getAction(target)
* 2: new Invocation(...).invoke()
* 3: render(...)
*/
public void handle(String target, HttpServletRequest request, HttpServletResponse response, boolean[] isHandled) {
if (target.indexOf('.') != -1) {
return;
}
isHandled[0] = true;
String[] urlPara = {null};
Action action = actionMapping.getAction(target, urlPara);
if (action == null) {
if (log.isWarnEnabled()) {
String qs = request.getQueryString();
log.warn("404 Action Not Found: " + (qs == null ? target : target + "?" + qs));
}
renderManager.getRenderFactory().getErrorRender(404).setContext(request, response).render();
return;
}
Controller controller = null;
try {
controller = controllerFactory.getController(action.getControllerClass());
if (injectDependency) {
com.jfinal.aop.Aop.inject(controller);
}
CPI._init_(controller, action, request, response, urlPara[0]);
new Invocation(action, controller).invoke();
Render render = controller.getRender();
if (render instanceof ForwardActionRender) {
String actionUrl = ((ForwardActionRender) render).getActionUrl();
if (target.equals(actionUrl)) {
throw new RuntimeException("The forward action url is the same as before.");
} else {
handle(actionUrl, request, response, isHandled);
}
return;
}
if (render == null) {
render = renderManager.getRenderFactory().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) {
handleActionException(target, request, response, action, e);
} catch (Exception e) {
if (log.isErrorEnabled()) {
String qs = request.getQueryString();
log.error(qs == null ? target : target + "?" + qs, e);
}
renderManager.getRenderFactory().getErrorRender(500).setContext(request, response, action.getViewPath()).render();
} finally {
if (controller != null) {
CPI._clear_(controller);
}
}
}
/**
* 抽取出该方法是为了缩短 handle 方法中的代码量,确保获得 JIT 优化,
* 方法长度超过 8000 个字节码时,将不会被 JIT 编译成二进制码
* <p>
* 通过开启 java 的 -XX:+PrintCompilation 启动参数得知,handle(...)
* 方法(73 行代码)已被 JIT 优化,优化后的字节码长度为 593 个字节,相当于
* 每行代码产生 8.123 个字节
*/
private void handleActionException(String target, HttpServletRequest request, HttpServletResponse response, Action action, ActionException e) {
int errorCode = e.getErrorCode();
String msg = null;
if (errorCode == 404) {
msg = "404 Not Found: ";
} else if (errorCode == 400) {
msg = "400 Bad Request: ";
} else if (errorCode == 401) {
msg = "401 Unauthorized: ";
} else if (errorCode == 403) {
msg = "403 Forbidden: ";
}
if (msg != null) {
if (log.isWarnEnabled()) {
String qs = request.getQueryString();
msg = msg + (qs == null ? target : target + "?" + qs);
if (e.getMessage() != null) {
msg = msg + "\n" + e.getMessage();
}
log.warn(msg);
}
} else {
if (log.isErrorEnabled()) {
String qs = request.getQueryString();
log.error(errorCode + " Error: " + (qs == null ? target : target + "?" + qs), e);
}
}
e.getErrorRender().setContext(request, response, action.getViewPath()).render();
}
}反射调用
import com.jfinal.aop.Invocation;
import com.jfinal.core.*;
import com.jfinal.log.Log;
import com.jfinal.render.Render;
import com.jfinal.render.RenderException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class MyActionHandler extends ActionHandler {
private static final Log log = Log.getLog(ActionHandler.class);
/**
* handle
* 1: Action action = actionMapping.getAction(target)
* 2: new Invocation(...).invoke()
* 3: render(...)
*/
public void handle(String target, HttpServletRequest request, HttpServletResponse response, boolean[] isHandled) {
if (target.indexOf('.') != -1) {
return;
}
isHandled[0] = true;
String[] urlPara = {null};
Action action = actionMapping.getAction(target, urlPara);
if (action == null) {
if (log.isWarnEnabled()) {
String qs = request.getQueryString();
log.warn("404 Action Not Found: " + (qs == null ? target : target + "?" + qs));
}
renderManager.getRenderFactory().getErrorRender(404).setContext(request, response).render();
return;
}
Class<Controller> controllerClass = Controller.class;
Controller controller = null;
Method init_ = null;
try {
init_ = controllerClass.getDeclaredMethod("_init_", Action.class, HttpServletRequest.class, HttpServletResponse.class, String.class);
init_.setAccessible(true);
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
Method clear_ = null;
try {
clear_ = controllerClass.getDeclaredMethod("_clear_");
clear_.setAccessible(true);
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
try {
// Controller controller = action.getControllerClass().newInstance();
controller = controllerFactory.getController(action.getControllerClass());
if (injectDependency) {
com.jfinal.aop.Aop.inject(controller);
}
init_.invoke(controller, action, request, response, urlPara[0]);
new Invocation(action, controller).invoke();
Render render = controller.getRender();
if (render instanceof ForwardActionRender) {
String actionUrl = ((ForwardActionRender) render).getActionUrl();
if (target.equals(actionUrl)) {
throw new RuntimeException("The forward action url is the same as before.");
} else {
handle(actionUrl, request, response, isHandled);
}
return;
}
if (render == null) {
render = renderManager.getRenderFactory().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) {
handleActionException(target, request, response, action, e);
} catch (Exception e) {
if (log.isErrorEnabled()) {
String qs = request.getQueryString();
log.error(qs == null ? target : target + "?" + qs, e);
}
renderManager.getRenderFactory().getErrorRender(500).setContext(request, response, action.getViewPath()).render();
} finally {
if (controller != null) {
try {
clear_.invoke(controller);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
}
}
/**
* 抽取出该方法是为了缩短 handle 方法中的代码量,确保获得 JIT 优化,
* 方法长度超过 8000 个字节码时,将不会被 JIT 编译成二进制码
* <p>
* 通过开启 java 的 -XX:+PrintCompilation 启动参数得知,handle(...)
* 方法(73 行代码)已被 JIT 优化,优化后的字节码长度为 593 个字节,相当于
* 每行代码产生 8.123 个字节
*/
private void handleActionException(String target, HttpServletRequest request, HttpServletResponse response, Action action, ActionException e) {
int errorCode = e.getErrorCode();
String msg = null;
if (errorCode == 404) {
msg = "404 Not Found: ";
} else if (errorCode == 400) {
msg = "400 Bad Request: ";
} else if (errorCode == 401) {
msg = "401 Unauthorized: ";
} else if (errorCode == 403) {
msg = "403 Forbidden: ";
}
if (msg != null) {
if (log.isWarnEnabled()) {
String qs = request.getQueryString();
msg = msg + (qs == null ? target : target + "?" + qs);
if (e.getMessage() != null) {
msg = msg + "\n" + e.getMessage();
}
log.warn(msg);
}
} else {
if (log.isErrorEnabled()) {
String qs = request.getQueryString();
log.error(errorCode + " Error: " + (qs == null ? target : target + "?" + qs), e);
}
}
e.getErrorRender().setContext(request, response, action.getViewPath()).render();
}
}最后配置一下

有两个改进建议,对于 _init_() _clear_() 的调用,jfinal 早就准备好了工具类:
CPI._init_(....);
CPI._clear_();
省去反射调用, 性能会更好