new webproject ->javaEE5.0->
配置:
先拷struts2.xml到src中,再拷lib目录下的类到web-inf的lib中,再拷web.xml文件中的
fliter和mapping标签
Struts2:请求和视图分开
Struts2的原理:
client->Tomcat->检查web.xml->filter->处理类->namespace->action->jsp文件
namespace:
namespace:='' namespace=/'name' name='abc' namespace等于空包括其他package处理不了的事情
Action:
具体视图的返回可以由用户自己定义的Action来决定
具体的手段是根据返回的字符串找到对应的配置项,来决定视图的内容
具体Action的实现可以是一个普通的java类,里面有public String execute方法即可
或者实现Action接口
不过最常用的是从ActionSupport继承,好处在于可以直接使用Struts2封装好的方法
Path:
struts2中的路径问题是根据action的路径而不是jsp路径来确定,所以尽量不要使用相对路径。
虽然可以用redirect方式解决,但redirect方式并非必要。
解决办法非常简单,统一使用绝对路径。(在jsp中用request.getContextRoot方式来拿到webapp的路径)
或者使用myeclipse经常用的,指定basePath
jsp文件中写入:
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>
并在html的head标签内加入
<base href="<%=basePath%>">
在body标签引用的文件若无路径名则默认为basepath
MDI
动态方法调用
WildCard
<action name="*_*" class="com.bjsxt.struts2.action.{1}Action" method="{2}">
<result>/{1}_{2}_success.jsp</result>
<!-- {0}_success.jsp -->
</action>
{n}依次匹配*号
jsp页面命名规则“约定优于配置”
首先匹配最精确的,同一等级按顺序匹配
Action的属性接受参数:
使用action属性接收参数<a href="user/user!add?name=a&age=8">添加用户</a>
在对应的add()方法中有:
getName();setName();getAge;setAge
DomainModel接收参数(最常用)
使用Domain Model接收参数<a href="user/user!add?user.name=a&user.age=8">添加用户</a>
相当于调用usr.setUser,然后调用User的setName(),setAge()
UserDTO (vo value object) (do data object) (dto data transfer object)
ModelDrivenParamInput接受参数:
MVC
中文问题:
struts的配置文件放在References Libraries的 structs-core-2.1.6 的Jar的org.apache.struts2的static文件夹中
default.properties中
表单提交尽量用post
配置文件中加入:2.1.7 的bug
<constant name="struts.i18n.encoding" value="GBK" /> <!-- internationalization -->
将2.1的filter改为2.0
<filter-class>org.apache.struts2.dispatcher.FilterDispatcher</filter-class>
不建议
数据验证:
if(name == null || !name.equals("admin")) {
this.addFieldError("name", "name is error");
this.addFieldError("name", "name is too long");
return ERROR;
}
<%@taglib uri="/struts-tags" prefix="s" %>
...........
...........
<body>
User Add Error!
<s:fielderror fieldName="name" theme="simple"/>
<br />
<s:property value="errors.name[0]"/>
<s:debug></s:debug>
</body>
访问web元素:
小技巧:利用javascript对同一表单采取不同的提交
<input type="button" value="submit1" onclick="javascript:document.form1.action='user/user!add';document.form1.submit();"/>
<input type="button" value="submit2" onclick="javascript:document.form1.action='user/user!del';document.form1.submit();"/>
IOC(inverse of control)控制反转
Action类实现RequestAware,SessionAware,ActionAware接口
package cn.edu.haut.GetParameter; import java.util.Map; import org.apache.struts2.interceptor.ApplicationAware; import org.apache.struts2.interceptor.RequestAware; import org.apache.struts2.interceptor.SessionAware; import com.opensymphony.xwork2.ActionSupport; public class GetParameter extends ActionSupport implements RequestAware,SessionAware,ApplicationAware{ private String name; private String password; private Map<String,Object> request; private Map<String,Object> session; private Map<String,Object> application; public String add(){ request.put("r1", "r1"); session.put("s1","s1"); application.put("a1","a1"); System.out.println("name="+name); System.out.println("password="+password); if(name==null||!name.equals("admin")){ this.addFieldError("name", "Name Error!"); return ERROR; } return SUCCESS; } public String del(){ return "del"; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public void setSession(Map<String, Object> session) { this.session=session; } public void setApplication(Map<String, Object> application) { this.application=application; } public void setRequest(Map<String, Object> request) { this.request=request; } }
前台接受:
<%@ taglib uri="/struts-tags" prefix="s" %> ............ ............ <s:property value="#request.r1"/>|<%=request.getAttribute("r1") %><br/> <s:property value="#session.s1"/>|<%=session.getAttribute("s1") %><br/> <s:property value="#application.a1"/>|<%=application.getAttribute("a1") %><br/> <s:debug></s:debug>
include models
在struts.xml文件中加入
<include file="login.xml"/>可以包含其他模块
default-action
默认的action,当访问namespace下找不到对应的action时访问默认action
<default-action-ref name="index"></default-action-ref>
<package name="default" namespace="/" extends="struts-default"> <default-action-ref name="index"></default-action-ref> <action name="index"> <result>/default.jsp</result> </action> </package>
Action总结:
1. 实现一个Action的最常用方式:从ActionSupport继承
2. DMI动态方法调用 !
3. 通配符配置 * {1} {2} …
a) *_*
4. 接收参数的方法(一般用属性或者DomainModel来接收)
5. 简单参数验证addFieldError
a) 一般不使用Struts2的UI标签
6. 访问Web元素
a) Map类型
i. IoC
ii. 依赖Struts2
b) 原始类型
i. IoC
ii. 依赖Struts2
7. 包含文件配置
8. 默认action处理
Result配置:
服务器端跳转:dispatcher
客户端跳转:redirect
result类型(type):
dispatcher(默认)
redirect
chain
(action位与不同的包查看doc)
redirectAction
global result类型
package下加入
<global-results>
<result name="mainpage">/main.jsp</result>
</global-result>
extends从另外的包继承
extends="struts-default"
extends="packageName"
dynamic result(不常用)
<result>${r}</result>
Action类中定义变量r返回不同值
带参数的result
服务器forward一般不需要传参,一次request只有一个Value Stack
redirect需要传参,从ActionContext中取参
<s:property value="#parameter.t">
OGNL表达式:
Object Graph Navigator Language
OGNL Object Graph Navigation Language
${}
username,password execute() get() set()
<s:property value="password">
user.xxx 必须传参才能构造user类
想初始化domain model,可以自己New,也可以传参数,
但此时需要保持空参数为空的构造方法。
class cat
get() set() Dog()
值栈中对象的普通方法:
password.length()
cat.miaomiao()
hello()
访问静态方法:
@classname@functionname()
访问静态属性:
@classname@attibutename()
xml中配置:
struts.ognl.allowStaticMethodAccess=true
<constant name="struts.ognl.allowStaticMethodAccess" value="true" />
访问普通类的构造方法:
直接访问
访问集合:
private List<User> users=new ArrayList<User>();
private Set<Dog> dogs=new HashSet<Dog>();
private Map<String,Dog> dogMap=new HashMap<String,Dog>();
users[1]
users.{age} {}可以代表一个集合
users[0].age
set是没有顺序的,不能按下标值取
OGNL中可以用'代表字符串也可以用/"代替字符串
dogMap.dog101 访问Map
过滤:
?#
^#
$#
<body> <ol> <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> <li>访问静态属性:<s:property value="@com.bjsxt.struts2.ognl.S@STR"/></li> <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> <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 /> <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 /> <li>[]:<s:property value="[0].username"/></li> </ol> <s:debug></s:debug> </body>
标签:Tags:
$#%:
$用于i18n和struts配置文件
#取得ActionContext的值
%将原本的文本属性解析为ognl,对原来就是ognl的属性不起作用
<?xml version="1.0" encoding="GB18030" ?> <%@ page language="java" contentType="text/html; charset=GB18030" pageEncoding="GB18030"%> <%@ taglib uri="/struts-tags" prefix="s" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=GB18030" /> <title>Struts-Tags学习</title> </head> <body> <ol> <li>property: <s:property value="username"/> </li> <li>property 取值为字符串: <s:property value="'username'"/> </li> <li>property 设定默认值: <s:property value="admin" default="管理员"/> </li> <li>property 设定HTML: <s:property value="'<hr/>'" escape="false"/> </li> <hr /> <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 设定范围: <s:set name="adminPassword" value="password" scope="page"/></li> <li>set 从相应范围取值: <%=pageContext.getAttribute("adminPassword") %></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> <hr /> <%--<li>push:<s:set name="myDog" value="new com.bjsxt.struts2.ognl.Dog('oudy')"></s:set></li> <li> push:<s:push value="#myDog"> <s:property value="name"/> </s:push> </li> <li>push: <s:property value="name"/></li> --%> <hr /> <li>bean 定义bean,并使用param来设定新的属性值: <s:bean name="com.bjsxt.struts2.tags.Dog" > <s:param name="name" value="'pp'"></s:param> <s:property value="name"/> </s:bean> </li> <li>bean 查看debug情况: <s:bean name="com.bjsxt.struts2.tags.Dog" var="myDog"> <s:param name="name" value="'oudy'"></s:param> </s:bean> 拿出值: <s:property value="#myDog.name"/> </li> <hr /> <li>include _include1.html 包含静态英文文件 <s:include value="/_include1.html"></s:include> </li> <li>include _include2.html 包含静态中文文件 <s:include value="/_include2.html"></s:include> </li> <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> <li> <s:fielderror fieldName="fielderror.test" theme="simple"></s:fielderror> </li> </ol> </body> </html>
定义自己的theme
1.css覆盖原来的struts2标签
2.覆盖单个文件
3.定义自己的theme
4.实战:
a.把所有的主题定义为simple
b.fielderror特殊处理
c.自己控制其他标签展现