[Java面试四]Strust2总结及在面试中的一些问题.

1. JavaEE软件三层结构和MVC的区别?

JavaEE软件三层机构是由sun公司提供JavaEE开发规范的:Web层(表现层)、业务逻辑层、数据持久层。【其中WEB层会使用前端控制器模式】
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的处理流程?

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配置文件加载顺序

通过查看StrutsPrepareAndExecuteFilter源码可以得到答案!

此处,我们以及清晰了看到了该类加载配置文件的顺序,我们依次围绕标号查看对应方法产生的文件即可。

对应产生文件依次如下:

   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加载

结论 :【前三个是默认的,不用关注,后面三个需要注意】

① default.properties 该文件保存在 struts2-core-2.3.7.jar 中 org.apache.struts2包里面  (常量的默认值)

② 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的时候有哪几种方式?他们有什么区别?

有三种方式:

①普通POJO(简单Java对象),这种方式我们不需要继承任何父类,实现任何接口。Struts2框架读取struts.xml文件,获得完整的action类名。

  1. obj =Class.forName("完整类名").newInstance();
  2. Method m =Class.forName("完整类名").getMethod("execute");
  3. m.invoke(obj);//通过反射 执行execute()方法

②编写Action实现Action接口

  1. Action接口中,定义默认五种逻辑视图名称
  2. // 数据处理成功 (成功页面)
  3. publicstatic final String SUCCESS ="success";
  4. // 页面不跳转 return null; 效果一样
  5. publicstatic final String NONE ="none";
  6. // 数据处理发送错误 (错误页面)
  7. publicstatic final String ERROR ="error";
  8. // 用户输入数据有误,通常用于表单数据校验 (输入页面)
  9. publicstatic final String INPUT ="input";
  10. // 主要权限认证 (登陆页面)
  11. publicstatic final String LOGIN ="login";

③编写Action继承ActionSupport(推荐)

在Action中使用表单校验、错误信息设置、读取国际化信息三个功能

  1. 代理模式,控制目标对象访问
  2. /hello.action 请求时StrutsPrepareAndExecuteFilter的 doFilter一定执行
  3. //判断配置文件中有没有对应Action
  4. ActionMapping mapping = prepare.findActionMapping(request, response,true);
  5. //根据配置创建代理对象
  6. ActionProxy proxy = config.getContainer().getInstance(ActionProxyFactory.class).createActionProxy(namespace, name, method, extraContext,true,false);
  7. 执行时:先执行interceptor的intercept拦截方法,最后指向action的execute

6、Action是如何接受请求参数的?

属性驱动和模型驱动

Struts2内部提供了参数封装功能,不需要使用BeanUtils进行封装。Struts2大部分内置功能都是拦截器实现的。

当点击登录提交表单时,就会被下面的拦截器进行封装,进行set注入值,实现参数封装。

<interceptor name="params"class="com.opensymphony.xwork2.interceptor.ParametersInterceptor"/>

第一种 :Action 本身作为model对象,通过成员setter封装 (属性驱动 )

主要用于参数较少的封装,如果分层,不利于将数据传递到业务层。

页面:

用户名:<inputtype="text"name="username"/><br/>

Action:

publicclassRegistAction1extendsActionSupport{

privateString username;

publicvoid setUsername(String username){

this.username = username;

}

}

Struts2 action是多实例,不会有线程安全问题,使用这种数据封装方式,数据封装到action属性中,不能将action对象传递给业务层,我们需要再单独定义javabean,将action属性封装到javabean。

第二种 :创建独立model对象,页面通过ognl表达式封装 (属性驱动)

具体封装流程如下:传递username,调用setUsername,把username注入User中,将会新建一个User对象,当第二个参数password传递过来时,struts框架将首先调用getUser方法询问User是否为空,如果为空,将会新建一个User,否则不会新建,直接注入值。如果只有一个Set方法,那么每set一次数据,就会新建一个User对象,那么就是把username、password封装在两个不同的User对象中了。这样封装失败。

页面:

<!--基于OGNL表达式的写法-->

用户名:<inputtype="text"name="user.username"/><br/>

密 码:<inputtype="password"name="user.password"/><br/>

model(User):

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;

}

}

Action:

publicclassRegistAction2extendsActionSupport{

    privateUser user;

publicvoid setUser(User user){

    this.user = user;

}

//必须提供get方法(封装第一个参数时,创建新的User对象, 封装第二个参数需要使用第一个创建user对象)

publicUser getUser(){

    return user;

    }

}

由params的拦截器完成参数的封装

<interceptorname="params"class="com.opensymphony.xwork2.interceptor.ParametersInterceptor"/>

