动作类实现了 Preparable,ModelDriven 这两个接口,但是却无法在其方法 prapare 和 getModel 方法里获得 其它参数,进而无法根据其它参数来查询数据库。
在 prapare,getModel 这两个方法都断点了,显示执行顺序为 prapare——》 getModel,但是其它参数(如 categoryId (有对应的get / set 方法)JSP 页面上已确定没有写错。
一、业务场景:
自己想要的结果是:先根据 参数 categoryId 来查询数据库,
public void prepare() throws Exception {
// 前端传递了参数,表示 需要 查看详细属性
if( categoryId !=null ) {
//查询数据库 该类对应的 Java 类名,因为 不同种类的属性差异很大,必须获得 对应的 类
String detailsClassName = categoryService.getDetailsClassName(categoryId);
// 安全起见:只允许加载 com.jian.vo 包下的 类
if(detailsClassName !=null && detailsClassName.startsWith("com.jian.vo") ) {
try {
itemInfo = Class.forName(detailsClassName).newInstance();
logger.info("顾客需要浏览商品详情:" + itemInfo.getClass().getName() );
} catch (InstantiationException | IllegalAccessException
| ClassNotFoundException e) {
logger.error("没有对应的 VO 类:" + detailsClassName );
e.printStackTrace();
}
}
}else {
itemInfo = new ItemBaseInfoVO();
}
}
@Override
public Object getModel() {
// 让模型 去接收 前端传递过来的 参数,最后保存这个模型即可
return itemInfo;
}
但是 categoryId 的值却为 null,这就导致 查询数据库失败,后者无法查到正确值。
二、分析:
(1)因为方法执行顺序为:prapare——》getModel,并且参数没有获得,所以拦截器执行的执行顺序为:prapare——》modelDriven——》params。
默认的拦截器栈为 defaultStack( 因为 struts2 配置文件里 的 package 设置 extends="struts-default" ,在 struts-core.jar 包下的 struts-default.xml 配置文件里有 设置
defaultStack 中拦截器的 设置信息为:
dojo\..*,^struts\..*,^session\..*,^request\..*,^application\..*,^servlet(Request|Response)\..*,parameters\...*
input,back,cancel,browse
input,back,cancel,browse
(2)解决之道:
调整 拦截器的先后顺序:params——》prepare——》modelDrive,去 struts-core.jar 里的 struts-default.xml 搜索 符合这要求得 拦截器执行栈,(*^__^*) 嘻嘻……还真发现了有这一执行栈: paramsPrepareParamsStack
dojo\..*,^struts\..*,^session\..*,^request\..*,^application\..*,^servlet(Request|Response)\..*,parameters\...*
dojo\..*,^struts\..*,^session\..*,^request\..*,^application\..*,^servlet(Request|Response)\..*,parameters\...*
input,back,cancel,browse
input,back,cancel,browse
最后在 自个的 struts.xml 配置文件里的 引用这个 执行栈: paramsPrepareParamsStack
/jsp/home/HomeLayout.jsp
最后:
感知到了 Struts2 的优良设计,把一些功能模块划分成拦截器,也渐渐理解了 责任链模式的 解耦合,谢谢Struts2 作者 的无私奉献!!!