1. Struts2 开发步骤
这里使用的版本是:Struct2.3.1
导入jar包:
把 \apps\struts2-blank\WEB-INF\lib下的jar都导入eclipse中
配置web.xml
配置struts.xml ; 该文件放到src根目录下
扩展添加源代码路径:
E:/BaiduYunDownload/share/0750_Struts2.3.1/soft/struts-2.3.15.1/src/core/src/main/java
添加DTD约束,使得在eclipse开发中Struts2可以有代码提示
2. Namespace
namespace决定了action的访问路径,默认为”“,可以接收所有路径的action
namespace可以写为/,或者/xxx,或者/xxx/yyy,对应的action访问路径为/index.action, /xxx/index.action,或者/xxx/yyy/index.action.
namespace最好也用模块来进行命名
3 .Action
具体视图的返回可以由用户自己定义的Action来决定
具体的手段是根据返回的字符串找到对应的配置项,来决定视图的内容
具体Action的实现可以是一个普通的java类,里面有public String execute方法即可
或者实现Action接口
不过最常用的是从ActionSupport继承,好处在于可以直接使用Struts2封装好的方法
执行流程:
Action执行的时候并不一定要执行execute方法
可以在配置文件中配置Action的时候用method=来指定执行哪个方法 也可以在url地址中动态指定(动态方法调用DMI)(推荐)
!+需要调用的方法名
DMI 方式: 如:
http://localhost:8080//Struts2_0500_ActionMethod/user/user!add
路径问题
struts2中的路径问题是根据action的路径而不是jsp路径来确定,所以尽量不要使用相对路径。
建议使用绝对路径
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
//再给所有的href前加上该路径
<base href="<%=basePath%>" />
即是,例如:http://localhost:8080/Struts2_0300_Action/ 获得以上这样的路径
使用通配符
可以给action name属性指定通配符* 第一个星号 代表{1} , 第二个星号代表{2}…
*内容,则是在请求路径中传入。
Action通过属性接收参数
请求方式:http://localhost:8080/Struts2_0700_ActionAttrParamInput/user/user!add?name=a&age=18
通过给Action 设置属性,对应参数名,并且带有get set方法,Struct2 会自动把参数值,通过调用setXX方法填充到相应的字段
public class UserAction extends ActionSupport {
private String name;
private int age;
public String add() {
System.out.println("name=" + name);//name=a
System.out.println("age=" + age)//age=18
return SUCCESS;
}
public String getName() {
return name;
} .......
用域模型(DomainModel)接收参数(最常用)
并且可以直接用以下请求方式对属性赋值
http://localhost:8080/Struts2_07011_ActionAttrParamInput/user/user!add?user.name=a&user.age=18
相当于// setUser(User user).setName(String name)
当参数与属性不一致时候,可以使用DTO(数据传输对象)匹配为一致。
相当于 // newUser(UserDTO dto)
通过ModelDriven接收参数 (比较少用, 思想很好)
请求方式:
http://localhost:8080/Struts2_0712_ActionAttrParamInput/user/user!add?name=a&age=18
中文编码问题 可以使用常量 struts.i18n.encoding 解决
<constant name="struts.i18n.encoding" value="UTF-8" />
数据校验
使用addFieldError方法和s:fieldError标签简单处理数据校验 ——添加用户
Struct2 把所有属性放进 Value Stack里面,可以通过s:property 标签取值
Structs2 访问web元素
Stack Context (Action Context)
使用IOC 访问web元素
IOC(inverse of control 控制反转)或者 DI (dependency injection 依赖注入)
Struts2 从filter开始,获得HttpRequest 对象, 把这个对象内容放到一个Map里,也起个名字叫request。即: Map 和HttpRequest之间做了映射,转成一个 Map request
request属性依赖于容器(Struct2) 调用 setRequest(Map String, Object> request) 把相关的值注入进去,谁调用,谁负责注入对象。(最常用)
include 文件
Action 总结:
result_type
type=“dispatcher”服务器跳转,只能跳到html,jsp freemarker,不能是action。(常用)
type=”redirect”(常用)客户端跳转,请求地址将改变。
type=”chain” 可以调到action。
type=”redirectAction” 客户端跳到action,请求地址将改变。
当使用type=“chain”时,跳转到不同包下的action 可以这样写
<param name="actionName">dashboard</param>
<param name="namespace">/secure</param>
带参数的结果集
例子:
<result type="redirect">/user_success.jsp?t=${type}</result>
如何取得t的值呢?
从ActionContext中,通过#parameters.X 取得参数值的内容
Result总结:
OGNL表达式 (对象图导航语言)
<li>访问值栈中的action的普通属性: username = <s:property value="username"/> </li>
<li>访问值栈中对象的普通属性(get set方法):<s:property value="user.age"/> | <s:property value="user['age']"/> | <s:property value="user[\"age\"]"/> | wrong: <%--<s:property value="user[age]"/>--%></li>
<li>访问值栈中对象的普通属性(get set方法): <s:property value="cat.friend.name"/></li>
<li>访问值栈中对象的普通方法:<s:property value="password.length()"/></li>
<li>访问值栈中对象的普通方法:<s:property value="cat.miaomiao()" /></li>
<li>访问值栈中action的普通方法:<s:property value="m()" /></li>
<hr />
//格式 @+完整类名+@+方法名或属性名
<li>访问静态方法:<s:property value="@com.bjsxt.struts2.ognl.S@s()"/></li>
//@@max
<li>访问Math类的静态方法:<s:property value="@@max(2,3)" /></li>
<hr />
<li>访问普通类的构造方法:<s:property value="new com.bjsxt.struts2.ognl.User(8)"/></li>
<hr />
<li>访问List:<s:property value="users"/></li>
<li>访问List中某个元素:<s:property value="users[1]"/></li>
<li>访问List中元素某个属性的集合:<s:property value="users.{age}"/></li>
<li>访问List中元素某个属性的集合中的特定值:<s:property value="users.{age}[0]"/> | <s:property value="users[0].age"/></li>
<li>访问Set:<s:property value="dogs"/></li>
// 由于set是无序的,所以取不到值
<li>访问Set中某个元素:<s:property value="dogs[1]"/></li>
<li>访问Map:<s:property value="dogMap"/></li>
<li>访问Map中某个元素:<s:property value="dogMap.dog101"/> | <s:property value="dogMap['dog101']"/> | <s:property value="dogMap[\"dog101\"]"/></li>
<li>访问Map中所有的key:<s:property value="dogMap.keys"/></li>
<li>访问Map中所有的value:<s:property value="dogMap.values"/></li>
<li>访问容器的大小:<s:property value="dogMap.size()"/> | <s:property value="users.size"/> </li>
<hr />
//{?#或者^#或$#开头} this: 遍历users里面的每一个对象,当前对象
//?:过滤条件 ^开头那个,$是结尾那个
<li>投影(过滤):<s:property value="users.{?#this.age==1}[0]"/></li>
<li>投影:<s:property value="users.{^#this.age>1}.{age}"/></li>
<li>投影:<s:property value="users.{$#this.age>1}.{age}"/></li>
<li>投影:<s:property value="users.{$#this.age>1}.{age} == null"/></li>
<hr />
//[0]意思:值栈中的object从第0个开始到栈底这个集合
//[0].username 找里面的Action,如果第一个没有,找第二个
//当result tyep="chain",就可以有多个action
<li>[]:<s:property value="[0].username"/></li>
Struts-Tags
<li>property: <s:property value="username"/> </li>
//取值为字符串:加个单引号,表示普通字符串
<li>property 取值为字符串: <s:property value="'username'"/> </li>
<li>property 设定默认值: <s:property value="admin" default="管理员"/> </li>
//escape="false" 不要解析成字符串,按照原来HTML标签左右解析
<li>property 设定HTML: <s:property value="'<hr/>'" escape="false"/> </li>
<hr />
//把var变量adminName既放到request里面,又放到ActionContext里面
<li>set 设定adminName值(默认为request 和 ActionContext): <s:set var="adminName" value="username" /></li>
<li>set 从request取值: <s:property value="#request.adminName" /></li>
<li>set 从ActionContext取值: <s:property value="#adminName" /></li>
<li>set 设定var,范围为ActionContext: <s:set var="adminPassword" value="password" scope="session"/></li>
<li>set 使用#取值: <s:property value="#adminPassword"/> </li>
<li>set 从相应范围取值: <s:property value="#session.adminPassword"/> </li>
<li>bean 查看debug情况: //name: new 哪个对象,var:放到ActionContext里面
<s:bean name="com.bjsxt.struts2.tags.Dog" var="myDog">
//设置Dog对象里面的name属性的默认值为 'oudy' 需要加引号表示字符串
<s:param name="name" value="'oudy'"></s:param>
</s:bean>
拿出值:
<s:property value="#myDog.name"/>
</li>
<hr />
//include标签(少用)
<li>include _include1.html 包含静态英文文件
<s:include value="/_include1.html"></s:include>
</li>
<li>include _include2.html 包含静态中文文件
<s:include value="/_include2.html"></s:include>
</li>
//%{}将原本的文本属性解析为ongl
<li>include _include1.html 包含静态英文文件,说明%用法
<s:set var="incPage" value="%{'/_include1.html'}" />
<s:include value="%{#incPage}"></s:include>
</li>
<hr />
<li>if elseif else:
age = <s:property value="#parameters.age[0]" /> <br />
<s:set var="age" value="#parameters.age[0]" />
<s:if test="#age < 0">wrong age!</s:if>
<s:elseif test="#parameters.age[0] < 20">too young!</s:elseif>
<s:else>yeah!</s:else><br />
<s:if test="#parameters.aaa == null">null</s:if>
</li>
<hr />
<li>遍历集合:<br />
<s:iterator value="{1, 2, 3}" >
<s:property/> |
</s:iterator>
</li>
<li>自定义变量:<br />
<s:iterator value="{'aaa', 'bbb', 'ccc'}" var="x">
<s:property value="#x.toUpperCase()"/> |
</s:iterator>
</li>
<li>使用status:<br />
<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"/>
<br />
</s:iterator>
</li>
<li>
<s:iterator value="#{1:'a', 2:'b', 3:'c'}" >
<s:property value="key"/> | <s:property value="value"/> <br />
</s:iterator>
</li>
<li>
<s:iterator value="#{1:'a', 2:'b', 3:'c'}" var="x">
<s:property value="#x.key"/> | <s:property value="#x.value"/> <br />
</s:iterator>
</li>
设计约定
I18N