Struts2学习笔记
1.Struts2 简介
1.1 Struts2概念
Struts2是一个基于MVC设计模式的Web应用框架,它本质上相当于一个servlet,在MVC设计模式中,Struts2作为控制器(controller)来建立模型与视图的数据交互。Struts2是Struts2的下一代产品,这个框架充分发挥了Struts2和WebWork这两种技术的优势,抛弃原来Struts1的缺点,使得Web开发更加容易。
1)、运行在web层.负责处理请求的.
2)、struts2已经帮我们封装了很多web中常用的功能(拦截器)
3)、struts2 与 struts1 没什么关系. struts2是基于webwork框架
1.2 Struts2的优点
项目开源,使用及扩展方便;
提供Exception处理机制;
Result方式的页面导航,通过Result标签很方便的实现重定向和页面跳转;
通过简单、集中的配置来调度业务类,使得配置和修改都非常容易;
提供简单、统一的表达式语言来访问所有可供访问的数据;
提供标准、强大的验证框架和国际化框架;
提供强大的、可以有效减少页面代码的标签;
提供良好的Ajax支持;
拥有简单的插件,只需要放入响应的jar包,任何人都可以扩展Struts2框架
1.3 Struts2与Servlet比较
优点:业务代码解耦,提高开发效率。提供了对MVC的一个清晰的实现,这一实现包含了很多参与对所以请求进行处理的关键组件,
如:拦截器、OGNL表达式语言、堆栈。
缺点:执行效率偏低,需要使用反射、解析XML等技术手段,结构复杂。
2.Struts2的MVC实现方式
3.Struts2的工作原理
Struts2处理一个完整的请求的步骤:
工作流程:
(1)客户端浏览器发送HTTP请求到Web应用
(2)Web容器将请求传递到标准ActionContextCleanUp过滤器以消除属性,而不让后续过滤器清楚,以延长Action中属性(包括自定义属性)的生命周期。
(3)再经过如stimesh等其他过滤器后,请求传递给StrutsPrepareAndExecuteFilter核心控制器
(4)StrutsPrepareAndExecuteFilter调用ActionMapper(Action映射器)确定调用哪个Action,再将控制权转移给ActionProxy代理
(5)ActionProxy代理调用配置管理器ConfigurationManager从配置文件struts.xml中读取配置信息,然后创建ActionInvocation对象
(6)ActionInvocation在调用拦截器链中的拦截器后再调用Action,根据Action返回的结果字符串查找对应的Result
(7)Result调用视图模板,再以相反的顺序执行拦截器链,返回HTTP响应
(8)HTTP响应以相反的顺序返回给核心控制器StrutsPrepareAndExecuteFilter以及其他web.xml中定义的过滤器,最终返回给客户端。
3.Struts2配置
3.1 Struts2配置文件加载顺序
init_DefaultProperties()加载的是 default.properties 文件
位置:struts2-core.jar 包 org.apache.struts2 包下
作用:主要是声明了 struts2 框架的常量
init_TraditionXmlConfigurations()加载的是一批配置文件
Struts-default.xml
位置:struts2-corl.jar
作用:声明了 interceptor result bean
Struts-plugin.xml
位置:在 struts2 的插件包中
作用:主要用于插件的配置声明
Struts.xml
位置:在我们自己的工程中
作用:用于我们自己工程使用 struts2 框架的配置
init_LegacyStrutsProperties()加载的是自定义的struts.properties
位置:都是在自己工程的 src 下
作用:定制常量
init_CustomConfigurationProviders()自定义配置提供
init_FilterInitParmeters()加载的是 web.xml 配置文件
主要是加载 struts2 框架在 web.xml 文件中的相关配置.
init_AliasStandardObjects() bean 相关配置
重点掌握:
1.Default.properties
2.Struts-default.xml
3.Struts-plugin.xml
4.Struts.xml
5.web.xml
3.2 struts.xml件配置介绍
3.2.1 package配置(strust.xml只存在一个package相当于一个struts的项目)
name属性作用:定义一个包的名称,它必须唯一。
namespace属性作用:主要是与action标签的name属性联合使用来确定一个 action的访问路径。
extends属性作用:指定继承自哪个包。一般值是struts-default,struts-default包是 在struts-default.xml文件中声明的。
abstruct属性它代表当前包是一个抽象的,主要是用于被继承。
3.2.2 action配置(对应相应的以action结尾的类,一个package可以有多个action)
name属性作用:主要是与package的namespace联合使用来确定action的访问路径。
class属性作用:用于指示当前的action类。
method属性作用:用于指示当前的action类中的哪个方法执行。
3.2.3 result配置(用于显示视图的结果)
name属性作用是与action类的method方法的返回值进行匹配,来确定跳转路径。
type属性作用是用于指定跳转方式。
4 Action类详解
Action类相当于javaWeb阶段下的Servlet类,做着调用service层的关系,实现页面的 跳转,完成业务逻辑操作。
4.1 Action类的创建(注意:action类的全路径(即包名)必须含有"action”的词汇)
(1) 创建一个POJO类;(hibernate自动会封装成PO类)
(2) 创建一个类实现一个Action接口;
(3) 创建一个类继承ActionSupport类。
4.2 访问Action类
(1) 直接通过<action>标签来配置,通过method来指定访问的方法,如果method没有,默认访问的是execute方法;
(2) 简化的 action 访问方式,可以使用*通配符来访问,使用*来简化操作方案,它对名称规范必须进行一个统一。
5 Struts2框架封装数据
5.1 属性驱动
两种方式
(1) 直接在 action 类中提供与请求参数匹配属性,提供get/set方法
(2) 在action 类中创始一个javaBean,对其提供get/set,在请求时页面上要进行修改,
例如 user.username user.password ,要使用ognl表达式
以上两种方式的优缺点:
第一种比较简单,在实际操作我们需要将action的属性在赋值给模型(javaBean)去操作;
第二种:不需要在直接将值给javaBean过程,因为直接将数据封装到javaBean中。它要求在页面上必须使用ognl表达式,就存在页面不通用问题。
5.2 模型驱动
(1)让 Action 类要实现一个指定接口 ModelDriven;
(2)实例化模型对象(就是要new出来javaBean);
(3)重写getModel方法将实例化的模型返回。
6 Struts2中获取Servlet(开发禁用)
第一种方式:ServletActionContext获取
获取request: ServletActionContext.getRequest();
获取response: ServletActionContext.getResponse();
获取servletContext: ServletActionContext.getServletContext();
第二种方式:采用注入方式
Struts2框架在运行时,请求会被StrutsPrepareAndExecuteFilter拦截,会根据请求,去strtus.xml文件中查找到匹配的action,
在action执行前,会走一些interceptor默认执行的拦截器是struts-default.xml文件中定义的,在默认执行的拦截器中有一个。
ServletRequestAware, 实现这个接口可以获取HttpServletRequest;
ServletResponseAware ,实现这个接口可以获取HttpServletResponse;
ServletContextAware 实现这个接口可以获取ServletContext;
7 OGNL表达式
OGNL是Object-Graph Navigation Language(对象图导航语言)的缩写,它是一种功能强大的表达式语言,通过它简单一致的表达式语法,可以存取对象的任意属性,
调用对象的方法,遍历整个对象的结构图,实现字段类型转化等功能。它使用相同的表达式去存取对象的属性。
Struts2框架内置了OGNL,OGNL本身也是一个项目,它是可以单独使用。
7.1 OGNL作用:
支持对象的操作,调用对象的方法;
支持静态成员访问;
支持赋值操作与表达串联;
访问OGNL上下文,访问ActionContext;
操作集合对象。
7.2 Strtus2框架中如何使用ognl表达式
在struts2框架中我们使用ognl表达式的作用是从valueStack中获取数据,在struts2框架中可以使用ognl+valueStack达到在页面(jsp)上来获取相关的数据,
要想在jsp页面上使用ognl表达式,就需要结合struts2框架的标签<s:property value=”表达式”>来使用。
8 valueStack(值栈)
8.1 valueStack介绍
valueStack的主要目的是为action中产生的数据携带到页面上,也就是说valueStack它就是一个容器,在Struts2框架中将valueStack设计成一个接口,
当客户端向我们发送一个请求,服务器就会创始一个Action来处理请求,struts2中的action是一个多例,每一次请求都会有一个新的action对应。
所以它不存在线程安全问题,一个valueStack对应一个action,valueStack贯穿整个action的生命周期,struts2框架将valueStack保存在request中。
8.2 valueStack内部结构
valueStack主要有两部分组成:
CompoundRoot:它就是一个ArrayList它主要存储的是action的相关数据;
Map<String,Object> context:就是一个Map,Context中主要存储了一些引用,这个引用主要是关于web开发中相关信息;
pameters :请求参数;
request:请求对象中所有属性;
session:会话对象中所有属性;
application:application:对象中的所有发展;
在struts2框架中我们通过ognl表达式来获取valueStack中数据,没有使用#就会从CompoundRoot中获取数据,如果使用#来获取,这时就会从context中来获取。
8.3 获取ValueStack
(1) 通过request对象来获取;
ValueStack vs = (ValueStack)ServletActionContext.getRequest().getAttribute(ServletActionContext.STURTS_VALUESTACK_KEY);
(2) 通过ActionContext来获取
ValueStack vs = ActionContext.getServletContext()getValueStack();
8.4 ActionContext
ActionContext它是action上下文,Strtus2框架它使用ActionContext来保存Action在执行过程中所需要的一些对象,例如 session, application… ActionContext的获取 是通过它的静态方法getContext()得到。Struts2会根据每一次的http请求来创建对应的ActionContext,它是与当前线程绑定的。每一次请求,就是一个线程,对应着一个request,每一次请求,会创建一个Action,每一个action对应一个ActionContext.每一次请求也对应着一个valueStack。它们都对应着一次请求(一个线程),valueStack与ActionContext本质上是可以获取。
8.5 ValueStack的存储数据
(1) 手动向valueStack存储数据;
vs.push(String str); 和 vs.set(Object obj String str);
(2) Struts2框架自动向valueStack中存储数据;
每次请求,访问action,这个对象会存储到valueStack中。
在DefaultActionInvocation的init方法内,调用:vs.push(Action action);
在ModelDrivernInterceptor中,调用ModelDrivern的getModel()方法;
8.6 ValueStack的获取数据
(1) Jsp页面获取,导入s标签库
<s:property value = “ “ />
(2) 在Action中属性
调用PO类getter方法;
(3) 在Model类中(即模型驱动)
调用getModel()方法;
8.7 EL表达式从ValueStack中获取数据
El表达式可以从valueStack中获取信息,在jsp页面中显示:如:{$ model.name},org.apache.struts2.dispatcher.StrutsRequestWrapper这个类可以使ValueStack使用EL表达式,Struts2框架对request进行了增强,重写了getAttribute方法,如果在request域中查找不到数据,就会在valueStack中获取。
8.8 Ognl表达式中特殊字符
OGNL是通常要结合Struts 2的标志一起使用。主要是#、%和$这三个符号的使用,#号:它是从非root中获取数据,%号用于强制是否要解析ognl表达式,$号主要是从配置文件中来获取valueStack中数据。
9 Interceptor拦截器
9.1 Interceptor拦截器介绍
Struts2中的interceptor它是基于spring aop思想,而aop思想它本质上是通过动态代理来实现。我们strtus2的拦截器它主要是拦截Action的操作,在action的执行前或执行后进行一些其它的功能操作。
拦截器链(拦截器栈)简单说,就是可以将多个拦截器形成一个链,在访问它们时依次访问。
执行的过程:
当我们发送请求访问Action时,会被StrutsPrepareAndExecuteFilter拦截在其doFilter方法内执行了execute.executeAction(request, response, mapping);这个代码执行后dispatcher.serviceAction(request, response, mapping);serviceAction方法执行在这个方法执行过程中会创建Action代理对象ActionProxy proxy = getContainer().getInstance(ActionProxyFactory.class).createActionProxy( namespace, name, method, extraContext, true, false);通过proxy去执行了proxy.execute();在execute方法内return invocation.invoke();invocation它是ActionInvocation一个对象。会去加载我们的配置文件,将配置文件中所有的interceptor得到进行遍历。在struts-default.xml文件中定义了默认加载的拦截器栈 defaultStack,在每一个拦截器的interceptor方法内,又调用了DefaultActionInvocation的invoke方法,其实就是递归调用。
9.2 自定义Interceptor
所有的Interceptor都要实现一个接口,在配置文件中声明Interceptor,可以将多个interceptor封装成一个stack,可以在Action的配置中引入自己的interceptor,在使用时name也可以引入一个interceptor stack。注意:当我们显示的引入了一个自定义的Interceptor,那么默认的defaultStack就不会在导入,需要手动导入。
10 Struts2注解开发(现阶段主流)
10.1 xml文件与注解互换
@Namespace来代替<package namespace=””>(开发中禁用这个,我也不知道为啥)
@ParentPackage来代替<package extends=””>
@Action来描述关于<action>配置
value属性<action name=””>
使用@Action的results来描述关于结果类型的配置<result>
<result name=”” type=””>;@Action(results={@Result(name=””,type=””,location=””)})
10.2 其他注解
@Actions
作用:可以通过多个映射来访问同一个action;
@Results
类似于全局的结果视图;
@InterceptorRef
它是用于处理拦截器的;
11 Struts2-ActionSupport定义的五个常量
11.1 Struts2最主要是二个映射:
请求的命令《===》类的映射
返回的结果《===》转发的视图的映射
<action name="" class="" converter="" method="">
<result name="" type="">/xxx.jsp</result>
</action>
11.2 ActionSupport定义的五个常量
(1)static final String SUCCESS
英文解释:The action execution was successful. Show result view to the end user.
汉语翻译: 行动的执行是成功的。结果视图展示给最终用户。
(2)static final String NONE
英文解释:The action execution was successful but do not show a view. This is useful for actions that are handling the view in another fashion like redirect
汉语翻译:Action执行成功,但是不会显示一个视图。通常产生这种情况的原因是被其他视图重定向了。
(3)static final String ERROR
英文解释:The action execution was a failure. Show an error view, possibly asking the user to retry entering data
汉语翻译:Action执行失败。显示一个错误的视图(页面),这个页面可以要求用户再次输入相关数据。
(4)static final String INPUT
英文解释:The action execution require more input in order to succeed. This result is typically used if a form handling action has been executed so as to provide defaults for a form. The form associated with the handler should be shown to the end user.
This result is also used if the given input params are invalid, meaning the user should try providing input again.
汉语翻译:Action的执行成功需要更多的输入。这个结果是一个典型的结果,它表明如果一个表单通过提供默认的表单来操作一个Action。这个表单会显示给最终用户。
这个结果也用于用户输入无效,意味着用户需要再次输入。
(5)static final String LOGIN
英文解释:The action could not execute, since the user most was not logged in. The login view should be shown.
汉语翻译:Action不能执行,因为用户没有登录。已登录的画面会被关闭。