【面试】【Struts2常见问题总结】【01】

来源:互联网 发布:软件平台是什么 编辑:程序博客网 时间:2024/06/05 11:44

【常见面试问题总结目录>>>】


001 请简述struts1的工作流程和机制:

  Struts的工作流程:
  在web应用启动时就会加载初始化ActionServlet,ActionServlet从
  struts-config.xml文件中读取配置信息,把它们存放到各种配置对象
  当ActionServlet接收到一个客户请求时,将执行如下流程.
    (1) 检索和用户请求匹配的ActionMapping实例,如果不存在,就返回请求路径无效信息;
    (2) 如果ActionForm实例不存在,就创建一个ActionForm对象,把客户提交的表单数据保存到ActionForm对象中;
    (3)根据配置信息决定是否需要表单验证.如果需要验证,就调用ActionForm的validate()方法;
    (4)如果ActionForm的validate()方法返回null或返回一个不包含ActionMessage的ActuibErrors对象, 就表示表单验证成功;
    (5)ActionServlet根据ActionMapping所包含的映射信息决定将请求转发给哪个Action,如果相应的 Action实例不存在,就先创建这个实例,然后调用Action的execute()方法;
    (6)Action的execute()方法返回一个ActionForward对象,ActionServlet在把客户请求转发给 ActionForward对象指向的JSP组件;
    (7)ActionForward对象指向JSP组件生成动态网页,返回给客户;
  对于以上流程的流程(4),如果ActionForm的validate()方法返回一个或多个ActionMessage的ActionErrors对象,就表示表单验证失败,此时ActionServlet将直接把请求转发给包含用户提交表单的JSP组件( input=”验证失败要转的页面”)。再这种情况下,不会再创建Action对象并 调用Action的execute()方法。

002 struts1和struts2的区别和对比?

  Action 类:
  • Struts1要求Action类继承一个抽象基类。Struts1的一个普遍问题是使用抽象类编程而不是接口。
  • Struts 2 Action类可以实现一个Action接口,也可实现其他接口,使可选和定制的服务成为可能。Struts2提供一个ActionSupport基类去 实现 常用的接口。Action接口不是必须的,任何有execute标识的POJO对象都可以用作Struts2的Action对象。
  线程模式:
  • Struts1 Action是单例模式并且必须是线程安全的,因为仅有Action的一个实例来处理所有的请求。单例策略限制了Struts1 Action能作的事,并且要在开发时特别小心。Action资源必须是线程安全的或同步的。
  • Struts2 Action对象为每一个请求产生一个实例,因此没有线程安全问题。(实际上,servlet容器给每个请求产生许多可丢弃的对象,并且不会导致性能和垃圾回收问题)
  Servlet 依赖:
  • Struts1 Action 依赖于Servlet API ,因为当一个Action被调用时HttpServletRequest 和 HttpServletResponse 被传递给execute方法。
  • Struts 2 Action不依赖于容器,允许Action脱离容器单独被测试。如果需要,Struts2 Action仍然可以访问初始的request和response。但是,其他的元素减少或者消除了直接访问HttpServetRequest 和 HttpServletResponse的必要性。
  可测性:
  • 测试Struts1 Action的一个主要问题是execute方法暴露了servlet API(这使得测试要依赖于容器)。一个第三方扩展--Struts TestCase--提供了一套Struts1的模拟对象(来进行测试)。
  • Struts 2 Action可以通过初始化、设置属性、调用方法来测试,“依赖注入”支持也使测试更容易。
  捕获输入:
  • Struts1 使用ActionForm对象捕获输入。所有的ActionForm必须继承一个基类。因为其他JavaBean不能用作ActionForm,开发者经 常创建多余的类捕获输入。动态Bean(DynaBeans)可以作为创建传统ActionForm的选择,但是,开发者可能是在重新描述(创建)已经存 在的JavaBean(仍然会导致有冗余的javabean)。
  • Struts 2直接使用Action属性作为输入属性,消除了对第二个输入对象的需求。输入属性可能是有自己(子)属性的rich对象类型。Action属性能够通过 web页面上的taglibs访问。Struts2也支持ActionForm模式。rich对象类型,包括业务对象,能够用作输入/输出对象。这种 ModelDriven 特性简化了taglib对POJO输入对象的引用。
  表达式语言:
  • Struts1 整合了JSTL,因此使用JSTL EL。这种EL有基本对象图遍历,但是对集合和索引属性的支持很弱。
  • Struts2可以使用JSTL,但是也支持一个更强大和灵活的表达式语言--”Object Graph Notation Language” (OGNL).
   绑定值到页面(view):
  • Struts 1使用标准JSP机制把对象绑定到页面中来访问。
  • Struts 2 使用 “ValueStack”技术,使taglib能够访问值而不需要把你的页面(view)和对象绑定起来。ValueStack策略允许通过一系列名称相同但类型不同的属性重用页面(view)。
  类型转换:
  • Struts 1 ActionForm 属性通常都是String类型。Struts1使用Commons-Beanutils进行类型转换。每个类一个转换器,对每一个实例来说是不可配置的。
  • Struts2 使用OGNL进行类型转换。提供基本和常用对象的转换器。
  校验:
  • Struts 1支持在ActionForm的validate方法中手动校验,或者通过Commons Validator的扩展来校验。同一个类可以有不同的校验内容,但不能校验子对象。
  • Struts2支持通过validate方法和XWork校验框架来进行校验。XWork校验框架使用为属性类类型定义的校验和内容校验,来支持chain校验子属性