第三种 :使用ModelDriven接口,对请求数据进行封装 (模型驱动 ) ----- 企业开发的主流(模型驱动有很多特性)

<interceptorname="modelDriven"class="com.opensymphony.xwork2.interceptor.ModelDrivenInterceptor"/> 为模型驱动提供了更多特性

页面:

用户名:<inputtype="text"name="username"/><br/> 

model(User):

Action :

publicclassRegistAction3extendsActionSupportimplementsModelDriven<User>{

// 模型对象必须手动实例化

    privateUser user =newUser();

publicUser getModel(){

    return user;

}

}

对比第二种、第三种 : 第三种只能在Action中指定一个model对象(返回一个model对象),第二种可以在Action中定义多个model对象

<inputtype="text"name="user.username"/> 

<inputtype="text"name="product.info"/>

7、Action的相关配置?

1)必须要为<action>元素 配置<package>元素  (struts2 围绕package进行Action的相关配置 )

配置package 三个常用属性

<packagename="default"namespace="/"extends="struts-default">

①name包名称,在struts2的配置文件中,包名不能重复,name并不是真正包名,只是为了管理Action

②namespace和 <action>的name属性,决定 Action的访问路径  (以/开始 )

namespace=""        :默认的名称空间

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">

①<action>的name和 <package>的namespace属性共同决定 Action的访问路径

②class:类全路径

③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>

此时的访问路径 http://localhost:8080/Struts2/demo1/user/hello.action

①result中的name:结果页面逻辑视图名称,默认为success

②type:结果类型(后面会做详细介绍,默认为转发)

3) <action> 元素配置默认值

<package> 的namespace 默认值 /

<action> 的class 默认值 ActionSupport 类     <default-class-ref class="com.opensymphony.xwork2.ActionSupport" />

<result> 的 name 默认值 success

8、Action访问Servlet API有哪几种方式,简单的介绍一下

①.方式一:使用ActionContext对象(在Action中解耦合方式间接访问Servlet API)

在struts2中Action API已经与Servlet API 解耦合(没有依赖关系),开发简单,便于测试。

Servlet API 常见操作 : 表单提交请求参数获取,向request、session、application三个范围存取数据

②.方式二:使用接口注入的方式操作Servlet API(藕合)

通过Aware接口,在构造Action时,自动注入需要操作Servlet对象(需要哪个对象就实现哪个Aware接口)

③.方式三:在Action中直接通过 ServletActionContext 获得Servlet API

静态方法返回request,不会有线程问题(使用了ThreadLocal来实现的)

总结:理论来说,第一种方式最好,实现了解耦和,但是第三种我们使用最为简单,企业中没有很大的限制,自己熟悉哪种就使用哪种。

9. 说说Struts2的输入校验流程

Struts2校验框架进行校验时,将执行以下流程:

A:类型转换器负责对字符串的请求参数执行类型转换,并将这些值设置成Action的属性值

B:在执行类型转换过程中可能出现异常,如果出现异常,将异常信息保存到ActionContext中,convertionError拦截器将负责将其封装到fieldError里,如果没有异常,直接进入第3步

C:调用Struts2的内置校验规则进行输入校验

D:通过反射调用validateXXX()方法

E:调用Action类中的validate()方法

F:如果上面的几步中没有出FiledError,就调用Acton中的逻辑处理方法,如果有,则进入input视图

所以,在进行校验时,别忘记在Action中的配置名为input的结果如:<result name=“input”>validate.jsp</result>

10. Struts2 form标签数据为什么可以回显?

11. 什么是值栈?值栈的内部结构?

ValueStack 是 struts2 提供一个接口,实现类 OgnlValueStack ---- 值栈对象 (OGNL是从值栈中获取数据的 )每个Action实例都有一个ValueStack对象 (一个请求对应 一个ValueStack对象 )在其中保存当前Action 对象和其他相关对象 (值栈中是有Action引用的 )Struts 框架把 ValueStack 对象保存在名为“struts.valueStack” 的请求属性中,request中(值栈对象是request一个属性)

值栈由两部分组成,ObjectStack和ContextMap

ObjectStack: Struts 把动作和相关对象压入 ObjectStack 中--List

ContextMap: Struts 把各种各样的映射关系(一些 Map 类型的对象) 压入ContextMap中,Struts 会把下面这些映射压入 ContextMap 中

parameters: 该 Map 中包含当前请求的请求参数

request: 该 Map 中包含当前 request 对象中的所有属性

session: 该 Map 中包含当前 session 对象中的所有属性

application:该 Map 中包含当前 application  对象中的所有属性

attr: 该 Map 按如下顺序来检索某个属性: request, session, application

