目录
1. 简述 Struts2 的工作流程 :
答案:
- 请求发送给 StrutsPrepareAndExecuteFilter
- StrutsPrepareAndExecuteFilter过滤器拦截该请求并判定该请求是否是一个 Struts2 请求
- 若该请求是一个 Struts2 请求(ActionMapping),则 StrutsPrepareAndExecuteFilter把请求的处理交给 ActionProxy
- ActionProxy 创建一个 ActionInvocation 的实例,并进行初始化,当然在这之前ActionProxy还会通过ConfigurationManager按加载struts2的配置文件(Action和Interceptors)
- ActionInvocation 实例在调用 Action 的过程前后,涉及到相关拦截器(Intercepter)的调用。
- Action 执行完毕,ActionInvocation 负责根据 struts.xml 中的配置找到对应的返回结果。调用结果的 execute 方法,渲染结果。
- 执行各个拦截器 invocation.invoke() 之后的代码
- 把结果发送到客户端
解析:
Struts2工作流程-官方图:
简化版Struts2工作流程图:
这是我通过查找资料画的简化版Struts2工作流程图,会比官方的图好记忆。
2. Struts2拦截器和过滤器的区别:
答案:
- 拦截器用到的是java反射机制,过滤器是函数回调
- 过滤器依赖于 Servlet 容器,而拦截器不依赖于Servlet 容器
- Struts2 拦截器只能对 Action 请求起作用,而过滤器则可以对几乎所有请求起作用
- 拦截器可以访问 Action 上下文(ActionContext)、值栈里的对象(ValueStack),而过滤器不能
- 在 Action 的生命周期中,拦截器可以多次调用,而过滤器只能在容器初始化时被调用一次
解析:
- 什么是拦截器?
在AOP中用于在某个方法或字段被访问之前进行拦截,然后在之前或之后加入某些操作。拦截是AOP的一种实现策略。 AOP基本上是通过代理模式实现的
拦截器aop编程
重复代码,横向抽取
- 什么是过滤器?
过滤器是处于客户端与服务器资源文件之间的一道过滤网,在访问资源文件之前,通过一系列的过滤器对请求进行修改、判断等,把不符合规则的请求在中途拦截或修改。也可以对响应进行过滤,拦截或修改响应。.滤器用到了责任链的设计模式
filter的访问流程图
3. 为什么要使用 Struts2 & Struts2 的优点?
答案:
- 基于 MVC 架构,框架结构清晰,使开发者只关注业务逻辑的实现
- 与OGNL结合使用:OGNL 可以快捷的访问值栈中的数据、调用值栈中对象的方法
- 提供丰富的拦截器实现:Struts2 的拦截器是一个 Action 级别的 AOP,Struts2 中的许多特性都是通过拦截器来实现的,例如异常处理,文件上传,验证等。拦截器是可配置与重用的
- Struts2的可扩展性高:可以自定义拦截器,用户开发了插件只要很简单的配置就可以很容易的和Struts2框架融合,这实现了框架对插件的可插拔的特性
- 异常处理机制:只需在配置文件中配置异常的映射,即可对异常做相应的处理
4. Struts2 如何访问 HttpServletRequest、HttpSession、ServletContext三个域对象?
答案:
- 通过 ActionContext 访问域对象对应的 Map 对象
- 通过 ServletActionContext 直接获取 Servlet API 对象
- 通过实现接口方式(例如:ServletRequestAware、ServletResponseAware等)
解析:
1. Struts2访问ServletAPI原理图:
2. 通过ActionContext
//如何在action中获得原生ServletAPIpublic class DemoTestAction extends ActionSupport { public String execute() throws Exception { //request域=> map (struts2并不推荐使用原生request域) //因为request域和actioncontext域的生命周期是一样的,并且struts包装了request域,建议用ActionContext //不推荐使用 MaprequestScope = (Map ) ActionContext.getContext().get("request"); //推荐使用(Struts核心过滤器已经对request对象进行过包装,改变了取值位置,即会找request,也会继续找ActionContext) ActionContext.getContext().put("name", "requestTom"); //session域 => map Map sessionScope = ActionContext.getContext().getSession(); sessionScope.put("name", "sessionTom"); //application域=>map Map applicationScope = ActionContext.getContext().getApplication(); applicationScope.put("name", "applicationTom"); return SUCCESS; }}
3. 通过ServletActionContext(不推荐)
//如何在action中获得原生ServletAPIpublic class Demo6Action extends ActionSupport { //并不推荐,其实也是从ActionContext中获得的,而且struts本来就希望你脱离原生的session类 public String execute() throws Exception { //原生request HttpServletRequest request = ServletActionContext.getRequest(); //原生session HttpSession session = request.getSession(); //原生response HttpServletResponse response = ServletActionContext.getResponse(); //原生servletContext ServletContext servletContext = ServletActionContext.getServletContext(); return SUCCESS; } }
4. 通过实现接口方式(不推荐)
//如何在action中获得原生ServletAPIpublic class DemoTestAction extends ActionSupport implements ServletRequestAware { private HttpServletRequest request; public String execute() throws Exception { System.out.println("原生request:"+request); return SUCCESS; } @Override public void setServletRequest(HttpServletRequest request) { this.request = request; } }
5. Struts2中的默认包struts-default有什么作用?
答案:
- struts-default 包是 struts2 内置的,它定义了 struts2 内部的众多拦截器和 Result 类型,而 Struts2 很多核心的功能都是通过这些内置的拦截器实现,如:从请求中把请求参数封装到 action、文件上传和数据验证等等都是通过拦截器实现的。当包继承了 struts-default 包才能使用 struts2 为我们提供的这些功能
- struts-default 包 是 在 struts-default.xml中定义,struts-default.xml 也是 Struts2 默认配置文件 Struts2 每次都会自动加载 struts-default.xml 文件。
- 通常每个包都应该继承 struts-default 包
6. 说出Struts2中至少5个的默认拦截器
答案:
exception、fileUpload、i18n、modelDriven、params、prepare、validation 等
解析:
拦截器栈对应的拦截器
已配置栈名 | 包含的拦截器 | 描 述 |
---|---|---|
basicStack | exception、servletConfig、prepare、checkbox、params、conversionError | 如使用栈,最起码要使用这几个拦截器 |
validationWorkflowStack | basicStack、validation、workflow | 在基本栈的基础上增加验证和工作流特性 |
fileUploadStack | fileUpload、basicStack | 在基本栈的基础上增加文件上传特性 |
modelDrivenStack | modelDriven、basicStack | 在基本栈的基础上增加模型功能特性 |
chainStack | chain、basicStack | 在基本栈的基础上增加链接特性 |
i18nStack | i18n、basicStack | 在基本栈的基础上增加区域持久化特性 |
paramPrepareParamsStack | exception、alias、params、servletConfig、prepare、i18n、chain、modelDriven、file- Upload、checkbox、staticParams、params、conversionError、vali- dation、workflow | 提供包括前action(pre-action)方法调用的完整栈。params栈使用两次:第一次是在调用prepare()方法之前提供参数,第二次是在预备阶段为可能被检索的对象重新使用参数 |
defaultStack | exception、alias、servlet- Config、prepare、i18n、chain、debugging、profiling、scoped- ModelDriven、modelDriven、fileUpload、checkbox、static- Params、params、conversion- Error、validation、workflow | 提供一个完整栈,包括调试和概要 |
executeAndWaitStack | execAndWait、defaultStack、execAndWait | 提供执行与等待栈,比如在上传文件时需要向用户显示一个等待页面时,就可以使用这个栈 |
7. 谈谈你对ValueStack的理解
答案:
- ValueStack 贯穿整个 Action 的生命周期,保存在 request 域中,所以 ValueStack 和 request 的生命周期一样。 当Struts2收到一个请求时,会迅速创建 ActionContext、ValueStack、Action;然后把 Action 存放进ValueStack;最后再把值栈对象放入request中,传入jsp页面。所以 Action 的实例变量可以被OGNL访问。
- 值栈是多实例的,因为 Action 是多例的(和 Servlet 不一样,Servelt是单例的),
- 每个 Action 都有一个对应的值栈,Action 对象默认保存在栈顶
- ValueStack 本质上就是一个 ArrayList(查看源代码得到)
解析:
Struts2和OGNL表达式结合原理图
Root:默认情况下,栈中放置当前访问的Action对象
Context:Context部分就是ActionContext数据中心
8. ActionContext 、ServletContext 、pageContext的区别?
答案:
- ActionContext Struts2 的 API:是当前的 Action 的上下文环境,通过ActionContext可以获取到request、session、ServletContext等与Action有关的对象的引用
- ServletContext是域对象,一个web应用中只有一个ServletContext,生命周期伴随整个web应用
- pageContext是JSP中的最重要的一个内置对象,可以通过pageContext获取其他域对象的应用,同时它是一个域对象,作用范围只针对当前页面,当前页面结束时,pageContext销毁, 生命周期是JSP四个域对象中最小的
9. Struts2有哪几种结果类型?
答案:
dispatcher(转发)、redirect(重定向)、chain(转发到某个action上)、redirectAction(重定向到某个action上)等
参看 struts-default.xml 中的相关配置:
10. struts2是如何管理action的?这种管理方式有什么好处?
答案:
Struts2框架中使用包来管理Action,包的作用和java中的类包是非常类似的
主要用于管理一组业务功能相关的action。在实际应用中,我们应该把一组业务功能相关的Action放在同一个包下