Interceptor問題

請問在Interceptor我可以塞參數然後讓Controller的Method去接參數這樣嗎?

评论区

JFinal

2017-03-24 11:38

具体一点,贴点代码出来表达希望的用法,否则我只能猜测,猜错后会浪费双方的时间

jerry1216

2017-03-24 13:32

@JFinal
我在CheckKeyInterceptor先做了一個檢核確認user,但我到EcardController.getCardInfo()時其實還是要再取一次user,有辦法在CheckKeyInterceptor檢核過了以後就把user物件丟到EcardController.getCardInfo()嗎?這樣我就不用query兩次了

public class CheckKeyInterceptor implements Interceptor {

@Override
public void intercept(Invocation inv) {
if (User.dao.getUserByserverKey(Common.getServerKey(inv.getController())) == null) {
Res resEn = I18n.use(inv.getController().getHeader("Accept-Language"));
inv.getController().getResponse().setStatus(HttpServletResponse.SC_UNAUTHORIZED);
inv.getController().renderJson("msg", "{\"Message\":\"" + resEn.get("checkKey") + "\"}");
return;
}
inv.invoke();
}

}

public class EcardController extends Controller{
private EcardService service = enhance(EcardService.class);

public void index() {
render("index.html");
}

public void login() throws Exception{
service.addLogin(this);
renderJson();
}

@Before({CheckKeyInterceptor.class})
public void getCardInfo() throws Exception{
service.getCardInfo(this);
renderJson();
}

}

JFinal

2017-03-24 17:48

这个业务层场景最好是直接在业务层中直接写代码去做验证,验证失败返回一个jfinal 提供的 Ret 对象,然后 renderJson(ret) 即可,俱乐部的 jfinal-club 中有大量的这种用法,非常方便

如果一定要用拦截器,建议如下方法:
1:将 CheckKeyInterceptor 拦截器直接用于业务层,而非控制层
2:业务层的 getCardInfo(...) 使用 User 为形参
3:在 CheckKeyInterceptor 之中通过 inv.getArg() 可获取到 User 参数值,对该值进行验证即可
4:此方法的缺点是你无法在业务层拦截器中直接 renderJson()

如果你希望在拦截器中直接 renderJson 建议采用如下办法
1:仍然使用控制层拦截器
2:在拦截器中通过 inv.getController().setAttr("user", user) 将对象传到控制器
3:控制器中通过 getAttr("user") 得到 user
4:控制器调用业务层时直接传入 user 对象

注意:以上两种办法都需要将业务层改造为传递 User user 形参,而不是 Controller 形参

注意:控制层到业务层只能是单向依赖,不能让业务层去依赖于控制层,所以 EcardService.addLogin(this) 是绝对不可以的,这种依赖方式缺点很多,例如,将来无法将业务层重用于其它场景

jerry1216

2017-03-24 18:09

@JFinal 非常感謝您的說明,我知道怎麼做了 感謝

jerry1216

2017-03-24 18:24

@JFinal 那我請教一下如果我是把EcardController都extends一個BaseController,這樣我丟到service層都用BaseController來操作就好了,也可以重用 這樣會有問題嗎?

JFinal

2017-03-24 21:13

@jerry1216 如果这种重用特别多,抽取一个 BaseController 是值得的,例如 jfinal club 就抽取了 BaseController 专门处理当前登录用户,极其方便,jfinal club 项目的BaseController 中有这些方法:
User getLoginUser()
boolean isLogin()
int getLoginUserId()

这些方法在控制器中直接获取,然后再转头去调用业务层的相关方法极为便利

热门反馈

扫码入社