struts2 笔记

文档 --> google --> 老师
读书方法:记最常用的。 不常用的脑子里留印象,用到的时候再去查。不要在那边每个知识点来回扣。90%的书溜一遍,90%的书是用来查的(书是用来查的,不是用来扣的)。扣的书比如:数据结构,设计模式。
学了各种各样的方法,参加工作以后只要找到一种方法能解决它就行了,千万不要老钻牛角尖非要把那种特殊的方法研究出来。
请大家不要去研究现在用不上对现在没有意义的东西,不要把你的精力放在将来才会用到的东西上,永远把你的精力用在java right now。
不要用当前的时间去做以后的事,人没有这么多精力,也不一定记得住。因为你还没学会走呢,就逼着你去跑,你还没学会用呢,就逼着你去读源码。
一定要多多地关注在业务这个方面,而技术这方面要多多地学它的原理,弄明白原理,拿来用(除了业务方面,其他的全是copy改),原理在很多方面是相通的。

struts2核心:将请求与视图分开了。
让myeclipse在写struts时自动提示:打开preferences搜索catalog 打开xml子项中的 xml.catalog增加dtd文件
让struts开发者模式:sttuts.xml增加<constant name="struts.devMode" value="true" />
让myeclipse增加java文件的api关联,右键 properties编辑java source attachment
让myeclipse增加classs文件的反编译文件,右键 properties编辑resource
设置Java Source Attachment:struts2源码目录:struts2根目录/src/core/src/main/java/
设置Javadoc Location:URL:struts2根目录/doc/strut2-core/apidoc
namespace:默认为空
一个url路径要是里面没有对应的<action>的name属性时,它会去上层目录的namespace里找<action>
每个action不要和不同<package>里面的<action>相冲突,
action:
定义:只要是一个普通的class类,类中包含execute()方法,并且返回值为String时,这个类就可以被strut2当成action
也可以是implements Action,是要实现String execute()
也可以是extends ActionSupport。(只用这一种),封装了各种常用的方法,可以直接拿来使用。
struts2每次访问必定new一个,strut1每次访问用的同一个
如果不定义,默认new ActionSupport的一个实例,默认返回success。

具体视图的返回可以由用户自己定义的Action来决定。
具体的手段是根据返回的字符串找到对应的配置项,来决定视图的内容
具体Action的实现可以是一个普通的java类,里面有public String execute方法即可或者实现Action接口,不过最常用的是ActionSupport继承,好处在于可以直接使用Strut2封装好的方法

发来的请求首先交给struts.xml处理,如果没有在struts.xml里找到对应请求的namespace,则交给web.xml处理

struts2中的路径问题是根据action的路径,即浏览器上显示的action的上下文路径。而不是jsp路径来确定,所以尽量不要使用相对路径,使用绝对路径
虽然可以使用redirect方式解决,但redirect方式并非必要,不要使用它。
解决办法非常简单,统一使用绝对路径(在jsp中用request.getContextRoot方式来拿到webapp的路径)或者使用myeclipse经常用的,指定basePath

Action执行的时候并不一定要执行execute方法
可以在配置文件中配置Action的时候用method=来指定执行哪个方法(可以忘了),也可以在url地址中动态指定(动态方法调用DMI(使用!调用需要使用的方法))(推荐),前者会产生太多的action,所以不推荐

使用通配符,将配置降到最低
*_* * {1} {2}...
不过,一定要遵守“约定优于配置”原则
只要包括(*)都是同一等级,哪个配置放前面调哪个,完全匹配高于带(*)的匹配

接受参数:
1 在action中定义成员变量,写上对应的getXxx(),和setXxx()方法,即可使用参数
2 也可以使用域模型的概念(类似于javabean),只需要在域模型类中定义好接受参数成员变量的get/set方法,即可在action使用这个域模型的参数。(当然这个域模型成员变量(不用初始化new)和相应的get/set方法还需定义),url传递时也要使用对应的域模型对象进行设置,如:http://localhost:8080/BBS/action?user.setName("")
参数传递过来的参数与后面的DomainModel 匹配不上,这时可以使用两种方式,1属性接收过来再给DomainModel。2用DTO接受参数然后 在action相应方法处理完了后(前台参数与DTO模型匹配,比如密码确认) 把DTO对象中取出参数的值再填充给DomainModel。
3 url传递参数时,不用使用域模型对象。可以直接用 属性=值 的方式传递。action只需implements ModelDriven<域模型类>接口,域模型成员变量需要初始化才行。实现一个方法public 域模型类 getModel(){return 域模型类成员变量}
中文问题:传递中文参数时,在struts.xml配置文件中加上:<constant name="struts.i18n.encoding" value="GBK" />

