Struts1.3-DispatchAction类-根据请求参数实现业务分派
来源:互联网 发布:外汇黄金走势软件 编辑:程序博客网 时间:2024/06/06 03:45
本文将着重来理解下org.apache.struts.actions.DispatchAction类。
在有些时候一个Action可能有多种操作,比如查询,增加,删除等,都集中在了一个Action中,每个操作都会被封装在一个独立的方法中,此时需要使用某个变量来区分Action接收到的请求需要执行哪个操作,根据操作类型再去调用相应的方法。
DispatchAction类
DispatchAction类为我们实现了这个根据请求动态的分发业务给不同的方法。
比如某个Action地址为”hello.do”,当访问”hello.do?method=add”时,将调用Action类中的add方法;访问”hello.do?method=show”时,将调用Action类中show方法。
这里的请求路径参数”?method=add”,
前者参数名”method”需要在struts-config.xml配置文件中的action元素中使用parameter属性定义,
后者参数值对应着Action类中的同名方法。
我们需要将自己的Action继承DispatchAction类,DispacthAction类又是继承Action类的。然后需要声明自己的业务处理方法,
public class HelloAction extends DispatchAction{ public ActionForward add (ActionMapping mapping , ActionForm form , HttpServletRequest request , HttpServletResponse response) { System.out.println("HelloAction.add()"); return null; } public ActionForward show (ActionMapping mapping , ActionForm form , HttpServletRequest request , HttpServletResponse response) { System.out.println("HelloAction.show()"); return null; }}
这里需要注意的是,自定义的业务处理方法的格式为:
public ActionForward methodName (ActionMapping mapping , ActionForm form , HttpServletRequest request , HttpServletResponse response)
{
…
}
方法的返回类型与方法参数都是固定的,方法名可以自定义。
对应的struts-config.xml文件中action元素:
<action attribute="helloForm" input="/index.jsp" name="helloForm" path="/hello" scope="request" type="com.yourcompany.struts.action.HelloAction" cancellable="yes" parameter="method" />
最后一个parameter属性是关键。
当访问 “/hello.do?method=add”时,将调用add方法,输出”HelloAction.add()”
当访问”/hello.do?method=show”时,将调用show方法,输出”HelloAction.show()”
上面的例子是比较简单的一个DispacthAction。我们还可以重写DispacthAction类中的某些方法,比如unspecified方法,cancelled方法,execute方法等。
cancelled方法,默认方法内容为空,返回null
protected ActionForward cancelled (ActionMapping mapping , ActionForm form , HttpServletRequest request , HttpServletResponse response) throws Exception{ return null;}
当JSP页面上的<html:cancel />被按下时,cancelled方法被调用,可以重写这个方法,实现cancel按钮点击的事件处理。
@Overridepublic ActionForward cancelled (ActionMapping mapping , ActionForm form , HttpServletRequest request , HttpServletResponse response) throws Exception{ System.out.println("HelloAction.cancelled()"); ... return mapping.findForward("indexPage");//返回主页}
unspecified方法,如果当前Parameter名与配置中的parameter属性值不一样时,被调用。
比如访问地址 “/hello.do?action=add”,因为配置文件的Action元素的parameter属性值为”method”,与action不符合,此时将调用unspecified方法。
如果是参数值不同,找不到相应的方法,将抛出NoSuchMethodException异常。
默认的方法内容是直接抛出异常的:
protected ActionForward unspecified (ActionMapping mapping , ActionForm form , HttpServletRequest request , HttpServletResponse response) throws Exception{ String message = messages.getMessage("dispatch.parameter" , mapping.getPath() , mapping.getParameter()); //message:Request[{0}] does not contain handler parameter named '{1}'. This may be caused by whitespace in the label text. log.error(message); throw new ServletException(message);}
execute方法,请求当前Action时,首先被调用的方法。关于方法内部细节,请看注释。
public ActionForward execute (ActionMapping mapping , ActionForm form , HttpServletRequest request , HttpServletResponse response) throws Exception{ if (isCancelled(request)) { // 如果已经退出,调用cancelled方法。 ActionForward af = cancelled(mapping , form , request , response); // 如果返回值不为null,则直接return,否则如果为null,继续执行后面的代码。 if (af != null) { return af; } } // 获取参数名,使用ActionMapping.getParameter()方法,如果参数名为null,在getParameter方法内部会抛出ServletException异常。 String parameter = getParameter(mapping , form , request , response); // 根据参数名获取参数值 使用request.getParameter(parameter) 方法,获得希望要访问的方法名 String name = getMethodName(mapping , form , request , response , parameter); // 方法名不能为execute或者perform,否则将抛出ServletException异常。 if (("execute".equals(name)) || ("perform".equals(name))) { String message = messages.getMessage("dispatch.recursive" , mapping.getPath()); log.error(message); throw new ServletException(message); } //调用dispatchMethod方法,参数name为希望要访问的方法名,在dispatchMethod方法内部将使用反射机制去调用与name同名的方法。 //如果name==null,将调用unspecified方法,并直接返回。 return dispatchMethod(mapping , form , request , response , name);}
我们可以重写execute方法,在利用反射调用相应的方法前,对mapping,form,request,response做一定的操作,最后再:
return super.execute(mapping,form,request,response);
使用Myeclipse自动生成的Action类,一般都会默认生成一个execute方法,此时必须手动修改代码(或者直接删除execute方法),调用super.execute方法,不然覆盖了父类的execute方法将导致分发功能失效。
getParameter方法,获取配置文件中的参数名。如果参数名为null,将抛出异常。
@Overrideprotected String getParameter (ActionMapping mapping , ActionForm form , HttpServletRequest request , HttpServletResponse response) throws Exception{ // 获取配置文件中parameter属性值 String parameter = mapping.getParameter(); // 如果为null,抛出ServletException异常。 if (parameter == null) { String message = messages.getMessage("dispatch.handler" , mapping.getPath()); // DispatchMapping[{0}] does not define a handler property log.error(message); throw new ServletException(message); } return parameter;}
getMethodName方法,根据参数名获得希望访问的方法名。
@Overrideprotected String getMethodName (ActionMapping mapping , ActionForm form , HttpServletRequest request , HttpServletResponse response , String parameter) throws Exception{ return request.getParameter(parameter);}
注意,在这里使用的parameter是从配置文件的parameter属性中获取的,并不是地址栏链接参数中等于号前面的参数名。
所以,如果配置文件中的parameter值和实际访问地址中的参数名不相同的话,返回的String为null。这个null值将传递到dispatchMethod方法…
dispatchMethod方法,方法内部使用反射调用相应的方法。具体细节,请看注释。
protected ActionForward dispatchMethod (ActionMapping mapping , ActionForm form , HttpServletRequest request , HttpServletResponse response , String name) throws Exception{ // 接在execute方法内部传过来的name,如果为null,将调用unspecified方法,并直接return。 if (name == null) { return unspecified(mapping , form , request , response); } Method method = null; try { // 根据name值,获得一个Method对象,如果未找到相应的方法,将抛出NoSuchMethodException异常。 method = getMethod(name); } catch (NoSuchMethodException e) { String message = messages.getMessage("dispatch.method" , mapping.getPath() , name); log.error(message , e); String userMsg = messages.getMessage("dispatch.method.user" , mapping.getPath()); throw new NoSuchMethodException(userMsg); } ActionForward forward = null; try { // 封装4个参数为Object数组,在利用反射调用方法时作为参数传递。 Object [] args = { mapping , form , request , response }; // 利用上面获得的Method对象使用invoke从当前类中调用方法。 // 返回的对象被强转为ActionForward。 forward = (ActionForward) method.invoke(this , args); } catch (ClassCastException e) {// 当invoke方法返回的对象 无法强转为ActionForward时抛出。 String message = messages.getMessage("dispatch.return" , mapping.getPath() , name); log.error(message , e); throw e; } catch (IllegalAccessException e) {// 无法访问 方法时抛出。在自定义方法时,方法不能为私有。 String message = messages.getMessage("dispatch.error" , mapping.getPath() , name); log.error(message , e); throw e; } catch (InvocationTargetException e) { Throwable t = e.getTargetException(); if ((t instanceof Exception)) { throw ((Exception) t); } String message = messages.getMessage("dispatch.error" , mapping.getPath() , name); log.error(message , e); throw new ServletException(t); } // 最后返回我们自定义方法的返回结果 return forward;}
getMethod方法,根据方法名获取Method对象:
protected Class clazz = getClass();protected HashMap methods = new HashMap();protected Class[] types = { ActionMapping.class, ActionForm.class, HttpServletRequest.class, HttpServletResponse.class };@Overrideprotected Method getMethod (String name) throws NoSuchMethodException{ synchronized (this.methods) { Method method = (Method) this.methods.get(name);//根据name直接从HashhMap中直接获得Method对象 if (method == null)//如果为null { method = this.clazz.getMethod(name , this.types);//获取Method对象 this.methods.put(name , method);//保存在HashMap中。 } return method; }}
第一次访问时,会将获取的Method对象保存在hashMap中,下次获取时直接从HashMap中获取。
下面是综上所述形成的一个流程图…还是画的不是很好看,将就下了。
- Struts1.3-DispatchAction类-根据请求参数实现业务分派
- struts1 DispatchAction类例子
- Struts1 DispatchAction类
- struts1 DispatchAction
- Struts1 DispatchAction
- Struts1学习笔记(5)-----用DispatchAction类实现方法的动态分配
- Struts1的DispatchAction()方法
- struts1(11)-----DispatchAction
- struts1读取请求参数乱码
- 关于struts1.3中使用DispatchAction的一个问题
- struts1.3中使用DispatchAction的一个问题
- Struts1.3——DispatchAction、DynamicForm和全局跳转
- Struts1.3——DispatchAction、DynamicForm和全局跳转
- Struts1.3业务层的抽取实现DWR和Strtus业务代码共享
- struts 1 中的DispatchAction-【分派action】
- 动态方法调用和使用通配符实现类似struts1.x的dispatchAction功能
- struts2.0中如何实现struts1.2中dispatchaction的功能
- RequestDispatcher分派请求
- ural 1018 Binary Apple Tree
- android中实现sqlite打包到APK发布
- MFC、ATL窗口消息封装机制对比分析
- QEMU虚拟机关键源代码学习
- Android屏蔽home键的代码,咋摁也不响应的方法
- Struts1.3-DispatchAction类-根据请求参数实现业务分派
- Android中使用ListView以及在Listview中添加CheckBox时若干问题
- XTU 1095 连续自然数和
- PHP缓存opcode加速之APC配置使用介绍 (深入理解)
- 杭电 2857 计算几何
- 关于DN名称乱码的解决办法!
- DBGridEh的事件备忘
- Android模拟器增大内存的方法
- InstallShield安装新版本时卸载老版本