1,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一起使用。
2 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并返回,返回结果
3步骤
一 导包
二 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>
4一些常识:
可以有多个包,每个包有一个命名空间
一个包里有多个action,一个action里有多个result
访问action时先以命名空间查找
开发模式的常量设置:将<constant name="struts.devMode" value="false" />中的value值改为true。
.action
不带类名与包名 逐层访问路径 默认 result success 继承extends="struts-default"(为什么呢,后面拦截器会有说明)
包名 命名空间 寻找顺序(最精确匹配)
先找命名空间,如果在该命名空间不存在该action则报错[unknown location]
,当命名空间存在该action时,则可以在该命名空间下后面紧跟其它路径逐层访问 当逐层访问路径与有命名空间冲突时,以有命名空间的为主。
<constant name="struts.action.extension" value="action" />修改后缀名的常量
5 <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标签
6 类名
实现Action与不实现action接口
不extends ActionSupport 重写execute方法
extends ActionSupport 重写execute方法
?传值注意 method=post
表单提交 用 method=post
7 struts2 中 Actionsupport 的作用
(1)实现Action接口 具备5个常量
(2)数据校验,Action接口的基础上还定义了一个validate()方法
(3)国际化
8 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)方法还实现国际化,该方法从资源文件上获取国际化信息.
9从 action属性到页面的传值 bean list bena中bean bean中list list中bean map
action属性必须提供get方法
<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'>
10动态方法
1感叹号定位方法 action名!方法名.action
2 method定位方法 配置多个action
3 通配符匹配法(action中的name class method都支持通配符 result也支持)
action的匹配顺序 先找最精确匹配 当用通配符匹配时 配置在前面的优先匹配
11
全局结果与局部结果 ----- 全局异常与局部异常
<global-results><result name="ggg">/ggg.jsp</result></global-results>
全局结果 所有的action共用 局部结果 自己的action用 当两者重名时,优先选择局部结果
全局异常与局部异常(附件 struts1.x中的异常处理.txt)
<global-exception-mappings>
<exception-mapping result="geror"(此处的geror是指result中的配置(包含局部与全局 ,然后跳转到result中的配置中的jsp页面))
exception="异常类型如java.lang.Exception" >
</exception-mapping>
</global-exception-mappings>
如假设有result中配置<result name="geror">/geror.jsp</result>
则在geror.jsp页面可以使用Struts2的标签来输出异常信息
<s:property value="exception.message"/>
<s:property value="exceptionStack"/>
全局异常 所有的action共用 局部异常 自己的action用 当两者重名时,优先选择局部异常
12类型转换
1 内建类型转换器
常规类型的转换:
比如表单提交的信息有 用户名,生日, 年龄, Action中对应的数据类型分别是 String, Date, int. Struts2会自动完成.
Struts2内建了常用的类型转换器,如String ,boolean,char,int,long,float,double,Date,
数组(假定元素是String类型), 集合(假定元素是String类型,用ArrayList封装)
利用ognl的内建支持
<1>直接把页面属性转换成action中的bean属性,页面属性分开,假设action中bean属性名为user 则如下
<input type=text name="user.username">
<input type=text name="user.password">
在页面输入值后 action中bean属性名为user可以直接拿到值
<2>直接把页面属性转换成action中的集合属性,不需要转换器
map版
第一个用户名:<input type="text" name="action中的集合属性名['one'].name"/>
第一个密码:<input type="text" name="action中的集合属性名['one'].pass"/>
第二个用户名:<input type="text" name="action中的集合属性名['two'].name"/>
第二个密码:<input type="text" name="action中的集合属性名['two'].pass"/>
list或数组版本
第一个用户名:<input type="text" name="action中的集合属性名[0].name"/>
第一个密码:<input type="text" name="action中的集合属性名[0].pass"/>
第二个用户名:<input type="text" name="action中的集合属性名[1].name"/>
第二个密码:<input type="text" name="action中的集合属性名[1].pass"/>
2 自定义
从范围来讲 有局部转换器和全局转换器 从实现的角度而言有基于ognl的转换和基于strut2转换
(1) 写自定义类型转换类
ognl的转换 extends DefaultTypeConverter 重写convertValue方法
举例 把字符串转换成bean对象 bean作为action中的一个属性 bean名为User,action中的bean属性名为user
假设把页面上的用户名和密码,用户名和密码在同一个文本框输入,用,好隔开, 代码如下
public Object convertValue(Map context, Object value, Class toType)
{
if (toType == User.class )
{
String[] params = (String[])value;
User user = new User();
String[] userValues = params[0].split(",");
user.setName(userValues[0]);
user.setPass(userValues[1]);
return user;
}
else if (toType == String.class )
{
User user = (User) value;
return "<" + user.getName() + "," + user.getPass() + ">";
}
return null ;
}
基于struts2的转换 extends StrutsTypeConverter 编写convertFromString与convertToString方法
public Object convertFromString(Map context, String[] values, Class toClass)
{
User user = new User();
String[] userValues = values[0].split(",");
user.setName(userValues[0]);
user.setPass(userValues[1]);
return user;
}
@Override
public String convertToString(Map context, Object o)
{
User user = (User)o;
return "<" + user.getName() + "," + user.getPass() + ">";
}
(2) 配置类型转换(局部配置与全局配置)
局部类型转换器只在本action内有效,全局类型转换器在所有action内有效
如果是配置局部类型转换器,则在与Action类同包目录下建立Action类名-conversion.properties文件,里面配置
action中的bean属性名=包名.转换器类名
如果是配置全局类型转换器,则在src目录下建立xwork-conversion.properties,里面配置
包名.被转换的类名(action中的bean属性类名)=包名.转换器类名
把页面属性转换成action中的集合属性 有2种实现方式
(1 action中集合属性使用泛型指定里面元素类型 2 在局部配置文件配置Element_action中的集合属性名=包名.集合元素里的类名)
页面信息
请输入用户1信息:<input type="text" name="action中的集合属性名"/>
请输入用户2信息:<input type="text" name="action中的集合属性名"/>
3 错误处理
当类型转换出现错误,自动转发到input页面, 在页面用<s:fielderror />显示全部错误
在资源文件修改默认的错误显示信息
xwork.default.invalid.fieldvalue={0}字段类型转换失败!
13 校验
1 继承Actionsupport 重写validate方法
this.addFieldError("username", this.getText("xxx"));
this.addFieldError("username1", "yyy");
在页面用<s:fielderror />显示全部错误
显示某个错误
<s:fielderror>
<s:param value="%{'username1'}" />
</s:fielderror>
2 validateXxx方法
3 strut2的校验流程
4 校验框架
每个Action类有一个校验文件,命名 Action类名-validation.xml,且与Action类同目录,
当校验文件的取名为ActionClassName-validation.xml时,会对 action中的所有处理方法实施输入验证。
如果你只需要对action中的某个action方法实施校验,那么,校验文件的取名应为:ActionClassName-ActionName-validation.xml,
其中ActionName为struts.xml中action的名称。例如:在实际应用中,常有以下配置:
<action name="user_*" class="cn.itcast.action.UserAction" method="{1}“ >
<result name="success">/WEB-INF/page/message.jsp</result>
<result name="input">/WEB-INF/page/addUser.jsp</result>
</action>
UserAction中有以下两个处理方法:
public String add() throws Exception{
....
}
public String update() throws Exception{
....
}
要对add()方法实施验证,校验文件的取名为: UserAction-user_add-validation.xml
要对update()方法实施验证,校验文件的取名为: UserAction-user_update-validation.xml ld>
客户端校验:功能不咋的 不建议使用
1,form的主题(theme)一定不能设定为simple
2,将form的validate属性设置为true
字段校验 字段用什么校验器来校验
非字段校验是用校验器校验什么字段
通俗点讲: 字段校验:校验谁,用什么方法 非字段校验:用什么校验,校验谁
字段校验
举例
内建的校验器在 xwork lib包中 如 xwork-2.0.7\com\opensymphony\xwork2\validator\validators\default.xml 文件中
<?xml version="1.0" encoding="GBK"?>
<!DOCTYPE validators PUBLIC "-//OpenSymphony Group//XWork Validator 1.0.2//EN"
"http://www.opensymphony.com/xwork/xwork-validator-1.0.2.dtd">
<validators>
<field name="name">
<field-validator type="requiredstring">
<param name="trim">true</param>
<message>必须输入名字</message>
</field-validator>
<field-validator type="regex">
<param name="expression"><![CDATA[(\w{4,25})]]></param>
<message>您输入的用户名只能是字母和数组,且长度必须在4到25之间</message>
</field-validator>
</field>
<field name="pass">
<field-validator type="requiredstring">
<param name="trim">true</param>
<message>必须输入密码</message>
</field-validator>
<field-validator type="regex">
<param name="expression"><![CDATA[(\w{4,25})]]></param>
<message>您输入的密码只能是字母和数组,且长度必须在4到25之间</message>
</field-validator>
</field>
<field name="age">
<field-validator type="int">
<param name="min">1</param>
<param name="max">150</param>
<message>年纪必须在1到150之间</message>
</field-validator>
</field>
<field name="birth">
<field-validator type="date">
<param name="min">1900-01-01</param>
<param name="max">2050-02-21</param>
<message>年纪必须在${min}到${max}之间</message>
</field-validator>
</field>
</validators>
非字段校验
<validator type="校验器名称">
<param name="fieldName">需要被检验的字段</param>
<param name="参数名">参数值</param>
<message key="i18nkey">校验错误信息</message>
</validator>
举例
<validators>
<validator type="requiredstring">
<param name="fieldName">name</param>
<param name="trim">true</param>
<message>${getText("name.requried")}</message>
</validator>
<validator type="regex">
<param name="fieldName">name</param>
<param name="trim">true</param>
<param name="expression"><![CDATA[(\w{4,25})]]></param>
<message>${getText("name.regex")}</message>
</validator>
<validator type="requiredstring">
<param name="fieldName">pass</param>
<param name="trim">true</param>
<message>${getText("pass.requried")}</message>
</validator>
<validator type="regex">
<param name="fieldName">pass</param>
<param name="trim">true</param>
<param name="expression"><![CDATA[(\w{4,25})]]></param>
<message>${getText("pass.regex")}</message>
</validator>
<validator type="int">
<param name="fieldName">age</param>
<param name="min">1</param>
<param name="max">150</param>
<message>${getText("age.range")}</message>
</validator>
<validator type="date">
<param name="fieldName">birth</param>
<param name="min">1900-01-01</param>
<param name="max">2050-02-21</param>
<message>${getText("birth.range")}</message>
</validator>
</validators>
校验国际化配置<message key="name.regex"/> 如该种方式出错,则采用${getText("key名")}
向资源文件传递参数 ${getText("key名",{'aa','bb'})}
模型驱动的校验
模型驱动的配置 需要为模型驱动的action中bean提供get方法,当然喜欢加上set方法也可以
配置
<field name="action中bean属性名.name">
<field-validator type="requiredstring">
<message>模型驱动用户的:</message>
</field-validator>
visitor校验 2个校验文件 当属性为javabean时的校验 区别于模型驱动
第一个校验文件 Action类名-validation.xml中的配置如下
<validators>
<field name="action中的bean属性名">
<field-validator type="visitor">
<param name="context">userContext</param>
<param name="appendPrefix">true</param>
<message>用户的:</message>
</field-validator>
</field>
</validators>
jsp页面输入框示例
<input type=text name="action中的bean属性名.bean中的属性"> 如
<input type=text name="user.name">
第2个校验文件 bean类名-第一个校验文件context参数值-validation.xml 如User-userContext-validation.xml,
该文件中就可以写校验bean中的属性,如同前面的校验
14访问 servletapi
1. 非IoC方式
要获得上述对象,关键Struts 2.0中com.opensymphony.xwork2.ActionContext类。我们可以通过它的静态方法getContext()获取当前Action的上下文对象。
另外,org.apache.struts2.ServletActionContext作为辅助类(Helper Class),可以帮助您快捷地获得这几个对象。
HttpServletRequest request = ServletActionContext.getRequest();
HttpServletResponse response = ServletActionContext.getResponse();
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;
}
15 struts2 中的ognl 以及标签语法
两个栈 第一个是值栈ognl上下文(value stack) 第2个是ActionContext 栈 访问里面的数据ActionContext 栈通过前面加上 #号实现
Struts 2中的表达式语言
Struts 2支持以下几种表达式语言:
1. OGNL(Object-Graph Navigation Language),可以方便地操作对象属性的开源表达式语言;
2. JSTL(JSP Standard Tag Library),JSP 2.0集成的标准的表达式语言;
3. Groovy,基于Java平台的动态语言,它具有时下比较流行的动态语言(如Python、Ruby和Smarttalk等)的一些起特性;
4. Velocity,严格来说不是表达式语言,它是一种基于Java的模板匹配引擎,具说其性能要比JSP好。
Struts 2默认的表达式语言是OGNL,原因是它相对其它表达式语言具有下面几大优势:
1. 支持对象方法调用,如xxx.doSomeSpecial();
2. 支持类静态的方法调用和值访问,表达式的格式为@[类全名(包括包路径)]@[方法名 | 值名],例如:@java.lang.String@format('foo %s', 'bar')或@tutorial.MyConstant@APP_NAME;
3. 支持赋值操作和表达式串联,如price=100, discount=0.8, calculatePrice(),这个表达式会返回80;
4. 访问OGNL上下文(OGNL context)和ActionContext;
5. 操作集合对象。
“#”主要有三种用途:
1. 访问OGNL上下文和Action上下文,#相当于ActionContext.getContext();下面有几个ActionContext中有用的属性:
parameters
包含当前HTTP请求参数的Map
#parameters.id[0]作用相当于request.getParameter("id")
request
包含当前HttpServletRequest的属性(attribute)的Map
#request.userName相当于request.getAttribute("userName")
session
包含当前HttpSession的属性(attribute)的Map
#session.userName相当于session.getAttribute("userName")
application
包含当前应用的ServletContext的属性(attribute)的Map
#application.userName相当于application.getAttribute("userName")
attr
用于按request > session > application顺序访问其属性(attribute)
#attr.userName相当于按顺序在以上三个范围(scope)内读取userName属性,直到找到为止
2. 用于过滤和投影(projecting)集合,如books.{?#this.price<100};
<s:iterator value="books.{?#this.price > 35}">
<li><s:property value="title" /> - $<s:property value="price" /></li>
</s:iterator>
<s:property value="books.{?#this.title=='Code Complete, Second Edition'}.{price}[0]"/>
问题:?#this的多个判断问题 &&
3. 构造Map,如#{'foo1':'bar1', 'foo2':'bar2'}。 之前讲过
%的特性 计算表达式 类似javascript中的eval函数 可用s:url举例说明%用法
“%”符号的用途是在标志的属性为字符串类型时,计算OGNL表达式的值
<s:textfield key="state.label" name="state" value="%{'CA'}" />
计算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}"/>
表示式语言符号
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'}" />
$”有两个主要的用途
1. 用于在国际化资源文件中,引用OGNL表达式,参考前面的国际化校验配置
2. 在Struts 2配置文件中,引用OGNL表达式,如
<action name="AddPhoto" class="addPhoto">
<interceptor-ref name="fileUploadStack" />
<result type="redirect">ListPhotos.action?albumId=${albumId}</result>
</action>
16拦截器
拦截器,用于在某个方法或字段被访问之前,进行拦截然后在之前或之后加入某些操作。
拦截器是AOP(Aspect-Oriented Programming 面向方面编程)中的一种实现策略。
1 用代理模式与动态代理编写拦截器
所谓Dynamic Proxy是这样一种class:它是在运行时生成的class,在生成它时你必须提供一组interface给它,
然后该class就宣称它实现了这些interface。你当然可以把该class的实例当作这些interface中的任何一个来用。
当然啦,这个Dynamic Proxy其实就是一个Proxy,它不会替你作实质性的工作,
在生成它的实例时你必须提供一个handler,由它接管实际的工作
那么如何实现动态代理呢
1 写一个动态代理,implements InvocationHandler接口,实现方法
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
method.invoke(sub,args);
return null;
}
2 调用 ,
真实实现类名 xxx = new 真实实现类名(); // 在这里指定被代理类
InvocationHandler ds = new DynamicSubject(xxx); // 初始化代理类
接口 接口变量= (接口) Proxy.newProxyInstance(xxx.getClass().getClassLoader(), xxx.getClass().getInterfaces(), ds);
接口变量.方法
/**
* 从以上可以看出,动态代理可以任意指定被代理的类,即真实对象类,而代理模式则无法实现该功能,
* 因为他把真实对象的写死在代理类里,如果要按照上述的方法使用代理模式,那么真实角色必须是事先已经存在的,并将其作为代理对象的内部属性。但是
* 实际使用时,一个真实角色或其接口必须对应一个代理角色,如果大量使用会导致类的急剧膨胀
*/
2 struts2拦截器
解压strut2的核心包,根目录下struts-default.xml中有struts2的拦截器配置
拦截器几乎完成了Struts2框架70%的工作,包括解析请求参数、将请求参数赋值给Action属性、执行数据校验、
文件上传……,Struts2设计的灵巧性,更大程度地得益于拦截器设计,当需要扩展Struts2功能时,只需要提供对应拦截器,
并将它配置在Struts2容器中即可;如果不需要该功能时,也只需要取消该拦截器的配置即可。
这种可插拔式的设计,正是软件设计领域一直孜孜以求的目标。
实际上,Struts2的精髓就在于拦截器,掌握了Struts2的拦截器机制,你就可以说精通了Struts2。
从某个角度来看,我们可以把Struts2框架理解成一个空壳,而这些拦截器像一个一个抽屉,随时可以
插进入,也可以拔出来——这是软件产品一直追求的目标。
如果你喜欢,你可以把Struts2的全部插件拔出,那么Struts2就成了一个空容器——
而这种空,正是 Struts2的魅力,你可以把任何自己想要的东西填入进去,甚至包括自己完全实现这个框架。
另一方面,因为Struts2的插件机制,Struts2提供了无限扩展的可能性,你可以把自己想要的任何
东西做成插件,然后填入Struts2——这样的结果是:一个企业,一个团队,可以把自己业务相关的东西
做成插件,随时随地地复用。
也就是说:如果你想要,你可以把Struts2改造成属于自己的框架。
当然,Struts2也内建了大量的拦截器,这些拦截器以name-class对的形式配置在struts-default. xml文件中,其中name是拦截器的名字,就是以后使用该拦截器的唯一标识;class则指定了该拦截器的实现类,如果我们定义的package继承了Struts2的默认struts-default包,则可以自由使用下面定义的拦截器,否则必须自己定义这些拦截器。
3 自定义拦截器
(1)编写拦截器类,继承AbstractInterceptor类 重写intercept(ActionInvocation arg0)方法
调用用参数类ActionInvocation的invoke方法,即 String result= arg0.invoke(); 返回该result=
invoke就是回调使用了该拦截器的action得相应方法,此时可在该方法执行前后加入我们想要的代码,达到我们拦截action的目的
利用 arg0.getAction()方法还可以得到拦截器拦截的action实例
public String intercept(ActionInvocation arg0) throws Exception {
// LoginAction loginaction=LoginAction(arg0.getAction());
System.out.println("执行ction之前");
String result= arg0.invoke();
System.out.println("执行ction之后");
return result;
}
、(2)在struts.xml配置拦截器
<package name="default" extends="struts-default" namespace="/">
<!--配置拦截器 -->
<interceptors>
<interceptor name="拦截器名" class="包名.拦截器类名">
<!--设置拦截器类属性值,如没有则不用设置 -->
<param name="拦截器类属性名">属性值</param>
</interceptor>
</interceptors>
<action name="login" class="com.LoginAction" >
<result name="success">/welcome.jsp</result>
<result name="error">/error.jsp</result>
<interceptor-ref name="defaultStack"></interceptor-ref>
<!--使用拦截器 -->
<interceptor-ref name="拦截器名"></interceptor-ref>
</action>
</package>
多个拦截器在一起组成一个拦截器栈
<interceptor-stack name="拦截器栈">
<interceptor-ref name="拦截器名1"/>
<interceptor-ref name="拦截器名2"/>
<interceptor-ref name="拦截器名3"/>
</interceptor-stack>
使用拦截器栈 与 使用拦截器一样语法
当配置一个包时,可以为其指定默认的拦截器,每个包只能有一个默认的拦截器,一旦为某个包指定了默认的拦截器,
如果该包中的action没有指定
自己的拦截器,则action使用包指定的默认拦截器,但是一旦为action指定了自己拦截器,
则包的默认拦截器将会失效,如果还想
使用包的默认拦截器,则必须显示的指定,我们的包继承另一个包时,也继承了另一个包的默认拦截器,
当然我们可以定义自己包的默认拦截器覆盖之
从这里可以解释为什么我们刚刚开始学struts2的时候老是extends="struts-default"
因为struts-default包中的默认拦截器是个好东东
配置默认拦截器 在 包package中 <default-interceptor-ref name="拦截器名或拦截器栈"></default-interceptor-ref> 放后面
上面拦截器会拦截action中的所有方法 要想拦截某个方法怎么办 拦截指定方法
编写拦截器类,extends MethodFilterInterceptor MethodFilterInterceptor是AbstractInterceptor的子类
重写doIntercept方法
public String doIntercept(ActionInvocation invocation)
throws Exception
{
// LoginAction loginaction=LoginAction(arg0.getAction());
System.out.println("执行action方法之前");
String result= arg0.invoke();
System.out.println("执行action方法之后");
return result;
}
使用配置指定拦截的方法
<!-- 拦截器一般配置在result元素之后! -->
<interceptor-ref name="拦截器名1">
<param name="excludeMethods">execute,haha</param> <!-- 不拦截! -->
<param name="includeMethods">execute</param> <!-- 拦截! -->
</interceptor-ref>
可以重复使用一个拦截器,拦截器的执行顺序是在方法执行前,先配先执行,在方法执行后,后配先执行
拦截结果的监听 是在action结束后,返回result之前的一个监听器,可以在该监听器里写我们的代码,以便在返回结果前执行,
这个监听器通过手动注册在拦截器内部的
监听器示例代码 implements PreResultListener
public class MyPreResultListener implements PreResultListener
{
public void beforeResult(ActionInvocation invocation,String resultCode)
{
System.out.println("返回的逻辑视图为:" + resultCode);
}
}
拦截器示例代码
public class BeforeResultInterceptor extends AbstractInterceptor
{
public String intercept(ActionInvocation invocation) throws Exception
{
invocation.addPreResultListener(new MyPreResultListener()); //注册监听器
System.out.println("execute方法执行之前的拦截...");
String result = invocation.invoke();
System.out.println("execute方法执行之后的拦截......");
return result;
}
}
监听器代码在action结束后,返回结果前执行,和在action结束后在拦截器内部写的代码相比, 监听器代码把action结束后的代码
放到监听器似乎更精确和清晰些
给拦截器栈传递参数时会出现一个问题,当拦截器栈中拦截器类中的属性名相同时,不知道这个参数到底要传给那个拦截器,为了
解决这个问题,可作如下配置
<interceptor-ref name="拦截器栈名">
<param name="拦截器名(不是类名,注意哦).属性名">属性值</param>
</interceptor-ref>
17 struts2的四个主题
simple,xhtml(默认主题),css_xhtml和ajax,这4个主题的模板文件放在Struts2的核心类库里(struts2-core.jar包)。template目录下
也可以自定义自己的主题,建议继承它的已有主题
simple主题是最简单的主题,它是最底层的结构,主要用于构建附加的功能或者行为(例如在此主题基础上进行扩展),
使用simple主题时,每个UI标签只生成一个简单的HTML元素,不会生成其他额外的内容。
Struts2的xhtml, css_xhtml主题都是对simple主题的包装和扩展。
xhtml主题是Struts2的默认主题,它对simple主题进行扩展,在该主题的基础上增加了如下附加的特性:
1,针对HTML标签(如textfield和select标签)使用标准的两列表格布局。
2,每个HTML标签的Label,即可以出现在HTML元素的左边,也可以出现在上边,这取决于labelposition属性的设置。
3,自动输出校验错误信息。
4,输出JavaScript的客户端校验。
css_xhtml主题则对原有的xhtml主题进行了扩展,在xhtml主题基础上加入了CSS样式控制。
ajax主题目对xhtml主题目进行了扩展,在xhtml主题上为每个标签提供了额外的Ajax支持。
ajax主题的Ajax支持是以Dojo和DWR为基础的。ajax主题在xhtml主题基础上增加了如下特性:
1,支持Ajax方式的客户端校验。
2,支持远程表单的异步提交(最好和submit标签一起使用)。
3,提供高级的div标签,允许实现局部更新部分HTML的功能。
4,提供高级的a标签,允许动态加载并执行远端的javaScript代码。
5,提供支持ajax的tabbedPanel。
6,提供"富客户端"模型的pub-sub事件模型。
5,Struts2的表单标签
18零配置
零配置 约定大于配置原则 使用注解编程替代xml配置 首先要澄清一点,这里说的零配置并不是一点配置都没有,只是说配置很少而已
2.0的零配置
web.xml配置加载的action所在的包名,在过滤器中作如下修改
<filter>
<filter-name>struts2</filter-name>
<filter-class>org.apache.struts2.dispatcher.FilterDispatcher</filter-class>
<init-param>
<param-name>actionPackages</param-name>
<param-value>com</param-value>
</init-param>
</filter>
表名要加载com包下的aciton 命名空间默认为"/"
在action类中配置
@Namespace("/aaa")
@Results({
@Result(name="success", type=NullResult.class, value="/success.jsp")
})
例如
@Results({
@Result(name="success",type=NullResult.class,value="/xxx.jsp")
})
public class Test extends ActionSupport {
public String execute() throws Exception {
return super.execute();
}
直接访问http://localhost:8080/struts20zero/类名(首字母小写).action
当类名以Action结尾时候,则Action可以省略
如类名XxxAction,则访问 直接访问http://localhost:8080/struts20zero/xxx.action
如果有Xxx类的action。如果实在同一命名空间下,前面的应该会得到匹配
如果是早不同的包名下,则与包名的字母排列顺序有关,后面的一半会执行
19Convention Plugin插件
包命名习惯来指定Action位置
" 命名习惯制定结果(支持JSP,FreeMarker等)路径
" 类名到URL的约定转换
" 包名到命名空间(namespace)的约定转换
"
遵循SEO规范
分享到:
相关推荐
Struts2 知识点 Struts2 是一个基于 Java 语言的开源 Web 应用程序框架,由 Apache 软件基金会维护。Struts2 是 Struts1 的改进版本,提供了更加灵活和强大的功能。下面是 Struts2 的一些重要知识点: 1. Struts2 ...
以下是对Struts2知识点的详细总结: 1. **Struts2核心组件** - **FilterDispatcher**(或现在的`StrutsPrepareAndExecuteFilter`):这是Struts2的核心过滤器,它负责拦截请求,处理Action映射,并转发到相应的...
### Struts2知识点详解 #### 一、Struts2框架概览 Struts2是Apache组织推出的一个基于Java EE的Web应用框架,它遵循MVC(Model-View-Controller)设计模式,为开发者提供了构建可扩展、易于维护的Web应用程序的...
这个"Struts2知识点详解"涵盖了从基础到高级的所有核心概念,旨在帮助开发者深入理解并熟练运用Struts2。 1. **Struts2框架结构**:Struts2的核心是Action类,它是处理用户请求的中心。通过Action类,开发者可以...
### Struts2 学习重点知识点总结 #### 一、Struts2 概念与架构 **1.1 Struts2 简介** - **定义**:Struts2 是 Apache 组织提供的一个基于 MVC 架构模式的开源 Web 应用框架。 - **核心**:Struts2 的核心其实是 ...
以下是对压缩包中文件所涵盖的Struts2知识点的详细说明: 《Struts2标签库详解.doc》: 该文档可能详细介绍了Struts2提供的各种内置标签库,如s:form、s:textfield、s:textarea、s:submit等,这些都是在JSP页面中...
**Struts2知识点:** 1. **Action类**:实现了Struts2的Action接口,处理用户的请求,执行业务逻辑。 2. **配置文件**:`struts.xml`是Struts2的配置文件,定义了Action的映射、拦截器链等。 3. **结果类型**:...
### Struts2自学文档知识点详解 #### 一、Struts2简介 Struts2是一个用于构建企业级Java Web应用程序的开源框架。它基于MVC(Model-View-Controller)架构模式,提供了一种灵活的方式来组织代码,使得业务逻辑、...
**Struts2知识点:** Struts2是Apache软件基金会的产品,它是Struts1的升级版,提供了更灵活的架构和更好的插件支持。Struts2的核心是拦截器模型,通过拦截器链实现了业务逻辑和表现层的分离。Action类是Struts2的...
### Struts2 知识点概览 #### Struts2 概述与来历 - **Struts2**是由Apache组织维护的一款开源MVC框架,主要应用于Java Web开发领域。其定位仅作为表现层(MVC)框架,专注于处理前端用户交互逻辑。 - **Struts1**...
struts知识点总结struts知识点总结,觉得有需要的就拿去看看吧
【FreeMarker + Struts2 知识点详解】 FreeMarker 和 Struts2 是两种常见的 Java Web 开发技术,它们在构建 MVC(Model-View-Controller)架构的应用程序中发挥着关键作用。 **FreeMarker 知识点:** 1. **...
以下是对Struts2知识点的详细解释: 一、Struts2入门及基本配置 要开始使用Struts2,首先需要配置开发环境,包括JDK、Tomcat服务器和IDE,如MyEclipse。Struts2的依赖库包括Apache Commons Logging、FreeMarker、...
Xmind文件《struts2 in action.xmind》可能是作者或读者为整理Struts2知识点创建的思维导图,可能包含框架的主要概念、重要类库、关键配置元素以及学习路径等。这样的思维导图可以帮助学习者更直观地理解和记忆...
Struts2是一个流行的Java web开发框架,主要用于构建MVC(模型-视图-控制器)架构的应用程序。它的设计目标是简化开发过程,提供强大的验证和国际化功能,以及灵活的插件架构。Struts2的核心是基于拦截器的Action...
**JavaEE + Struts2 知识点详解** JavaEE(Java Platform, Enterprise Edition)是Java平台的一个版本,主要用于开发和部署企业级应用程序。它包含了众多的组件和服务,如Servlet、JSP、EJB(Enterprise JavaBeans...
**Struts2知识点** 1. **Struts2框架概述**:Struts2是Apache软件基金会的开源项目,它基于MVC模式,提供了处理HTTP请求、控制业务逻辑和展示视图的能力。 2. **Action类与结果映射**:Struts2的核心是Action类,...
在介绍Struts2时,我们需要了解以下几个关键知识点: 1. **MVC模式**:MVC是一种将业务逻辑、数据和用户界面分离的设计模式,Struts2作为表现层框架,主要处理控制器(Controller)部分。 2. **Web应用的三层结构**...