[Java面试四]Strust2总结及在面试中的一些问题.
1. JavaEE软件三层结构和MVC的区别?
MVC是一种思想,是一种模式,将软件分为 Model模型、View视图、Controller控制器。【JavaEE开发更强调三层结构,web层开发更注重MVC】
Struts2 就是web层开发框架,符合MVC模式;struts1 、webwork 、jsf 、SpringMVC 都是MVC
2. Struts和struts2的区别有哪些?
Action类
Struts 1要求Action类要扩展自一个抽象基类。Struts 1的一个共有的问题是面向抽象类编程而不是面向接口编程。
Struts 2的Action类实现了一个Action接口,连同其他接口一起实现可选择和自定义的服务。Struts 2提供一个名叫ActionSupport的基类实现一般使用的接口。虽然,Action接口不是必须的。任何使用execute方法的POJO对象可以 被当作Struts 2的Action对象使用。
程模型
Struts 1 Action类是单例类,因只有一个示例控制所有的请求。单例类策略造成了一定的限制且给开发带来了额外的烦恼。Action资源必须是程安全或者同步 的。
Struts 2 Action对象每一个请求都实例化对象,所以没有程安全的问题。(实践中,servlet容器生许多丢的对象对于每一个请求,多于一个的对象并不影响垃 圾收集)
Servlet 依赖
Struts 1的Action类依赖于servlet API以HttpServletRequest和HttpServletResponse作参数传给execute方法当Action被调用时。
Struts 2的Action不和容器有关。Servlet上下文被表现简单的Maps,允许Action被独立的测试。Struts 2的Action可以访问最初的请求和相应,如果需要的话。然而,其他的架构元素少或者排除直接访问HttpServletRequest或者 HttpServletResponse的需要。
易测性
测试Struts 1的主要障碍是execute方法暴露了Servlet API。第三方的扩展,Struts测试用例,提供Struts 1的集合对象。
Struts 2的Action可以通过实例化Action测试,设置属性,然后调用方法。依赖注入的支持也是测试变得更简单。
接受输入
Struts 1使用ActionForm对象捕获输入。象Action一样,所有的ActionForm必须扩展基类。因其他的JavaBean不能作 ActionForm使用,开发者经常创建多余的类捕获输入。DynaBeans可以被用来作替代ActionForm的类创建。但是开发者可以重新描述 已经存在的JavaBean。
Struts 2 Action属性作输入属性,排除第二个输入对象的需要。输入属性可能有丰富的对象类型这些类型有他们自己的属性。Action的属性可以通过标签库访 问。Struts 2也支持ActionForm形式。丰富的对象类型,包含业务或者域对象,可以被当作输入或者输出对象使用。馍型驱动特性简化标签对POJO输入对象的引 用。
表达式语言
Struts 1整和JSTL,所以它使用JSTL的表达式语言。表达式语言有基本的图形对象移动,但是相对很弱的集合和被索引的属性支持。
Struts 2使用JSTL,但是框架也支持更大和更灵活的表达式,叫做“对象图形符号语言”(OGNL)。
将值绑定要视图上
Struts 1使用标准JSP机制来绑定对象到页面上下文。
Struts 2使用“ValueStack”技术了标签库可以不用链接你的视图到对象的表现类型访问值。ValueStack策略允许重用视图。
类型转换
Struts 1的ActionForm属性经常都是String的。Struts 1使用Commons-Beanutils类型转换。转换每一个类,不是每一个实例配置。
Struts 2使用OGNL类型转换。框架包含转换器基本的和共同的对象类型和原始类型。
验证
Struts 1支持手动验证凭借ActionForm的validate方法,或者通过扩展的公用验证器。类可以有不同的验证上下文未相同的类,但是不能不能包括验证 子对象。
Struts 2支持手动验证凭借validate方法和XWork验证框架。Xwork验证框架支持一连串的验证子属性使用的验证了属性类的类型和严正上下文而定义。
Action执行的控制
Struts 1支持独立的请求处理器对于每一个模型,但是所有在模型中的Action必须共享同一个生命周期。
Struts 2支持在每一个Action基础上凭借拦截栈创建不同的生命周期。自定义栈可以被创建且使用不同的所需 的Action。
3. 简要说说Struts2的处理流程?
1、加载类(FilterDispatcher)2、读取配置(struts配置文件中的Action)3、派发请求(客户端发送请求)4、调用Action(FilterDispatcher从struts配置文件中读取与之相对应的Action )5、启用拦截器(WebWork拦截器链自动对请求应用通用功能,如验证)6、处理业务(回调Action的execute()方法)7、返回响应(通过execute方法将信息返回到FilterDispatcher)8、查找响应(FilterDispatcher根据配置查找响应的是什么信息如:SUCCESS、ERROER,将跳转到哪个jsp页面)9、响应用户(jsp--->客户浏览器端显示)10、struts2标签库(相比struts1的标签库,struts2是大大加强了,对数据的操作功能很强大)
请求(.action)---->经过StrutsPrepareAndExecuteFilter 核心控制器---->进入到Struts2的拦截器Interceptor(实现代码功能)----->通过action的名称找对应的Action类----->执行Action类的execute方法----->通过execute方法中返回的字符串,在Struts.xml中找对应的结果页面(result)【在action执行之前,执行了defaultStack拦截器栈】
* 拦截器 在 struts-default.xml定义 【它位于sruts2-core-xxx.jar目录下】
* 执行拦截器 是 defaultStack 中引用拦截器
4、Struts2配置文件加载顺序
init_DefaultProperties(); // [1]---- org/apache/struts2/default.properties
init_TraditionalXmlConfigurations(); // [2] --- struts-default.xml,struts-plugin.xml,struts.xml
init_LegacyStrutsProperties(); // [3] --- 自定义struts.properties
init_CustomConfigurationProviders(); // [5] ----- 自定义配置提供
init_FilterInitParameters() ; // [6] ----- web.xml
init_AliasStandardObjects() ; // [7] ---- Bean加载
② struts-default.xml 该文件保存在 struts2-core-2.3.7.jar (Bean、拦截器、结果类型 )
③ struts-plugin.xml 该文件保存在struts-Xxx-2.3.7.jar (在插件包中存在 ,配置插件信息 )struts-config-browser-plugin-2.3.7.jar里面有
④ struts.xml 该文件是web应用默认的struts配置文件 (实际开发中,通常写struts.xml )
⑤ struts.properties 该文件是Struts的默认配置文件 (配置常量 )
⑥ web.xml 该文件是Web应用的配置文件 (配置常量 )
后加载配置文件中修改的常量的值会覆盖前面配置文件修改的常量的值!
5、我们在书写Action的时候有哪几种方式?他们有什么区别?
obj =Class.forName("完整类名").newInstance();
Method m =Class.forName("完整类名").getMethod("execute");
m.invoke(obj);//通过反射 执行execute()方法
Action接口中,定义默认五种逻辑视图名称
// 数据处理成功 (成功页面)
publicstatic final String SUCCESS ="success";
// 页面不跳转 return null; 效果一样
publicstatic final String NONE ="none";
// 数据处理发送错误 (错误页面)
publicstatic final String ERROR ="error";
// 用户输入数据有误,通常用于表单数据校验 (输入页面)
publicstatic final String INPUT ="input";
// 主要权限认证 (登陆页面)
publicstatic final String LOGIN ="login";
代理模式,控制目标对象访问
/hello.action 请求时StrutsPrepareAndExecuteFilter的 doFilter一定执行
//判断配置文件中有没有对应Action
ActionMapping mapping = prepare.findActionMapping(request, response,true);
//根据配置创建代理对象
ActionProxy proxy = config.getContainer().getInstance(ActionProxyFactory.class).createActionProxy(namespace, name, method, extraContext,true,false);
执行时:先执行interceptor的intercept拦截方法,最后指向action的execute
6、Action是如何接受请求参数的?
<interceptor name="params"class="com.opensymphony.xwork2.interceptor.ParametersInterceptor"/>
用户名:<inputtype="text"name="username"/><br/>
publicclassRegistAction1extendsActionSupport{
privateString username;
publicvoid setUsername(String username){
this.username = username;
}
}
<!--基于OGNL表达式的写法-->
用户名:<inputtype="text"name="user.username"/><br/>
密 码:
<inputtype="password"name="user.password"/><br/>publicclassUser{
privateString username;
privateString password;
publicString getUsername(){
return username;
}
publicvoid setUsername(String username){
this.username = username;
}
publicString getPassword(){
return password;
}
publicvoid setPassword(String password){
this.password = password;
}
}
publicclassRegistAction2extendsActionSupport{
privateUser user;
publicvoid setUser(User user){
this.user = user;
}
//必须提供get方法(封装第一个参数时,创建新的User对象, 封装第二个参数需要使用第一个创建user对象)
publicUser getUser(){
return user;
}
}
<interceptorname="params"class="com.opensymphony.xwork2.interceptor.ParametersInterceptor"/>
<interceptorname="modelDriven"class="com.opensymphony.xwork2.interceptor.ModelDrivenInterceptor"/> 为模型驱动提供了更多特性
用户名:<inputtype="text"name="username"/><br/>
publicclassRegistAction3extendsActionSupportimplementsModelDriven<User>{
// 模型对象必须手动实例化 privateUser user =newUser();
publicUser getModel(){
return user;
}
}
<inputtype="text"name="user.username"/>
<inputtype="text"name="product.info"/>
7、Action的相关配置?
配置package 三个常用属性
<packagename="default"namespace="/"extends="struts-default">
②namespace和 <action>的name属性,决定 Action的访问路径 (以/开始 )
namespace="/" :根名称空间
namespace="/aa/" :带有名称空间的路径
③extends继承哪个包,通常开发中继承struts-default包 (struts-default包在 struts-default.xml中定义 )【可以使用包中默认的拦截器和结果集】
2)Action是通过<action>元素配置
<action name="hello"class="cn.itcast.struts2.demo1.HelloAction" method="execute">
例如:
<package name="default"namespace="/user" extends="struts-default">
<action name="hello"class="cn.itcast.struts2.demo1.HelloAction">
<result name="success">/demo1/success.jsp</result>
</action>
</package>
3) <action> 元素配置默认值
<action> 的class 默认值 ActionSupport 类 <default-class-ref class="com.opensymphony.xwork2.ActionSupport" />
<result> 的 name 默认值 success
8、Action访问Servlet API有哪几种方式,简单的介绍一下
9. 说说Struts2的输入校验流程
A:类型转换器负责对字符串的请求参数执行类型转换,并将这些值设置成Action的属性值B:在执行类型转换过程中可能出现异常,如果出现异常,将异常信息保存到ActionContext中,convertionError拦截器将负责将其封装到fieldError里,如果没有异常,直接进入第3步C:调用Struts2的内置校验规则进行输入校验D:通过反射调用validateXXX()方法E:调用Action类中的validate()方法F:如果上面的几步中没有出FiledError,就调用Acton中的逻辑处理方法,如果有,则进入input视图
10. Struts2 form标签数据为什么可以回显?
11. 什么是值栈?值栈的内部结构?
ContextMap: Struts 把各种各样的映射关系(一些 Map 类型的对象) 压入ContextMap中,Struts 会把下面这些映射压入 ContextMap 中
parameters: 该 Map 中包含当前请求的请求参数request: 该 Map 中包含当前 request 对象中的所有属性session: 该 Map 中包含当前 session 对象中的所有属性application:该 Map 中包含当前 application 对象中的所有属性attr: 该 Map 按如下顺序来检索某个属性: request, session, application
* CompoundRoot 就是ArrayList
* OgnlContext 就是 Map
* context中还存在 request、 session、application、 attr、 parameters 对象引用
* OGNL表达式,访问root中数据时 不需要 #, 访问 request、 session、application、 attr、 parameters 对象数据 必须写 #
* 操作值栈 默认指 操作 root 元素
12. 值栈对象的创建 ,ValueStack 和 ActionContext 是什么关系 ?
13.如何获得值栈对象?
14.如何向值栈中保存数据?如何在jsp页面中获取值栈的数据?
<s:property value="[0].top"/> //取值栈顶对象
valueStack:<s:property value="username"/>
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[0]"/>
15.为什么EL也能访问值栈中的数据?
* 对Request对象进行了包装 ,StrutsRequestWrapper* 重写request的 getAttribute
16.你在开发中,值栈主要有哪些应用?
this.addFieldError("msg", "字段错误信息");this.addActionError("Action全局错误信息");this.addActionMessage("Action的消息信息");
<s:fielderror fieldName="msg"/><s:actionerror/><s:actionmessage/>