struts2

strut2.0版本
Struts1和Struts2的区别和对比
1 Struts1要求Action类继承一个抽象基类。Strut1的一个普遍问题是使用抽象类编程而不是接口。
2 Struts 2 Action类可以实现一个Action接口,也可实现其他接口,使可选和定制的服务成为可能。
Struts2提供一个ActionSupport基类去 实现 常用的接口。Action接口不是必须的,
任何有execute标识的POJO(javabean)对象都可以用作Struts2的Action对象。

3 线程模式:
Struts1 Action是单例模式并且必须是线程安全的,因为仅有Action的一个实例来处理所有的请求。单例策略限制了Struts1 Action能作的事,
并且要在开发时特别小心。Action资源必须是线程安全的或同步的。
Struts2 Action对象为每一个请求产生一个实例,因此没有线程安全问题。(实际上,servlet容器给每个请求产生许多可丢弃的对象,
并且不会导致性能和垃圾回收问题)

4 Servlet 依赖:
Struts1 Action 依赖于Servlet API ,因为当一个Action被调用时HttpServletRequest 和 HttpServletResponse 被传递给execute方法。
Struts 2 Action不依赖于容器,允许Action脱离容器单独被测试。如果需要,Struts2 Action仍然可以访问初始的request和response。
但是,其他的元素减少或者消除了直接访问HttpServetRequest 和 HttpServletResponse的必要性。

5 可测性:
测试Struts1 Action的一个主要问题是execute方法暴露了servlet API(这使得测试要依赖于容器)。
一个第三方扩展--Struts TestCase--提供了一套Struts1的模拟对象(来进行测试)。
Struts 2 Action可以通过初始化、设置属性、调用方法来测试,"依赖注入"支持也使测试更容易。

6 捕获输入:
Struts1 使用ActionForm对象捕获输入。所有的ActionForm必须继承一个基类。
因为其他JavaBean不能用作ActionForm,开发者经 常创建多余的类捕获输入。
动态Bean(DynaBeans)可以作为创建传统ActionForm的选择,但是,
开发者可能是在重新描述(创建)已经存 在的JavaBean(仍然会导致有冗余的javabean)。
Struts 2直接使用Action属性作为输入属性,消除了对第二个输入对象的需求。
输入属性可能是有自己(子)属性的rich对象类型。Action属性能够通过 web页面上的taglibs访问。
Struts2也支持ActionForm模式。rich对象类型,包括业务对象,能够用作输入/输出对象。
这种 ModelDriven 特性简化了taglib对POJO输入对象的引用。

7 表达式语言:
Struts1 整合了JSTL,因此使用JSTL EL。这种EL有基本对象图遍历,但是对集合和索引属性的支持很弱。
Struts2可以使用JSTL,但是也支持一个更强大和灵活的表达式语言--"Object Graph Notation Language" (OGNL).

8 绑定值到页面(view):
Struts 1使用标准JSP机制把对象绑定到页面中来访问。
Struts 2 使用 "ValueStack"技术,使taglib能够访问值而不需要把你的页面(view)和对象绑定起来。
ValueStack策略允许通过一系列名称相同但类型不同的属性重用页面(view)。

9 类型转换:
Struts 1 ActionForm 属性通常都是String类型。Struts1使用Commons-Beanutils进行类型转换。每个类一个转换器,对每一个实例来说是不可配置的。
Struts2 使用OGNL进行类型转换。提供基本和常用对象的转换器。

10 校验:
Struts 1支持在ActionForm的validate方法中手动校验,或者通过Commons Validator的扩展来校验。同一个类可以有不同的校验内容,但不能校验子对象。
Struts2支持通过validate方法和XWork校验框架来进行校验。XWork校验框架使用为属性类类型定义的校验和内容校验,来支持chain校验子属性

11 Action执行的控制:
Struts1支持每一个模块有单独的Request Processors(生命周期),但是模块中的所有Action必须共享相同的生命周期。
Struts2支持通过拦截器堆栈(Interceptor Stacks)为每一个Action创建不同的生命周期。堆栈能够根据需要和不同的Action一起使用。