数据校验:
使用addFieldError方法(action)和s:fieldError标签(jsp)简单处理数据校验
在action中:
校验:有错误则:this.addFieldError("name","name is error!");
在jsp中:
<%@taglib uri="/struts-tags" prefix="s" %>
<s:fielderror fieldName="name" theme="simple"/>
<s:property value="error.name[0]"/>//从值栈取值
<s:property value="#parameters.t" />//从ActionContext中取值,用#运算符
<s:debug></s:debug>//打印值栈(保存Action的所有属性)和ActionContext(保存Action的上下文环境)的内容

取得(Map类型):request,session,application,(真实类型):HttpServletRequest,HttpSession,HttpContext的引用:
1前三者:依赖于容器
2前三者:IOC
3后三者:依赖于容器
4后三者:IOC
第一种方式(依赖于容器):
在action中定义和初始化:
如:private Map request;//在action中定义Map类型的变量
private Map session;
private Map application;

public Action名字(){ //可以在构造方法里取值或者在execute()方法里取值。
request=(Map)ActionContext.getContext().get("request");//ActionContext即action的上下文环境。
session=ActionContext.getContext().getSession();
application=ActionContext.getContext().getApplication();
}
存入属性值:(在action中的execute())
如:request.put("r1","r1");
session.put("s1","s1");
application.put("a1","a1");
在视图jsp中获取属性值:
<s:property value="#request.r1"/>|<%=request.getAttribute("r1")%>
第二种方式(常用,IOC)(主要使用这种方式中的session,其他方式基本不用):
需要implements RequestAware,SessionAware,applicationAware接口
在action中定义相应变量:
private Map<String,Object> request;
private Map<String,Object> session;
private Map<String,Object> application;
写上实现接口的方法:
public void setRequest(Map<String,Object>,request) {
this.request = request;
}
第三种方式(依赖于容器):
定义:
private HttpServletRequest request;
private HttpSession session;
private ServletContext application;
构造方法:
public action类(){
request = ServletActionContext.getRequest();
session = request.getSession();
application = session.getServletContext();
}
设置属性:request.setAttribute("r1","r1");
第四种方式:(IOC)
实现接口:implements ServletRequestAware
定义:
private HttpServletRequest request;
private HttpSession session;
private ServletContext application;
实现方法:
public void setServletRequest(HttpServletRequest request){
this.request = request;
this.session = request.getSession();
this.application = session.getServletContext();
}

包含配置文件:
在struts.xml文件中的<struts>标签中加入:<include file="login.xml">,login.xml同struts.xml,为了分模块

默认action(慎用):
写在<package>标签里面<default-action-ref name="index"></default-action-ref>//如果在对应namespace找不到匹配的<action>,则交由默认<action>处理。
注意:默认action只返回对应的<result>页面,并不执行相应的action类.


总结:将来开发主要就是:action类从ActionSupport继承,按照约定写好自己的各种方法add,delete...写完之后用DomainModel接受参数,如果需要访问Session,用IOC访问。


result
类型:
配置<action>时,指定其子元素<result>的type属性。(掌握前四种,重点是上面两种)
dispatcher:服务器跳转,同forward(),只能跳转非action的视图页面(默认)
redirect:客户端跳转到一个视图页面
chain:forward到一个action
redirectAction:重定向到一个action
freemarker
httpheader:http头信息
stream:下载
velocity:干不过freemarker
xslt:和xml相关
plaintext:将页面的源码显示出来,用于教学
tiles:

全局Result:
如果同一个<package>中的多个<action>共用一个结果,可以将它配置为共用结果。
配置在<package>子元素下:<global-results>
<result name="mainpage">/mainpage.jsp </result>
<global-results>
如果不同的<package>想用,用<package>的extends属性继承一个包。

动态结果集:
在<result>元素下可以使用${值栈中的名值对}这种方式去读取值栈中的内容(对于action它的任何一个属性都会放在值栈里面)。了解即可,用的并不多
在action中可以用一个属性来保存一个具体结果(视图)的location,这个属性里面的结果可以由我们动态确定,在struts.xml用${}这种表达式访问属性
一次request只有一个值栈,forward过程分享同一个值栈,redirect使用不同值栈,所以redirect要使用url?新参数名=${action属性名}