Action执行的控制:
  • Struts1支持每一个模块有单独的Request Processors(生命周期),但是模块中的所有Action必须共享相同的生命周期。
  • Struts2支持通过拦截器堆栈(Interceptor Stacks)为每一个Action创建不同的生命周期。堆栈能够根据需要和不同的Action一起使用。

003 简述Struts Form Bean的表单验证流程

  1、当用户提交了HTML表单,Struts框架自动把表单数据组装到ActionForm Bean中。
  2、接下来Struts框架会调用ActionForm Bean的validate()方法进行表单验证。
  3、如果validate()方法返回的ActionErrors 对象为null,或者不包含任何ActionMessage对象,就表示没有错误,数据验证通过。
  4、如果ActionErrors中包含ActionMessage对象,就表示发生了验证错误,Struts框架会把ActionErrors对象保存到request范围内,然后把请求转发到恰当的视图组件,视图组件通过<html:errors>标签把request范围内的ActionErrors对象中包含的错误消息显示出来,提示用户修改错误。
  对于以上流程的步骤4 。如果ActionForm的validate()方法返回一个包含一个或多个ActionError的ActionErrors对象,就表示表单验证失败,此时ActionServlet将直接把请求转发给包含客户提交表单的JSP组件。在这种情况下,不会再创建Action对象并调用Action的execute方法。

004 Action是不是线程安全的?如果不是 有什么方式可以保证Action的线程安全?如果是,说明原因

  Struts1不是
  声明局部变量,或者扩展RequestProcessor,让每次都创建一个Action,或者在spring中用scope=”prototype”来管理

005 action是单实例还是多实例,为什么?

  Struts1的action是单实例的。当多个用户访问一个请求的时候,服务器内存中只有一个与之对应的action类对象。
  因为当服务器第一次加载struts的配置文件的时候,创建了一个Action后,每发送一个请求,服务器都会先去检索相应的范围内(request,session)是否存在
  这样一个action实例,如果存在,则使用这个实例,如果不存在,则创建一个action实例。

006 struts2.0的mvc模式?与struts1.0的区别?

  struts2的mvc模式:当用户在页面提交用户请求时,该请求需要提交给struts2的控制器处理。struts2的控制器根据处理结果, 决定将哪个页面呈现给客户端。
  与struts1最大的不同是:struts2的控制器。struts2的控制器不再像struts1的控制器,需要继承一个Action父类,甚至可以无需实现任何接口,struts2的Action就是一个普通的POJO。实际上,Struts2 的Action就是一个包含execute方法的普通Java类,该类里包含的多个属性用于封装用户的请求参数。