Struts2请求流程
1、客户端发送请求 (客户端初始化一个指向Servlet容器(如Tomcat)的请求)
2、请求经过一系列过滤器(如ActionContextCleanUp、SiteMesh等),ActionContextCleanUp-->FilterDispatcher
3、FilterDispatcher通过ActionMapper来决定这个Request需要调用哪个Action
4、如果ActionMapper决定调用某个Action,FilterDispatcher把请求的处理交给ActionProxy,
5、ActionProxy通过Configuration Manager询问Struts配置文件(Struts.xml),找到需要调用的Action类。
6、ActionProxy创建一个ActionInvocation的实例
7、ActionInvocation调用真正的Action,当然这涉及到相关拦截器的调用
8、Action执行完毕,ActionInvocation创建Result并返回,


一 导包
二 web.xml 配置过滤器
<filter>
<filter-name>struts2</filter-name>
<filter-class>org.apache.struts2.dispatcher.FilterDispatcher</filter- class>

</filter>

<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>


三 src目录下建立 struts.xml
<!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
"http://struts.apache.org/dtds/struts-2.0.dtd">
<struts>
<include file="struts-default.xml" />
<package name="取个名字" extends="struts-default" >
<action name="取个名字" >
<result name="success">/xxx.jsp</result>
</action>
</package>

</struts>

一些常识:
可以有多个包,每个包有一个命名空间
一个包里有多个action,一个action里有多个result
访问action时先以命名空间查找


.action
不带类名与包名 逐层访问路径 默认 result success 继承extends="struts-default"
包名 命名空间 寻找顺序(最精确匹配)
先找命名空间,如果在该命名空间不存在该action则报错[unknown location]
,当命名空间存在该action时,则可以在该命名空间下后面紧跟其它路径逐层访问 当逐层访问路径与有命名空间冲突时,以有命名空间的为主。