VaValueStack中 存在root属性 (CompoundRoot) 、 context 属性 (OgnlContext )

* CompoundRoot 就是ArrayList

* OgnlContext 就是 Map

cncontext 对应Map 引入 root对象

* context中还存在 request、 session、application、 attr、 parameters 对象引用

* OGNL表达式,访问root中数据时 不需要 #, 访问 request、 session、application、 attr、 parameters 对象数据 必须写 #

* 操作值栈 默认指 操作 root 元素

12. 值栈对象的创建 ,ValueStack 和 ActionContext 是什么关系 ?

值栈对象是请求时创建的

doFilter中 prepare.createActionContext(request, response);

* 创建ActionContext对象过程中,创建值栈对象ValueStack

* ActionContext对象对ValueStack对象有引用的(在程序中通过 ActionContext 获得值栈对象 )

Dispatcher类 serviceAction 方法中将值栈对象保存到request范围

request.setAttribute(ServletActionContext.STRUTS_VALUESTACK_KEY, proxy.getInvocation().getStack());

13.如何获得值栈对象?

获得值栈对象 有两种方法

ValueStack valueStack = (ValueStack) ServletActionContext.getRequest().getAttribute(ServletActionContext.STRUTS_VALUESTACK_KEY);

ValueStack valueStack2 = ActionContext.getContext().getValueStack();

14.如何向值栈中保存数据?如何在jsp页面中获取值栈的数据?

两种方式

// 将数据保存root的索引0位置,放置到第一个元素 ArrayList add(0,element);

valueStack.push("itcast");

// 在值栈创建参数map, 将数据保存到map中

valueStack.set("company", "传智播客");

在jsp中 通过 <s:debug /> 查看值栈的内容

获取值栈数据时,如果访问root中数据不需要# ,访问其它对象数据加 #

通过下标获取root中对象

<s:property value="[0].top"/> //取值栈顶对象

直接在root中查找对象属性 (自上而下自动查找)

valueStack:<s:property value="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[0]"/>

15.为什么EL也能访问值栈中的数据?

StrutsPreparedAndExecuteFilter的doFilter代码中 request = prepare.wrapRequest(request);

* 对Request对象进行了包装 ,StrutsRequestWrapper

* 重写request的 getAttribute

Object attribute = super.getAttribute(s);

if (attribute == null) {

attribute = stack.findValue(s);

}

访问request范围的数据时,如果数据找不到,去值栈中找

16.你在开发中,值栈主要有哪些应用?

值栈主要解决Action向JSP传递数据问题

Action 向JSP 传递数据处理结果 ,结果数据有两种形式

1)消息 String类型数据

this.addFieldError("msg", "字段错误信息");

this.addActionError("Action全局错误信息");

this.addActionMessage("Action的消息信息");

* fieldError 针对某一个字段错误信息 (常用于表单校验)、actionError (普通错误信息,不针对某一个字段 登陆失败)、 actionMessage 通用消息

在jsp中使用 struts2提供标签 显示消息信息

<s:fielderror fieldName="msg"/>

<s:actionerror/>

<s:actionmessage/>

2)数据 (复杂类型数据)

使用值栈  valueStack.push(products);

哪些数据默认会放入到值栈 ???

1)每次请求,访问Action对象 会被压入值栈 ------- DefaultActionInvocation 的 init方法 stack.push(action);

* Action如果想传递数据给 JSP,只有将数据保存到成员变量,并且提供get方法就可以了

2)ModelDriven 接口有一个单独拦截器

<interceptor name="modelDriven" class="com.opensymphony.xwork2.interceptor.ModelDrivenInterceptor"/>

在拦截器中,将model对象压入了值栈 stack.push(model);

* 如果Action 实现ModelDriven接口,值栈默认栈顶对象就是model对象

17.如何防止表单重复提交?

哪些情况会导致重复提交?

服务器处理服务后,转发页面,客户端点击刷新(重定向)

客户端网络过慢,按钮连续点击(按钮点击一次后,禁用按钮)

使用令牌机制

18.简单的说一下ActionProxy的运行原理?

Struts2的拦截器的本质就是AOP思想,而AOP就是基于代理模式。

19.拦截器和过滤器有什么区别?

1、①拦截器是基于java的反射机制的,而过滤器是基于函数回调

2、②过滤器依赖与servlet容器,而拦截器不依赖与servlet容器

3、③拦截器只能对action请求起作用,而过滤器则可以对几乎所有的请求起作用

4、④拦截器可以访问action上下文、值栈里的对象,而过滤器不能

5、⑤在action的生命周期中,拦截器可以多次被调用,而过滤器只能在容器初始化时被调用一次

