封装数据(重要)
1.1普通字段,action属性【★★】
*编写表单,提供表单元素,<input name="" /> name的值为普通字符串,及javaweb编写内容。
<inputname="userName">
*将name的值当成action属性(property),提供setter方法
publicvoid setUserName(String uesrName){}
//用于封装数据
private String userName;
public void setUserName(String userName) {
this.userName = userName;
}
private String userPwd;
public void setUserPwd(String userPwd) {
this.userPwd = userPwd;
}
@Override
public String execute() throws Exception {
System.out.println(this.userName);
System.out.println(this.userPwd);
return NONE;
}
}
1.2OGNL表达式,javabean【★】
*编写action提供javabean的setter和getter
privateUser user; setter getter
*修改表单,将name的值格式:user.uesrName ,将给action中user对象的userName进行赋值。
表单
<form action="${pageContext.request.contextPath}/paramDemo02Action" method="post">
用户名:<input type="text" name="userBean.userName"/> <br/>
密码:<input type="text" name="userBean.userPwd"/> <br/>
<input type="submit" value="登录"/>
</form>
action
public class ParamDemo02Action extends ActionSupport {
//用于封装数据
private User userBean;
/* userBean.userName 表达式解析过程
* 首先获得userBean,执行getter,获得对象,此时对象null,将执行setter
* 在执行user对象 userName的setter方法,进行赋值。
* userBean.userPwd
* 先执行userBean的 getter,此时对象已经存在
* 在执行user对象 userPwd的setter方法进行赋值
*/
public User getUserBean() {
return userBean;
}
public void setUserBean(User userBean) {
this.userBean = userBean;
}
@Override
public String execute() throws Exception {
System.out.println(this.userBean);
return NONE;
}
}
1.3普通字段,ModelDriven【★★★】
*javaweb时表单,将数据封装到javabean
*Action编写
1实现接口implements ModelDriven<JavaBean类型>
2提供javabean实例, private User user = new User();
3实现getModel方法,并将javabean实例返回, getModel(){ return this.user;}
//#1.1 实现接口
public class ParamDemo03Action extends ActionSupport implements ModelDriven<User> {
//#1.2 提供实例
private User user = new User();
//#1.3 实现方法
@Override
public User getModel() {
return this.user;
}
@Override
public String execute() throws Exception {
System.out.println(this.user);
return NONE;
}
}
1.4集合(了解)
*通过OGNL表达式给List/Map/Array等容器赋值。
*action中容器必须提供getter和setter方法
建议:之后如果需要给action提供getter或setter,都提供两个方法。
表单
<form action="${pageContext.request.contextPath}/paramDemo04Action" method="post">
用户名1:<input type="text" name="userList[0].userName"/> <br/>
密码1:<input type="text" name="userList[0].userPwd"/> <br/>
用户名2:<input type="text" name="userList[1].userName"/> <br/>
密码2:<input type="text" name="userList[1].userPwd"/> <br/>
<input type="submit" value="登录"/>
</form>
封装
public class ParamDemo04Action extends ActionSupport {
private List<User> userList;
public List<User> getUserList() {
return userList;
}
public void setUserList(List<User> userList) {
this.userList = userList;
}
@Override
public String execute() throws Exception {
for (User user : userList) {
System.out.println(user);
}
return NONE;
}
}
类型转换
2.1默认类型转换
*字符串转换 基本类型(包装类型)
boolean 和 Boolean
char和 Character
int 和 Integer
long 和 Long
float 和 Float
double 和 Double
*字符串转换 数组|集合
*字符串转换 时间 java.util.Date
yyyy-MM-dd或 yyyy-MM-ddHH:mm:ss
注意:
如果类型转换出现错误,struts将返回结果集类型为input,为了给用户提示错误。
需要使用struts标签进行错误信息回显<s:fielderror>
给action配置input
<action name="convertDemo01Action" class="cn.itcast.c_convert.ConvertDemo01Action">
<!--错误处理页面 -->
<result name="input">/c_convert/form1.jsp</result>
</action>
在jsp页面使用jsp标签
<%@taglib uri="/struts-tags"prefix="s" %>
<s:fielderror></s:fielderror>
错误信息修改自定义
Struts2打印的类型转换错误信息是英文的,这说明我们需要自定义错误信息。
自定义错误信息需要在Action(或javabean)所在目录下创建ActionName.properties文件(与Action/javabean同名的properties文件),
然后在该文件中给出:invalid.fieldvalue.属性名=错误信息,其中invalid.fieldvalue是固定的。
例如:invalid.fieldvalue.person=无法将请求参数转换成Person类型!
PersonAction.proeprties
invalid.fieldvalue.person=无法把表单参数转换成Person类型
2.2自定义类型转换
2.2.1实现类
*实现接口:com.opensymphony.xwork2.conversion.TypeConverter
*实现类: com.opensymphony.xwork2.conversion.impl.DefaultTypeConverter
api
publicObject convertValue(Object value, Class toType) {
value:实际值
toType:需要转换的类型
浏览器 发送 服务器 -- 表单提交
*目的:需要字符串 转成 时间
value:字符串数组,及表单提交的数据
String[]request.getParameterValues(name)
toType:时间java.util.Date.class 需要转换的类型
服务器 发送 浏览器 -- 标签回显,必须使用struts标签
*目的:需要时间 转成字符串
value:时间
toType:java.lang.String.class
@Override
publicObject convertValue(Object value, Class toType) {
try{
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy/MM/dd");
//1浏览器 发送服务器,value 字符串[] , toType : date.class
if(Date.class == toType) {
//目的:字符串 转换时间
String[] params = (String[]) value;
String firstParam = params[0];
return simpleDateFormat.parse(firstParam);
}
//2服务器 发送浏览器 -- 回显 , value 时间, toType String.class
if(String.class== toType){
//目的:将时间 转成字符串
Date date = (Date) value;
return simpleDateFormat.format(date);
}
}catch (Exception e) {
throw new RuntimeException(e);
}
return super.convertValue(value, toType);
}
2.2.2编写配置文件
2.2.2.1局部转换器
*只对当前action中属性有效,及private Date birthday; getter
*文件位置:与action类同包
*文件名称:Action类名-conversion.properties
例如:UserAction-conversion.properties
*文件内容:
action属性名 = 转换器的全乡定类名
例如:birthday = cn.itcast.....
2.2.2.2全局转换器
*使用范围:所有的action
*文件位置:src
*文件名称:xwork-conversion.properties
*文件内容:
需要转换类型的全限定名称 = 转换器
例如:java.util.Date = cn.itcast....
数据校验
3.1介绍
*浏览端校验:使用JavaScript,之后使用JavaScript的框架 jQuery,但JS校验不安全。
*服务器校验:更安全,理论必须完成。必须首先获得数据,然后再进行校验。提供一个特殊的javabean接收表单的数据,类型必须是String
3.2struts校验
3.2.1手动校验
*Action类所有方法校验
Action必须实现接口:Validateable ,但 ActionSupport类已经实现了
实现方法:validate()
*Action类指定方法校验
编写方法:validate方法名()
*总结:先执行“指定方法”,再执行“所有方法”
*跳过某个方法的校验
为不需要校验的方法@SkipValidation注解
*阻止目标方法的执行,及校验没有通过。
使用
public void validateAdd() {//方法首字母必须大写
// 将返回 input ,到指定的jsp显示错误信息
this.addFieldError("userName", "用户名已经存在");
解释
addActionError() action类存在错误。
<s:fielderror>jsp显示错误
addActionMessage action类希望发送提示信息
<s:actionmessage/>jsp显示错误
addFieldError 用户输入有误添加
<s:actionerror/>jsp显示错误
3.2.2xml配置校验(重要)
*全部方法校验:
文件位置:Action类同包
文件名称:Action类名-validation.xml
文件内容:添加约束,确定标签名称
*单个方法校验:
文件位置:Action类同包
文件名称:Action类名-配置名称-validation.xml <action name="配置名称">
文件内容:添加约束,切点标签名称
例如:访问路径,/personAction_add
单个方法文件名称,PersonAction-personAction_add-validation.xml
*xml约束
位置:lib\xwork-core-2.3.15.1.jar /xwork-validator-1.0.3.dtd
内容:
<!DOCTYPE validators PUBLIC
"-//Apache Struts//XWork Validator1.0.3//EN"
"http://struts.apache.org/dtds/xwork-validator-1.0.3.dtd">
@InputConfig(resultName="loginInput") //登录校验返回位置(修改登陆校验返回值)
*数据校验类型
struts已经提供可以使用类型,用此类型可以约束字段。
位置:xwork-core-2.3.15.3.jar!/com/opensymphony/xwork2/validator/validators/default.xml
required,必填,底层判断是否为null
requiredstring,必须是字符串,底层判断 "".trim() 【】
int、long、short、double,是否整形【】
date,日期【】
expression,表达式
fieldexpression,字段表达式。多个字段之间操作【】
email,邮件【】
url,访问路径
conversion,转换
stringlength,字段长度【】
regex,正则表达式【】
3.2.3注解校验 (用于取代xml) (暂不研究)
3.3xml校验步骤(练习)
3.3.1编写表单
*struts标签:标签可以回显
*位置:/struts_day02/WebRoot/d_validate/form2.jsp
<s:form namespace="/" action="userAction_register">
<s:textfield name="username" label="用户名"></s:textfield>
<s:password name="password" label="密码" showPassword="true"></s:password>
<s:password name="repassword" label="确认密码" showPassword="true"></s:password>
<s:textfield name="email" label="邮箱"></s:textfield>
<s:textfield name="age" label="年龄"></s:textfield>
<s:textfield name="userId" label="身份证"></s:textfield>
<s:submit value="注册"></s:submit>
</s:form>
3.3.2编写struts.xml
*配置action
<!-- #4.2 xml校验 -->
<action name="userAction_*" class="cn.itcast.d_validate2.UserAction" method="{1}">
<!-- 校验成功 -->
<result>/d_validate/success.jsp</result>
<!-- 校验不成功 -->
<result name="input">/d_validate/form2.jsp</result>
</action>
3.3.3编写action类
*位置:/struts_day02/src/cn/itcast/d_validate2/UserAction.java
public class UserAction extends ActionSupport implements ModelDriven<User>{
//封装数据
private User user = new User();
public User getModel(){
return user;
}
//################################3
public String register(){
System.out.println(user);
return SUCCESS;
}
}
*表单可以正常提交,数据都自动封装到javabean中。需要提供javabean。
3.3.4添加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>
<!-- #1 用户名进行校验 -->
<field name="username">
<!-- 必填 -->
<field-validator type="requiredstring">
<message>用户名不能为空</message>
</field-validator>
<!-- 范围 -->
<field-validator type="stringlength">
<param name="minLength">2</param>
<param name="maxLength">16</param>
<message>用户名必须${minLength}-${maxLength}之间</message>
</field-validator>
</field>
<!-- #2 密码 和 确认密码必须一致 -->
<field name="repassword">
<field-validator type="fieldexpression">
<param name="expression">password == repassword</param>
<message>密码 和 确认密码不一致 </message>
</field-validator>
</field>
<!-- #3 邮件 -->
<field name="email">
<field-validator type="email">
<message>邮件格式不正确,例如:zuoci@itcast.cn</message>
</field-validator>
</field>
<!-- #4 整形 -->
<field name="age">
<field-validator type="int">
<param name="min">18</param>
<param name="max">120</param>
<message>年龄必须${min}-${max}之间</message>
</field-validator>
</field>
<!-- #5 身份证,使用正则 -->
<field name="userId">
<field-validator type="regex">
<param name="regex"><![CDATA[^[\d]{6}-[\d]{8}-[\d]{4}$]]></param>
<message>身份证格式不对,例如:142729-19960808-0001</message>
</field-validator>
</field>
</validators>
国际化(了解)
4.1介绍
*国际化:i18n , internationalization ,全球不同国家的人,使用软件看到界面问题提示不同。
*国际化资源文件:用于配置不同国家的提示信息
格式:baseName[_语言[_国家|地区]].properties
例如:message_zh_CN.properties
内容:key=value
注意:不支持非英文资源
4.2struts 国际化资源文件
*action单独使用:同包,同名
*指定包:package.properties ,当前包下的所有的action可以使用
*给整个web设置,需要在struts.xml配置
<!-- 配置使用哪些国际化资源文件
* src/message.properties ,value="message"
* src/cn/itcast/message.properit,value="cn/itcast/message"
* 多个文件使用逗号分隔
-->
<constant name="struts.custom.i18n.resources" value="message"></constant>
*struts标签也可以使用国际化
通过执行action到jsp
<s:text name="username"></s:text>
<s:text name="password"></s:text>
<s:text name="company"></s:text><span style="font-family: Arial, Helvetica, sans-serif; font-size: 12px; background-color: rgb(255, 255, 255);"> </span>
执行使用jsp
<s:i18n name="cn.itcast.e_i18n.I18nDemoAction">
<s:text name="username"></s:text>
</s:i18n>
拦截器(重点)
5.1介绍
*拦截器:struts2提供用于在目标方法之前或之后编写内容一种程序,简称为方法增强。
每一个拦截器完成一个功能。
*拦截器栈:一组拦截器的组合,完成一组功能。
默认拦截器:struts-default.xml 配置好的。 defaultStack
5.2默认拦截器栈分析(多读)
workflow 拦截器,默认出现错误时,返回的是input结果集名称。
通过给目标方法添加注解 @InputConfig 配置出现错误时,返回结果集名称。@InputConfig(resultName="自定义返回值")
默认拦截器关联值栈分析图
5.3自定义拦截器
3种自定义拦截器的方式:
1.实现interceptor接口
2.继承Abstractceptor抽象类
3.继承MethodFilterInterceptor抽象类
书写拦截器步骤:
1.书写拦截器类
2.在xml中注册拦截器
3.在action/拦截器栈中引用拦截器
*接口:com.opensymphony.xwork2.interceptor.Interceptor
*实现类:com.opensymphony.xwork2.interceptor.MethodFilterInterceptor
过滤 或 指定 需要执行的方法
*放行:ActionInvocation.invoke();
案例:用户登录
6.1自定义拦截器使用
6.1.1编写自定义拦截器
*位置:/struts_login/src/cn/itcast/interceptor/LoginInterceptor.java
public class LoginInterceptor extends MethodFilterInterceptor {
@Override
public String doIntercept(ActionInvocation ai) throws Exception {
//判断session是否存在用户
Object loginUser = ActionContext.getContext().getSession().get("loginUser");
if(loginUser == null){
//需要登录
return "nonLogin"; //直接返回没有登录
}
//已经登录--放行
return ai.invoke();
}
}
6.1.2配置自定义拦截器
*拦截器必须注册才能使用
*如果使用,将覆盖默认。
<struts>
<!-- 开发模式:自动加载配置文件 -->
<constant name="struts.devMode" value="true" />
<package name="default" namespace="/" extends="struts-default">
<!-- #1 拦截器:1.必须注册 2.使用 () -->
<interceptors>
<!-- #1.1 注册 -->
<interceptor name="loginInterceptor" class="cn.itcast.interceptor.LoginInterceptor"></interceptor>
</interceptors>
<action name="userAction_*" class="cn.itcast.action.UserAction" method="{1}">
<!-- 登录成功 ,重定向首页(action:方便管理,及可以使用拦截器,jsp不使用拦截器)-->
<result name="success" type="redirectAction">userAction_home</result>
<!-- 首页 -->
<result name="home">/pages/success.jsp</result>
<!-- 错误处理 -->
<result name="input">/index.jsp</result>
<!-- # 需要登录 -->
<result name="nonLogin">/index.jsp</result>
<!-- #1.2 使用自定拦截器,如果使用,将覆盖默认拦截器栈。
* 必须先引用默认栈,使用struts原有的功能
* 在使用自定义的,完成登录校验
-->
<interceptor-ref name="defaultStack"></interceptor-ref>
<interceptor-ref name="loginInterceptor">
<!-- 如果是登录方法,就不拦截 -->
<param name="excludeMethods">login</param>
</interceptor-ref>
</action>
</package>
</struts>