Struts2 第三讲 -- Struts2的处理流程
4.Struts2的处理流程
以下是struts-defautl.xml中的拦截器
建议通过这个struts-default的副本查看,更形象
它实现了很多的功能,其中包括国际化,文件上传,类型转换,表单验证,都是在跳转到Action类处理之前就做好了,所有我们只需要在Action类中使用就可以了,大大方便了我们的开发
下面通过使用eclipse的断点调试,看看拦截器的执行过程。我们分别在一下三个拦截器中设置断点,在我们的三个拦截器类中(invocation.invoke()所在函数中断点)中设置断点,然后根据流程查看拦截器执行顺序.
@Override public String doIntercept(ActionInvocation invocation) throws Exception { Object action = invocation.getAction(); if (action instanceof Preparable) { try { String[] prefixes; if (firstCallPrepareDo) { prefixes = new String[] {ALT_PREPARE_PREFIX, PREPARE_PREFIX}; } else { prefixes = new String[] {PREPARE_PREFIX, ALT_PREPARE_PREFIX}; } PrefixMethodInvocationUtil.invokePrefixMethod(invocation, prefixes); } catch (InvocationTargetException e) { /* * The invoked method threw an exception and reflection wrapped it * in an InvocationTargetException. * If possible re-throw the original exception so that normal * exception handling will take place. */ Throwable cause = e.getCause(); if (cause instanceof Exception) { throw (Exception) cause; } else if(cause instanceof Error) { throw (Error) cause; } else { /* * The cause is not an Exception or Error (must be Throwable) so * just re-throw the wrapped exception. */ throw e; } } if (alwaysInvokePrepare) { ((Preparable) action).prepare(); } } return invocation.invoke(); }
可见简写成下面,容易理解
PrepareInterceptor @Override public String doIntercept(ActionInvocation invocation) throws Exception { //invoke()表示放行,跳转到Action类(在跳转到Action类之前,先将所有的拦截器先执行完成) //invoke()方法的返回值,返回Action类方法的返回值 System.out.println("PrepareInterceptor的being方法"); String value = invocation.invoke(); System.out.println("PrepareInterceptor的end方法"); return value }
ChainingInterceptor @Override public String intercept(ActionInvocation invocation) throws Exception { ValueStack stack = invocation.getStack(); CompoundRoot root = stack.getRoot(); if (shouldCopyStack(invocation, root)) { copyStack(invocation, root); } //invoke()表示放行,跳转到Action类(在跳转到Action类之前,先将所有的拦截器先执行完成) //invoke()方法的返回值,返回Action类方法的返回值 System.out.println("ChainingInterceptorbeing的begin方法"); String value = invocation.invoke(); System.out.println("ChainingInterceptor的end方法"); return value
ParametersInterceptor @Override public String doIntercept(ActionInvocation invocation) throws Exception { //invoke()表示放行,跳转到Action类(在跳转到Action类之前,先将所有的拦截器先执行完成) //invoke()方法的返回值,返回Action类方法的返回值 System.out.println("ParametersInterceptor的begin方法"); String value = invocation.invoke(); System.out.println("ParametersInterceptor的end方法"); return value }
public class HelloWorldAction extends ActionSupport{ @Override public String execute() throws Exception { System.out.println("欢迎访问HelloWorldAction中的execute方法!"); return "success"; } //自定义add方法 public String add(){ System.out.println("欢迎访问HelloWorldAction中的add的方法!"); return "success"; } }
这里注意:当执行每个拦截器时,调用拦截器中的invocation.invoke();方法前的内容,此时会陆续继续执行拦截器,执行拦截器的顺序是prepare、chain、params。那么执行完Action的方法后,即调用invocation.invoke(); 方法,会继续执行params、chain、prepare拦截器中invocation.invoke();后的内容,所以我们看到顺序会是后又3,2,1.
注意上面只是为了方便理解,所以简化了源码并在源码中添加输出语句,实际源码不能改变,具体可以自己打断点,看一下流程运转;