拦  拦截器 :是在面向切面编程的就是在你的service或者一个方法,前调用一个方法,或者在方法后调用一个方法比如动态代理就是拦截器的简单实现,在你调用方法前打印出字符串(或者做其它业务逻辑的操作),也可以在你调用方法后打印出字符串,甚至在你抛出异常的时候做业务逻辑的操作。

20.Struts2详细运行流程

请求首先通过Filter chain,Filter主要包括ActionContextCleanUp,它主要清理当前线程的ActionContext和Dispatcher;FilterDispatcher主要通过AcionMapper来决定需要调用哪个Action。

ActionMapper取得了ActionMapping后,在Dispatcher的serviceAction方法里创建ActionProxy,ActionProxy创建ActionInvocation,然后ActionInvocation调用Interceptors,执行Action本身,创建Result并返回,当然,如果要在返回之前做些什么,可以实现PreResultListener。

部分类介绍

①ActionMapper

ActionMapper其实是HttpServletRequest和Action调用请求的一个映射,它屏蔽了Action对于Request等java Servlet类的依赖。Struts2中它的默认实现类是DefaultActionMapper,ActionMapper很大的用处可以根据自己的需要来设计url格式,它自己也有Restful的实现,具体可以参考文档的docs\actionmapper.html。

②ActionProxy&ActionInvocation

Action的一个代理,由ActionProxyFactory创建,它本身不包括Action实例,默认实现DefaultActionProxy是由ActionInvocation持有Action实例。ActionProxy作用是如何取得Action,无论是本地还是远程。而ActionInvocation的作用是如何执行Action,拦截器的功能就是在ActionInvocation中实现的。

③ConfigurationProvider&Configuration

ConfigurationProvider就是Struts2中配置文件的解析器,Struts2中的配置文件主要是尤其实现类XmlConfigurationProvider及其子类StrutsXmlConfigurationProvider来解析。

Struts2请求流程

1、客户端发送请求

2、请求先通过ActionContextCleanUp-->FilterDispatcher

3、FilterDispatcher通过ActionMapper来决定这个Request需要调用哪个Action

4、如果ActionMapper决定调用某个Action,FilterDispatcher把请求的处理交给ActionProxy,这儿已经转到它的Delegate--Dispatcher来执行

5、ActionProxy根据ActionMapping和ConfigurationManager找到需要调用的Action类

6、ActionProxy创建一个ActionInvocation的实例

7、ActionInvocation调用真正的Action,当然这涉及到相关拦截器的调用

8、Action执行完毕,ActionInvocation创建Result并返回,当然,如果要在返回之前做些什么,可以实现PreResultListener。添加PreResultListener可以在Interceptor中实现。

源代码分析

①启动服务器(tomcat)将会自动加载配置文件,加载过程如下:

服务器启动,init()方法被执行

②客户端初始化一个指向Servlet容器(WEB容器)的请求;