007 Struts2工作原理

这里写图片描述
  一个请求在Struts2框架中的处理大概分为以下几个步骤:
  1、客户端初始化一个指向Servlet容器(例如Tomcat)的请求;
  2、这个请求经过一系列的过滤器(Filter)(这些过滤器中有一个叫做ActionContextCleanUp的可选过滤器,这个过滤器对于Struts2和其他框架的集成很有帮助,例如:SiteMeshPlugin);
  3、接着FilterDispatcher被调用,FilterDispatcher询问ActionMapper来决定这个请是否需要调用某个Action。
  4、如果ActionMapper决定需要调用某个Action,FilterDispatcher把请求的处理交给ActionProxy。
  5、ActionProxy通过ConfigurationManager询问框架的配置文件,找到需要调用的Action类。
  6、ActionProxy创建一个ActionInvocation的实例。
  7、ActionInvocation实例使用命名模式来调用,在调用Action的过程前后,涉及到相关拦截器(Intercepter)的调用。
  8、一旦Action执行完毕,ActionInvocation负责根据struts.xml中的配置找到对应的返回结果。返回结果通常是(但不总是,也可能是另外的一个Action链)一个需要被表示的JSP或者FreeMarker的模版。在表示的过程中可以使用Struts2框架中继承的标签。在这个过程中需要涉及到ActionMapper。

008 Struts的设计模式

  MVC模式:web应用程序启动时就会加载并初始化ActionServlet。用户提交表单时,一个配置好的ActionForm对象被创建,并被填入表单相应的数据,ActionServlet根据Struts-config.xml文件配置好的设置决定是否需要表单验证,如果需要就调用ActionForm的Validate()验证后选择将请求发送到哪个Action,如果Action不存在,ActionServlet会先创建这个对象,然后调用Action的execute()方法。Execute()从ActionForm对象中获取数据,完成业务逻辑,返回一个ActionForward对象,ActionServlet再把客户请求转发给ActionForward对象指定的jsp组件,ActionForward对象指定的jsp生成动态的网页,返回给客户。

009 Struts2 的特点

  Struts2 是一个相当强大的Java Web开源框架,是一个基于POJO的Action的MVC Web框架。它基于当年的Webwork和XWork框架,继承其优点,同时做了相当的改进。
  1、Struts2基于MVC架构,框架结构清晰,开发流程一目了然,开发人员可以很好的掌控开发的过程。
  2、使用OGNL进行参数传递。OGNL提供了在Struts2里访问各种作用域中的数据的简单方式,你可以方便的获取Request,Attribute,Application,Session,Parameters中的数据。大大简化了开发人员在获取这些数据时的代码量。
  3、强大的拦截器 。Struts2 的拦截器是一个Action级别的AOP,Struts2中的许多特性都是通过拦截器来实现的,例如异常处理,文件上传,验证等。拦截器是可配置与重用的,可以将一些通用的功能如:登录验证,权限验证等置于拦截器中以完成一些Java Web项目中比较通用的功能。
  4、易于测试 。Struts2的Action都是简单的POJO,这样可以方便的对Struts2的Action编写测试用例,大大方便了Java Web项目的测试。
  5、易于扩展的插件机制。在Struts2添加扩展是一件愉快而轻松的事情,只需要将所需要的Jar包放到WEB-INF/lib文件夹中,在struts.xml中作一些简单的设置就可以实现扩展。
  6、模块化管理。Struts2已经把模块化作为了体系架构中的基本思想,可以通过三种方法来将应用程序模块化:将配置信息拆分成多个文件把自包含的应用模块创建为插件创建新的框架特性,即将与特定应用无关的新功能组织成插件,以添加到多个应用中去。
  7、全局结果与声明式异常 。为应用程序添加全局的Result,和在配置文件中对异常进行处理,这样当处理过程中出现指定异常时,可以跳转到特定页面。