<jsp:forward 问题 struts2 jsp:forward 404错误
原因: struts 2 使用 filter 实现, <jsp:forword /> 的机制是 servlet
目前解决办法是:
1、用form表单提交
2、<meta http-equiv="refresh" content="0;url="xxx.action">;
3、<script language="javascript">location.replace(URL)</script>
4、通过过滤器改变请求地址。
配置web.xml
<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern >/*</url-pattern>
<dispatcher>REQUEST</dispatcher>
<dispatcher>FORWARD</dispatcher>
</filter-mapping>

5、可以用s:url标签


类名
实现Action与不实现action接口
不extends ActionSupport 重写execute方法
extends ActionSupport 重写execute方法
?传值注意 method=post
表单提交 用 method=post

struts2 中 Actionsupport 的作用
(1)实现Action接口 具备5个常量
(2)数据校验,Action接口的基础上还定义了一个validate()方法
(3)国际化
(4)

Action 跟 Actionsupport 的区别
当我们在写action的时候,可以实现Action接口,也可以继承Actionsupport这个类.到底这两个有什么区别呢?
Action接口有:
public static final java.lang.String SUCCESS = "success";
public static final java.lang.String NONE = "none";
public static final java.lang.String ERROR = "error";
public static final java.lang.String INPUT = "input";
public static final java.lang.String LOGIN = "login";
public abstract java.lang.String execute() throws java.lang.Exception;
而Actionsupport这个工具类在实现了Action接口的基础上还定义了一个validate()方法,
重写该方法,它会在execute()方法之前执行,如校验失败,会转入input处,必须在配置该Action时配置input属性。
另外,Actionsupport还提供了一个getText(String key)方法还实现国际化,该方法从资源文件上获取国际化信息.

这样在自定义标签时可以定义一个变量为new actionsupport对象实现国际化。
ActionSupport类的作用
struts2不要求我们自己设计的action类继承任何的struts基类或struts接口,
但是我们为了方便实现我们自己的action,大多数情况下都会继承com.opensymphony.xwork2.ActionSupport类,
并重写此类里的public String execute() throws Exception 方法。因为此类中实现了很多的实用接口,提供了很多默认方法,
这些默认方法包括国际化信息的方法、默认的处理用户请求的方法等,这样可以大大的简化Acion的开发。
Struts2中通常直接使用Action来封装HTTP请求参数,因此,Action类里还应该包含与请求参数对应的属性,并且为属性提供对应的getter和setter方法。


开发模式的常量设置:将<constant name="struts.devMode" value="false" />中的value值改为true。





四 从 action属性到页面的传值 bean list bena中bean bean中list list中bean map

<s:iterator value="list" status="xxx">
<s:property value="name"/>
</s:iterator>

<s:iterator value="map">
<s:property value="value.name" />
</s:iterator>

<s:property value="tb.name"/>
<s:property value="tb.sex"/>
<s:property value="tb.age"/>个

字符串判断
<s:if teest='属性名=="男"'>
数字类型判断
<s:if teest='属性名==111'>


form基本标签
<h3>使用s:radio生成多个单选框</h3>
<s:form>
<!-- 使用简单集合来生成多个单选框 -->
<s:radio name="a" label="请选择" labelposition="top"
list="{'a' , 'b' , 'c'}"/>
<!-- 使用简单Map对象来生成多个单选框 -->
<s:radio name="b" label="请选择您想选择出版日期" labelposition="top"
list="#{'a':'111' , 'b':'222' , 'c':'333'}"
listKey="key"
listValue="value"/>
<s:bean name="包名.类名" id="bs"/>
<!-- 使用集合里放多个JavaBean实例来生成多个单选框 -->
<s:radio name="c" label="请选择" labelposition="top"
list="#bs.bean中集合属性名"
listKey="集合里JavaBean实例属性1"
listValue="集合里JavaBean实例属性2"/>


<s:radio name="d" label="请选择您想选择出版日期" labelposition="top"
list="#bs.map"
listKey="key"
listValue="value"/>
</s:form>


<h3>使用s:select生成下拉选择框</h3>
<s:form>
<!-- 使用简单集合来生成下拉选择框 -->
<s:select name="a" label="请选择" labelposition="top" multiple="true"
list="{'a' , 'b' , 'c'}"/>
<!-- 使用简单Map对象来生成下拉选择框 -->
<s:select name="b" label="请选择" labelposition="top"
list="#{'a':'111' , 'b':'222' , 'c':'333'}"
listKey="key"
listValue="value"/>
<s:bean name="包名.类名" id="bs"/>
<!-- 使用集合里放多个JavaBean实例来生成下拉选择框 -->
<s:select name="b" label="请选择" labelposition="top" multiple="true"
list="#bs.bean中集合属性名"
listKey="集合里JavaBean实例属性1"
listValue="集合里JavaBean实例属性2"/>
</s:form>


<h3>使用s:checkboxlist生成多个复选框</h3>
<s:form>
<!-- 使用简单集合来生成多个复选框 -->
<s:checkboxlist name="a" label="请选择" labelposition="top"
list="{'a' , 'b' , 'c'}"/>
<!-- 使用简单Map对象来生成多个复选框 -->
<s:checkboxlist name="b" label="请选择" labelposition="top"
list="#{'a':'111' , 'b':'222' , 'c':'333'}"
listKey="key"
listValue="value"/>
<s:bean name="lee.BookService" id="bs"/>
<!-- 使用集合里放多个JavaBean实例来生成多个复选框 -->
<s:checkboxlist name="b" label="请选择" labelposition="top"
list="#bs.bean中集合属性名"
listKey="集合里JavaBean实例属性1"
listValue="集合里JavaBean实例属性2"/>
</s:form>


学生管理系统 动态方法


五 标签语法(ognl)

两个栈 第一个是值栈ognl上下文(value stack) 第2个是ActionContext 栈 访问里面的数据ActionContext 栈通过前面加上 #号实现 s:url举例说明%用法
%的特性 计算表达式 类似javascript中的eval函数

<s:textfield key="state.label" name="state" value="%{'CA'}" />


标签被设计用来显示动态的数据。为了创建输入域来显示属性“postalCode”,我们需要将“postalCode”传给textfield标签。

下面创建了一个动态的输入域:

<s:textfield name="postalCode"/>

如果在值栈中存在“postalCode”属性,它的值将会被放入该输入域中。当输入被提交到框架之后,它的值将会被放置到“postalCode”属性中。

有时候,我们想要传动态的数据到标签中。例如,我们可能需要用输入域来显示一个label,我们可能想要从应用程序的message资源中。相应地,框架将会解析在标签属性中的表达式。因此在运行时我们能够合并动态的数据到标签的属性中。表达式是像“%{…}”这样的。任何一个在其中嵌入的文本被作为表达式来计算。

使用一个表达式来设置label的例子:

<s:textfield key="postalCode.label" name="postalCode"/>

表达式语言(OGNL)使得我们能够调用方法和计算属性。getText()方法由ActionSupport(大多数Action的基类)提供。我们可以调用任何一个表达式提供的方法,包括getText方法。

非String型的属性

HTTP协议是基于文本的,但是有一些标签时非String类型的,例如bool和int。为了能够直接使用非String型的属性,本框架将所有的非String类型的属性作为一个表达式处理,在这种情况下,你不需要使用任何转义符(但是,如果你使用了转义符,框架也会将其跳过)。

计算boolean型的例子:

<s:select key="state.label" name="state" multiple="true"/>

一旦multiple属性跟一个boolean属性对应起来,框架不会将它作为一个String来解释,这个值将会被作为一个表达式来计算并且自动地将其转换为boolean值。

因为很容易忘记哪个属性是String,哪个属性是非String型的,你仍然可以使用转义符。

计算boolean值(带有转义符的):

<s:select key="state.label" name="state" multiple="%{true}"/>

带有属性的:

<s:select key="state.label" name="state" multiple="allowMultiple"/>

既带有转义符又带有属性的:

<s:select key="state.label" name="state" multiple="%{allowMultiple}"/>



值是一个对象

更通常的情况是,属性值是自动放入的,因为name属性通常告诉框架哪个属性来调用方法来set值。但是,如果需要直接设置值,建议那个值是Object型而不是String型。

注意:因为值是非String型的,无论传入什么,都是将他作为表达式来处理——而不是一个字面的String。

可能导致错误的例子:

<s:textfield key="state.label" name="state" value="CA"/>

如果textfield被传入 “CA”,本框架将会名字为getCa的属性。通常情况下,这不是我们的本意,我们想要做的是传送一个字符串。在表达式语言中,文字需要被置为单引号之间。

以正确的方式传入一个文字值:

<s:textfield key="state.label" name="state" value="%{'CA'}" />

另一种方法是使用value=”’CA’”,但是在这种情况下,推荐使用表达式符号。

标签属性使用如下三种规则计算:

1. 所有的String属性都被解析成“%{…}”符号;

2. 所有的非String属性没有被解析,而是直接按照表达式来算;

3. 规则2的异常情况是非String型的属性使用转义符号“{%{}”,符号被作为多余的符号被忽略,而只是计算内容。

表示式语言符号

1.在Freemarker、Velocity或者JSTL的表达式语言的JavaBean对象的标准文本

<p>Username: ${user.username}</p>

2.在值栈中的一个username属性

<s:textfield name="username"/>

3. 引用值栈中的属性的另一种方式

<s:url id="es" action="Hello">

<s:param name="request_locale">

es

</s:param>

</s:url>

<s:a href="%{es}">Espanol</s:a>

4. 在Session Context中获得user对象的userName属性

<s:property name="#session.user.username" />

5. 在一个静态map中,像("username","trillian")一样

<s:select label="FooBar" name="foo" list="#{'username':'trillian', 'username':'zaphod'}" />


六 模型驱动与属性驱动
action类实现 ModelDriven<javabean类名> 接口,采用泛型
在 action类中定义javabean属性,实现getModel方法

七 访问 servletapi
1. 非IoC方式

要获得上述对象,关键Struts 2.0中com.opensymphony.xwork2.ActionContext类。我们可以通过它的静态方法getContext()获取当前Action的上下文对象。
另外,org.apache.struts2.ServletActionContext作为辅助类(Helper Class),可以帮助您快捷地获得这几个对象。

o HttpServletRequest request = ServletActionContext.getRequest();

o HttpServletResponse response = ServletActionContext.getResponse();

o HttpSession session = request.getSession();

如果你只是想访问session的属性(Attribute),你也可以通过ActionContext.getContext().getSession()获取或添加session范围(Scoped)的对象。

2. IoC方式
要使用IoC方式,我们首先要告诉IoC容器(Container)想取得某个对象的意愿,通过实现相应的接口做到这点
实现相关接口SessionAware, ServletRequestAware, ServletResponseAware
private Map att;
private HttpServletRequest request;
private HttpServletResponse response;

publicvoid setSession(Map att) {
this.att = att;
}

publicvoid setServletRequest(HttpServletRequest request) {
this.request = request;
}

publicvoid setServletResponse(HttpServletResponse response) {
this.response = response;
}


八 资源文件与国际化

国际化常量配置
<constant name="struts.custom.i18n.resources" value="ApplicationResource"></constant>//ApplicationResource前缀

可以在资源文件中定义日期及其数字的格式化,例如在.properties文件中如下定义
product.orderDate = {0,date,dd-MM-yyyy}
format.number = {0,number,###,###.##}
format.discount = {0,number,###.#######%}


{}里面的意思如下
{ 参数序号(0表示格式第一个参数,1表示格式第2个参数,如下所示), 格式类形(number | date | time | choice), 格式样式}

用<s:text>引用
<s:text name="format.number">

<s:param name="format.discount" value="myDate"/>//第一个参数
<s:param name="format.number" value="myDate"/>第2个参数
</s:text>



在Struts 2框架中有3种配置常量的方式,或者说是可以在3类文件中配置常量,这3种配置常量的方式如下所述。

(1) 在struts.properties文件中配置常量:这种配置常量的方式是从WebWork框架继承下来的,目的是为了保持与WebWork框架的兼容性。在Sturts 2中病不建议使用这种方式来配置常量。

(2) 在struts.xml文件及其他Struts 2配置文件中配置常量:这是Struts 2推荐的配置常量的方式。在Struts 2中可以使用<constant>标签来配置常量。

(3) 在web.xml文件中配置常量:这种配置常量的方式在前面已经提到过。对于和Web整合的框架来说,应尽量避免在web.xml文件中配置常量。

既然Struts 2可以再多个文件中配置常量,那就涉及一个搜索和加载顺序的问题,Struts 2框架将按如下的搜索顺序加载Struts 2常量:

Struts-default.xml:该文件保存在Struts-core-2.0.11.2.jar文件中。
Struts-plugin.xml:该文件是Struts 2插件配置文件,保存在类似Struts2-Xxx-2.0.11.jar这样的文件中。
Struts.xml:该文件中Struts 2框架默认的配置文件。
Struts.properties:该文件时Struts 2框架默认的属性文件(为了保持和WebWork框架兼容)。
Web.xml:该文件时Web应用程序的核心配置文件。
如果在多个文件中配置同一常量,则后一个配置文件中的常量会覆盖前一个配置文件中的同名常量的值。虽然在不同的配置文件中配置常量的方式不同,但配置常量都需要两个必须的属性:
Name:该属性指定了常量名。
Value:该属性指定了常量值。
如果在struts.xml中通过devMode属性来设置Struts 2的工作模式,可以按照如下的代码来设置:
<struts>
<!--了Struts 2的工作模式为开发模式 -->
<constant name=”truts.devMode”value=”true” />
</struts>
Struts.properties文件中的属性和属性值是key-value对,其中key对应于Struts 2常量的name属性,而value对应于Struts 2常量的value属性,配置代码如下:

# 设置了Struts 2处于开发模式
Struts.devMode = true
在web.xml文件中配置Struts 2常量,可通过<filter>标签的<init-param>子标签来指定,每个<init-param>标签配置了一个Struts 2常量。下面的代码通过web.xml文件来配置devMode属性。

<filter>
<!-- 配置核心Filter的名字 -->
<filter-name>struts</filter-name>
<!-- 配置核心Filter的类名 -->
<filter-class>org.apache.Struts2.dispatcher.FilterDispatcher</filter-class>
<!—通过init-param元素配置Struts 2常量 -->
<init-param>
<param-name>configProviders</param-name>
<param-value>providers.MyConfigurationProvider</param-value>
</init-param>
</filter>


注意:在实际的开发中,最好不要再struts.properties和web.xml文件中配置常量,而Struts 2推荐在struts.xml中配置常量。


debug,性能优化. ROR


九 校验
十 动态方法与通配符 跳转结果(源文件与重定向) action的匹配顺序
十一 局部转发与异常处理
十二 类型转换
十三 拦截器
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值