③这个请求经过一系列的过滤器(Filter)(这些过滤器中有一个叫做ActionContextCleanUp的可选过滤器,这个过滤器对于Struts2和其他框架的集成很有帮助,例如:(SiteMesh Plugin)。

④接着StrutsPrepareAndExecuteFilter被调用,StrutsPrepareAndExecuteFilter询问ActionMapper来决定这个请求是否需要调用某个Action。

⑤如果ActionMapper决定需要调用某个Action,FilterDispatcher把请求的处理交给ActionProxy。ActionProxy通过Configuration Manager询问框架的配置文件,找到需要调用的Action类

⑥ActionProxy创建一个ActionInvocation的实例。ActionInvocation实例使用命名模式来调用,在调用Action的过程前后,涉及到相关拦截器(Intercepter)的调用。拦截器默认执行<default-interceptor-ref name="defaultStack"/>defaultStack里面有一系列的interceptor。

⑦一旦Action执行完毕,ActionInvocation负责根据struts.xml中的配置找到对应的返回结果。返回结果通常是(但不总是,也可能是另外的一个Action链)一个需要被表示的JSP或者FreeMarker的模版。在表示的过程中可以使用Struts2框架中继承的标签。在这个过程中需要涉及到ActionMapper,响应的返回是通过我们在web.xml中配置的过滤器

⑧如果ActionContextCleanUp是当前使用的,则FilterDispatecher将不会清理threadlocal ActionContext;如果ActionContextCleanUp不使用,则将会去清理threadlocals。

时间: 2024-10-13 12:01:01

[Java面试四]Strust2总结及在面试中的一些问题.的相关文章

Java数据结构四之——二叉树的前、中、后序遍历

程序来自Program Creek 前 Preorder binary tree traversal is a classic interview problem about trees. The key to solve this problem is to understand the following: What is preorder? (parent node is processed before its children) Use Stack from Java Core lib

7年Java老兵闭关整理出430道面试真题,全部掌握阿里也不过如此!

题目基本覆盖了整个Java后端题,因文章篇幅问题,我这里就不解答了,我已把题目整理成pdf文档,内容很全面,有需要的可以 点击这里 获取资料 话不多说,直接往下看↓ ↓ ↓ 一.性能调优面试专栏 1.1.tomcat性能优化整理 你这样给tomcat调优 如何加大comcat连接数 怎样加大tomcat的内存 Tomcat有几种部署方式 Tomcat的优化经验 1.2.JVM性能优化整理 Java类加载过程 Java内存分配 描述一下jVM加载class文件的原理机制? GC是什么?为什么要有G

面试官:能解释一下javascript中bind、apply和call这三个函数的用法吗

一.前言    不知道大家还记不记得前几篇的文章:<面试官:能解释一下javascript中的this吗> 那今天这篇文章虽然是介绍javascript中bind.apply和call函数,但是多少也和this有点关联. 假如在前面那场面试末尾,面试官不依不饶继续问你javascript中的this,那看完本篇文章后一定还会有收获. (本篇文章不会站在this的角度去回答问题,而是重于解释bind.apply和call这三个函数的用法和使用场景) 二.正戏开始 面试官:能解释一下javascr

【真实面试经历】我和阿里面试官的一次“邂逅”(附问题详解)

本文的内容都是根据读者投稿的真实面试经历改编而来,首次尝试这种风格的文章,花了几天晚上才总算写完,希望对你有帮助. 本文主要涵盖下面的内容: 分布式商城系统:架构图讲解: 消息队列相关:削峰和解耦: Redis 相关:缓存穿透问题的解决: 一些基础问题: 网络相关:1.浏览器输入 URL 发生了什么? 2.TCP 和 UDP 区别? 3.TCP 如何保证传输可靠性? Java 基础:1. 既然有了字节流,为什么还要有字符流? 2.深拷贝 和 浅拷贝有啥区别呢? 下面是正文! 面试开始,坐在我前面

微软架构详谈,从面试官的角度谈面试:剑指Offer名企面试官精讲典型编程题

前言 我在微软做了很多年的面试官,后面七年多作为把关面试官也面试了很多应聘者.应聘者要想做好面试,确实应把面试当作一门技巧来学习,更重要的是要提高自身的能力.我遇到很多应试者可能自身能力也不差但因为不懂得怎样回答提问,不能很好发挥.也有很多校园来的应聘者也学过数据结构和算法分析,可是到处理具体问题时不能用学过的知识来有效地解决问题.这些朋友读读海涛的这本书,会很受益,在面试中的发挥也会有很大提高.这本书也可以作为很好的教学补充资料,让学生不只学到书本知识,也学到解决问题的能力. 主页 目录 第1

java第四章编程题(初学篇)

代码: 1 /* 2 test.java 3 */ 4 package test; 5 public class test { 6 public static void main(String args[] ) 7 { 8 CPU ccp= new CPU(); 9 HardDisk hhd=new HardDisk(); 10 PC pc =new PC(); 11 ccp.setSpeed(2200); 12 hhd.setAmount(200); 13 pc.setCPU(ccp); 14

Java的四种引用类型

Java中有四种引用类型:强引用.软引用.弱引用.虚引用.--应该是从1.2版本开始添加的. 这个概念是与垃圾回收有关的. 如果你不知道这几个概念,那你用的肯定都是强引用.例如String str = new String(); 这个str到 new String() 的引用类型就是强引用. 那什么是弱引用呢?先看一段代码: 1 package cn.larry.pojo; 2 3 public final class Product { 4 private String name; 5 6 p

Java解惑四:异常之谜

谜题36 finally语句中的return语句会覆盖掉try语句中的. 谜题37 该部分还需要进一步理解 一个方法可以抛出的被检查异常集合是它所适用的所有类型声明要抛出的被检查集合的交集. Java解惑四:异常之谜,布布扣,bubuko.com

Java基础四

Java基础四 一.Switch语句 二.if和switch区别 推荐使用if 三.函数 Java中的函数和方法是同一个词 四.数组 4.1.数组常见错误 五.内存机制 六.转换成十六进制 移位 &操作 6.2 查表法求十六进制 查表法很多时候都非常好用,这样就非常好了,真的非常好用 算的时候直接移四位,我喜欢,我觉得以后可以多做移位运算,真的是简单方便 6.3 查表法求星期几