010 Struts2拦截器原理

  Struts2的拦截器实现相对简单。当请求到达Struts 2的ServletDispatcher时,Struts2会查找配置文件,并根据其配置实例化相对的拦截器对象,然后串成一个列表(list),最后一个一个地调用列表中的拦截器。事实上,我们之所以能够如此灵活地使用拦截器,完全归功于“动态代理”的使用。

011 自定义拦截器:

  1、实现拦截器类:com.opensymphony.xwork2.interceptor.Interceptor。
  2、注册自定义拦截器:需要在<interceptors>中注册。
  3、可以将拦截器放入拦截器栈<interceptor-stack>。
  4、在action中应用拦截器。
  5、也可以设置默认的拦截器。<default-interceptor-refname=”myInterceptor”/>

012 拦截器和过滤器的差异

  拦截器和过滤器之间有很多相同之处,但是两者之间存在根本的差别。其主要区别为以下几点:
  1)拦截器是基于JAVA反射机制的,而过滤器是基于函数回调的。
  2)过滤器依赖于Servlet容器,而拦截器不依赖于Servlet容器。
  3)拦截器只能对Action请求起作用,而过滤器可以对几乎所有的请求起作用。
  4)拦截器可以访问Action上下文、值栈里的对象,而过滤器不能
  5)在Action的生命周期中,拦截器可以多次被调用,而过滤器只能在容器初始化时被调用一次(init方法)。

