实现方式
1、在struts.xml或xwork.xml加如下配置信息
<global-results>
<result name="auto">/${proxy.config.packageName}/${proxy.method}.jsp</result>
</global-results>
2、在BaseAction类中加入proxy的方法实现
private ActionProxy proxy;
public ActionProxy getProxy(){
if(proxy == null)
proxy = ActionContext.getContext().getActionInvocation().getProxy();
return proxy;
}
3、做一个JSP文件,文件名一定要与action的方法名相同,列如:a.jap那么action的方法的写法
public String a() throws Exception{
return AUTO;
}
4、在某个Jsp页面中调于这个无配置actoin的写法
actionName!a.action
分析
ActionProxy类是struts2或webwork提供的一个action代理类,它的作用是它的作用是记录当前这个action的对象、action的名称、配置信息及该action所属的包名等信息。该接口的声明如下
public interface ActionProxy {
/**
* @return the Action instance for this Proxy
*/
Object getAction();
/**
* @return the alias name this ActionProxy is mapped to
*/
String getActionName();
/**
* @return the ActionConfig this ActionProxy is built from
*/
ActionConfig getConfig();
/**
* Sets whether this ActionProxy should also execute the Result after executing the Action
*
* @param executeResult
*/
void setExecuteResult(boolean executeResult);
/**
* @return the status of whether the ActionProxy is set to execute the Result after the Action is executed
*/
boolean getExecuteResult();
/**
* @return the ActionInvocation associated with this ActionProxy
*/
ActionInvocation getInvocation();
/**
* @return the namespace the ActionConfig for this ActionProxy is mapped to
*/
String getNamespace();
/**
* Execute this ActionProxy. This will set the ActionContext from the ActionInvocation into the ActionContext
* ThreadLocal before invoking the ActionInvocation, then set the old ActionContext back into the ThreadLocal.
*
* @return the result code returned from executing the ActionInvocation
* @throws Exception
* @see ActionInvocation
*/
String execute() throws Exception;
/**
* Sets the method to execute for the action invocation. If no method is specified, the method provided by
* in the action's configuration will be used.
*
* @param method the string name of the method to invoke
*/
void setMethod(String method);
/**
* Returns the method to execute, or null if no method has been specified (meaning "execute" will be invoked)
*/
String getMethod();
}
J-Hi借用了这个代理类,在action的基类也就是BaseAction中添加了对该类实例的引用,从而实体全局配置
<result name="auto">/${proxy.config.packageName}/${proxy.method}.jsp</result>
其中
${proxy.config.packageName}用来指定当前action所属的包名,例如,"testjs"就是配置文件的包名
<xwork>
<package name="testjs" extends="hi" >
<action name="materialList"
class="org.hi.testjs.action.webwork.MaterialListAction">
<result name="success">/testjs/MaterialList.jsp</result>
<interceptor-ref name="modelParamsStack" />
</action>
.
</xwork>
${proxy.method}是指调用该action的方法名
name="auto" 是我们特意为这样无配置的actoin起了一个特定的名字,也就是说
public String a() throws Exception{
return "auto";
或
return AUTO;
}
效果是一样的
我们特意将这段result的配置放在了<global-results>中原因是省去写配置文件,只要是return "auto";就会调用这个结果。那么它的结果是什么呢?对,是一个JSP,也就是说你通过actionName!method.action后,系统会自动执行这个方法,并自动调用这个aciton所属包名下的与方法名相同的jsp文件。例如配置文件的包名为"testjs",actionName为"materialList",对应的class为"
org.hi.testjs.action.webwork.MaterialListAction",你在这个action类中增加了一个a(),想通过调用该方法实现无配置调用jsp,那么你就应该将这个jsp文件放到web/testjs(与包名相同)目录下,并且该jsp的文件名为a.jsp(与方法名相同)。调用这个action方法的写法如下:
materialList!a.action。OK,大工告成!!
技巧
为了适应不同人对action的开发习惯,J-Hi对struts2与webwork的生成方式是不同的。struts2是所有的操作都放在一个Action类中通过方法调用,而webwork是每个一操作一个Action类。两种方式均有优势也优有不足之处,大家在使用时全凭自己的习惯就好。我们之所以实现无配置,主要是考虑到J-Hi它不只是一个开发管理系统的平台,也应该可以做网站或电子商务前端的开发。我们知道对于后台管理系统主要考虑的是系统安全性(页面的布局与样式风格要统一),而网站或电子商务前端恰好相反,它追求的是安全不是问题因为它欢迎更多的浏览者不需要对每个操作都做权限控制(页面的风格也五花八门,炫、酷不规则是这类系统的特点)。因此提供了无配置文件的方式,以满足这类需求(当然纯页面还是要由美工来完成,无规则平台的生成器是无法胜任该工作的)。由此而带来的另一个问题是,平台已经生成了很多aciton的功能,如何让前台与后台共用这些已生成的action类呢?下面我们以struts2为例
在BaseAction中有一个
protected String returnCommand()方法,该方法是确定返回的结果的名字
protected String returnCommand(String message){
String viewMode = HiConfigHolder.getViewMode();
if(viewMode.equals("dwz")){
if ((ajax == null || !ajax.trim().equals("1")) && message == null)
return SUCCESS;
if(message == null)
return ajaxForwardSuccess(I18NUtil.getString("操作成功")); //如果是dwz版就返回一个json对象的字符串
else
return ajaxForwardError(message);
}
return SUCCESS; //如果是经典版就返回success字符串
}
如果你想在前台调用平台已生成的action,而跳过权限控制,就可以通过无配置文件这种方式来实现,解决方案为,你在要做无配置的action类中覆盖BaseAction的retunCommand()方法,覆盖的实现方法如下:
protected String returnCommand() {
if(this.getRequest().getRequestURI().indexOf("!") >0) //如果在URL中包含!就说明是无配置的,它就会返回auto
return "auto";
return super.returnCommand(); //否则就走BaseAction也就是父类的retunCommand()方法
}
例如struts的action配置文件如下
<struts>
<package name="testjs" extends="hi" >
<action name="material"
class="org.hi.testjs.action.struts.MaterialAction">
<interceptor-ref name="modelParamsStack" />
</action>
.
</struts>
平台生成的
MaterialAction类会有一个materialList(),你想在前台调用而忽略权限,就可以写成
material!materialList.action,就可以了