OGNL表达式:
OGNL:Object Graph Navigation Language
访问值栈中的action的普通属性:<s:property value="username" /> //value="username"这部分内容是OGNL表达式。
访问值栈中对象的普通属性(get set方法):<s:property value="user.age" />
url?user.age=9:只有url传递参数才会构造,或者手动new。如果Domain Model在action里没有手动new初始化,那么你想让struts2为你自己new出来的时候,你必须要给domain Model传值,而且你的domain Model必须有一个参数为空的构造方法,不然它不知道调用哪一个构造方法。
想初始化domain model,可以自己new,也可以传递参数值,但这时候需要保持参数为空的构造方法。
如果想访问对象的对象,只需要使用(.)操作符一层一层深入即可。
访问值栈中对象的普通方法:<s:property value="password.length()"/> //password为action的一个String属性,所以可以调用String的相关方法。也可以调用自定义对象的方法。
访问值栈中action的普通方法:<s:property value="m()" /> //访问action的普通方法,即定义在action的普通方法。
访问静态方法:<s:property value="@com.gmail.yangunilay.xxxAction@xxx()" /> //前面@跟类名,后面@跟静态方法名
需要在struts.xml中在struts中配置:<constant name="struts.ognl.allowStaticMethodAccess" value="true"></constant>
访问静态属性:<s:property value="@com.gmail.yangunilay.xxxAction@STR"/>//前面@跟类名,后面@跟静态属性名
访问Math类的静态方法:<s:property value="@@max(2,3)" /> //@@只能访问Math类的静态方法。
访问普通类的构造方法:<s:property value="new com.bjsxt.struts2.orgl.User(8)"/>//可以在value里面new对象
数组的访问方式和List一模一样
访问List:<s:property value="users" />//只需用对应的List对象即可
访问List中的某个元素:<s:property value="users[1]" />
访问List中元素某个属性的集合:<s:property value="users.{age}" />//把users这个List中每个元素拿出来,然后把每个元素对象的age属性组合在一起成为一个新的 集合。
访问List中元素某个属性的集合的特定值:<s:property value="users.{age}[0]"/>|<s:property value="users[0].age"/>
访问Set和访问List一模一样,有一点不同:不能访问set的下标值,因为它是无序的。
访问Map:<s:property value="dogMap" />
访问Map中的某个元素:<s:property value="dogMap.key" /> |<s:property value="dogMap['dog101']"/>|<s:property value="dogMap[\"dog101\"]" />
访问Map中所有的key:<s:property value="dogMap.keys" />
访问Map中的所有value:<s:property value="dogMap.values" />
访问容器的大小:<s:property value="dogMap.size()" /> |<s:property value="dogMap.size"/>
投影(用正则表达式过滤):<s:property value="usesrs.{?#this.age==1}[0]" />//用?#开头表示是过滤条件
投影:<s:property value="users.{^#this.age>1}.{age}" />
投影:<s:property value="users.{$#this.age>1}.{age}" />
投影:<s:property value="users.{$#this.age>1}.{age} == null" />
用[]访问元素:<s:property value="[0]" /> //访问值栈对象
什么时候在stack中会有两个Acton? chain
其他参考orgl.jsp

$:
用于i18n(99%不用,除非你的网站面向国际化)或struts.xml配置文件里面来代表一个OGNL表达式
struts.xml中应用OGNL表达式,在Resource.properties中放置将要在struts.xml引用的字段的值,然后在struts.xml中使用${}进行引用
#:
取得ActionContext的值,
#parameters,代表request提交的所有参数,#parameters.id返回的是String[]类型,相当于JSP中的request.getParameterValues("id");一般使用#parameters.id[0]
#request,代表request里的所有属性,#request.account相当于JSP中的request.getAttribute("account")
#session,代表session里的所有参数,#session.account相当于JSP中的session.getAttribute("account")
#application,代表ServletContext里的所有属性,#application.account相当于JSP中的application.getAttribute("account")
#attr,代表request或session或application的所有属性,#attr.account相当于EL表达式中的${account}依次查找request,session,application的属性,找到为止。
用于过滤或帅选集合:
<struts:property value="magazineList.{?#this.name.contains('时代')}.size()"/>
构造Map:
如:#{'foo1':'bar1','foo2':'bar2'}
%:将原本的文本属性解析为ognl,对于本来就是ognl属性不起作用。%{ }:把大括号里面的内容强制转换成OGNL表达式。

