1、struts2在web.xml配置的Filter叫什么?
org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter
负责初始化整个Struts框架并且处理所有的请求
Struts2.1以前调用FilterDispatcher
2、struts2的Action有几种编写方式?
第一种 创建类,这个类不继承任何类,不实现任何的接口
第二种 创建类,实现接口 Action接口
第三种 创建类,继承类 ActionSupport类,ActionSupport类是Action接口的实现类
3、能否在struts2的Action定义多个业务方法?如何做到不同的请求访问Action的不同方法?
1method=...
2使用通配符方式进行操作 ,使用符号 * 星号代表任意内容
3访问Action中指定方法,不进行配置
1) 在工程中使用 动态方法调用 ,必须保证 struts.enable.DynamicMethodInvocation = true 常量值 为true
2) 在action的访问路径 中 使用 "!方法名"
4、xml进行struts2请求参数校验时,指定方法的校验和所有方法校验文件命名规则是什么?
对指定的方法校验
1针对动作类中的指定方法进行校验,使用@SkipValidation注解
2格式 Action类名-ActionName(<action>元素name属性)-validation.xml
例如 : 校验AddCustomerAction中execute方法 配置 <action name="addcustomer" .../>
校验文件名字:
AddCusotmerAction-addcustomer-validation.xml
所有方法校验
在Action所在包 编写 Action类名-validation.xml 对Action所有业务方法进行校验
5、struts2的Action中如何使用ServletAPI?
1、 在Action 中解耦合方式 间接访问 Servlet API --------- 使用 ActionContext 对象
actionContext = ActionContext.getContext();
1) actionContext.getParameters(); 获得所有请求参数Map集合
2) actionContext.put("company", "传智播客"); / actionContext.get("company") 对request范围存取数据
3) actionContext.getSession(); 获得session数据Map,对Session范围存取数据
4) actionContext.getApplication(); 获得ServletContext数据Map,对应用访问存取数据
2、 使用接口注入的方式,操作Servlet API (耦合)
ServletContextAware : 注入ServletContext对象
ServletRequestAware :注入 request对象
ServletResponseAware : 注入response对象
3、 在Action中直接通过 ServletActionContext 获得Servlet API
ServletActionContext.getRequest() : 获得request对象 (session)
ServletActionContext.getResponse() : 获得response 对象
ServletActionContext.getServletContext() : 获得ServletContext对象
6、struts2中有哪些常用结果类型?
1) dispatcher :Action 转发给 JSP
2) chain :Action转发到另一个Action (同一次请求)
3) redirect : Action重定向到 JSP
4) redirectAction :Action重定向到另一个Action
stream:下载用的(文件上传和下载时再议)
plainText:以纯文本的形式展现内容
7、struts2中修改常量的方式?
1) struts2 默认常量 在 default.properties 中配置
2) 开发者自定义常量
struts.xml (要求)
格式 : <constant name="struts.devMode" value="true" />
struts.properties (要求)
格式 : struts.devMode = true
web.xml
格式 :
<filter>
<filter-name>struts2</filter-name>
<filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
<init-param>
<param-name>struts.devMode</param-name>
<param-value>true</param-value>
</init-param>
</filter>
8、struts2中全局国际化的配置方式?
创建一系列的资源文件 ,命名规范 :基本名称_小写语言_大写的国家.properties
messages_zh_CN.properties
messages_en_US.properties
配置全局国际化
使用struts.xml里面常量进行配置
常量名称:struts.custom.i18n.resources
常量的值:资源文件的基本名称
如果资源文件在src下面,直接写基本名称
如果资源文件在包下面,添加包路径 比如 cn/itcast/messages
9、addFieldError、addActionError 有何区别?
都是com.opensymphony.xwork2.ActionSupport类下的方法.
addActionError (String anErrorMessage)
添加一个Action级别的错误消息到Action
anErrorMessage: 错误消息,被存放在List列表中
显示消息的标签是(如放在jsp页面中):
<s:actionerror /> 显示全部的 Action级别的错误消息,可以加CSS代码
addFieldError (String fieldName, String errorMessage)
给一个字段(属性) 添加错误消息
fieldName: 字段(属性)名
errorMessage: 错误消息,被存放在一个Map<key, value>中(其中key存放的是fieldName,value存放的是errorMessage)。
显示消息的标签是(如放在jsp页面中):
<s:fielderror /> 显示全部的错误消息(用addFieldError方法添加的 )
ActionSupport类还有一个 public boolean hasErrors () 方法, 其实他内部实现是这样的:
(hasActionErrors() || hasFieldErrors()) , 分别检查有无Action级别的错误信息, 有无Fidld级别的错误的信息.
只要一个为真, 就跳回input 实图, 并显示错误信息(如果你写了相应的标签)
10、简述struts2中自定义拦截器实现步骤?
第一步 创建类 ,继承AbstractInterceptor类或继承MethodFilterInteceptor类
第二步 重写AbstractInterceptor类里面 intercept方法,在这个方法中写逻辑
最后执行下一个操作return invocation.invoke();
第三步 注册拦截器
在要拦截的action所在的package里面声明拦截器
在要拦截的action里面使用拦截器
如果使用自定义的拦截器,默认的拦截器不会执行的,手动使用默认的拦截器
<package name="demo2" namespace="/" extends="struts-default">
<interceptors>
<interceptor name="pre" class="cn.itcast.demo2.Invacaton"></interceptor>
</interceptors>
<action name="demo2" class="cn.itcast.demo2.DemoAction" >
<result>/index.jsp</result>
<result name="login">/demo100.jsp</result>
<interceptor-ref name="pre"></interceptor-ref>
<interceptor-ref name="defaultStack"></interceptor-ref>
</action>
</package>
11、简述struts2 的拦截器执行原理?
1.struts2中的拦截器的实现原理是AOP思想.
2.struts2中的拦截器采用的是责任链模式
当Action请求到来的时候,会由系统的代理生成一个Action的代理对象,
由这个代理对象调用Action的execute()或指定的方法前,
在struts.xml中查找与该Action对应的拦截器。
如果有对应的拦截器,就在Action的方法执行前(后)调用这些拦截器;
如果拦截器堆栈中还有其他的Interceptor,那么invocation.invoke()将调用堆栈中下一个Interceptor的执行。
如果拦截器堆栈中只有Action了,那么invocation.invoke()将调用Action执行。
一个有序链表,通过递归调用,变成了一个堆栈执行过程,
将一段有序执行的代码变成了2段执行顺序完全相反的代码过程,
从而巧妙地实现了AOP。这也就成为了Struts2的Action层的AOP基础
2个非常重要的推论:
1. 如果在拦截器中,我们不使用invocation.invoke()来完成堆栈中下一个元素的调用,
而是直接返回一个字符串作为执行结果,那么整个执行将被中止。
2. 我们可以以invocation.invoke()为界,将拦截器中的代码分成2个部分,
在invocation.invoke()之前的代码,将会在Action之前被依次执行,
而在invocation.invoke()之后的代码,将会在Action之后被逆序执行。
由此,我们就可以通过invocation.invoke()作为Action代码真正的拦截点,从而实现AOP
12、使用struts2如何实现多文件上传?
1第一步 上传表单页面,满足三个要求,提交到action里面,要求:多个文件上传项name属性值必须要一样
2创建action,在action实现多文件的上传,在action中使用数组形式得到多个文件的信息
private File[] uploadImages;//得到上传的文件
private String[] uploadImagesContentType;//得到文件的类型
private String[] uploadImagesFileName;//得到文件的名称
3遍历数组,得到每一个文件的信息,一个一个上传到服务器中
if(uploadImages!=null&&uploadImages.length>0){
for(int i=0;i<uploadImages.length;i++){
File destFile = new File(realpath,uploadImageFileNames[i]);
FileUtils.copyFile(uploadImages[i], destFile);
}
}
13、什么是值栈?
贯穿整个 Action 的生命周期(每个 Action 类的对象实例都拥有一个ValueStack 对象).
相当于一个数据的中转站. 在其中保存当前 Action 对象和其他相关对象
ValueStack 是 struts2 提供一个接口,实现类 OgnlValueStack ---- 值栈对象 (OGNL是从值栈中获取数据的 )
每个Action实例都有一个ValueStack对象 (一个请求 对应 一个ValueStack对象 )
在其中保存当前Action 对象和其他相关对象 (值栈中 是有Action 引用的 )
Struts 框架把 ValueStack 对象保存在名为 “struts.valueStack” 的请求属性中,request中 (值栈对象 是 request一个属性)
14、值栈的内部结构?
值栈由两部分组成
root :compoundRoot其实就是一个ArrayList.
context :OgnlContext其实就是一个Map.context中有root的引用,request/session/application/parameters/attr对象引用.
ValueStack中 存在root属性 (CompoundRoot) 、 context 属性 (OgnlContext )
* CompoundRoot 就是ArrayList
* OgnlContext 就是 Map
context 对应Map 引入 root对象
* context中还存在 request、 session、application、 attr、 parameters 对象引用
* OGNL表达式,访问root中数据时 不需要 #, 访问 request、 session、application、 attr、 parameters 对象数据 必须写 #
* 操作值栈 默认指 操作 root 元素
15、值栈ValueStack 和 ActionContext关系?
每一个Action都有一个属于自己的ValueStack对象.ActionContext是Action的上下文.从ActionContext中获取到ValueStack值栈对象.
值栈对象是请求时创建的
doFilter中 prepare.createActionContext(request, response);
* 创建ActionContext 对象过程中,创建 值栈对象ValueStack
* ActionContext对象 对 ValueStack对象 有引用的 (在程序中 通过 ActionContext 获得 值栈对象 )
Dispatcher类 serviceAction 方法中 将值栈对象保存到 request范围
request.setAttribute(ServletActionContext.STRUTS_VALUESTACK_KEY, proxy.getInvocation().getStack());
16、如何获得值栈对象?
获得值栈对象 有两种方法
ValueStack valueStack = (ValueStack) ServletActionContext.getRequest().getAttribute(ServletActionContext.STRUTS_VALUESTACK_KEY);
ValueStack valueStack2 = ActionContext.getContext().getValueStack();
17、向值栈保存数据?
1// 将数据保存root的索引0位置,放置到第一个元素 ArrayList add(0,element);
valueStack.push("itcast");
2// 在值栈创建参数map, 将数据保存到map中
valueStack.set("company", "传智播客");
在jsp中 通过 <s:debug /> 查看值栈的内容
3Action这个类默认就在栈中!!!如果Action有一个属性必然会在值栈中.
操作的时候只需要在Action中提供一个属性.并且对这个属性提供get方法就可以在页面中获得。
18、在jsp中获取值栈内容?
访问root中数据 不需要#
访问 其它对象数据 加 #
通过下标获取root中对象
<s:property value="[0].top"/> //取值栈顶对象
直接在root中查找对象属性 (自上而下自动查找)
valueStack:<s:property value="username"/>
(1)对象保存到值栈
<s:property value="user.username"/>
(2) 集合保存到值栈
<s:property value="list[0].username"/>
在OgnlContext中获取数据
request:<s:property value="#request.username"/>
session:<s:property value="#session.username"/>
application:<s:property value="#application.username"/>
attr:<s:property value="#attr.username"/>
parameters:<s:property value="#parameters.cid"/>
19、EL为什么能访问值栈中的数据?
StrutsPreparedAndExecuteFilter的doFilter代码中
request = prepare.wrapRequest(request);
* 对Request对象进行了包装 ,StrutsRequestWrapper
* 重写request的 getAttribute
Object attribute = super.getAttribute(s);
if (attribute == null) {
attribute = stack.findValue(s);
}
访问request范围的数据时,如果数据找不到,去值栈中找
request对象 具备访问值栈数据的能力 (查找root的数据)
Struts2中也可以使用EL表达式,但有些变化
从request范围中找不到那个属性,EL表达式就变成了OGNL表达式。其他EL功能都不变。
结论:
原来EL:${p} page----->request----->session---->application
Struts2EL:${p} page------>request----->根栈中的属性getP()--->从contextMap中找---->session---->application
20、过滤器和拦截器的区别
过滤器:在目标资源之前进行的操作
过滤所有的内容,比如action、servlet、jsp、html
拦截器:在目标资源之前进行的操作
不能拦截所有的内容,拦截action,不能拦截jsp,不能拦截html
拦截器和过滤器之间有很多相同之处,但是两者之间存在根本的差别。其主要区别为以下几点:
1)拦截器是基于JAVA反射机制的,而过滤器是基于函数回调的。
2)拦截器依赖于Servlet容器,而过滤器依赖于Servlet容器
3)拦截器只能对Action请求起作用,而过滤器可以对几乎所有的请求起作用。
4)拦截器可以访问Action上下文、值栈里的对象,而过滤器不能
5)在Action的生命周期中,拦截器可以多次被调用,而过滤器只能在容器初始化时被调用一次 |
|