Controller拦截*.action结尾的类失败

之前的项目是struts2,现在升级为jfinal

在启动类中设置ControllerKey

public void configRoute(Routes me) {
  me.setMappingSuperClass(true);
  me.add("/hello", HelloController.class);
  me.add("/ask.action", RobotRroposeController.class);
  me.add("/ask", RobotRroposeController.class);
}

访问ask返回正确数据

http://192.168.99.128/robot/ask?key=value

访问ask.action提示not fount

http://192.168.99.128/robot/ask.action?key=value

如何将ask.action作为controllerkey注册到controller上呢?

image.png

image.png

评论区

杜福忠

2019-09-30 11:10

https://www.jfinal.com/doc/2-7
自建一个MyActionHandler
handle方法里面大致就是截取一下target参数再next.handle到后面就可以了

李通

2019-09-30 11:34

@杜福忠 测试无效,代码如下
ActionSuffixHandler
```
@Slf4j
public class ActionSuffixHandler extends Handler {

@Override
public void handle(String target, HttpServletRequest request, HttpServletResponse response, boolean[] isHandled) {
log.info("target:" + target);
next.handle(target, request, response, isHandled);
return;
}
}
```
注册handler
````
@Override
public void configHandler(Handlers me) {
me.add(new ActionSuffixHandler());
}
````
显示的日志如下
```
11:32:06.477 INFO com.alit.robot.prepose.handler.ActionSuffixHandler 15 handle - target:/ask.action
```
问题
1.理论上Handler,可以接受所有的 http请求,但是Handler如何http请求转发到指定的controller进行处理呢?
2.我设置me.setDevMode(true);但是访问ask.action时并没有看到访问的参数信息

李通

2019-09-30 11:43

我找到了原因,和解决办法
jfinal-4.2.jar 包中类,com.jfinal.core.ActionHandler的handle方法如下

public void handle(String target, HttpServletRequest request, HttpServletResponse response, boolean[] isHandled) {
if (target.indexOf('.') != -1) {
return ;
}
我感觉作者这样在大代码中写死不是很好,应该允许某些配置的后缀传入进来

李通

2019-09-30 11:50

有点小麻烦
controller._init_(action, request, response, urlPara[0]);
在编辑器中出现下面的错误信息
The method _init_(Action, HttpServletRequest, HttpServletResponse, String) from the type Controller is not visible

李通

2019-09-30 11:53

解决上面的问题,作者已经提供了方法
com.jfinal.core.CPI

// controller._init_(action, request, response, urlPara[0]);
CPI._init_(controller, action, request, response, urlPara[0]);

李通

2019-09-30 12:15

问题已经解决,最终编写的Hanlder如下
package com.alit.robot.prepose.handler;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.jfinal.aop.Invocation;
import com.jfinal.config.Constants;
import com.jfinal.core.*;
import com.jfinal.handler.Handler;
import com.jfinal.kit.ReflectKit;
import com.jfinal.render.Render;
import com.jfinal.render.RenderException;
import com.jfinal.render.RenderManager;

import lombok.extern.slf4j.Slf4j;

@Slf4j
public class ActionSuffixHandler extends Handler {
protected boolean devMode;
protected boolean injectDependency;
protected ControllerFactory controllerFactory;
protected static final RenderManager renderManager = RenderManager.me();

public ActionSuffixHandler(){
Constants constants = JFinal.me().getConstants();
init(constants);
}
protected void init(Constants constants) {
this.devMode = constants.getDevMode();
this.injectDependency = constants.getInjectDependency();
this.controllerFactory = constants.getControllerFactory();
}

/**
* 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 && !target.contains(".action")) {
return;
}

isHandled[0] = true;
String[] urlPara = { null };
//Action action = actionMapping.getAction(target, urlPara);
Action action = JFinal.me().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 controller = action.getControllerClass().newInstance();
controller = controllerFactory.getController(action.getControllerClass());
if (injectDependency) {
com.jfinal.aop.Aop.inject(controller);
}
// controller._init_(action, request, response, urlPara[0]);
CPI._init_(controller, action, request, response, urlPara[0]);

if (devMode) {
if (ActionReporter.isReportAfterInvocation(request)) {
new Invocation(action, controller).invoke();
ActionReporter.report(target, controller, action);
} else {
ActionReporter.report(target, controller, action);
new Invocation(action, controller).invoke();
}
} else {
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();
String targetInfo = (qs == null ? target : target + "?" + qs);
String sign = ReflectKit.getMethodSignature(action.getMethod());
log.error(sign + " : " + targetInfo, e);
}
renderManager.getRenderFactory().getErrorRender(500).setContext(request, response, action.getViewPath()).render();
} finally {
controllerFactory.recycle(controller);
}
}

/**
* 抽取出该方法是为了缩短 handle 方法中的代码量,确保获得 JIT 优化,
* 方法长度超过 8000 个字节码时,将不会被 JIT 编译成二进制码
*
* 通过开启 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();
}
}
@杜福忠 感谢你提供的使用handler的思路 @詹波 希望在后续版本中可以配置action的拦截后缀

杜福忠

2019-09-30 12:52

想太多了,只需要 if... next.handle(target.submit(0, target.length()-7), request, response, isHandled);使/robot/ask.action 变成 /robot/ask 继续向后传递就可以了

李通

2019-10-04 13:03

@杜福忠 真是一个好办法,向后传递的时候去除.action,谢谢

热门反馈

扫码入社