Struts标签:
1通用标签:
property:
输出变量值
取值为字符串:<s:property value="'username'" />
设定默认值:<s:property value="admin" default="管理员" /> //如果有一个值取不到,则使用这里设定的默认值。
设定HTML:<s:property value="'<hr/>'" escape="false" /> //escape如果为false,则它就把它当成是一个html
set(换名后放入ActionContext):
设定adminName的值(默认为request和ActionContext):<s:set var="adminName" value="username" />//它会把adminName这个变量放在request和ActionContext里面
从request取值:<s:property value="#request.adminName" />
从ActionContext取值:<s:property value="#adminName" />
设定范围:<s:set name="adminPassword" value="password" scope="page" />//scope属性设定有效的范围
从相应的范围取值:<%=pageContext.getAttribute("adminPassword") %>
设定var,默认范围为action(即request和ActionContext都有),如果设定scope,则就放在对应的scope范围内,ActionContext则没有了。
使用#取值:<s:property value="#adminPassword" />
从相应范围取值:<s:property value="#session.adminPassword" />
bean(实例化一个bean类):
在开始时它会new一个对象放在value stack contents里面,在结束时候它会把这个对象从value stack contents(栈)里拿出来,放入Stack Context(ActionContext)里面,名字为var设置的值。
定义bean,并使用param来设定新的属性值
<s:bean name="com.bjsxt.struts2.tags.Dog" var="myDog">
<s:param name="name" value="'oudy'"><s:param>//通过setter方法将字符串set到name属性上
<s:property value="sex"/>会调用sex属性的getter方法输出属性的值
<s:bean>
include
可以用jsp包含代替,最好不要用,对中文支持有问题。
<s:include value="/_include1.html"><s:include> //包含文件用 _ 开头。
fielderror
在execute() 方法内增加:this.addFieldError("fielderror.test","wrong!"); return ERROR;
就可以在对应的错误页面:<s:fielderror fieldName="fielderror.test" theme="simple"></s:fielderror>
action
用于访问某个acion,并将结果包含进来,相当于JSP中的include,ignoreContextParams表示是否将本页面的参数传递给被调用的Action
date
格式化日期时间输出,属性format设置日期时间格式字符串,如yyyy-MM-DD HH:mm:ss
param
传递参数
2控制标签:
if:具有test属性进行判断
<s:if test="#parameters.age[0] < 0">wrong age!</s:if>
<s:elseif test="#parameters.age[0] <20">too young!</s:elseif>
<s:else>yeah!</s:else>
iterator:可以使用OGNL对数据进行过滤
可以遍历:collections map enumeration iterator array
遍历集合:
<s:iterator value="{1,2,3}">
<s:property /> //打印集合中的每个元素
</s:iterator>
自定义变量:
<s:iterator value="{'aaa','bbb','ccc'}" var="x">
<s:property value="#x.toUpperCase()" /> //x指循环变量
</s:iterator>
使用status
<s:iterator value="{'aaa','bbb','ccc'}" status="status">
<s:property/>
遍历过的元素总数:<s:property value="#status.count"/>
遍历过的元素索引:<s:property value="#status.index"/>
当前是偶数?:<s:property value="#status.even"/>
当前是奇数?:<s:property value="#status.odd"/>
是第一个元素?:<s:property value="#status.first"/>
是最后一个元素?<s:property value="#status.last"/>
</s:iterator>
定义map
<s:iterator value="#{1:'a',2:'b',3:'c'}" var="x"> //定义map需要加#
<s:property value="#x.key"/>
<s:property value="#x.value"/>
<s:property value="key"/>
<s:property value="value"/>
</s:iterator>
遍历列表:
<struts:iterator id="book" value="bookList"> <!--bookList为一个Book属性的列表,book为一个javabean-->
<tr>
<td><struts:property value="name"/></td>
<td><struts:property value="author"/></td>
<td><struts:property value="publishedDate"/></td>
</tr>
</struts:iterator>
append:连接多个List
<s:append id="myAppendList"><!--在myAppendList后面追加数据-->
<s:param value="%{maleList}"/><!--追加maleList(action中的两个List类型变量)-->
<s:param value="%{femaleList}"/><!--追加femaleList-->
<s:append>
generator:将字符串转化为List,相当于java中的split
<s:generator val="%{'李宁,安踏,双喜,阿达,耐克'}" separator=",">
<s:iterator>
<s:property/>
</s:iterator>
<s:generator>
merge:取集合的并集
作用同append,只是增加数据的顺序不同,append是先增加一个集合的全部数据,再增加另一个集合的全部数据,merge是先增加一个集合的一个数据,再增加另一个集合的一个数据,交叠增加
subset:过滤集合元素
3 UI标签
theme
simple xhtml(默认) css_xhtml ajax
基本不用,可以用其他框架替代,非要用的时候用simple(只有fielderror最麻烦)就够了
定义自己的theme
1 css(覆盖struts2原来的css)
2 覆盖单个文件
3 定义自己的theme
4 实战
a 把所有的主题定义为simple
b fielderror特殊处理
c 自己控制其他标签的展现(当你改成simple后,它就恢复为最原始的html了)
4 非表单UI标签
debug
输出调试信息
fielderror,action,actionmessage
fielderror用于显示数据校验错误信息,actionerror用于显示action中的错误信息,actionmessage用于显示action中的消息
action中使用方法增加消息:分别为:
fielderror:this.addFieldError("password","密码不能为空");
actionerror:this.addActionError("执行error()方法,抛出了第一个error消息")
actionmessage:this.addActionMessage("执行message()方法,抛出第一个message消息");

