Struts2是一个基于POJO Action的MVC 开源的Web框架。它基于当年的Webwork和XWork框架,继承其优点,同时做了相当的改进。
1、拦截器和过滤器的区别
1、拦截器是基于java反射机制的,而过滤器是基于函数回调的。
2、过滤器依赖于servlet容器,而拦截器不依赖于servlet容器。
3、拦截器只能对Action请求起作用,而过滤器则可以对几乎所有请求起作用。
4、拦截器可以访问Action上下文、值栈里的对象,而过滤器不能。
5、在Action生命周期中拦截器可以多次调用.而过滤器只能在容器初始化时被调用一次。
2、struts2工作流程?
1、客户端浏览器发出HTTP请求
2、根据web.xml配置,该请求被FilterDispatcher接收
3、根据struts.xml配置,找到需要调用的Action类和方法,并通过IoC方式,将值注入给Aciton
4、Action调用业务逻辑组件处理业务逻辑,这一步包含表单验证。
5、Action执行完毕,根据struts.xml中的配置找到对应的返回结果result,并跳转到相应页面
6、返回HTTP响应到客户端浏览器
3、struts2工作原理?
1)客户端初始化一个指向Servlet容器(例如Tomcat)的请求
2)这个请求经过一系列的过滤器(Filter)(这些过滤器中有一个叫做ActionContextCleanUp的可选过滤器,这个过滤器对于Struts2和其他框架的集成很有帮助,例如:SiteMesh Plugin)
3) 接着FilterDispatcher被调用,FilterDispatcher询问ActionMapper来决定这个请是否需要调用某个Action
4)如果ActionMapper决定需要调用某个Action,FilterDispatcher把请求的处理交给ActionProxy
5) ActionProxy通过Configuration Manager询问框架的配置文件,找到需要调用的Action类
6) ActionProxy创建一个ActionInvocation的实例。
7) ActionInvocation实例使用命名模式来调用,在调用Action的过程前后,涉及到相关拦截器(Intercepter)的调用。
8) 一旦Action执行完毕,ActionInvocation负责根据struts.xml中的配置找到对应的返回结果。返回结果通常是(但不总是,也可 能是另外的一个Action链)一个需要被表示的JSP或者FreeMarker的模版。在表示的过程中可以使用Struts2 框架中继承的标签。在这个过程中需要涉及到ActionMapper。
3、Struts2的执行过程?
tomcat启动的时候加载应用的web.xml,实例化并初始化过滤器,过滤器的初始化方法加载struts.xml。客户端发送请求,请求到达过滤器,截取请求的动作名称(没有或以action结尾),并从struts.xml中找,找到后,实例化动作类。调用对应的动作方法,方法有返回值,根据返回值,找到name取值对应的结果视图,找到jsp页面。
4、Struts2与Struts1的联系与区别 为什么要用Struts2?
struts1与struts2都是mvc框架的经典实现模式。
Struts2不是从Struts1升级而来,而是有WebWork改名而来,而WebWork只是Xwork加了很多WEB拦截器。
区别:
- 核心控制器改成了过滤器(过滤器比Servlet的级别要高,因为程序运行时是先进入过滤器再进入Servlet)
2) struts1要求业务类必须继承Action或dispatchAction,struts2不强制这么做,只需要提供一个pojo类。
3) 绑定值到业务类时struts1是通过ActionForm,struts2是通过模型或属性驱动直接绑定到Action属性。
4) struts1严重依赖于Servlet(因为太过于依赖于api的HttpServletRequest与HttpServletResponse的两个参数),struts2就则脱离了Servlet的API。
5) 管理Action时struts1是单例模式,struts2是每个请求产生一个实例。
6) 在表达式的支持上struts2不仅有jstl,还有功能更加强大的ognl表达式。
7) struts1的类型转换是单向的(页面到ActionForm),struts2是双向的(页面到Action再到页面回显)
8) 校验,struts1没有针对具体方法的校验,struts2提供了指定某个方法进行效验,还有框架校验。
9) struts2提供了拦截器,利用拦截器可以在访问Action之前或之后增加如权限拦截等功能。
10) struts2提供了全局范围,包范围,Action范围的国际化资源文件管理实现。
11) struts2支持多种视图类型,如:jsp,freemaker,velocity,源代码等。
5、Struts2有哪些优点?
1)在软件设计上Struts2的应用可以不依赖于Servlet API和struts API。 Struts2的这种设计属于无侵入式设计;
2)拦截器,实现如参数拦截注入等功能;
3)类型转换器,可以把特殊的请求参数转换成需要的类型;
4)多种表现层技术,如:JSP、freeMarker、Velocity等;
5)Struts2的输入校验可以对指定某个方法进行校验;
6)提供了全局范围、包范围和Action范围的国际化资源文件管理实现
7) 实现MVC模式,结构清晰,使开发者只关注业务逻辑的实现。有丰富的tag可以用,大大提高了开发效率。(简要)
6、Struts2是如何实现mvc的:struts2的底层视图默认是freemaker。
什么是mvc? M:模型,V:视图,C:控制器 在struts2中分别对应什么?
M(模型):除核心控制器外都属于模型,实现业务的类(service层与dao层)。
V(视图):result,type,dispatcher默认的(jsp,freemaker,velocity,源代码等)。
C(控制器):核心控制器与业务控制器。
mvc解决了数据封装,类型转换,数据效验,国际化,异常处理等问题。
7、Struts2是单线程还是多线程?Spring是单线程还是多线程?
Struts2的Action需要传递一些客户端参数,所以每次都会请求都会创建一个Action对象,每个对象中存放本次请求的参数。所以从Action角度看 Struts2是单线程的。
Spring的bean可以通过 prototype控制 bean是单例的还是多例的。
7、Struts2的配置文件加载时机和加载顺序?
当应用被tomcat加载的时候,struts2的配置文件就已经被加载过了。加载顺序:default.properties、struts-default.xml、struts-plugin.xml、struts.xml、web.xml
struts.xml文件的作用:通知Struts2框架加载对应的Action资源
8、struts2配置文件覆盖顺序
struts.xml -> struts.properties -> web.xml(配置过滤器时,指定参数。程序员可以编写)
9、Struts2的核心是什么,体现了什么思想
Struts2的核心是拦截器,拦截器的实现体现AOP(面向切面编程)思想
10、struts2框架的核心控制器是什么?它有什么作用?
1)Struts2框架的核心控制器是StrutsPrepareAndExecuteFilter。
2)作用:负责拦截由<url-pattern>/*</url-pattern>指定的所有用户请求,当用户请求到达时,该Filter会过滤用户的请求。默认情况下,如果用户请求的路径不带后缀或者后缀以.action结尾,这时请求将被转入struts2框架处理,否则struts2框架将略过该请求的处理。可以通过常量"struts.action.extension"修改action的后缀,如: <constant name="struts.action.extension" value="do"/>
如果用户需要指定多个请求后缀,则多个后缀之间以英文逗号(,)隔开。<constant name="struts.action.extension" value="do,go"/>
11、Struts2 如何定位action中的方法
1 感叹号定位方法(动态方法)。
2 在xml配置文件中通过配置多个action,使用action的method指定方法。
3 使用通配符(*)匹配方法。
12、怎么防止表单重复提交?
a.禁掉提交按钮。表单提交后使用 Javascript 使提交按钮 disable。
b.Post/Redirect/Get 模式。在提交后执行页面重定向,这就是所谓的 Post-Redirect-Get (PRG) 模式。简言之,当用户提交了表单后,你去执行一个客户端的重定向,转到提交成功信息页面。
c.在 session 中存放一个特殊标志。当表单页面被请求时,生成一个特殊的字符标志串,存在 session 中,同时放在表单的隐藏域里。接受处理表单数据时,检查标识字串是否存在,并立即从 session 中删除它,然后正常处理数据。
12、struts2常量的修改方式?
常量可以在struts.xml或struts.properties中配置,两种配置方式如下:
1)在struts.xml文件中配置常量 <constant name="struts.action.extension" value="do"/>
2)在struts.properties中配置常量(struts.properties文件放置在src下):
struts.action.extension=do
13、常量中struts.devMode是什么意思,如何配置?
开发模式。修改了struts.xml中的配置,你不必每次都重启服务器。
<constant name="struts.devMode" value="true" />
14、模型驱动和属性驱动的区别是什么? 模型驱动使用时注意什么问题?
模型驱动与属性驱动都是用来封装数据的。
1.模型驱动:在实现类中实现ModelDriven<T>接口使用泛型把属性类封装起来,重写getModel()方法,然后在实现类里创建一个属性类的实例,通过这个实例拿到封装进来的值,拿返回值的时候使用工具进行值拷贝。
2.属性驱动:在实现类里定义属性,生成get与set方法,通过属性来拿值。
注意:模型驱动使用时注意的是在使用前先把属性类实例化,否则会出现空指针错误,拿返回对象的值需要用拷贝内存因为地址发生改变。
模型驱动不可以使用局部类型转换器。
15、Struts2是怎样进行值封装的?
struts2的值封装实际上是采用了ognl表达式.
struts2的拦截器经过模型驱动时会先判断action是否实现了ModelDriven,如果是则拿到模型的实例放在了栈的顶部,
到属性驱动的时候会从栈里面把栈顶的实例取出来,从页面传进来的值放在一个map集合当中,通过map集合进行迭代,会通过ognl技术把值封装到实例中。
16、什么是拦截器 说说Struts2用拦截器来干什么 说出6个拦截器来
拦截器是struts2核心组成部分,它提供了一种机制,在访问类的某个方法或者属性之前执行,拦截的是Action的请求,进行拦截然后在方法的执行前或者之后加入某些操作。
拦截器有:国际化,表单重复提交,类型转换,自动装配,数据封装,异常处理,模型驱动,请求参数,处理类型转换错误,日志拦截器。
常用的拦截器有:
chain:在不同请求之间将请求参数在不同名字件转换,请求内容不变
fileUpload:提供文件上传。
i18n:记录用户选择的区域环境
logger:输出Action的名字
params:将请求中的参数设置到Action中去。
alias 在不同请求之间将请求参数在不同名字件转换,请求内容不变
cookies 使用配置的name,value来是指cookies
17、如何实现自定义拦截器?
1.可以继承MethodFilterInterceptor重写doIntercept方法指定某个方法进行拦截,或者继承AbstractInterceptor,重写intercept方法,
2.在xml配置文件中定义自定义拦截器,然后注入到拦截器栈中,再把拦截器引用到action中。在把拦截器注入拦截器栈时配置<param>标签,使用name属性配置excludeMethods表示不拦截指定方法。
在配置文件中配置includeMethods指定拦截某个方法。
可以配置到某个action单独使用,也可以配置到包下面所有action使用。
19、拦截器的生命周期与工作过程?
1、每个拦截器都是实现了Interceptor接口的 Java 类;
2、init(): 该方法将在拦截器被创建后立即被调用, 它在拦截器的生命周期内只被调用一次. 可以在该方法中对相关资源进行必要的初始化;
3、intercept(ActionInvocation invocation): 每拦截一个动作请求, 该方法就会被调用一次;
4、destroy: 该方法将在拦截器被销毁之前被调用, 它在拦截器的生命周期内也只被调用一次; 5、struts2中有内置了18个拦截器。
20、Struts2拦截器实现了哪种设计模式?
Struts2拦截器基于拦截滤波器设计模式。堆栈中拦截器的调用非常类似责任链设计模式。
21、Struts2动作和拦截器是否是线程安全的?
Struts2 Action类是线程安全的,因为对象是为每个处理它的请求实例化的。
Struts2拦截器是单例类,并且创建了一个新线程来处理请求,因此它不是线程安全的,我们需要仔细实现它们以避免共享数据的任何问题。
22、 Struts2中全局,动作范围和包范围,哪个加载优先级高?页面上如何读取指定的消息资源包? 动作范围。
23、我们如何编写自己的拦截器并将其映射为动作?
我们可以实现com.opensymphony.xwork2.interceptor.Interceptor接口来创建自己的拦截器。一旦拦截器类准备就绪,需要在我们想要使用它的struts.xml包中定义它。还可使用自定义拦截器和defaultStack拦截器创建拦截器堆栈。之后可为想要使用拦截器的动作类配置它。
24、Struts2中拦截器的执行时机?
拦截动作方法之前,正序执行;拦截动作方法之后,倒序执行。
25、自定义拦截器的步骤是什么?
a) 编写一个类,继承AbstractInterceptor类或者实现Interceptor接口。重写intercept方法。
b) 配置拦截器:注意拦截器必须先声明再使用
26、多个拦截器如何确定执行顺序? 使用顺序。
27、自定义拦截器除了继承AbstractInterceptor还可以继承哪个?另一个有什么好处?
可以继承MethodFilterInterceptor并且重写doIntercept方法。
通过参数注入的方式,哪个拦截和不拦截。
28、哪个拦截器负责将请求参数映射到动作类Java Bean属性?
com.opensymphony.xwork2.interceptor.ParametersInterceptor拦截器负责将请求参数映射到Action类的java bean属性。此拦截器在struts-default包中配置,名称为“params”。此拦截器是basicStack和defaultStack拦截器堆栈的一部分。
29、哪个拦截器负责i18n支持?
com.opensymphony.xwork2.interceptor.I18nInterceptor拦截器负责Struts2应用程序中的i18n支持。此拦截器在struts-default包中配置,名称为“i18n”,它是i18nStack和defaultStack的一部分。
30、在struts2中如何实现转发和重定向?
在struts.xml中配置type="redirect"(重定向);type="redirectAction"(转发)
31、action访问两种方式?
1.动态方法的调用。 在struts.xml中开启动态方法的使用。
<constant name=”struts.enable.DynamicMethodInvocation” value =”true”/>
2. 通配符的使用 eg: <action name="userAction_*">
31、Action实现的三种方式
1.单纯的POJO
2.实现Action接口 (提供了格式化的返回参数)
3.继承ActionSupport(实现了Action接口并且其中还做了一些国际化和验证的功能)
32、如何封装静态请求参数?
在struts.xml配置文件中,给动作类注入值。调用的是setter方法。
33、动作类和模型分开的动态封装请求参数,set和get方法是怎么调用的?
先get出来,判断存不存在,存在直接get第二次(给这个对象赋值),不存在(把这个对象创建出来,set回去,然后再get出来)
34、使用模型驱动动态封装请求参数的要求是什么?
实现ModelDriven接口,动作类和实体模型分开,创建模型对象并将其实例化,重写getModel方法,返回一个引用。
35、实际开发中类型转换的两种情况是什么?
转字符串,转其他类型。
写的时候,发送请求,经过过滤器,最后到数据库,字符串转其他类型。
读的时候,到页面,其他类型转成字符串
36、Struts2中提供的常用类型转换分几类?
a.基本数据类型自动转换。
b.日期类型:默认按照本地日期格式转换(yyyy-MM-dd)。
c.字符串数组:默认用逗号+空格,连接成一个字符串
37、自定义类型转换器是如何注册的?(两种情况)
局部类型转换器:只能指定javabean中的属性用
按照属性来注册。在属性所属的javabean的包下建立一个.properties文件。文件名称:javabean名称-conversion.properties
全局类型转换器:(推荐)
按照要转换的数据类型来注册。at the top op classpath,建立一个固定名称xwork-conversion.properties的属性文件。
38、如何解决编程式验证动作类中的全部动作方法都验证?
在动作类中覆盖public void validate()方法。
39、声明式验证的分别可以基于什么? 基于字段和验证器。
40、命名声明式验证xml文件名的两种方式,有什么不同?
a.针对动作类中的所有动作进行验证:在动作类所在的包中,建立一个ActionClassName-validation.xml的文件
b、针对动作类中的某个动作进行验证:在动作类所在的包中建立一个xml文件,名称为ActionClassName-ActionName-validation.xml。
41、如何处理Struts2中应用程序抛出的异常?
Struts2为异常处理提供了一个非常强大的框架。我们可以在包中指定全局结果,然后将特定的例外映射到这些结果页面。异常映射可以在全局包级别和操作级别完成。
当发生一些未由应用程序处理的意外异常时,让异常结果页面向用户提供一些信息是个好主意。
42、为什么要继承默认的包?
因为在Strtus2里面默认有很多的常量,拦截器,还有一些bean。
如果继承默认的包,这些默认值和常量就会继承过来
43、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包。
44、struts2是如何管理action的?这种管理方式有什么好处?
struts2框架中使用包来管理Action,包的作用和java中的类包是非常类似的。
主要用于管理一组业务功能相关的action。在实际应用中,我们应该把一组业务功能相关的Action放在同一个包下。
45、struts2默认能解决get和post提交方式的乱码问题吗?
不能。struts.i18n.encoding=UTF-8属性值只能解析POST提交下的乱码问题。
46、开发项目时struts2在页面怎样拿值?
从值栈中或者是ognl的上下文
47、常见的有那些有十几种结果集类型(result的type属性中有哪几种结果类型?)
常见的结果集类型有dispatcher,redirect,redirectAction,stream等
默认的是dispatcher, 把控制权转发给应用程序里的某个资源不能把控制权转发给一个外部资源,若需要把控制权重定向到一个外部资源, 应该使用
Redirect 指重定向, 把响应重定向到另一个资源(包括一个外部资源)
redirectAction 把响应重定向到另一个 Action
stream 是返回一个流,一般用在文件下载上面
freemarker、velocity、chain、httpheader、xslt、plainText、stream
49、简单讲下struts里面的标签,说不少于5个
s:if s:elseif s:property s:iterater s:form s:url s:date等等
50、标签<s:property>和el表达式有什么区别,
它们都可以从值栈里面取值,但是el表达式只能取属性有get set方法的简单数据类型,
如果要取得数组的一些方法等复杂数据对象类型,就要用s:property标签
51、默认struts2里面的标签取值都是从那里取值的
默认都是从OGNL值栈里面取值的?
52、Struts2操作URI的默认后缀是什么?我们如何更改它?
Struts2操作的默认URI后缀是.action,在Struts1中,默认后缀为.do。我们可以通过在Struts2配置文件中定义struts.action.extension常量值来更改此后缀:
<constant name="struts.action.extension" value="action,do"></constant>
53、ValueStack分为那两部分,组成部分是什么,分别怎么访问
valueStack分为对象栈和ContextMap ,对象栈里面放入的是Action及其用户定义的对象,在前台可以直接访问,contextMap里面放入的是Servlet对象转化后map,譬如requestMap,sessionMap,访问的时候前面加#即可.
54、值栈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)注意: Struts2中,OGNL表达式需要配合Struts标签才可以使用。<s:property value="name"/>
8)在struts2配置文件中引用ognl表达式 ,引用值栈的值 ,此时使用的"$",而不是#或者%;
55、ActionContext和ValueStack什么时候创建?是否是线程安全的?
明确:动作类是多例的,每次动作访问,动作类都会实例化。所以是线程安全的。与Struts1的区别是,struts1的动作类是单例的。
在每次动作执行前,核心控制器StrutsPrepareAndExecuteFilter都会创建一个ActionContext和ValueStack对象。且每次动作访问都会创建。
这两个对象存储了整个动作访问期间用到的数据。并且把数据绑定到了线程局部变量(ThreadLocal)上了。所以是线程安全的。
56、ContextMap中的结构是什么样的?
除了value stack之外,全是map,而contextMap也是一个map。其实就是Map中又封装的Map。(很像dbutils中KeyedHandler封装数据的结构)只是封装数据的结构
57、Strust2如何访问Servlet API
1:通过ActionContext可以获得request,application,session三个作用域(struts2实际上是通过适配器来把servlet的api转换为一个map,并把这些map放在ActionContext里)。
2:通过ActionContext的子类ServletActionContext去获取原生的API。
3:可以通过实现ServletRequestAware接口(或ServletResponseAware),重写里面setServletRequest方法可以获得request,实际上是通过set的依赖注入。
59、为何继承ActionSupport?
因为ActionSupport实现了Action接口,提供了国际化,校验功能。
ActionSupport实现了国际化功能:因为它提供了一个getText(String key)方法实现国际化,该方法从资源文件上获取国际化信息。
Action接口提供了五个常量(success,error,login,input,none)。
60、ActionContext是用来干什么的
ActionContext是Action的上下文。通过ActionContext这个类来可以获得:request,application,session,Locale、ValueStack,ConversionErrors
1 可以获得servlet的api:request,application,session。
2 进行国际化:获得语言环境 Locale。
3 收集错误信息:ConversionErrors。
4 有个值栈来装action实例与创建的模型驱动的实例:ValueStack。
5 ActionContext是线程安全的-用本地线程实现的。
61、struts2如何访问HttpServletRequest、HttpSession、ServletContext三个域对象?
方案一:
HttpServletRequest request =ServletActionContext.getRequest();
HttpServletResponse response =ServletActionContext.getResponse();
HttpSession session= request.getSession();
ServletContext servletContext=ServletActionContext.getServletContext();
方案二:
类 implements ServletRequestAware,ServletResponseAware,SessionAware,ServletContextAware 注意:框架自动传入对应的域对象
62、ActionContext、ServletContext、pageContext的区别?
1)ActionContext是当前的Action的上下文环境,通过ActionContext可以获取到request、session、ServletContext等与Action有关的对象的引用;
2)ServletContext是域对象,一个web应用中只有一个ServletContext,生命周期伴随整个web应用;
3)pageContext是JSP中的最重要的一个内置对象,可以通过pageContext获取其他域对象的应用,同时它是一个域对象,作用范围只针对当前页面,当前页面结束时,pageContext销毁, 生命周期是JSP四个域对象中最小的。
63、OGNL是什么?使用它能否访问普通方法?能否直接访问静态方法?
OGNL是Object Graphic Navigation Language(对象图导航语言)的缩写,它是一个单独的开源项目。 Struts2框架使用OGNL作为默认的表达式语言。
可以直接访问普通方法。不能直接访问静态方法。需要在struts.xml中启用。
64、OGNL是什么你在项目中如何使用它
访问session中的user对象的username属性:注意的是:使用前需要在页面头部导入taglib prefix="s" uri="/struts-tags"
原ognl是单个对象的,在struts2的应用是多个对象的,struts2的类型转换也是通过ognl来实现的。
Struts2中默认的表达式语言就是ognl,struts2的取值设值都是通过ognl来实现的,struts2要依靠它的标签才可以使用ognl。
相对于jstl或者其他表达式语言,它有如下优势:
1 能够调用对象实例的方法 2 能够调用类的静态方法
3 操作集合对象 4 访问Ognl上下文
取值时ognl有三个参数:1 表达式,2 ognl的上下文(map),3 对象实例(值栈)。
如果表达式带#号是从上下文中(map)拿值,否则是从值栈中拿值。
设值时有四个参数:1 表达式,2 ognl的上下文(map),3 对象实例,4 设入的值
如果表达式带#号是把值设入上下文中(map),否则是把值设入值栈中。
在struts2中 ognl的实现关系:ActionConetxt。
ognl 3个常用的符号 # $ %
# 1 构造map,list集合。
2 取ognl上下文的值。
3 用来过滤集合。
$ 1 在校验框架中取资源文件中的值。
2 可以在配置文件中传递参数。
% 使用百分号可以进行转义。
65、Struts2如何进行校验
1 编程校验
1 继承ActionSupport,重写validate方法(针对所有方法)(服务器端编程,不推荐)。
2 validateXxx方法(Xxx代表的是方法名,针对某个方法进行效验)。
3 如果有错误就把错误信息放在FieldError中,并且跳转到指定的错误业务类,没有就会进行action方法的调用。
2 校验框架
每个Action类有一个校验文件,命名 Action类名-validation.xml,且与Action类同目录,这是对action里面所有的方法进行校验。
对Action里面的指定方法做校验使用Action的类名-访问路径_方法名-validation.xml。
如:StudentAction-student_add-validation.xml
在效验文件里又分为两种:
字段校验:字段用什么校验器来校验。
非字段校验:是用校验器校验什么字段。
通俗点讲:字段校验:校验谁,用什么方法。
非字段校验:用什么校验,校验谁 。
65、struts2如何对指定的方法进行验证?
1)validate()方法会校验action中所有与execute方法签名相同的方法;
2)要校验指定的方法通过重写validateXxx()方法实现, validateXxx()只会校验action中方法名为Xxx的方法。其中Xxx的第一个字母要大写;
3)当某个数据校验失败时,调用addFieldError()方法往系统的fieldErrors添加校验失败信息(为了使用addFieldError()方法,action可以继承ActionSupport), 如果系统 的fieldErrors包含失败信息,struts2会将请求转发到名为input的result;
4)在input视图中可以通过显示失败信息。
5)先执行validateXxxx()->validate()->如果出错了,会转发所指定的页面,如果不出错,会直接进行Action::execute()方法
65、struts2如何对指定的方法进行验证
- 验证功能是由validation拦截器来负责处理的。回显错误信息是由workflow拦截器来负责处理的。
- 验证失败以后错误信息回显需要设置 <result name="input">/regist.jsp</result> 结果视图
- 对类中所有方法进行验证,复写validate()方法,当出错的时候addFieldError("name", "请输入用户名");
- 对指定方法:将validate()方法改写成为public void validateDemo1 后面是指定方法的名字(验证Demo1方法)
66、怎么样用Struts2进行文件的上传或者下载
Struts2里面已经提供了默认的拦截器来处理上传,只要在jsp用了s:file标签,把s:from的enctype 属性设置为 multipart/form-data,然后在action里面定义三个字段 File file ,String [file]ContentType,String [file]?FileName即可,如果有多个文件上传,那么就用List<File>来接受,然后把接受到的File构建成FileInputStream,转化成硬盘上面的文件即可(用输出流)下载用了result为stream的类型,然后在action定义四个属性,默认的有个是InputStream 的类型叫inputStream的,从硬盘上面读取文件到这个流赋值即可
66、struts2如何完成文件的上传?
1、JSP页面:
1)JSP页面的上传文件的组件:<s: file name=”upload” />,如果需要一次上传多个文件, 就必须使用多个 file 标签, 但它们的名字必须是相同的,即:
name=“xxx”的值必须一样;
2)必须把表单的enctype属性设置为:multipart/form-data;
3)表单的方法必须为post,因为post提交的数据在消息体中,而无大小限制。
2、对应的action:
1)在 Action 中新添加 3 个和文件上传相关的属性;
2)如果是上传单个文件, uploadImage属性的类型就是 java.io.File, 它代表被上传的文件, 第二个和第三个属性的类型是 String, 它们分别代表上传文 件的文件名和文件类型,定义方式是分别是:
jsp页面file组件的名称+ContentType, jsp页面file组件的名称+FileName
3)如果上上传多个文件, 可以使用数组或 List
67、文件上传是哪个拦截器为我们做的?如何限定上传文件的大小和类型?
fileupload拦截器
在struts.xml中改变default.properties文件中的常量。
给fileUpload拦截器注入参,数通过限制上传文件的MIME类型
68、struts2中文件下载是由哪个结果类型完成的?需要我们提供什么参数?
stream类型。输入流的字段名称(inputname)、文件类型(contentType)、响应消息头(contentDisposition)
69、谈谈Struts2 的国际化
在struts2中是使用了拦截器来实现国际化。
struts2的国际化分为三部分:
1.Action范围,这种范围是用Action的实现类的类名来作为前缀__语言名称_国家地区名(大写).properties. 在WEB-INF下添加i8n.tld
2.包范围,包范围是用package作为前缀__语言名称_国家地区名(大写).properties。
3.全局范围,全局范围的前缀默认的是application,可以通过xml配置文件配置常量(使用constant标签注册i18l拦截器)来指定前缀,前缀__语言名称_国家地区名(大写).properties。<%@ taglib uri="/i18n" prefix="i18n" %>
国际化实现的原理:通过i18n拦截器获得请求参数request—locale的值(zh或者是en)并把当前的值转化为locale对象,把locale对象存在ww_trans_i18n_locale的session作用域中,根据struts2的请求处理流程,拦截器只会在进入action的时候才会调用,所有我们一般把对jsp的访问转化为对action的访问。
70、什么是国际化,struts2实现国际化的原理?
国际化是根据不同的国家和地区的语言文化的不同,所设计的适用于不同地区编码格式。
实现方法:
1)首先在src目录下新建message_en.properties(英文);
2)页面获取国际化信息或者使用
原理:程序得到当前运行环境的国际/区域,语言环境并存放于Locale,ResourceBundle根据Locale中信息自动搜索对应的国际化资源文件并加载。
71、国际化的消息资源文件如何命名?
一个资源包由多个文件组成,这些文件名都有命名规范:主要文件名_语言代码_国家代码.properties。
语言代码:由iso规定的。国家代码:有iso规定的当文件只有主要文件名.properties时,表明它是默认资源包。浏览器会根据不同的语言环境找对应语言环境的资源包,当没有时,找默认的。
每个资源包的内容都由相同的key和对应语言环境的value组成。
比如:global_zh_CN.properties global_en_US.properties global_ru_RU.properties
72、列举Struts2中引入的一些有用的注释?
Struts2中引入的一些重要注释是:
- @Action创建动作类
- @Actions为多个动作配置单个类
- @Namespace和@Namespaces用于创建不同的模块
- @Result用于结果页面
- @ResultPath用于配置结果页面位置
73、Struts2中动作映射中命名空间的用途是什么?
Struts2命名空间配置允许我们轻松创建模块。我们可以使用命名空间根据其功能分离我们的操作类,例如admin,user,customer等。
74、对我们的操作类使用Action接口和ActionSupport类有什么区别,您更喜欢哪一个?
我们可以实现Action接口来创建我们的动作类。这个接口有一个我们需要实现的方法execute()。使用此接口的唯一好处是它包含一些我们可以用于结果页面的常量,这些常量是SUCCESS,ERROR,NONE,INPUT和LOGIN。
ActionSupport类是Action接口的默认实现,它还实现了与Validation和i18n支持相关的接口。ActionSupport类实现Action,Validateable,ValidationAware,TextProvider和LocaleProvider接口。我们可以覆盖ActionSupport类的validate()方法,以在我们的操作类中包含字段级验证登录。
根据需求,我们可以使用任何方法来创建struts 2动作类,我最喜欢的是ActionSupport类,因为它有助于在动作类中轻松编写验证和i18n逻辑。
75、我们怎样才能在动作类中获得Servlet API请求,响应,HttpSession等对象?
Struts2操作类不提供对Servlet API组件的直接访问,例如Request,Response和Session。但是,有时我们需要在操作类中进行这些访问,例如检查HTTP方法或设置响应中的cookie。
这就是为什么Struts2 API提供了一堆* Aware接口,我们可以实现这些接口来访问这些对象。Struts2 API使用依赖注入在操作类中注入Servlet API组件。一些重要的Aware接口是SessionAware,ApplicationAware,ServletRequestAware和ServletResponseAware。
76、execAndWait拦截器有什么用?
Struts2为长时间运行的动作类提供了execAndWait拦截器。我们可以使用此拦截器将中间响应页面返回给客户端,一旦处理完成,最终响应将返回给客户端。此拦截器在struts-default包中定义,实现在ExecuteAndWaitInterceptor类中。
77、Struts2中令牌拦截器的用途是什么?
Web应用程序的主要问题之一是双表单提交。如果不注意,双重表单提交可能会导致向客户收取双倍金额或两次更新数据库值。我们可以使用令牌拦截器来解决双表格提交问题。这个拦截器是在struts-default包中定义的,但它不是任何拦截器堆栈的一部分,所以我们需要在我们的动作类中手动包含它。
78、我们如何在Struts2应用程序中集成log4j?
Struts2提供了log4j API的简单集成以便进行日志记录,我们需要的只是WEB-INF / classes目录中的log4j配置文件。
79、什么是不同的Struts2标签?我们怎样才能使用它们?
Struts2提供了许多自定义标记,我们可以在结果页面中使用它们来创建客户端请求的视图。这些标签大致分为三类: 数据标签,控制标签和UI标签。
我们可以通过使用taglib指令在JSP页面中添加这些标记来使用这些标记。
<%@ taglib uri="/struts-tags" prefix="s" %>
Data标签是property,set,push,bean,action,include,i18n和text标签。
控制标签用于处理和导航集合中的数据。if-elseif-else,iterator,append,merge,sort,subset和generator标签。
UI标签用于生成HTML标记语言,将HTML表单数据绑定到动作类属性,类型转换,验证和i18n支持。form,textfield,password,textarea,checkbox,select,radio,submit。
80、什么是Struts2中的自定义类型转换器?
Struts2支持OGNL表达式语言,它在Struts 2中执行两项重要任务-数据传输和类型转换。
OGNL非常灵活,我们可以轻松扩展它以创建我们自己的自定义转换器类。
创建和配置自定义类型转换器类非常简单,
第一步是修复自定义类的输入格式。第二步是实现转换器类。类型转换器类应该实现com.opensymphony.xwork2.conversion.TypeConverter接口。由于在Web应用程序中,我们总是以String的形式获取请求并以String的形式发送响应,Struts 2 API提供TypeConverter接口的默认实现,即StrutsTypeConverter。
StrutsTypeConverter包含两个抽象方法 - convertFromString将String转换为Object,convertToString将Object转换为String。
81、结果页面的默认位置是什么?我们如何更改它?
默认情况下,Struts2在{WEBAPP-ROOT} / {Namespace} /目录中查找结果页面,但有时我们希望将结果页面保存在另一个位置,我们可以在Struts2配置文件中提供struts.convention.result.path常量值来更改结果页面位置。
另一种方法是在操作类中使用@ResultPath批注来提供结果页面位置。
82、struts2源码与设计模式(讲完设计模式再回顾,暂不面试)
1)命令模式(发生.do请求封装成action调用execute方法),
2)代理模式(访问action时核心控制器把请求交给代理类(ActionProxy)去访问Action就是代理模式),
3)责任链模式(访问action时经过一系列的拦截器就使用了责任链模式),适配器(把Servlet的API通过适配器转换成Map,把Map放入ActionContext中),
4)组合模式(拦截器栈和拦截器就使用到组和模式)。
源码:
服务器启动的时候容器会创建FilterDispatcher实例,进入dispatcher.init()方法,在init方法里面会初始化sturts2的一系列的配置文件,
然后向服务器发送请求,进入doFilter方法,在里面通过调用dispatcher.serviceAction方法,进入到Dispatcher里面的serviceAction方法,
在这里就会把servlet的api转换为map,并把它一个个的放在ActionContext中,在这里还会创建ActionProxy的实例去调用execute方法,
到StrutsActionProxy的execute方法,通过DefaultActionInvocation的实例去调用invoke方法,在invoke方法里面会进行判断拦截器是否存在,如果存在就会调用intercept方法,在拦截器类(Intercept)中会通过DefaultActionInvocation实例调用里面的invock方法,它们会形成递归调用,
当拦截器不存在的时候就会进入invokeActionOnly方法,判断有没有返回结果前的监听器preResultListener如果有则进去一个个执行,最后调用 executeResult()方法,创建result返回,执行execute方法,并返回视图。
83、说下Struts的设计模式
MVC模式:
1)web应用程序启动时就会加载并初始化ActionServler。
2)用户提交表单时,一个配置好的ActionForm对象被创建,并被填入表单相应的数据,ActionServler根据Struts-config.xml文件配置好的设置决定是否需要表单验证,如果需要就调用ActionForm的Validate()验证后选择将请求发送到哪个Action,如果Action不存在,ActionServlet会先创建这个对象,然后调用Action的execute()方法.
3)Execute()从ActionForm对象中获取数据,完成业务逻辑,返回一个ActionForward对象,ActionServlet再把客户请求转发给ActionForward对象指定的jsp组件,ActionForward对象指定的jsp生成动态的网页,返回给客户。
84、项目中遇到什么问题
1.表单重复提交。
在页面使用标签<s:token/>(令牌机制),使用检验表单从复提交的拦截器tokenSession。
2.国际化必须经过Action
原因:因为国际化是通过i18拦截器来实现的,而拦截器是在访问Action的时候才执行。
解决方式:在对jsp的访问之前进行对action的访问。
3.使用模型驱动拿返回值的时候地址内存不一样,会拿不到值。
原因:因为struts2最开始是把创建action的实例放到ActionContext的栈顶,后来把创建模型驱动的实例放到栈顶,而通过struts2的标签去取值会取栈顶的实例,而此时拿到的还是最开始的创建的那个实例,所以为空。
解决方式:利用原型进行对象拷贝,使用拷贝工具,BeanUtils或者是propertyUtils。
4.在页面使用转发会报404错。
原因:struts2使用的是filter机制,<jsp:forward/>的机制是servlet。
解决方式:可以通过过滤器改变请求地址,
5.用字符串的时候需要用双引号而不是单引号,单引号在外,双引号在内。
7.当效验出错时,要跳转到相应的页面。 解决方式:使用通配符来解决。
85、开发Struts2应用程序时要遵循哪些最佳实践?
开发Struts2应用程序时的一些最佳实践是:
1.在创建程序包时始终尝试扩展struts-default程序包,避免在配置拦截器时出现代码冗余。
2.对于整个应用程序中的常见任务,例如记录请求参数,请尝试使用拦截器。
3.始终将动作类java bean属性保存在单独bean中以便重用代码并实现ModelDriven接口。
3.如果您有将在多个操作中使用的自定义拦截器,请为此创建拦截器堆栈,然后使用它。
4.尝试使用基于功能区域的命名空间配置在不同模块中划分应用程序。
5.尝试在结果页面中使用Struts2标记进行代码说明,如果需要可以创建自己类型转换器。
6.使用开发模式可以加快开发速度,但请确保生产代码不以dev模式运行。
7.使用Struts2 i18n支持资源包并支持本地化。
8.Struts2提供了许多可以拥有资源包的地方,但是尝试保留一个全局资源包,一个用于动作类以避免混淆。
9.struts-default包配置所有拦截器并创建不同的拦截器堆栈。尝试仅使用所需的内容,例如,如果您没有本地化要求,则可以避免使用i18n拦截器。
86、struts.xml配置文件中package的四个属性分别什么意思?
name:包名
extends:一般是继承struts-default包,但不是必须的。不过如果不继承的话,将无法使用struts2提供的核心功能。
abstract:把包声明为抽象包,抽象包就是用来被继承的。只要是没有<action>元素的包,就可以声明为抽象包。
namespace:名称空间。
87、访问带有名称空间的动作时,是如何查找的? /user/abc/action1.action
先找user/abc,有action1就执行,没有再找user下面的action1,有就执行最后找根目录。
88、action元素的三个属性什么意思
name:动作名称
class:动作类全名。默认的动作类是:com.opensymphony.xwork2.ActionSupport是在struts-default.xml中定义的。
method:动作类中的方法名称。默认是public String execute(){}
要求:1.public的
2.返回值必须是String
3.没有参数
89、result元素的两个属性分别指的是什么?
name:逻辑视图的名称,对应着动作方法的返回值。默认值是success。
type:结果类型,指的就是用什么方式转到定义的页面。默认是dispatcher。
90、Struts的validate框架是如何验证的?
在struts配置文件中配置具体的错误提示,再在FormBean中的validate()方法具体调用。