013 Struts2核心控制器的作用

  StrutsPrepareAndExecuteFilter的作用:负责拦截由<url-pattern>/*</url-pattern>指定的所有用户请求,当用户请求到达时,该Filter会过滤用户的请求。默认情况下,如果用户请求的路径不带后缀或者后缀以.action结尾,这时请求将被转入struts2框架处理,否则struts2框架将略过该请求的处理。
  可以通过常量”struts.action.extension”修改action的后缀,如:
<constant name=”struts.action.extension” value=”do”/>

014 Struts2获取HttpServletRequest、HttpSession、ServletContext对象

  通过ServletActionContext的相应的静态方法即可获取。

015 Struts2管理action的方式及优点

  Struts2框架中使用包来管理Action,包的作用和java中的类包是非常类似的。主要用于管理一组业务功能相关的action。在实际应用中,我们应该把一组业务功能相关的Action放在同一个包下。

016 Struts2的默认包struts-default的作用

  1)struts-default包是由struts内置的,它定义了struts2内部的众多拦截器和Result类型,而Struts2很多核心的功能都是通过这些内置的拦截器实现,如:从请求中把请求参数封装到action、文件上传和数据验证等等都是通过拦截器实现的。当包继承了##struts-default包才能使用struts2为我们提供的这些功能。
  2)struts-default包是在struts-default.xml中定义,struts-default.xml也是Struts2默认配置文件。 Struts2每次都会自动加载 struts-default.xml文件。
  3)通常每个包都应该继承struts-default包。

017 Struts2对指定的方法进行验证

  1)validate()方法会校验action中所有与execute方法签名相同的方法;
  2)要校验指定的方法通过重写validateXxx()方法实现,validateXxx()只会校验action中方法名为Xxx的方法。其中Xxx的第一个字母要大写;
  3)当某个数据校验失败时,调用addFieldError()方法往系统的fieldErrors添加校验失败信息(为了使用addFieldError()方法,action可以继承ActionSupport), 如果系统 的fieldErrors包含失败信息,struts2会将请求转发到名为input的result;
  4)在input视图中可以通过<s:fielderror/>显示失败信息。
  5)先执行validateXxxx()->validate()->如果出错了,会转发<result name=”input”/>所指定的页面,如果不出错,会直接执行Action.execute()方法。

018 struts2默认拦截器

  fileUpload:提供文件上传功能
  i18n:记录用户选择的locale
  cookies:使用配置的name,value来是指cookiescheckbox添加了checkbox自动处理代码,将没有选中的checkbox的内容设定为false,而html默认情况下不提交没有选中的checkbox。
  chain:让前一个Action的属性可以被后一个Action访问,现在和chain类型的result()结合使用。
  alias:在不同请求之间将请求参数在不同名字件转换,请求内容不变

019 ValueStack的原理与生命周期

  1)ValueStack贯穿整个Action的生命周期,保存在request域中,所以ValueStack和request的生命周期一样。当Struts2接受一个请求时,会迅速创建ActionContext,ValueStack,action。然后把action存放进ValueStack,所以action的实例变量可以被OGNL访问。请求来的时候,action、ValueStack的生命开始,请求结束,action、ValueStack的生命结束;
  2)action是多例的,和Servlet不一样,Servelt是单例的;
  3)每个action的都有一个对应的值栈,值栈存放的数据类型是该action的实例,以及该action中的实例变量,Action对象默认保存在栈顶;
  4)ValueStack本质上就是一个ArrayList;
  5)关于ContextMap,Struts会把下面这些映射压入ContextMap中,parameters:该Map中包含当前请求的请求参数;request:该Map中包含当前request对象中的所有属性;session:该Map中包含当前session对象中的所有属性;application:该Map中包含当前application对象中的所有属性;attr:该Map按如下顺序来检索某个属性:request,session, application。
  6)使用OGNL访问值栈的内容时,不需要#号,而访问request、session、application、attr时,需要加#号;
  7)OGNL表达式需要配合Struts标签才可以使用。如:<s:property value=”name”/>
  8)Struts2配置文件中引用OGNL表达式,引用值栈的值,此时使用的”$”,而不是#或者%。

020 ActionContext、ServletContext、pageContext的区别

  1)ActionContext是当前的Action的上下文环境,通过ActionContext可以获取到request、session、ServletContext等与Action有关的对象的引用;
  2)ServletContext是域对象,一个web应用中只有一个ServletContext,生命周期伴随整个web应用;
  3)pageContext是JSP中的最重要的一个内置对象,可以通过pageContext获取其他域对象的应用,同时它是一个域对象,作用范围只针对当前页面,当前页面结束时,pageContext销毁,生命周期是JSP四个域对象中最小的。

021 result的type有几种类型

  10种
  dispatcher:struts默认的结果类型,把控制权转发给应用程序里的某个资源。不能把控制权转发给一个外部资源,若需要把控制权重定向到一个外部资源,应该使用redirect。
  redirect:把响应重定向到另一个资源(包括一个外部资源)。
  redirectAction:把响应重定向到另一个Action。
  freemarker、velocity、chain、httpheader、xslt、plainText、stream

022 拦截器的生命周期与工作过程

  1)每个拦截器都是实现了Interceptor接口的 Java 类;
  2)init():该方法将在拦截器被创建后立即被调用,它在拦截器的生命周期内只被调用一次。可以在该方法中对相关资源进行必要的初始化;
  3)intercept(ActionInvocation invocation):每拦截一个动作请求,该方法就会被调用一次;
  4)destroy:该方法将在拦截器被销毁之前被调用,它在拦截器的生命周期内也只被调用一次;
  5)Struts2中有内置了18个拦截器。

023 Struts2如何启动

  Struts2是通过web.xml中的过滤器StrutsPrepareAndExecuteFilter启动的,Tomcat服务器启动的时候,会执行一次StrutsPrepareAndExecuteFilter里面的init方法,加载struts.xml配置文件,将配置文件的内容封装为javabean存放在内存中,以后用户请求将会读取内存,读取数据,而不用每次都在struts.xml中读取。

024 Struts2的核心控制器StrutsPrepareAndExecuteFilter的作用

  StrutsPrepareAndExecuteFilter 主要负责拦截 url请求,可以在web.xml中配置拦截的url,<url-pattern>/*</url-pattern>代表拦截所有的请求,执行doFilter方法默认情况下,如果用户请求的路径不带后缀或者后缀以.action结尾,这时请求将被转入struts2框架处理,否则struts2框架将略过该请求的处理。

025 struts2配置文件的加载顺序?

  struts.xml -> struts.properties常量可以在struts.xml或struts.properties中配置,如果在多个文件中配置了同一个常量,则后一个文件中配置的常量值会覆盖前面文件中配置的常量值. struts.xml文件的作用:通知Struts2框架加载对应的Action资源。

026 struts2中的默认包struts-default有什么作用?

  1.struts-default包是由struts内置的,它定义了struts2内部的众多拦截器和Result类型,而Struts2很多核心的功能都是通过这些内置的拦截器实现,如:从请求中 把请求参数封装到action、文件上传和数据验证等等都是通过拦截器实现的。当包继承了struts-default包才能使用struts2为我们提供的这些功能。
  2.struts-default包是在struts-default.xml中定义,struts-default.xml也是Struts2默认配置文件。 Struts2每次都会自动加载 struts-default.xml文件。
  3.通常每个包都应该继承struts-default包。
struts2的action的URL访问路径由什么构成?
由两部分组成:包的命名空间+action的名称 [ + action的后缀 ],/crud1/userAdd.action,crud1是命名空间,userAdd是struts.xml中配置的action的名称。

027 在struts.xml中可以不为action指定class属性吗?struts2中有哪些默认的属性?

  可以,如果没有为action指定class,默认是com.opensymphony.xwork2.ActionSupport
  默认属性:
  如果没有为action指定class ActionSupport
  如果没有为action指定method execute()
  注意:ActionSupport的execute方法里面就一句话return “success”;
  如果没有指定result的name success
  如果没有指定result的type dispatcher
action中默认都有一个拦截器的引用,即:<interceptor-ref name=”defaultStack”>;
   注意:
   1.一旦我们为该包中的某个action显式指定了某个拦截器,则默认拦截器不会起作用,所以此时要显式的引进默认的拦截器;
  2.每个包只能指定一个默认拦截器,每个默认拦截器只针对当前包下有效。

028 Struts2的工作流程:

  (1) 客户端提交一个HttpServletRequest请求(.action或JSP页面)
  (2) 请求被提交到一系列Filter过滤器,如ActionCleanUp和FilterDispatcher等
  (3) FilterDispatcher是Struts2控制器的核心,它通常是过滤器链中的最后一个过滤器
  (4) 请求发到FilterDispatcher后,FilterDispatcher询问ActionMapper是否需要调用某个Action来处理这个Request(一般根据URL后缀是否为.action来判断)
  (5) 如果ActionMapper决定需要调用某个Action,FilterDispatcher则把请求交到ActioProxy,由其进行处理.
  (6) ActionProxy通过Configuration Manager(它会访问struts.xml)询问框架的配置文件,找到需要调用的Action类.
  (7) ActionProxy创建一个ActionInvocation实例,而ActionInvocation通过代理模式调用Action,(在调用之前会根据配置文件加载相关的所有Interceptor拦截器)
  (8) Action执行完毕后,返回一个result字符串,此时再按相反的顺序通过Interceptor拦截器.
  (9) 最后ActionInvocation负责根据struts.xml中配置的result元素,找到与返回值对应的result,决定进行下一步输出.

029 struts2是如何管理action的?这种管理方式有什么好处?

  struts2框架中使用包来管理Action,包的作用和java中的类包是非常类似的。 主要用于管理一组业务功能相关的action。在实际应用中,我们应该把一组业务功能相关的Action放在同一个包下。

030 Action和ActionForm是单例的吗?Action是线程安全的吗?

  Struts1的Action是单例的,不是线程安全的
  Struts2的Action是多例的,是线程安全的
  每当有一次用户的请求,ActionFrom就会被创建一次。

3 0