异常处理:
声明式异常处理:你要是有异常了,你尽管往外抛,到最后我会给你一个统一的接口,然后让你在特殊的页面做出处理。
在catch中捕获的异常往外抛:throw(e);
在try catch的方法声明抛出特定的异常:throws SQLException
在使用这个方法的Action继续往外把异常的父类抛给struts.xml处理:throws Exception
异常处理:
特定的<action>异常处理: 然后在<action>里关联特定的页面处理异常:
<exception-mappng result="error" exception="java.sql.SQLException" />//当这个action遇到特定的异常时,交给<result>为error的页面处理
<result name="error">/error.jsp</result>
也可以写一个异常处理器包:
<package name="" extends="struts-default">
<global-results>
<result name="error">/error.jsp</result>
</global-results>
<global-exception-mappings>
<exception-mapping result="error" exception="java.lang.Exception"></exception-mapping>
</global-exception-mappings>
</package>
//其他包只要 extends 这个包就可以使用了,
总结:
1在action标签中进行异常映射
2在package标签中进行全局异常映射
3使用继承共用异常映射
4struts2中异常由拦截器实现(观察struts-default.xml)
实际上struts2的大多数功能都由拦截器实现

i18N:
i18N原理:
a ResourceBundle和Locale的概念
b 资源文件
c native2ascii
Struts 的资源文件
a Action-Package-App级
一般只用App级别
配置:struts.xml struts.custom.i18n.resources=资源文件开头的部分
要把资源文件放在classes目录下
资源文件的命名:
bbs2009_en_US.properties
bbs2009_CN_CN.properties
使用:对应在jsp页面使用struts2标签:<s:property value="getText('对应配置文件中的属性名')"/>
动态语言切换:只需在请求url跟上参数:request_locale=en_US即可
b PropertiesEditor插件
解压
features plugin覆盖到myeclipse中的eclipse目录下

拦截器以及源码解析:
1 struts架构图
见文档
2 struts执行过程分析
3 interceptor拦截器过程模拟
4 定义自己的拦截器(很少用,大部分拦截图都已经定义了,也可以用其他方法替代)
acegi-spring security
5 使用token拦截器控制重复提交(很少用)
6 类型转换
默认转换
日期转换
写自己的转换器
1 public class MyPointConverter extends DefaultTypeConverter{
public Object convertValue(Object value,Class toType){
if(toType == Point.class){
Point p = new Point();
String [] strs = (String[]) value;
String [] xy = strs[0].split(",");
p.x = Integer.parseInt(xy[0]);
p.y = Integer.parseInt(xy[1]);
return p;
}
}
}
————————————————————————————————————————————————————————————————
2 public class MyPointConverter extends StrutsTypeConverter{
public Object convertFromString(Map context,String[] values,Class toClass){
Point p = new Point();
String[] strs = (String[])values;
String[] xy = strs[0].split(",");
p.x = Integer.parseInt(xy[0]);
p.y = Integer.parseInt(xy[1]);
return p;
}
public String convertToString(Map context,Object o){
return o.toString();
}
}
三种注册方式
局部:XXXAction-conversion.properties
p(属性名称) = converter
全局:xwork-conversion.properties
com.xxx.xxx(类名) = converter
Annotation
如果遇到非常麻烦的映射转换
request.setAttribute();
session


Struts总结
1 Action
namespace(掌握)
path(掌握)
DMI(掌握 )
wildcard(掌握)
接受参数(掌握前两种)
访问request等(掌握Map IOC方式)
简单数据验证(掌握addFieldError和<s:fieldError>)
2 Result
结果类型(掌握四种,重点两种)
全局结果(掌握)
动态结果(了解)
3 OGNL表达式(精通)
# % $
4 Struts标签
掌握常用的
5 声明式异常处理(了解)
6 i18N(了解)
7 CRUD的过程(最重要是设计与规划)(精通)
8 Interceptor的原理(掌握)
9 类型转换(掌握默认,了解自定义)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值