<filter>
<filter-name>struts2</filter-name>
<filter-class>
org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter
</filter-class>
</filter>
<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
"http://struts.apache.org/dtds/struts-2.3.dtd">
<!-- 头部信息可以在自带jar包的例子中找 -->
<struts>
</struts>
命名规则: actionname+“-”+conversion.properties
配置demo:birthday = cn.xiaoge.convert.MyConverter
birthday:需要转换的字段名称
cn.xiaoge.convert.MyConverter:自定义类型转换器的全称类名
1.4.1 自定义拦截器类
a. 实现Interceptor接口
b. 继承AbstractInterceptor类
c. 继承MethodFilterInterceptor类(首选)
1.4.2 配置拦截器(在struts.xml中配置)
a.注册自定义拦截器
b.自定义拦截器栈
c.将自定义拦截器栈生命为默认拦截器栈
<interceptors>
<!-- #1 配置自定义的拦截器 -->
<interceptor name="loginInterceptor" class="cn.xiaoge.web.interceptor.LoginInterceptor">
</interceptor>
<!-- #2 配置自定义拦截器栈 -->
<interceptor-stack name="loginStack">
<interceptor-ref name="defaultStack"></interceptor-ref>
<interceptor-ref name="loginInterceptor">
param name="excludeMethods">login</param>
</interceptor-ref>
</interceptor-stack>
</interceptors>
<!-- 3.配置自定义拦截器栈 -->
<default-interceptor-ref name="loginStack"></default-interceptor-ref>
1.5.1 全局配置
命名规则:配置名+“_”+“国家”+”_”+“地区”(可省略)+”.properties”
存放位置: src目录下
配置文件中配置: name = value
在jsp中的用法:<s:text name="tip"></s:text>
备注: tip是配置文件中的name
在struts.xml中配置:
<constant name="struts.custom.i18n.resources" value="wel"></constant>
1.5.2 包级别配置
命名规则:配置名+“_”+“国家”+”_”+“地区”(可省略)+”.properties”
存放位置:相应包下
备注:在通过action访问页面时,会加载包级别的国际化资源配置
1.5.3 action级别配置
命名规则:Action名字+“_”+“国家”+”_”+“地区”(可省略)+”.properties”
存放位置:与相应的action同包
备注:访问action时,会加载action级别的国际化资源配置,
1.5.3 临时配置
命名规则:配置名+“_”+“国家”+”_”+“地区”(可省略)+”.properties”
存放位置:src文件夹下
备注:在jsp中使用方法(其中,“ls”是临时配置文件的文件名)
<s:i18n name="ls">
<s:text name="tip"></s:text>
</s:i18n>
备注:
在action中使用时:(使用getText()方法)
public class I18nAction extends ActionSupport {
private String name;
@Override
public String execute() throws Exception {
addFieldError("name", getText("title"));
System.out.println(getText("title"));
return SUCCESS;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
在xml文件中使用时:(title是国际化配置文件中的键)
<validators>
<field name="name">
<field-validator type="requiredstring">
<message key="title" ></message>
</field-validator>
</field>
</validators>
1.6.1 xml配置信息(记得添加dtd文件: xwork-core-2.3.15.3.jar /xwork-validator-1.0.3.dtd)
单个方法进行校验配置(针对某个action的方法有效)
命名规则:ActionName +“-”+ action的请求路径(xx_add) +“-”+validation.xml
放置位置:与访问的action同包
全局方法进行校验配置(对action中的所有方法有效)
命名规则:ActionName +“-”+validation.xml
放置位置:与访问的action同包
1.6.2 数据校验器:
位置:xwork-core-2.3.15.3.jar /com.opensymphony.xwork2.validator.validators/default
<validator name="required" 判断对象是否为空
<validator name="requiredstring" 判断字符串是否为空
<validator name="int" 可判断数值范围
<validator name="long" 可判断数值范围
<validator name="short" 可判断数值范围
<validator name="double" 可判断数值范围
<validator name="date" 可判断日期范围
<validator name="expression" 可判断表达式
<validator name="fieldexpression"
<validator name="email" 可判断格式是否符合eamil的格式
<validator name="url" 可判断格式是否符合URL格式
<validator name="visitor"
<validator name="conversion"
<validator name="stringlength"
<validator name="regex" 可用来自定义正则表达式
<validator name="conditionalvisitor"
1.6.3 xml验证案例:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE validators PUBLIC
"-//Apache Struts//XWork Validator 1.0.3//EN"
"http://struts.apache.org/dtds/xwork-validator-1.0.3.dtd">
<validators>
<field name="name">
<field-validator type="requiredstring">
<message>用户名不能为空</message>
</field-validator>
</field>
<field name="age">
<field-validator type="required">
<message>年龄不能为空</message>
</field-validator>
<field-validator type="int">
<param name="min">1</param>
<param name="max">160</param>
<message>请输入${min}到${max}之间的数字</message>
</field-validator>
</field>
<field name="birthday">
<field-validator type="date">
<param name="min">1900-01-01</param>
<param name="max">2016-01-01</param>
<message>请输入有效日期[${min}-${max}]</message>
</field-validator>
</field>
</validators>
1.6.4 手动数据校验
在action中,重写validate方法(action必须先继承ActionSupport类)
@Override
public void validate() {
if("".equals(vname.trim()) || vname.length() == 0){
addFieldError("", "用户名不能为空");
}
if("".equals(vpsd.trim()) || vpsd.length() == 0){
addFieldError("", "密码不能为空");
}else{
if(vpsd.length() < 6){
addFieldError("", "密码长度不能低于6位");
}
}
}
小结:
配置文件比较总结 |
||||
配置类型 |
web.xml |
struts.xml |
.xml文件 |
.properties文件 |
前端控制器 |
1 |
|
|
|
Action配置 |
|
1 |
|
|
数据转换器 |
|
|
|
1 |
拦截器 |
|
1 |
|
|
数据校验器 |
|
|
1 |
|
国际化资源 |
|
1 |
|
1 |
OGNL可分为context与root部分(存放数据,要求有OgnlContext对象)
context中存放Map类型数据,root理论上存放任何类型数据(root底层也是map)
//获取root中对象的username属性值
System.out.println(Ognl.getValue("userName", oc, oc.getRoot()));
//获取context中键名为name1的值的长度
System.out.println(Ognl.getValue("#name1.length()", oc, oc.getRoot()));
//获取context中键名为name2的值
System.out.println(Ognl.getValue("#name2", oc, oc.getRoot()));
//将context中键名为name2的值以大写形式输出
System.out.println(Ognl.getValue("#name2.toUpperCase()", oc, oc.getRoot()));
//获取数组中指定位置的值
System.out.println(Ognl.getValue("{1,2,3}[2]", oc, oc.getRoot()));
System.out.println(Ognl.getValue("{1,2,3}.get(2)", oc, oc.getRoot()));
//获取数组中指定键的值
System.out.println(Ognl.getValue("#{'name':'tommap','age':18}['name']", oc, oc.getRoot()));
System.out.println(Ognl.getValue("#{'name':'tommap','age':18}.get('name')", oc, oc.getRoot()));
//投影及选择都是对list而言的
//投影(记得是在root中取值,即list)
List<User> list = new ArrayList<User>();
list.add(new User("tom",18));
list.add(new User("jack",20));
list.add(new User("jerry",12));
list.add(new User("rose",16));
oc.setRoot(list);
System.out.println(Ognl.getValue("#this.{userName}", oc, oc.getRoot()));
//选择(从投影结果中,选取内容)
System.out.println(Ognl.getValue("#this.{?age > 15}.{userName}", oc, oc.getRoot()));
备注:
获取root中的数据,不需要添加“#”,但是获取Context中的数据,必须添加“#”
访问静态类的静态方法或属性,需要在类前及方法前添加“@“
将strut2中的Map类型数据,放到ognl的context中,其他类型数据放入到root,以便在前台jsp页面中,利用ognl表达式进行取值显示。
其中,需要用到ActionContext进行存值
表单标签demo:
<s:form action="personAction" namespace="/" method="post">
<s:textfield name="name" label="姓名"></s:textfield>
<s:password name="password" label="密码"></s:password>
<s:textfield name="age" label="年龄"></s:textfield>
<s:select list="#{'UK':'英国','US':'美国','KR':'韩国'}" label="国籍" name="country" headerKey="CN" headerValue="中国"></s:select>
<s:radio list="#{'boy':'男','girl':'女'}" name="gender" label="性别"></s:radio>
<s:checkboxlist name="hobby" label="爱好" list="{'篮球','足球','乒乓球'}"></s:checkboxlist>
<s:submit value="提交"></s:submit>
</s:form>
数据标签:
<s:if if elseif else一般连用,类似于c标签库中的 <c:choose>标签
<s:elseif
<s:else
<s:iterator 迭代器,用法类似于c标签库中的 <c:foreach>标签
<s:iterator value="#person.hobby" var="hob">
<s:property value="hob"/>
</s:iterator>
控制标签:
a 超链接标签,提供namespace与actionname可自动拼装访问路径
param 参数标签,一般与a标签连用,用来存放标签中的参数
url 访问路径标签,可以自动生成路径,在拼装时,注意设置escapeApm属性
property 属性标签,用来获取ognl中存放的数值
非表单标签:
ActionMessage action中的提示信息
ActionError action中的错误信息
FiledError 字段错误信息
文件上传中jsp的要求:
(1)form中enctype=”multipart/form-data”
(2)form表单的提交方式要求是post
(3)form中上传组件的name要与action中的file的name保持一致
Action中要求:
(1)要求准备三个属性:
private File image; //其中image是上传的jsp文件中的组件名
private String imageFilename; //用于保存上传文件的文件名
private String imageContentType; //用于保存上传文件的文件类型
(2)准备这个三个属性的setter方法: 用于封装上传文件的相关数据
Action中execute的流程:
(1)获取上传位置的真实路径
String dir = ServletActionContext.getServletContext().getRealPath("/WEB-INF/temp");
(2)拷贝文件
FileUtils.copyFile(image, new File(dir , imageFileName));
(3)返回视图
jsp页面:
准备下载的超链接,action=“执行下载操作的action”
下载action中:
准备两个属性:
private InputStream target; //用于存放文件流
private String downName; //用于存放文件名
准备这两个属性的getter方法:getTarget() 及getDownName()
//getter方法作用:便于在strust.xml中读取字符流,获取文件名
准备执行的下载方法:
在方法中准备 InputStream 及 文件名:
//下载文件
public String download() throws UnsupportedEncodingException{
//获取下载的文件名
String dname = ServletActionContext.getRequest().getParameter("dfilename");
//解决下载文件中的中文乱码问题
this.downName = new String(dname.getBytes("ISO-8859-1"),"UTF-8");
//获取下载的文件路径并以流的方式获取要下载的文件
String dpath = ServletActionContext.getRequest().getParameter("dpath");
this.target = ServletActionContext.getServletContext().getResourceAsStream(dpath);
//返回视图
return "download";
}
struts.xml中配置:
<result name="download" type="stream">
<param name="contentDisposition">attachment;filename=${downName}</param>
<param name="inputName">target</param>
</result>
类似于验证码的功能,主要用于避免表单的重复提交,恶意注册等
jsp中:
随机生成一个字符串
将随机字符串存放到session作用域
将随机字符串以隐藏域的方式发送给浏览器
(<input type=”hidden”name=”token” value=”随机字符串”>)
token拦截器:
获得session中存放的随机字符串,然后将session作用域的内容移除
获得标签提交的隐藏域的字符串
将获得的session中的字符串与表单提交的字符串进行比较匹配
如果一致,正常提交;
如果不一致,返回字符串“invalid.token”
自定义实现:
<%--
//自定义实现
String tokenId = UUID.randomUUID().toString(); //生成随机字符串
session.setAttribute("tokenId", tokenId); //将字符串放到session域中
//将随机字符串放到hidden标签中,并在浏览器端保存
out.print("<input type='hidden' name='mytoken' value='"+tokenId+"'>");
--%>
jsp中代码:
<s:form namespace="/" action="demo05Action">
<s:token></s:token>
<s:submit value="提交"></s:submit>
</s:form>
action中代码:
public String execute() throws Exception {
System.out.println("成功");
return NONE;
}
struts.xml中配置:
<action name="demo05Action" class="cn.itcast.demo05.TokenAction">
<!-- token出错处理 -->
<result name="invalid.token">/demo05/message.jsp</result>
<!-- 添加拦截器,属于action级别的拦截器,与package级别的拦截器不同-->
<interceptor-ref name="defaultStack"></interceptor-ref>
<interceptor-ref name="token"></interceptor-ref>
</action>
message.jsp中代码:(用于显示错误信息)
<s:fielderror></s:fielderror>
<s:actionerror/>