一、用户输入验证
1、编程方式:
动作类中的所有方法进行验证:
步骤:
a、动作类继承ActionSupport
b、覆盖调用public void validate()方法
c、在validate方法中,编写不符合要求的代码判断,并调用父类的addFieldError(String fieldName,String errorMessage)
如果fieldError(存放错误信息的Map)有任何的元素,就是验证不通过,动作方法不会执行。
Struts2框架会返回到name=input的result
d、在name=input指定的页面上使用struts2的标签显示错误信息。<s:fielderror/>
例子:
********************************************************************************************************************
Action类:
public class UserAction extends ActionSupport implements Serializable {
private String username; // 用户名不能为空,其去掉首位空格
private String password; // 3~6为数字
// set/get属性
public String add(){
System.out.println("执行了user的add方法");
return SUCCESS;
}
// 验证方法: 只考虑不符合条件的 注: 要继承com.opensymphony.xwork2.ActionSupport类
@Override
public void validate() {
if(username==null||"".equals(username)){
addFieldError("username", "用户名不能为空");
}
if(password==null||!password.matches("\\d{3,6}")){
addFieldError("password", "密码长度必须是3~6位数字");
}
}
}
jsp:
<body>
<!-- 注:<s:fielderror fieldName="username"></s:fielderror> 要引入 uri="/struts-tags"包 用于动作类中数据校验的错误信息提示 -->
<!-- 访问地址:http://localhost:8080/struts2day02/validate/addUser.jsp -->
<form action="${pageContext.request.contextPath}/validate/user_add.action" method="post">
用户名:<input type="text" name="username"/> <s:fielderror fieldName="username"></s:fielderror> <br/><br/>
密码: <input type="text" name="password"/> <s:fielderror fieldName="password"></s:fielderror> <br/><br/>
<input type="submit" name="保存" />
</form>
</body>
********************************************************************************************************************
动作类中指定的方法进行验证:
编写步骤与上面相同
Action类中的验证方法书写有要求:
public void validateXxx() Xxx代表的是要验证的动作方法名,其中要把动作方法名的首字母变为大写。
输入校验的流程图
2、基于XML配置文件的方式:
动作类中的所有方法进行验证:
在动作类的包中,建立一个名称为:动作简单类名-validation.xml ,
比如要验证的动作类名是UserAction,则UserAction-validation.xml内容如下:
********************************************************************************************************************
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE validators PUBLIC
"-//OpenSymphony Group//XWork Validator 1.0.3//EN"
"http://www.opensymphony.com/xwork/xwork-validator-1.0.3.dtd">
<validators>
<!-- 写法1 根据字段提供不同的验证器 -->
<field name="username">
<!-- 内置验证器都是定义好的,在xwork-core.jar com.opensymphony.xwork2.validator.validators包中的default.xml文件中 -->
<field-validator type="requiredstring"> <!-- 不能为null或者""字符串,默认会去掉前后的空格 -->
<param name="trim">true</param>
<message>用户名不能为空</message>
</field-validator>
</field>
<field name="password">
<field-validator type="requiredstring">
<message>密码不能为空</message>
</field-validator>
<field-validator type="regex">
<param name="expression"><![CDATA[\d{3,6}]]></param> // 该参数由对应的内置验证器的类找,为了防止有特殊字符,转换成普通文本
<message>密码长度必须是3~6位数字</message>
</field-validator>
</field>
<!-- 写法2 根据验证器,提供不同的字段 注: 此种方式需使用 <s:actionerror/>标签来显示错误信息 -->
<validator type="requiredstring">
<param name="fieldName">username</param>
<message>用户名不能为空</message>
</validator>
</validators>
********************************************************************************************************************
动作类中指定的方法进行验证:
配置文件的名称书写有一定要求:
动作类名-动作名(配置文件中的动作名)-validation.xml
如: UserAction-user_add-validation.xml
struts2内置的各种验证器:
见struts2的参考讲义详解
3、自定义基于XML的验证器
a、编写一个类,继承FieldValidatorSupport类或validatorSupport类。
b、在public void validate(Object object)编写你的验证逻辑
不符合要求的就向fieldErrors中放消息
c、一定注册你的验证器才能使用
在WEB-INF/classes目录下建立一个名称为validators.xml的配置文件,内容如下:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE validators PUBLIC
"-//OpenSymphony Group//XWork Validator Config 1.0//EN"
"http://www.opensymphony.com/xwork/xwork-validator-config-1.0.dtd">
<validators>
<validator name="strongpassword" class="cn.itcast.validators.StrongPasswordValidator"/>
</validators>
d、日后就可以像使用Struts2提供的16个验证器方式去使用了。
二、Struts2对于i18n的支持
全局资源文件/包范围资源文件/动作类的资源文件
全局资源文件:放到WEB-INF/classes目录下
包范围资源文件:服务于Java类中的包下的动作类的。
取名:package_语言_国家.properties
动作类的资源文件:放到与动作类相同的包中
取名:动作类名_语言_国家.properties
jsp中如何读取国际化的消息
动作类中如何读取国际化的消息
三、OGNL表达式:
1. OGNL简介
OGNL是从ActionContext中获取数据的。使用OGNL表达式需结合struts的<s:property value="OGNL表达式"/>使用
struts2中的OGNL Context实现者为ActionContext,当struts接收一个请求时,会迅速创建ActionContext,ValueStack,action
然后把action放进ValueStack中,所以action的实例变量可以被OGNL访问。
2. ActionContext详解
ActionContext的结构:
ValueStack: List结构:动作类放在此处。
application: ServletContext中的那个Map
session: HttpSession中的那个Map
request: ServletRequest中的那个Map
parameters: 请求参数的那个Map。(如同EL表达式的paramValues内置对象)
attr: 相当于PageContext的findAttribute方法。在四大域范围内依次查找。
注:
valueStack: 取存放在ValueStack中的root的对象的属性,直接写即可,访问其他内容中的对象要使用#+(范围)
访问值栈对象中的属性时,可以直接根据属性名获取。如果栈顶元素没有该属性,则由第二个元素依次查找获取,
如果有多个相同名称的键,也可以由角标来确定
也可以直接通过EL表达式直接访问valueStack中对象的属性,struts2对HttpServletRequest进行了封装
先在request中找,如果找不到,则从栈顶元素找
如: ${username}就是获得值栈中某个对象的属性
application对象: 用于访问ServletContext,例如#application.username或者#application['username'],
相当于调用ServletContext的getAttribute("username");
session对象: 用来访问HttpSession,例如#session.username或者#session['username'],
相当于调用session.getAttribute("username");
request对象: 用来访问HttpServletRequest属性(attribute)的Map,例如#request.username或#request['username']
相当于调用request.getAttribute("username");
parameters对象: 用于访问Http的请求参数,例如#parameters.username或者#parameters['username']
相当于调用request.getParameter("username");
attr对象: 相当于PageContext的findAttribute方法。在四大域范围内依次查找。
page-->request-->session-->application的顺序;
小技巧:在页面中使用<s:debug/>查看上下文中的对象
s:debug标签用来显示对象是放在哪个域中,进而可以由此判断出ongl表达式要如何书写
例:
***********************************************************************************
Action类:
public class PersonAction extends ActionSupport implements Serializable {
private String username;
private int age;
// set/get属性
public String execute(){
// 默认是放到值栈对象中的,可以直接根据属性名获取
username = "zql";
age = 18;
// 放到request中
ActionContext.getContext().put("user", "请求范围");
// 放到session中,须要用#session.键来获取
ActionContext.getContext().getSession().put("user", "sesion范围");
return SUCCESS;
}
}
JSP:
<body>
<!-- 使用OGNL表达式 -->
<s:property value="username"/> <br/>
<s:property value="[0].username"/> <br/>
<s:property value="#request.user"/> <br/>
<s:property value="#session.user"/> <br/>
<s:property value="#attr.user"/> <br/>
<!-- 默认取valueStack中的栈顶对象 -->
<s:property/> <br/>
<!-- EL表达式实现相同的获取 -->
<!-- 注: 此处是ognl表达式对值栈对象中的属性获取的封装,如果没有,则调用findAttribute方法 -->
${username} <br/>
${sessionScope.user} <br/>
${user} <br/>
</body>
***********************************************************************************
3. 利用OGNL表达式创建List/Map集合
创建List集合
***********************************************************************************
<!-- 创建list集合 默认放到了ActionContext上下文件中 scope="action" -->
<s:set var="list1" value="{'a','b','c'}"></s:set> <br/>
<s:set var="list2" value="{'aa','bb','cc'}" scope="action" /> <br/>
<s:set var="list3" value="{'aaa','bbb','ccc'}" scope="session"></s:set> <br/>
<!-- 获取list集合中的元素 -->
<s:property value="#list1[1]"/> <br/>
<s:property value="#list2[1]"/> <br/>
<s:property value="#session.list3[1]"/> <br/> <br/>
<!-- 遍历list集合中的元素 -->
<s:iterator value="#session.list3" var="ls">
<s:property value="#ls"/> <br/>
</s:iterator>
<s:set var="list" value="{'a','b','c'}"></s:set>
<s:iterator value="#list"> <!-- 注: 遍历时,会将当前遍历的对象放到valueStack的栈顶 l="a"-->
<s:property/> <br/>
</s:iterator>
***********************************************************************************
创建Map集合
***********************************************************************************
<!-- 创建map集合 -->
<s:set var="map1" value="#{'a':'valuea','b':'valueb'}" scope="session" />
<!-- 获取map集合中的某个元素的值 ????? 取不出来 待百度 -->
<!-- 利用jstl标签来遍历session域中的map1集合 -->
<c:forEach items="${sessionScope.map1}" var="me">
${me.key} = ${me.value} <br/>
</c:forEach>
<!-- 遍历map集合中的元素 对比jstl标签-->
<s:iterator value="#session.map1" var="me">
<s:property value="#me.key"/> = <s:property value="#me.value"/> <br/>
</s:iterator>
<s:set var="map" value="#{'a':'aa','b':'bb','c':'cc'}"></s:set>
<s:iterator value="#map"> <!-- 注: 遍历时,会将当前遍历的对象放到valueStack的栈顶 me=map.Entry-->
<s:property value="key"/> : <s:property value="value"/> <br/>
</s:iterator>
***********************************************************************************
4. in表达式: <s:if test="'c' in {'a','b'}">
yes
</s:if>
<s:else>
no
</s:else>
not in表达式:
<s:if test="'c' not in {'a','b'}">
yes
</s:if>
<s:else>
no
</s:else>
5. ognl表达式的投影功能
允许使用某个规则获得符合集合对象的子集,常用的有以下3个相关的操作符:
?: 获得所有符合逻辑的元素
^: 获得符合逻辑的第一个元素
$: 获得符合逻辑的最后一个元素
例:
<!-- ognl表达式的投影功能 #this为当前遍历的对象 ?筛选符合条件的对象 -->
<s:iterator value="books.{?#this.price>20}" var="book">
<s:property value="#book.name" /> <s:property value="#book.price"/> <br/>
</s:iterator>
四、Struts2中常用的标签
1. 常用标签
<s:property/>标签:用于输出指定值
ognl表达式动作类中的字段的值
<s:property value="username" />
默认取valueStack中的栈顶对象
<s:property/> <br/>
<s:set/>标签: 用于将某个值放入指定范围。
scope: 指定变量被放置的范围,该属性可以接受application,session,request,page,或action,
如果没有设置该属性,则默认放置在OGNL Context中;
value: 赋给变量的值,如果没有设置该属性,则将ValueStack栈顶的值赋给该变量;
<s:if/else/>:
<s:set var="grade" value="'C'"></s:set> <!-- 如果把一个字符串当成了表达式,再用引号引起来就是字符串了 -->
<s:if test="#grade=='A'">
优秀
</s:if>
<s:elseif test="#grade=='B'">
良好
</s:elseif>
<s:else>
及格
</s:else>
</s:iterator>: 用于对集合进行迭代,包含list,set,和数组
当前迭代的元素在栈顶
<s:set var="records" value="{'辟邪剑法','玉女心经','葵花宝典','金瓶梅','艺术概论','小试牛刀','开发宝典'}" ></s:set>
<table border="1">
<tr>
<th>序号</th>
<th>书名</th>
</tr>
<s:iterator value="#records" status="vs">
<tr bgcolor="<s:property value='#vs.even?"red":"yellow"'/>">
<td>
<s:property value="#vs.count"/>
</td>
<td>
<s:property />
</td>
</tr>
</s:iterator>
</table>
<s:url/>: 生成路径
<!-- 输出: /struts2day03/validate2/user_add.action -->
<s:url action="user_add" namespace="/validate2"></s:url>
<s:url action="a12" var="url"> <!-- 还对URL进行了重写 -->
<s:param name="username" value="'admin'"></s:param> <!-- value的取值被当作表达式了,需要加引号才能转换为字符串 -->
<s:param name="age" value="'28'"></s:param>
</s:url>
<a href="<s:property value="#url"/>">猛点</a> <br/>
<s:set value="'addCustomer'" var="addr"></s:set> <!-- 存放的动作名称 -->
<s:url value="%{#addr}"></s:url> <!-- url标签中value的取值: 默认是当作字符串的 若想要当作是表达式,须使用%{} -->
<s:a action=""/>
表单的标签:
Action类:
public class StudentAction extends ActionSupport implements Serializable {
private String[] hobby1 = {"吃饭","睡觉","打豆豆"}; // 选项
private String[] hobby2; // 被选中的选项
// set/get属性
public String execute(){
hobby2 = new String[]{"打豆豆"};
return SUCCESS;
}
}
JSP:
<body>
<s:checkboxlist name="hobby" list="{'吃饭','睡觉','打豆豆'}" value="{'吃饭','打豆豆'}"></s:checkboxlist> <br>
<s:checkboxlist name="hh" list="hobby1" value="hobby2"></s:checkboxlist> <br>
<hr/>
<s:checkboxlist name="province1" list="#{'0':'北京','1':'上海','2':'深圳'}" value="'2'"></s:checkboxlist> <br>
<s:checkboxlist name="province2" list="#{'北京':'0','上海':'1','深圳':'2'}" listKey="value" listValue="key" value="{'1'}"></s:checkboxlist> <br>
<hr/>
<s:radio list="#{'0':'女','1':'男'}" value="'0'"></s:radio> <br/>
<s:radio list="#{'0':'女','1':'男'}" value="'1'"></s:radio> <br/>
<s:radio list="#{'0':'女','1':'男'}" listKey="key" listValue="value"></s:radio> <br/>
<hr/>
<s:select list="#{'0':'北京','1':'上海','2':'深圳'}" value="'1'"></s:select> <br/>
<s:select list="#{'0':'北京','1':'上海','2':'深圳'}" value="'2'"></s:select> <br/>
<s:select list="#{'0':'北京','1':'上海','2':'深圳'}" listKey="key" listValue="value"></s:select> <br/>
<hr/>
<s:form action="a11" namespace="/xxx">
用户名: <s:textfield name="用户名"></s:textfield>
密码: <s:password name="password"></s:password>
</s:form>
</body>
五、防止表单重复提交
步骤:
1. 在表单中加入<s:token/>标签
2. 在配置文件中的action中加入token的拦截器
<interceptor-ref name="defaultStack"></interceptor-ref>
<interceptor-ref name="token"></interceptor-ref>
3. 并在配置文件中的action中增加一个名称为invalide.token的结果集
<result name="invalid.token">/noSubmitMany/success.jsp</result>
例:
**************************************************************************************************
请求页面:
<body>
<!-- 访问地址: http://localhost:8080/struts2day03/noSubmitMany/addCustomer.jsp -->
<form action="addCustomer" namespace="/noSubmitMany">
<s:token></s:token> <!-- 防止表单重复提交步骤1: 添加s:token标签 -->
<s:textfield name="username" label="用户名"></s:textfield> <br/>
<s:submit value="保存"></s:submit>
</form>
</body>
配置文件:
<package name="noSubmitMany" namespace="/noSubmitMany" extends="struts-default">
<action name="addCustomer" class="cn.itcast.action.AddCustomerAction" method="add">
<!-- 防止表单重复提交步骤2 创建拦截器 -->
<interceptor-ref name="defaultStack"></interceptor-ref>
<interceptor-ref name="token"></interceptor-ref>
<!-- 防止表单重复提交步骤3 创建结果集 注:name="invalid.token" -->
<result name="invalid.token">/noSubmitMany/success.jsp</result>
<result name="success">/noSubmitMany/success.jsp</result>
</action>
</package>
Action类:
public class AddCustomerAction extends ActionSupport implements Serializable {
private String username;
// set/get属性
public String add(){
System.out.println("添加成功!");
return SUCCESS;
}
}
JSP:
<body>
${message}
</body>
**************************************************************************************************
六、 如何使用Struts的插件。(牵扯与其他框架整合)JFreeChart整合
使用标准插件:JFreeChart使用
图形的选择: 将jfreechart-1.0.13整个文件夹拷到C盘下,运行
java -jar C:\jfreechart-1.0.13\jfreechart-1.0.13-demo.jar
即可打开图形,拷贝里面的源码到动作类中,即可
最小jar包:
struts2-jfreechart-plugin-2.1.8.1.jar
jcommon-1.0.16.jar
jfreechart-1.0.13.jar
动作类
public class GetChartAction extends ActionSupport {
private static final long serialVersionUID = -7814290464584999876L;
private JFreeChart chart;
public JFreeChart getChart() {
return chart;
}
public String execute(){
ValueAxis xAxis = new NumberAxis("年度");
ValueAxis yAxis = new NumberAxis("产值");
XYSeries xySeries = new XYSeries("绿豆");
xySeries.add(0,300);
xySeries.add(1,200);
xySeries.add(2,400);
xySeries.add(3,500);
xySeries.add(4,600);
xySeries.add(5,500);
xySeries.add(6,800);
xySeries.add(7,1000);
xySeries.add(8,1100);
XYSeriesCollection xyDataset = new XYSeriesCollection(xySeries);
XYPlot xyPlot = new XYPlot(xyDataset,xAxis,yAxis,new StandardXYItemRenderer(StandardXYItemRenderer.SHAPES_AND_LINES));
chart = new JFreeChart(xyPlot);
return SUCCESS;
}
}
配置文件:
<!-- extends内容查看: WEB-INF/lib/struts2-jfreechart-plugin-2.1.8.1.jar/struts-plugin.xml-->
<package name="p2" extends="jfreechart-default">
<action name="chart" class="wiva.struts2.train.action.GetChartAction">
<result type="chart">
<param name="width">600</param>
<param name="height">400</param>
</result>
</action>
</package>
页面
<body>
<s:url action="chart" var="url"></s:url>
<img src="<s:property value="url"/>" alt="hello" />
1、编程方式:
动作类中的所有方法进行验证:
步骤:
a、动作类继承ActionSupport
b、覆盖调用public void validate()方法
c、在validate方法中,编写不符合要求的代码判断,并调用父类的addFieldError(String fieldName,String errorMessage)
如果fieldError(存放错误信息的Map)有任何的元素,就是验证不通过,动作方法不会执行。
Struts2框架会返回到name=input的result
d、在name=input指定的页面上使用struts2的标签显示错误信息。<s:fielderror/>
例子:
********************************************************************************************************************
Action类:
public class UserAction extends ActionSupport implements Serializable {
private String username; // 用户名不能为空,其去掉首位空格
private String password; // 3~6为数字
// set/get属性
public String add(){
System.out.println("执行了user的add方法");
return SUCCESS;
}
// 验证方法: 只考虑不符合条件的 注: 要继承com.opensymphony.xwork2.ActionSupport类
@Override
public void validate() {
if(username==null||"".equals(username)){
addFieldError("username", "用户名不能为空");
}
if(password==null||!password.matches("\\d{3,6}")){
addFieldError("password", "密码长度必须是3~6位数字");
}
}
}
jsp:
<body>
<!-- 注:<s:fielderror fieldName="username"></s:fielderror> 要引入 uri="/struts-tags"包 用于动作类中数据校验的错误信息提示 -->
<!-- 访问地址:http://localhost:8080/struts2day02/validate/addUser.jsp -->
<form action="${pageContext.request.contextPath}/validate/user_add.action" method="post">
用户名:<input type="text" name="username"/> <s:fielderror fieldName="username"></s:fielderror> <br/><br/>
密码: <input type="text" name="password"/> <s:fielderror fieldName="password"></s:fielderror> <br/><br/>
<input type="submit" name="保存" />
</form>
</body>
********************************************************************************************************************
动作类中指定的方法进行验证:
编写步骤与上面相同
Action类中的验证方法书写有要求:
public void validateXxx() Xxx代表的是要验证的动作方法名,其中要把动作方法名的首字母变为大写。
输入校验的流程图
2、基于XML配置文件的方式:
动作类中的所有方法进行验证:
在动作类的包中,建立一个名称为:动作简单类名-validation.xml ,
比如要验证的动作类名是UserAction,则UserAction-validation.xml内容如下:
********************************************************************************************************************
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE validators PUBLIC
"-//OpenSymphony Group//XWork Validator 1.0.3//EN"
"http://www.opensymphony.com/xwork/xwork-validator-1.0.3.dtd">
<validators>
<!-- 写法1 根据字段提供不同的验证器 -->
<field name="username">
<!-- 内置验证器都是定义好的,在xwork-core.jar com.opensymphony.xwork2.validator.validators包中的default.xml文件中 -->
<field-validator type="requiredstring"> <!-- 不能为null或者""字符串,默认会去掉前后的空格 -->
<param name="trim">true</param>
<message>用户名不能为空</message>
</field-validator>
</field>
<field name="password">
<field-validator type="requiredstring">
<message>密码不能为空</message>
</field-validator>
<field-validator type="regex">
<param name="expression"><![CDATA[\d{3,6}]]></param> // 该参数由对应的内置验证器的类找,为了防止有特殊字符,转换成普通文本
<message>密码长度必须是3~6位数字</message>
</field-validator>
</field>
<!-- 写法2 根据验证器,提供不同的字段 注: 此种方式需使用 <s:actionerror/>标签来显示错误信息 -->
<validator type="requiredstring">
<param name="fieldName">username</param>
<message>用户名不能为空</message>
</validator>
</validators>
********************************************************************************************************************
动作类中指定的方法进行验证:
配置文件的名称书写有一定要求:
动作类名-动作名(配置文件中的动作名)-validation.xml
如: UserAction-user_add-validation.xml
struts2内置的各种验证器:
见struts2的参考讲义详解
3、自定义基于XML的验证器
a、编写一个类,继承FieldValidatorSupport类或validatorSupport类。
b、在public void validate(Object object)编写你的验证逻辑
不符合要求的就向fieldErrors中放消息
c、一定注册你的验证器才能使用
在WEB-INF/classes目录下建立一个名称为validators.xml的配置文件,内容如下:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE validators PUBLIC
"-//OpenSymphony Group//XWork Validator Config 1.0//EN"
"http://www.opensymphony.com/xwork/xwork-validator-config-1.0.dtd">
<validators>
<validator name="strongpassword" class="cn.itcast.validators.StrongPasswordValidator"/>
</validators>
d、日后就可以像使用Struts2提供的16个验证器方式去使用了。
二、Struts2对于i18n的支持
全局资源文件/包范围资源文件/动作类的资源文件
全局资源文件:放到WEB-INF/classes目录下
包范围资源文件:服务于Java类中的包下的动作类的。
取名:package_语言_国家.properties
动作类的资源文件:放到与动作类相同的包中
取名:动作类名_语言_国家.properties
jsp中如何读取国际化的消息
动作类中如何读取国际化的消息
三、OGNL表达式:
1. OGNL简介
OGNL是从ActionContext中获取数据的。使用OGNL表达式需结合struts的<s:property value="OGNL表达式"/>使用
struts2中的OGNL Context实现者为ActionContext,当struts接收一个请求时,会迅速创建ActionContext,ValueStack,action
然后把action放进ValueStack中,所以action的实例变量可以被OGNL访问。
2. ActionContext详解
ActionContext的结构:
ValueStack: List结构:动作类放在此处。
application: ServletContext中的那个Map
session: HttpSession中的那个Map
request: ServletRequest中的那个Map
parameters: 请求参数的那个Map。(如同EL表达式的paramValues内置对象)
attr: 相当于PageContext的findAttribute方法。在四大域范围内依次查找。
注:
valueStack: 取存放在ValueStack中的root的对象的属性,直接写即可,访问其他内容中的对象要使用#+(范围)
访问值栈对象中的属性时,可以直接根据属性名获取。如果栈顶元素没有该属性,则由第二个元素依次查找获取,
如果有多个相同名称的键,也可以由角标来确定
也可以直接通过EL表达式直接访问valueStack中对象的属性,struts2对HttpServletRequest进行了封装
先在request中找,如果找不到,则从栈顶元素找
如: ${username}就是获得值栈中某个对象的属性
application对象: 用于访问ServletContext,例如#application.username或者#application['username'],
相当于调用ServletContext的getAttribute("username");
session对象: 用来访问HttpSession,例如#session.username或者#session['username'],
相当于调用session.getAttribute("username");
request对象: 用来访问HttpServletRequest属性(attribute)的Map,例如#request.username或#request['username']
相当于调用request.getAttribute("username");
parameters对象: 用于访问Http的请求参数,例如#parameters.username或者#parameters['username']
相当于调用request.getParameter("username");
attr对象: 相当于PageContext的findAttribute方法。在四大域范围内依次查找。
page-->request-->session-->application的顺序;
小技巧:在页面中使用<s:debug/>查看上下文中的对象
s:debug标签用来显示对象是放在哪个域中,进而可以由此判断出ongl表达式要如何书写
例:
***********************************************************************************
Action类:
public class PersonAction extends ActionSupport implements Serializable {
private String username;
private int age;
// set/get属性
public String execute(){
// 默认是放到值栈对象中的,可以直接根据属性名获取
username = "zql";
age = 18;
// 放到request中
ActionContext.getContext().put("user", "请求范围");
// 放到session中,须要用#session.键来获取
ActionContext.getContext().getSession().put("user", "sesion范围");
return SUCCESS;
}
}
JSP:
<body>
<!-- 使用OGNL表达式 -->
<s:property value="username"/> <br/>
<s:property value="[0].username"/> <br/>
<s:property value="#request.user"/> <br/>
<s:property value="#session.user"/> <br/>
<s:property value="#attr.user"/> <br/>
<!-- 默认取valueStack中的栈顶对象 -->
<s:property/> <br/>
<!-- EL表达式实现相同的获取 -->
<!-- 注: 此处是ognl表达式对值栈对象中的属性获取的封装,如果没有,则调用findAttribute方法 -->
${username} <br/>
${sessionScope.user} <br/>
${user} <br/>
</body>
***********************************************************************************
3. 利用OGNL表达式创建List/Map集合
创建List集合
***********************************************************************************
<!-- 创建list集合 默认放到了ActionContext上下文件中 scope="action" -->
<s:set var="list1" value="{'a','b','c'}"></s:set> <br/>
<s:set var="list2" value="{'aa','bb','cc'}" scope="action" /> <br/>
<s:set var="list3" value="{'aaa','bbb','ccc'}" scope="session"></s:set> <br/>
<!-- 获取list集合中的元素 -->
<s:property value="#list1[1]"/> <br/>
<s:property value="#list2[1]"/> <br/>
<s:property value="#session.list3[1]"/> <br/> <br/>
<!-- 遍历list集合中的元素 -->
<s:iterator value="#session.list3" var="ls">
<s:property value="#ls"/> <br/>
</s:iterator>
<s:set var="list" value="{'a','b','c'}"></s:set>
<s:iterator value="#list"> <!-- 注: 遍历时,会将当前遍历的对象放到valueStack的栈顶 l="a"-->
<s:property/> <br/>
</s:iterator>
***********************************************************************************
创建Map集合
***********************************************************************************
<!-- 创建map集合 -->
<s:set var="map1" value="#{'a':'valuea','b':'valueb'}" scope="session" />
<!-- 获取map集合中的某个元素的值 ????? 取不出来 待百度 -->
<!-- 利用jstl标签来遍历session域中的map1集合 -->
<c:forEach items="${sessionScope.map1}" var="me">
${me.key} = ${me.value} <br/>
</c:forEach>
<!-- 遍历map集合中的元素 对比jstl标签-->
<s:iterator value="#session.map1" var="me">
<s:property value="#me.key"/> = <s:property value="#me.value"/> <br/>
</s:iterator>
<s:set var="map" value="#{'a':'aa','b':'bb','c':'cc'}"></s:set>
<s:iterator value="#map"> <!-- 注: 遍历时,会将当前遍历的对象放到valueStack的栈顶 me=map.Entry-->
<s:property value="key"/> : <s:property value="value"/> <br/>
</s:iterator>
***********************************************************************************
4. in表达式: <s:if test="'c' in {'a','b'}">
yes
</s:if>
<s:else>
no
</s:else>
not in表达式:
<s:if test="'c' not in {'a','b'}">
yes
</s:if>
<s:else>
no
</s:else>
5. ognl表达式的投影功能
允许使用某个规则获得符合集合对象的子集,常用的有以下3个相关的操作符:
?: 获得所有符合逻辑的元素
^: 获得符合逻辑的第一个元素
$: 获得符合逻辑的最后一个元素
例:
<!-- ognl表达式的投影功能 #this为当前遍历的对象 ?筛选符合条件的对象 -->
<s:iterator value="books.{?#this.price>20}" var="book">
<s:property value="#book.name" /> <s:property value="#book.price"/> <br/>
</s:iterator>
四、Struts2中常用的标签
1. 常用标签
<s:property/>标签:用于输出指定值
ognl表达式动作类中的字段的值
<s:property value="username" />
默认取valueStack中的栈顶对象
<s:property/> <br/>
<s:set/>标签: 用于将某个值放入指定范围。
scope: 指定变量被放置的范围,该属性可以接受application,session,request,page,或action,
如果没有设置该属性,则默认放置在OGNL Context中;
value: 赋给变量的值,如果没有设置该属性,则将ValueStack栈顶的值赋给该变量;
<s:if/else/>:
<s:set var="grade" value="'C'"></s:set> <!-- 如果把一个字符串当成了表达式,再用引号引起来就是字符串了 -->
<s:if test="#grade=='A'">
优秀
</s:if>
<s:elseif test="#grade=='B'">
良好
</s:elseif>
<s:else>
及格
</s:else>
</s:iterator>: 用于对集合进行迭代,包含list,set,和数组
当前迭代的元素在栈顶
<s:set var="records" value="{'辟邪剑法','玉女心经','葵花宝典','金瓶梅','艺术概论','小试牛刀','开发宝典'}" ></s:set>
<table border="1">
<tr>
<th>序号</th>
<th>书名</th>
</tr>
<s:iterator value="#records" status="vs">
<tr bgcolor="<s:property value='#vs.even?"red":"yellow"'/>">
<td>
<s:property value="#vs.count"/>
</td>
<td>
<s:property />
</td>
</tr>
</s:iterator>
</table>
<s:url/>: 生成路径
<!-- 输出: /struts2day03/validate2/user_add.action -->
<s:url action="user_add" namespace="/validate2"></s:url>
<s:url action="a12" var="url"> <!-- 还对URL进行了重写 -->
<s:param name="username" value="'admin'"></s:param> <!-- value的取值被当作表达式了,需要加引号才能转换为字符串 -->
<s:param name="age" value="'28'"></s:param>
</s:url>
<a href="<s:property value="#url"/>">猛点</a> <br/>
<s:set value="'addCustomer'" var="addr"></s:set> <!-- 存放的动作名称 -->
<s:url value="%{#addr}"></s:url> <!-- url标签中value的取值: 默认是当作字符串的 若想要当作是表达式,须使用%{} -->
<s:a action=""/>
表单的标签:
Action类:
public class StudentAction extends ActionSupport implements Serializable {
private String[] hobby1 = {"吃饭","睡觉","打豆豆"}; // 选项
private String[] hobby2; // 被选中的选项
// set/get属性
public String execute(){
hobby2 = new String[]{"打豆豆"};
return SUCCESS;
}
}
JSP:
<body>
<s:checkboxlist name="hobby" list="{'吃饭','睡觉','打豆豆'}" value="{'吃饭','打豆豆'}"></s:checkboxlist> <br>
<s:checkboxlist name="hh" list="hobby1" value="hobby2"></s:checkboxlist> <br>
<hr/>
<s:checkboxlist name="province1" list="#{'0':'北京','1':'上海','2':'深圳'}" value="'2'"></s:checkboxlist> <br>
<s:checkboxlist name="province2" list="#{'北京':'0','上海':'1','深圳':'2'}" listKey="value" listValue="key" value="{'1'}"></s:checkboxlist> <br>
<hr/>
<s:radio list="#{'0':'女','1':'男'}" value="'0'"></s:radio> <br/>
<s:radio list="#{'0':'女','1':'男'}" value="'1'"></s:radio> <br/>
<s:radio list="#{'0':'女','1':'男'}" listKey="key" listValue="value"></s:radio> <br/>
<hr/>
<s:select list="#{'0':'北京','1':'上海','2':'深圳'}" value="'1'"></s:select> <br/>
<s:select list="#{'0':'北京','1':'上海','2':'深圳'}" value="'2'"></s:select> <br/>
<s:select list="#{'0':'北京','1':'上海','2':'深圳'}" listKey="key" listValue="value"></s:select> <br/>
<hr/>
<s:form action="a11" namespace="/xxx">
用户名: <s:textfield name="用户名"></s:textfield>
密码: <s:password name="password"></s:password>
</s:form>
</body>
五、防止表单重复提交
步骤:
1. 在表单中加入<s:token/>标签
2. 在配置文件中的action中加入token的拦截器
<interceptor-ref name="defaultStack"></interceptor-ref>
<interceptor-ref name="token"></interceptor-ref>
3. 并在配置文件中的action中增加一个名称为invalide.token的结果集
<result name="invalid.token">/noSubmitMany/success.jsp</result>
例:
**************************************************************************************************
请求页面:
<body>
<!-- 访问地址: http://localhost:8080/struts2day03/noSubmitMany/addCustomer.jsp -->
<form action="addCustomer" namespace="/noSubmitMany">
<s:token></s:token> <!-- 防止表单重复提交步骤1: 添加s:token标签 -->
<s:textfield name="username" label="用户名"></s:textfield> <br/>
<s:submit value="保存"></s:submit>
</form>
</body>
配置文件:
<package name="noSubmitMany" namespace="/noSubmitMany" extends="struts-default">
<action name="addCustomer" class="cn.itcast.action.AddCustomerAction" method="add">
<!-- 防止表单重复提交步骤2 创建拦截器 -->
<interceptor-ref name="defaultStack"></interceptor-ref>
<interceptor-ref name="token"></interceptor-ref>
<!-- 防止表单重复提交步骤3 创建结果集 注:name="invalid.token" -->
<result name="invalid.token">/noSubmitMany/success.jsp</result>
<result name="success">/noSubmitMany/success.jsp</result>
</action>
</package>
Action类:
public class AddCustomerAction extends ActionSupport implements Serializable {
private String username;
// set/get属性
public String add(){
System.out.println("添加成功!");
return SUCCESS;
}
}
JSP:
<body>
${message}
</body>
**************************************************************************************************
六、 如何使用Struts的插件。(牵扯与其他框架整合)JFreeChart整合
使用标准插件:JFreeChart使用
图形的选择: 将jfreechart-1.0.13整个文件夹拷到C盘下,运行
java -jar C:\jfreechart-1.0.13\jfreechart-1.0.13-demo.jar
即可打开图形,拷贝里面的源码到动作类中,即可
最小jar包:
struts2-jfreechart-plugin-2.1.8.1.jar
jcommon-1.0.16.jar
jfreechart-1.0.13.jar
动作类
public class GetChartAction extends ActionSupport {
private static final long serialVersionUID = -7814290464584999876L;
private JFreeChart chart;
public JFreeChart getChart() {
return chart;
}
public String execute(){
ValueAxis xAxis = new NumberAxis("年度");
ValueAxis yAxis = new NumberAxis("产值");
XYSeries xySeries = new XYSeries("绿豆");
xySeries.add(0,300);
xySeries.add(1,200);
xySeries.add(2,400);
xySeries.add(3,500);
xySeries.add(4,600);
xySeries.add(5,500);
xySeries.add(6,800);
xySeries.add(7,1000);
xySeries.add(8,1100);
XYSeriesCollection xyDataset = new XYSeriesCollection(xySeries);
XYPlot xyPlot = new XYPlot(xyDataset,xAxis,yAxis,new StandardXYItemRenderer(StandardXYItemRenderer.SHAPES_AND_LINES));
chart = new JFreeChart(xyPlot);
return SUCCESS;
}
}
配置文件:
<!-- extends内容查看: WEB-INF/lib/struts2-jfreechart-plugin-2.1.8.1.jar/struts-plugin.xml-->
<package name="p2" extends="jfreechart-default">
<action name="chart" class="wiva.struts2.train.action.GetChartAction">
<result type="chart">
<param name="width">600</param>
<param name="height">400</param>
</result>
</action>
</package>
页面
<body>
<s:url action="chart" var="url"></s:url>
<img src="<s:property value="url"/>" alt="hello" />
</body>