Struts2自学笔记
一,类型的转换
1,struts的标签放在struts的jar包下。MATE-INF - struts-tags.tld下的。定义了所有标签的机制。
2,导入标签<@ taglib prefix=”s(可自行定义)”uri=”/strusts-tags”>
当没有报错时,就说明正确了。
3,
这里当使用此标签是它地址默认为action,就不用去写action了,直接写名字就是了,不想form表单中的action要写成login.action。
文本框我们是用
Username 是文本框的名字,客户端处理的参数值。Label是文本框的名字。
相当于我们比较熟悉的username :
密码呢,用
提交用
4,和基本的jsp页面相比,struts2标签是自动换行的。
5,action类继承ActionSupport类,实现了很多接口,验证,等很多功能都可以用了。
有validate方法(验证)等
6, 在struts2中我们可以自动验证错误,不像在struts1中我们还要在jsp页面手动的添加一个error标签才能完成。
《------------------局部类型转换-----------------》。
1,ognl是一种强大的表达式语言。
2,我们继承ognl.DefaultTypeConverter,再重写
context,Object values,Class toType)方法就能实现类型的转换了。
分别代表:Map (应用的上下文) Object(类型转换的值) Class(类型的转换,看你转换成什么类型有两种,1。从字符串到我们自定义类型的转换 2。从自定义类型到String 的转换。它觉定你的转换为什么)
3,Struts2为我们默认提供的转换标志。(com.opensymphony.xwork2 中的action接口) ActionSupport是实现了Action接口了的。所以要用直接继承ActionSupport就可以了。
SUCCESS(表示Action的操作是成功的),INPUT(验证没有成功),NONE(表示Action的操作是成功,但是不显示任何视图),LOGIN(Action没有执行成功,用户不能登录。)ERROR(表示错误)
4,property标签用于输出值栈中的对象的属性值,使用value属性来指定要输出的对象属性,如果没有指定value属性,那么默认输出栈顶对象。自动调用它的get方法
属性如下:
1. default:可选,如果需要输出的属性值为null,则显示的default属性指定的
值
2. escape:可选,指定是否escapeHTML代码
3. value:可选,指定需要输出的属性值。如果没指定,默认输出ValueStack栈
顶的值
4. id:可选,指定该元素的标识
5, 文件名字的定义:转换的时候,在定义文件名字是要转换的属性action,要求属性所在Action+(-conversion.properties),后面是固定的。该文件必须建在和Action是同一包下的。
其中内容包括:你要对哪个属性的进行转换,和用哪个类对它进行转换。
例子:就是对坐标的一个转换。
6,流程: input.jsp页面—>通过struts.xml找到相应的action类。 在到point的set方法时,它通过我们配置的PointAction-conversion.properties自己找到我们为他执行转换的类的方法。这时就要选择PointConventer中的两个if语句看是执行那个语句。一个是从服务器到客户端if(String.class=toType),一个是从客户端到服务器if(Point.class=toType)。
《---------------------全局的类型转换-------------------》
1, 需要类型转换配置文件(名字是xwork-conversion.properties)
2,里面的内容是: 等号左边是你要转换的对像所对应的类的全称。右边是表示我要用这个类去转换我的前面的这个类。
《--------------Struts2的校验------------》
1,主要学习了用户的注册功能对用户的年龄,密码,用户名,出生日期,注册日期。并且要求的是出身日期不能大于我们的注册日期。年龄也有要求,必须在1到150之间。2,主要的实现过程是,我们的日期的判断前后的顺序是用Calender 中的before方法进行比较的。
Calendar ca = Calendar.getInstance();
ca.setTime(this.getDate());
Date d1= ca.getTime();
Calendar c1a = Calendar.getInstance();
c1a.setTime(birthday);
Date d2= c1a.getTime();
if(d1.before(d2)){
this.addFieldError("birthday", "Birthday before date");
}
※如何让我们的错误信息在页面中显示出来呢,要用到struts2的标签。
※现在客户有个要求:要求我们即便是输入错误的信息,返回让我们从新输入时,我原来的信息必须保留。这时应该怎么处理呢???
解决办法:1)用er表达式即可完成。示例:
value=”${requsetScope.age}”>。
2)可以用struts2的标签库。也可以实现此功能。不用写那么多的信息,因为标签库会自动为你保存内容。例子:
和上面就是一样的了。
注意:struts标签显示的错误信息只能显示fielderror里面的信息。不能显示
Actionerror里面的信息。
如果想它显示只有在显示的页面加上
《--------------------校验---------------》
4,遇到内型转换错误时,不能进行转换,struts框架自动生成一条错误信息。并且将错误信息放到 addFiledError里面。那么如何克服内置的错误信息的避免,因为这样客户端是看不懂的。如何避免呢。
在struts.xml里面多加一个属性是为了替代它的内置错误信息
他们分别表示的意思为:name(国际化的资源文件名字 ),value(国际化资源文件),这里的message不用写.properties
《---------------全局类型转换验证--------------------》
Message.properties中写的内容如下:
xwork.default.invalid.fieldvalue={0}error
表示哪个出错,就用哪个取代替。是动态的。这表示一个全局的
在我们的Struts.xml中的相应得配置为:
《---------------局部类型转换-验证-------------------》
1,当全局和局部并存时,局部会替代全局的。
2,要验证的Action的名字+properties
3,内容:invalid.filedvalue.属性名字(age)=…….(内容自定)
invalid.fieldvalue.age=age conversion error liutao
当类型转换错误的时候才出现age conversion error liutao的错误的信息。
类型转换和输入校验的关系:先进行的是类型的转换,然后才是输入校验。校验是建立在类型转换的基础上的。内容和message是不一样的。
在我们的Struts.xml中的相应得配置为:
◆我们的类型转换
1 属性所在Action+(-conversion.properties)和xwork-conversion.properties是一对的,一个是全局的一个是局部的。
◆我们的验证类型转换
2 message.properties和要验证的Action的名字+properties是一对的,一个是全局一个是局部的。
《=========输入校验和类型转换的流程==========》
1,首先struts对客户端传来的信息进行类型转换
2,类型转换完毕后再进行输入校验
3,如果都没有错误的发生,就进入execute方法(调用商业逻辑)
注意:如果类型转换不成功,也同样进入输入校验。
1,如果想不保留struts标签表格的默认形式,就在struts标签里每个都加上theme=””表主题的意思。一般参数写simple.这样我们就能随便的修改格式了。可以把他放在div里面,表格里面。也不再会有struts给他的错误提示。
2,如果你在XXXAction.java类里面定义了多个yxu方法,那么你的验证方法方法名则为ValidateYxu(). 则在struts的配置文件里,加上相应的
3,例子:(在RegisterAction.java中)
public String abc() throws Exception{
System.out.println("abc======");
return SUCCESS;
}
//验证方法
public void validateAbc(){
System.out.println("this validateAbc method!");
}
在(struts.xml中)
在Action类中因为extends了ActionSupport,所以有validate()方法。这时和自定义的validateAbc方法执行的先后顺序是:
先执行validateAbc后再执行validate。所以建议不要用validate,但又由于有execute方法,所以把validate改为validateExecute()方法。这样就避免了validate的无论怎么都要执行的问题。
《=========struts2的校验框架=========》
---------------------(基于xml的表单的输入校验,功能非常的强大)
《====字段校验器====》
1,要校验Action的名字+(-validation.xml),后面一部分都是一样的。
2,里面的内容是:
3,
4,
5,
6,
7,
8,分别得说明:一个
在RegisterAction-validate.xml文件中
xwork/com/opensymphony/xwork2/validator/validators/default.xml的文件中能找到。
short-circuit表示短路。默认为FALSE 当定义为TRUE是。我们的这个校验器不成功是不会执行下一个的。
true//trim表示去掉左右两边的空格.一个
6
10
<
二,S truts2可以进行客户端的校验.
1,form 的(theme)主题一定不能设置为simple。
2,将标签中的form的validate方法设置为true。
3,我们写的RegisterAction-validate.xml既可以作为服务器端的验证又可以做为客户端的验证。
注意:不建议使用struts2给我们提供的客户端校验。因为太死板。
《====非字段校验器====》
1,我们使用非字段校验器(validator)和字段校验器(filed)。
2,两者的区别在于:字段校验时字段优先,(就是我先去校验谁,我用谁来校验)
非字段校验校验器优先(就是我用谁去校验谁)
usernaem
username
6
10
${maxLength}
补充知识:
1,真正存放filed级别的错误的信息是LinkedHashMap.
2,该LinkedHashMap的key是String类型的。Value是ArrayList类型的。
3,对于Action级别的错误信息实际存放在ArrayList里面的。
《==========拦截器(Interceptor)===========》
1,说明:在执行一个放法之前给你添加信息。(它就是一个普通的类,没有什么高级的功能。)和现在的开发模式aop(面向放面编程)很类似,是spring最核心的知识之一。我们通过匹配它的url去用interceptor。它是从webwork中衍生出来的。会拦截程序中所有的Action方法。
3,角色:
1)目标对象;(拦截谁?)
2)拦截对象;(拦截器,就是普通的类)
3)代理对象;是系统自动产生出来的。这是真正去执行的。综合了目标对象,拦截对象的所有方法。
4,作用:实际就是拦截我们的Action。在执行Action之前会执行我们预先处理的代码,再执行我们Action里面相关的方法,在执行完Action之后又会回到我们的拦截器,执行后续的一些操作。相当于入口和出口,把我们的Action方法包在中间了。
5,拦截器的底层代码。在项目的TestStruts中.
6,要使用拦截器,我们要实现Interceptor接口。里面包括destroy(在销毁的时候调用),init(数组初始化的时候调用,只能执行一次,在服务器启动时就能执行。),intercpt (在真正的执行的时候调用,真正处理拦截的一个方法;只要执行目标方法执行一次该方法就要执行一次。)方法。
public String intercept(ActionInvocation arg0) throws Exception { System.out.println("intercept");
String result = arg0.invoke();//invoke方法的作用:判断如果还有下一拦截器就调用下一个拦截器。如果没有就直接跳到execute方法。
return result;
}
7,拦截器很像过滤器。过滤器可以组成过滤器链,拦截器可以组成拦截器栈。在系统启动时就能执行。
8,我们定义interceptor类后再在Struts.xml中配置。
9,这是在声明拦截器;
name="myInterceptor"class="com.test.interceptor.Interceptor">//name是我们intercptor的名字,可以随便起,class是我们的interceptor类的名字。 world//这是在给我们的拦截器添加一个元素,并赋值。并且在拦截器interceptor类中要定义hello的参数。这是第一种定义时,参数配置和赋值方式。可以称为默认的赋值。第二种是在使用时。
引用系统中配置好的拦截器:(为了告诉我们的interceptor是哪个Action引用它)
welcome//这是第二种参数的配置和赋值方式。这是在使用它。可以称为动态的赋值。如果两处都赋了值,那么最后的值会覆盖掉原来的值。
10,如果你手动的在Action里面添加一个拦截器,而他的默认拦截器就不会起作用。就像上面定义了一个
这就是在手动的拦截器。除非你手动的添加默认拦截器。如下:
※如何实现自己定义拦截器栈??关键的是使用
在我们的Struts.xml里面直接定义就可以了。
class="com.test.interceptor.Interceptor"> world
name="myInterceptor">
在我们Action里面的引用
我们用拦截器栈方便了,直接引用拦截器名字,就把它里的拦截器栈和自定义的拦截器一起都引用过来了。
※如何更改我们的默认拦截器??
※以下是在我们的Struts.xml中配置的。
※
※
※位置:在
※我们之前是实现interceptor接口,里面要求我们必须实现destroy init intercept方法。但是我们最常用的是intercept方法,现在想能有什么办法让我们只有intercept方法呢??
解决办法:就是继承AbstractInterceptor.因为它是实现了interceptor的。只是把其他的两个不常用的方法,都实现下来了,并让他们什么都不做。只去完成intercept方法就可以。因此我们大部分都是extends AbstractInterceptor。而不是实现
Interceptor。
注意:我们的Interceptor的执行顺序和我们在xml文件里面配置的顺序是息息相关的。
比如在其中配置了interceptor 再配置 interceptor2那么出来的顺序也是这样的顺序。但是结束的顺序是相反的。(例子:进门和出门的列子。先进1门再进 2 门。出门先出2门再出1门)
《======方法过滤拦截器======》
1,将自动以拦截器继承MethodFilterInterceptor。因为它是继承
AbstractInterceptor;可以细化到拦截到具体哪个方法。
2,该类给我们提供了
3,protected String doIntercept(ActionInvocation arg0) throws Exception {}
4,记住:不要配置到默认的拦截器中去,因为它是具体的拦截哪个方法。应指定在具体的Action的里面。配置方式和一般拦截器是一样的。唯一不样的是要在xml的配置中配
置如下:
test,execute//这句话的意思是拦截器拦截test,execute两个方法。Name中includeMethods 参数是固定的。
//这句话的意思是拦截器不拦截test,execute两个方法。Name中excludeMethods参数是固定的。
注:当includeMethods和excludeMethods方法都存在时,以include为准。
《===============监听器=============》
1,在包com.opensymphony.xwork2.interceptor 下的PreResultListener.java 里面有个方法是
public void beforeResult(ActionInvocation arg0, String arg1) { }
2,它表示是在结果之前进行监听的。
3,在自己定义好监听器(MyResultListener)后,我们还要在拦截器中去注册一个监听器。
注册方法就是
public extends MethodFilterInterceptor {
protected throws Exception {
arg0.addPreResultListener(new MyResultListener());//注册一个监听器。
System.out.println("This is MethodFilterInterceptor");
return arg0.invoke();
}}
4,执行过程是:先注册监听器,进我们的过滤拦截器 ->再调用invoke方法,判断是否还有拦截器。现在我们没有了就进入->Action中的execute方法,在找execute方法之前要调用validate方法对其进行验证。然后才是execute方法的执行。->进入我们的监听程序里面。->又回到我们的拦截器里面。
5,我们的PreResultListener的执行的时机是:在Action的execute方法执行之后,并返回结果后。在用户收到结果之前,执行我们的listener。之后又回到我们的拦截器。
利用拦截器来进行权限的校验???
参考项目,我要完成两个页面。一个login2.jsp和register2。Jsp页面。要求通过login2。Jsp页面才能进入成功页面。而想直接进入register2。Jsp页面就能成功的话,是不可以的,要求被反弹到login2。Jsp页面。
请参考我的项目,TestStruts项目。
《=========文件的上传=========》
1,在执行文件的上传时,我们要在jsp页面配置如下:
2,