概述
基于MVC设计模式,本质是servlet,是struts1和webwork技术的合并,是web层的框架,且标签库丰富。
MVC:前端控制器模型,所有请求先经过前端控制器,根据请求不同分发action(struts里servlet的称谓)。
传统设计模式:有一个请求就会有一个servlet。
配置环境
1、在web.xml里配置过滤器
2、新建名为struts.xml的配置文件,配置对应的action和返回页面路径
struts2的执行流程以及图示
客户端向服务器发送一个Action的请求,执行核心过滤器(doFilter)方法。在这个方法中,调用executeAction()方法,在这个方法内部调用dispatcher.serviceAction();在这个方法内部创建一个Action代理,最终执行的是Action代理中的execute(),在代理中执行的execute方法中调用ActionInvocation的invoke方法。在这个方法内部递归执行一组拦截器(完成部分功能),如果没有下一个拦截器,就会执行目标Action,根据Action的返回的结果进行页面跳转。
struts2配置文件加载顺序
过滤器的初始化方法里加载配置文件的方法:7种(4消失了,有待考察)
init_DefaultProperties() ----加载default.properties
init_TraditionalXmlConfigurations(); ----加载struts-default.xml、struts-plugin.xml、struts.xml
init_LegacyStrutsProperties(); ----加载struts.properties
init_CustomConfigurationProviders(); ----加载配置提供类
init_FilterInitParameters() ; ----加载web.xml中过滤器初始化参数
init_AliasStandardObjects() ;----加载Bean对象
重要性:后配置常量的值会覆盖前面配置的(加载顺序导致的)
配置文件struts.xml里标签解析
1、include标签
引入其他配置文件,用于分模块开发
2、package标签及其属性
name:命名,区别package
extends:继承,默认值为struts-default(里面包含各种拦截器)
namespace:命名空间,与action标签共同组成访问路径,三种写法(/什么;/;什么都不写)不同package有同一action访问顺序跟namespace写法相关
abstract:抽象,给别人继承
3、action标签及其属性,package的子标签
name:访问路径
class:跳转目标类的全路径
method:执行action中的指定方法,默认execute
convertor:自定义类型转换器,几乎不用,因为struts2底层有类型转换(如日期等)
4、result标签及其属性,action的子标签:写入跳转的页面
name:方法返回的字符串
常量的配置
default.properties(源码里)里提供了大量的常量配置
例:
struts.i18n.encoding=UTF-8 ----Struts2中所有的post请求的中文乱码不用处理。
struts.action.extension=action,, ----Struts2请求的默认的扩展名。默认扩展名是.action或者什么都不写。
修改常量的值
1、struts.xml中进行修改
2、struts.properties中进行修改
3、web.xml中进行修改
actoin类是三种写法
1、pojo类。pojo:没有实现接口,没有继承的一个简单java类。
2、实现接口。有五个常量(SUCCESS等),SUCCESS就是小写的success,INPUT:表单校验出错,拦截器内部跳转要用,其余略。
3、继承ActionSupport。推荐使用,功能多。
action的访问
1、通过method访问,多个方法配多个action,不推荐
页面:<a href="${pageContext.request.contextPath}/userFind.action">查询</a>
配置文件:action标签下,name=userFind,class=指定类路径,method=方法名
2、通配符访问,推荐
页面:<a hred="${pageContext.request.contextPath}/user_find">查询</a>
配置文件: action标签下,name=user_*,class=类路径,method="{1}"
method里的取值是由请求得到的,{1}代表通配符中第一个星号的取值
3、动态方法访问
先要开启动态访问(默认是关闭的),在配置文件里修改常量
<constant name="" value="true"/>
页面:<a href=” ${pageContext.request.contextPath} /user!find.action”>
配置:<action name="user” class=”...”>
Servlet的API的使用访问
Struts与Servlet的API是解耦合的。开发中经常使用servlet的api,如:登录,将信息存储到session中,向页面输出内容用response对象。
Struts的servlet的api(方法)访问,都需继承actionsupport
1、完全解耦合(只能获得域对象数据的map集合,不能获得对象的方法)
2、使用Servlet的API
3、接口注入,实现serveltRequestAware,Servlet是单例的,多个程序访问同一个Servlet只会创建一个Servlet的实例。Action是多例的,一次请求,创建一个Action的实例(不会出现线程安全的问题)。
一、完全解耦合的方式
编写JSP
编写Action
二、使用Servlet的API
编写Action
三、接口注入的方式
编写Action
数据封装
1、属性驱动:提供属性set方法的方式(不常用)
缺点:需自己封装数据到对象中
编写页面
编写Action,struts帮忙做类型转换,年龄、日期等属性,
2、属性驱动:页面中提供表达式方式
自动封装数据到对象
编写JSP,OGNL表达式
编写Action,必须要有对象的get方法,目的是拦截器封装数据时获取的是同一对象
3、模型驱动:采用模型驱动方式(最常用)
编写JSP
编写Action
缺点:只能同时向一个对象中封装数据。
使用第二种可以向多个对象中同时封装数据。
结果页面配置
全局结果页面
全局结果页面:全局结果页面指的是,在包中配置一次,其他的在这个包中的所有的action只要返回了这个值,都可以跳转到这个页面。
针对这个包下的所有的action的配置都有效。
局部结果页面
局部结果页面:局部结果页面指的是,只能在当前的action中的配置有效。
针对当前的action有效。
result标签
result标签的配置
在result标签上有两个属性:
name属性 :逻辑视图的名称。默认值:success
type属性及其值:页面跳转的类型。
dispatcher:默认值,请求转发。(Action转发JSP)
redirect:重定向。(Action重定向JSP)
chain :转发。(Action转发Action)
redirectAction :重定向。(Action重定向Action)
stream :Struts2中提供文件下载的功能。
INPUT逻辑视图
例子:密码输入字符
配置页面:
1、result标签的type为input
2、页面引struts2的标签库
3、页面<s:fielderror></s:fielderror>,代表某一个字段的错误
Struts2的复杂类型的数据封装
封装数据到List集合中
编写JSP
编写Action
封装数据到Map集合中
编写JSP
编写Action
OGNL
简述
OGNL ,对象图导航语言,比EL强大,第三方语言,被struts2纳入
OGNL与EL的区别
EL:获取域对象的数据
OGNL:调用对象方法,获取值栈的数据
组成
表达式(操作),获取静态方法格式:@类名@方法。
根对象(操作谁)。
context对象(在哪儿操作),获取里面的数据,表达式里要加#号。
在struts环境下访问对象的方法
1、引入标签库
2、例子:<s:property value=”’hello’.length()”/>
访问静态方法要改变常量,因为默认关闭
值栈
简述
1、数据中转站,框架中的数据保存到值栈中。
2、valueStack接口,实现类ognlvaluestack。
3、贯穿整个action的生命周期。
重要性
可以在页面里、action里、配置文件里获取数据,而request只能在页面获取数据。
内部结构
1、root:真实对象:CompoundRoot,继承arrayList,放置Object。获取里面的数据不加#号,值栈的操作通常是指root区域。
2、context:真实对象:OgnlContext,实现了Map,里面有root的引用,放置Web开发对象的引用。取里面的数据加#号。
与ActionContext关系
当请求过来时,会执行过滤器中的doFilter方法,就会创建ActionContext,在这过程中又会创建ValueStack对象。所以ActionContext之所以能访问Servlet的API(访问域对象的数据),是因为内部有值栈的引用。
值栈的获取方式
1、通过ActionContext获得
ValueStack valueStack = ActionContext.getContext().getValueStack();
2、通过request对象获得
ServletActionContext.getRequest().getAttribute(ServletContext.STRUTS.VALUE.STACK_KEY);
两个值栈是一样的,因为一个action实例只会创建一个valueStack对象。
值栈操作
存入数据
1、对象的get方法,默认情况下action对象压入到值栈,对象的属性也在值栈中。
2、ValueStack中的push方法(压栈),传入对象。
3、ValueStack中的set方法键值形式,创建map集合,将map集合压入栈顶。
获取数据
1、页面上:<s:property value=”user.username”/>,OGNL表达式
2、<s:property value=”username”/>,对象的属性最好不要同名
获取set方法存入的对象value写键名
获取list集合,value写list[0].username
EL可以获取值栈的值
1、例子:{username},能获取值栈中的数据,
2、原因:struts2增强了request.getAttribute()方法
OGNL特殊字符
1、#:获取context数据,构建map集合。
2、%:强制解析OGNL。
3、$:在配置文件中使用OGNL。
拦截器与过滤器的区别
interceptor:拦截客户端对action的请求,拦截具体方法
filter:过滤客户端到服务器的请求
自定义拦截器
编写拦截器类
编写一个类实现Interceptor接口或者继承AbstractInterceptor类。
对拦截器进行配置。
定义一个拦截器栈的方式。
标签库(略)