struts2工作流程(精选4篇)
这是Struts2官方站点提供的Struts 2 的整体结构。
一个请求在Struts2框架中的处理大概分为以下几个步骤: 1.客户端提起一个(HttpServletRequest)请求,如上文在浏览器中输入”http://localhost:8080/TestMvc/add.action”就是提起一个(HttpServletRequest)请求。
2.请求被提交到一系列(主要是三层)的过滤器(Filter),如(ActionContextCleanUp、其他过滤器(SiteMesh等)、FilterDispatcher)。注意这里是有顺序的,先ActionContextCleanUp,再其他过滤器(SiteMesh等)、最后到FilterDispatcher。
3.FilterDispatcher是控制器的核心,就是mvc中c控制层的核心。下面粗略的分析下我理解的FilterDispatcher工作流程和原理:FilterDispatcher进行初始化并启用核心doFilter
其代码如下:
1.public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)throws IOException, ServletException...{
2.HttpServletRequest request =(HttpServletRequest)req;
3.HttpServletResponse response =(HttpServletResponse)res;
4.ServletContext servletContext = filterConfig.getServletContext();
5.// 在这里处理了HttpServletRequest和HttpServletResponse。
6.DispatcherUtils du = DispatcherUtils.getInstance();7.du.prepare(request, response);//正如这个方法名字一样进行locale、encoding以及特殊request parameters设置
8.try...{
9.request = du.wrapRequest(request, servletContext);//对request进行包装 10.} catch(IOException e)...{
11.String message = “Could not wrap servlet request with MultipartRequestWrapper!”;12.LOG.error(message, e);
13.throw new ServletException(message, e);14.}
15.ActionMapperIF mapper = ActionMapperFactory.getMapper();//得到action的mapper
16.ActionMapping mapping = mapper.getMapping(request);// 得到action 的 mapping 17.if(mapping == null)...{
18.// there is no action in this request, should we look for a static resource?
19.String resourcePath = RequestUtils.getServletPath(request);
20.if(“".equals(resourcePath)&& null!= request.getPathInfo())...{
21.resourcePath = request.getPathInfo();22.}
23.if(”true“.equals(Configuration.get(WebWorkConstants.WEBWORK_SERVE_STATIC_CONTENT))
24.&& resourcePath.startsWith(”/webwork“))...{
25.String name = resourcePath.substring(”/webwork“.length());
26.findStaticResource(name, response);27.} else...{
28.// this is a normal request, let it pass through 29.chain.doFilter(request, response);30.} 31.// WW did its job here 32.return;33.}
34.Object o = null;35.try...{
36.//setupContainer(request);
37.o = beforeActionInvocation(request, servletContext);
38.//整个框架最最核心的方法,下面分析
39.du.serviceAction(request, response, servletContext, mapping);40.} finally...{
41.afterActionInvocation(request, servletContext, o);
42.ActionContext.setContext(null);43.} 44.}
45.du.serviceAction(request, response, servletContext, mapping);
46.//这个方法询问ActionMapper是否需要调用某个Action来处理这个(request)请求,如果ActionMapper决定需要调用某个Action,FilterDispatcher把请求的处理交给ActionProxy 47.48.public void serviceAction(HttpServletRequest request, HttpServletResponse response, String namespace, String actionName, Map requestMap, Map parameterMap, Map sessionMap, Map applicationMap)...{
49.HashMap extraContext = createContextMap(requestMap, parameterMap, sessionMap, applicationMap, request, response, getServletConfig());//实例化Map请求,询问ActionMapper是否需要调用某个Action来处理这个(request)请求
50.extraContext.put(SERVLET_DISPATCHER, this);51.OgnlValueStack stack =(OgnlValueStack)request.getAttribute(ServletActionContext.WEBWORK_VALUESTACK_KEY);
52.if(stack!= null)...{
53.extraContext.put(ActionContext.VALUE_STACK,new OgnlValueStack(stack));54.} 55.try...{
56.ActionProxy proxy = ActionProxyFactory.getFactory().createActionProxy(namespace, actionName, extraContext);
57.//这里actionName是通过两道getActionName解析出来的, FilterDispatcher把请求的处理交给ActionProxy,下面是ServletDispatcher的 TODO:
58.request.setAttribute(ServletActionContext.WEBWORK_VALUESTACK_KEY, proxy.getInvocation().getStack());59.proxy.execute();
60.//通过代理模式执行ActionProxy 61.if(stack!= null)...{
62.request.setAttribute(ServletActionContext.WEBWORK_VALUESTACK_KEY,stack);63.}
64.} catch(ConfigurationException e)...{ 65.log.error(”Could not find action“, e);
66.sendError(request, response, HttpServletResponse.SC_NOT_FOUND, e);
67.} catch(Exception e)...{ 68.log.error(”Could not execute action“, e);
69.sendError(request, response, HttpServletResponse.SC_INTERNAL_SERVER_ERROR, e);70.} 71.} 72.FilterDispatcher询问ActionMapper是否需要调用某个Action来处理这个(request)请求,如果ActionMapper决定需要调用某个Action,FilterDispatcher把请求的处理交给ActionProxy。
4.ActionProxy通过Configuration Manager(struts.xml)询问框架的配置文件,找到需要调用的Action类.如上文的struts.xml配置
1.
2. 3.
4.
5.
6.
7.class=”edisundong.AddAction“ > 8.
5.ActionProxy创建一个ActionInvocation的实例,同时ActionInvocation通过代理模式调用Action。但在调用之前ActionInvocation会根据配置加载Action相关的所有Interceptor。(Interceptor是struts2另一个核心级的概念)
下面我们来看看ActionInvocation是如何工作的:
ActionInvocation 是Xworks 中Action 调度的核心。而对Interceptor 的调度,也正是由ActionInvocation负责。ActionInvocation 是一个接口,而DefaultActionInvocation 则是Webwork 对ActionInvocation的默认实现。
Interceptor 的调度流程大致如下:
1.ActionInvocation初始化时,根据配置,加载Action相关的所有Interceptor。
2.通过ActionInvocation.invoke方法调用Action实现时,执行Interceptor。
Interceptor将很多功能从我们的Action中独立出来,大量减少了我们Action的代码,独立出来的行为具有很好的重用性。XWork、WebWork的许多功能都是有Interceptor实现,可以在配置文件中组装Action用到的Interceptor,它会按照你指定的顺序,在Action执行前后运行。那么什么是拦截器。
拦截器就是AOP(Aspect-Oriented Programming)的一种实现。(AOP是指用于在某个方法或字段被访问之前,进行拦截然后在之前或之后加入某些操作。)
拦截器的例子这里就不展开了。struts-default.xml文件摘取的内容:
1.< interceptor name =”alias“ class =”com.opensymphony.xwork2.interceptor.AliasInterceptor“ /> 2.< interceptor name =”autowiring“ class =”com.opensymphony.xwork2.spring.interceptor.ActionAutowiringInterceptor“ />
3.< interceptor name =”chain“ class =”com.opensymphony.xwork2.interceptor.ChainingInterceptor“ />
4.< interceptor name =”conversionError“ class =”org.apache.struts2.interceptor.StrutsConversionErrorInterceptor“ /> 5.< interceptor name =”createSession“ class =”org.apache.struts2.interceptor.CreateSessionInterceptor“ />
6.< interceptor name =”debugging“ class =”org.apache.struts2.interceptor.debugging.DebuggingInterceptor“ /> 7.< interceptor name =”external-ref“ class =”com.opensymphony.xwork2.interceptor.ExternalReferencesInterceptor“ />
8.< interceptor name =”execAndWait“ class =”org.apache.struts2.interceptor.ExecuteAndWaitInterceptor“ />
9.< interceptor name =”exception“ class =”com.opensymphony.xwork2.interceptor.ExceptionMappingInterceptor“ /> 10.< interceptor name =”fileUpload“ class =”org.apache.struts2.interceptor.FileUploadInterceptor“ />
11.< interceptor name =”i18n“ class =”com.opensymphony.xwork2.interceptor.I18nInterceptor“ />
12.< interceptor name =”logger“ class =”com.opensymphony.xwork2.interceptor.LoggingInterceptor“ />
13.< interceptor name =”model-driven“ class =”com.opensymphony.xwork2.interceptor.ModelDrivenInterceptor“ /> 14.< interceptor name =”scoped-model-driven“ class =”com.opensymphony.xwork2.interceptor.ScopedModelDrivenInterceptor“ /> 15.< interceptor name =”params“ class =”com.opensymphony.xwork2.interceptor.ParametersInterceptor“ />
16.< interceptor name =”prepare“ class =”com.opensymphony.xwork2.interceptor.PrepareInterceptor“ />
17.< interceptor name =”static-params“ class =”com.opensymphony.xwork2.interceptor.StaticParametersInterceptor“ />
18.< interceptor name =”scope“ class =”org.apache.struts2.interceptor.ScopeInterceptor“ />
19.< interceptor name =”servlet-config“ class =”org.apache.struts2.interceptor.ServletConfigInterceptor“ />
20.< interceptor name =”sessionAutowiring“ class =”org.apache.struts2.spring.interceptor.SessionContextAutowiringInterceptor“ />
21.< interceptor name =”timer“ class =”com.opensymphony.xwork2.interceptor.TimerInterceptor“ />
22.< interceptor name =”token“ class =”org.apache.struts2.interceptor.TokenInterceptor“ />
23.< interceptor name =”token-session“ class =”org.apache.struts2.interceptor.TokenSessionStoreInterceptor“ /> 24.< interceptor name =”validation“ class =”com.opensymphony.xwork2.validator.ValidationInterceptor“ />
25.< interceptor name =”workflow“ class =”com.opensymphony.xwork2.interceptor.DefaultWorkflowInterceptor“ /> 26.< interceptor name =”store“ class =”org.apache.struts2.interceptor.MessageStoreInterceptor“ />
27.< interceptor name =”checkbox“ class =”org.apache.struts2.interceptor.CheckboxInterceptor“ />
2.说说struts1与struts2的区别 都是MVC的WEB框架;
struts1的前端控制器是一个Servlet,名称为ActionServlet,struts1的action需要继承Action类,struts2的action可以不继承任何类; Struts1依赖与servlet的API struts1对同一个路径的所有请求共享一个Action实例,struts2对同一个路径的每个请求分别使用一个独立Action实例对象,所有对于struts2的Action不用考虑线程安全问题;
在struts1中使用formbean封装请求参数,在struts2中直接使用action的属性来封装请求参数; struts1中的多个业务方法放在一个Action中时(即继承DispatchAction时),要么都校验,要么都不校验;对于struts2,可以指定只对某个方法进行校验,当一个Action继承了ActionSupport且在这个类中只编写了validateXxx()方法,那么则只对xxx()方法进行校验;
3.转发和重定向的区别?
4.Struts2执行流程 客户端发出一个指向servlet容器的请求(tomcat)这个请求经过一系列的过滤器(Filter),最后达到StrutsPrepareAndExecuteFilter 过滤器是struts2框架的心脏,询问ActionMapper类来查找请求中需要用到的Action,如果找到需要调用的Action,过滤器会把请求的处理交给ActionProxy。ActionProxy为Action的代理对象。ActionProxy创建一个
ActionInvocation的实例,并调用
ActionInvocation的invoke(),ActionInvocation实例包含了一系列的拦截器,在调用Action的过程前,涉及到相关拦截器(Intercepter)的调用。
5.拦截器的生命周期 每个拦截器都实现了Interceptor接口的java类
init(): 在拦截器对象被创建后立即调用,只会调用一次,一般用来进行相关资源的初始化 intercept(ActionInvocation invocation):每个拦截一个动作请求,该方法就会被调用过一次 destory(): 该方法将在拦截器被销毁前条用,只会调用一次,一般用来释放资源 Struts2默认调用18个拦截器 一旦Action执行完毕,ActionInvocation负责根据struts.xml中的配置找到对应的返回结果。
struts2的过滤器转发:服务端跳转,在客户端浏览器地址栏中不会显示出转向后的地址,一次请求;
重定向:客户端跳转,浏览器将会得到跳转的地址,并重新发送请求链接,两次请求。在有些情况下,比如,需要跳转到一个其它服务器上的资源,则必须使用重定向。struts2的前端控制器是一个filter,在struts2.1中叫StrutsPrepareAndExecuteFilter;
Struts2不依赖与Servlet的API 6.Struts2有哪些优点
7.Struts2常量的修改方式?
常量可以在struts.xml或struts.properties中配置
8.Struts2如何访问HttpServletRequest,HttpSession,ServletContext,HttpServletResponse? 方式一:主动获取
HttpServletRequest request =ServletActionContext.getRequest();HttpSession session =request.getSession();ServletContext application =session.getServletContext();在struts.xml中配置常量
在struts.properties中配置常量
类型转换器,实现了字符串与特殊数据类类的转换 Struts2可以对指定某个方法进行校验
提供了全局范围。包范围和action范围的国际化资源文件管理
为应用程序添加了全局的result,和声明式异常处理
可以实现模块化管理,将应用程序模块化
HttpServletResponse response=ServletActionContext.getResponse();
方式二:依赖框架注入
定义类实现implements ServletRequestAware,ServletResponseAware,注入请求对象和响应对象,session对象和application对应通过request间接获得。
9.Struts2如何管理aciton,这种管理方式有什么好处?
Struts2框架使用包管理Action,包的作用和java中的类包相似,主要管理一组业务功能相关的action。在实际应用中,我们应该把一组业务功能相关的Action放在同一个包下。
10.Strus2中校验的执行流程
11.介绍ActionContext,ServletContext,pageContext? ActionContext是当前Action的上下文,通过ActionContext可以获取request,session.applicationd等于Action有关的对象引用。
ServletContext是域对象,生命周期伴随整个web应用。类型转换不管是否成功后,都会进行校验
先调用validateXxx()进行校验,只会校验action中方法名为xxx()的方法,如果校验失败,添加校验失败信息
再调用validate()方法,会校验action中所有与execute方法签名相同的方法,如果校验失败,添加校验失败信息
如果校验失败,则跳转到name=“input”的result指定的页面,否则,调用action的具体方法 pageContext也是一个域对象,其作用范围只是当前页面。12.Ajax的优点 页面无刷新,用户的体验非常好。与服务器通信,具有更加迅速的响应能力。
可以把以前一些服务器负担的工作转嫁到客户端,利用客户端闲置的能力来处理,减轻服务器和带宽的负担,节约空间和宽带租用成本。并且减轻服务器的负担,ajax的原则是“按需取数据”,可以最大程度的减少冗余请求,和响应对服务器造成的负担。
13.Ajax的缺点
14.XMLHttpRequest对象的常用属性和方法
常用属性:
readyState属性:请求的状态,有5个可取值 0=未初始化,1=正在加载 2=以加载,3=交互中,4=完成
responseText 属性: 服务器的响应,表示为一个字符串 reponseXML 属性:服务器的响应,表示为XML格式的对象
status :服务器的HTTP状态码,200对应ok 400对应not found。
常用方法:
open(“method”,”URL”)建立对服务器的调用;
第一个参数是HTTP请求,方式可以为GET,POST或任何服务器所支持的您想调用的方式。
第二个参数是请求页面的URL。send()方法,发送具体请求
15.谈谈XMLHttpRequest对象
Ajax的核心是JavaScript对象XMLHttpRequest。该对象在Internet Explorer 5中首次引入,它是一种支持异步请求的技术。简而言之,XMLHttpRequest使您可以使用JavaScript向服务器提出请求并处理响应,而不阻塞用户。通过XMLHttpRequest对象,Web开发人员可以在页面加载以后进行页面的局部更新。
破坏浏览器后退按钮的正常行为。
如果web.xml中struts2和servlet的配置如下:
.substring(target.lastIndexOf(“/”)+ 1);
if(this.includes.contains(target)){
RequestDispatcher rdsp = request.getRequestDispatcher(target);
rdsp.forward(req,resp);
} else
chain.doFilter(req, resp);
}
@Override
public void init(FilterConfig config)throws ServletException {
this.includes.addAll(Arrays.asList(config.getInitParameter(“includeServlets”).split(“,”)));
}
}
2.在web.xml中做适当配置,在struts2的配置前加上下面的代码:
includeServlets
ValidateEmail
其中,
拦截器与过滤器的区别:
1、拦截器是基于java的反射机制的,而过滤器是基于函数回调
2、过滤器依赖与servlet容器,而拦截器不依赖与servlet容器
3、拦截器只能对action请求起作用,而过滤器则可以对几乎所有的请求起作用
4、拦截器可以访问action上下文、值栈里的对象,而过滤器不能
5、在action的生命周期中,拦截器可以多次被调用,而过滤器只能在容器初始化时被调用一次
过滤器
也就是写一个自己的类,让这个类实现于Filter这个接口,这个接口里有三个方法。
init(),doFilter(),destroy();主要是对doFilter()进行操作,你可以在这个方法里写你想进行的操作.写完这些之后,就是在web.xml里的配置了
在
1、定义拦截器
a.方法一:实现Interceptor接口
public class MyInterceptor implements Interceptor { private String hello;//定义带参数的拦截器 public String getHello(){ return hello;} public void setHello(String hello){ this.hello = hello;} public void destroy(){ // TODO Auto-generated method stub System.out.println(“destroy”);} @Override public void init(){ //服务器启动时自动加载一次 System.out.println(“init”);System.out.println(“hello”);} @Override public String intercept(ActionInvocation arg0)throws Exception { System.out.println(“inercept”);String result=arg0.invoke();System.out.println(“finish”);return result;} } b.方法二:继承AbstractInterceptor类
public class MyInterceptor2 extends AbstractInterceptor { @Override public String intercept(ActionInvocation arg0)throws Exception { System.out.println(“intercept2”);String result=arg0.invoke();System.out.println(“finish2”);return result;} } c.方法三:继承MethodFilterInterceptor类,定义过滤方法的拦截器 public class MyInterceptor3 extends MethodFilterInterceptor { //过滤方法的拦截器 @Override protected String doIntercept(ActionInvocation arg0)throws Exception { arg0.addPreResultListener(new MyListener());//将监听器注册到里面
System.out.println(“myinterceptor3”);String result=arg0.invoke();System.out.println(“after myinterceptor3 ”);return result;} }
2、配置拦截器
一旦实现了上面的拦截器,就可以在所有需要实现控制的Action中复用上面的拦截器。为了使用该拦截器,首先在struts.xml文件中定义该拦截器,定义拦截器的配置片段如下: world
3、应用拦截器