封装数据(重要)
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>邮件格式不正确,例如:[email protected]</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();
注意:每个包只能指定一个默认拦截器。另外,一旦我们为该包中的某个action显式指定了某个拦截器,则默认拦截器不会起作用
案例:用户登录
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>