简介
以后如果没有特殊的要说,就在简介中介绍一下大概的知识点。今天主要学习封装请求参数及类型转换、用户输入校验、国际化、拦截器
Struts2封装请求参数的方式
方式一: Action 本身作为model对象,通过成员setter封装(一个名字为params的拦截器实现的) 产生疑问:使用第一种数据封装方式,数据封装到Action属性中,不可能将Action对象传递给 业务层 * 需要再定义单独JavaBean ,将Action属性封装到 JavaBean,得出第二种方式 方式二: 动作类和模型分开,在Action中创建Model对象,页面通过ognl表达式封装 (属性驱动) 方式三: 模型驱动 模型驱动实际上是由一个拦截器来做的。modelDriven拦截器来做。把getModel方法返回的对象,压入一个叫做ValueStack的栈顶。struts框架就会根据表单的name属性,调用对应栈顶对象的setter方法,从而把请求参数封装进来
封装复杂类型参数(集合类型 Collection 、 Map)
1. 封装数据到Collection 对象 页面: 产品名称 <input type="text" name="products[0].name" /><br/>--->注意这里的名字要和Action中的一致 Action : public class ProductAction extends ActionSupport { private List<Product> products; public List<Product> getProducts() { return products; } public void setProducts(List<Product> products) { this.products = products; } } 2. 封装数据到Map 对象 页面: 产品名称 <input type="text" name="map['one'].name" /><br/> ======= one是map的键值 Action : public class ProductAction2 extends ActionSupport { private Map<String, Product> map; public Map<String, Product> getMap() { return map; } public void setMap(Map<String, Product> map) { this.map = map; } }
封装参数--类型转换
1. 显示或者是数据回显:其他类型----->String 基本类型自动转换 boolean 和 Boolean char和 Character int 和 Integer long 和 Long float 和 Float double 和 Double java.util.Date<-------->String(中国:Struts2默认按照yyyy-MM-dd本地格式进行自动转换) # 数组 可以将多个同名参数,转换到数组中 # 集合 支持将数据保存到 List 或者 Map 集合 总结:在使用Struts2时,基本上不用写任何类型转换器。内置的完全够用 2. 自定义类型转换器 a). 实现方式 第一种 实现TypeConverter接口 第二种 继承 DefaultTypeConverter 第三种 继承 StrutsTypeConverter b). 类型转换器 一直都是双向转换 页面提交请求参数,封装到model --- 需要转换 model数据 需要在页面 回显 ---- 需要转换 c). 注册类型转换器 局部注册 : 只对当前Action有效 (针对属性) 全局注册 : 针对所有Action的日期类型有效 (针对类型 ) 局部注册 : 在Action类所在包 创建 Action类名-conversion.properties , 格式 : 属性名称=类型转换器的全类名 全局注册 : 在src下创建 xwork-conversion.properties ,格式 : 待转换的类型=类型转换器的全类名 3. 转换失败时的页面转向和错误消息提示 a、配置一个name=”input”的结果视图,一般指向用户输入数据的那个页面 b、在jsp中使用struts2的标签显示字段有关的错误 <%@ taglib uri="/struts-tags" prefix="s"%> <s:fielderror/> c、配置提示信息为中文的,在动作类所在的包中,建立一个名称为:动作类名.properties的配置文件
用户输入数据的校验
1. 校验方式: a:客户端校验。(防君子不防小人)在页面中写js脚本。 输入错误的话提醒比较及时 减轻服务器的压力 b、服务器端校验 数据安全 ***开发中使用:a+b 2. 服务器端校验 # 编程式校验(代码校验):自己编写一个校验代码(缺点:验证规则都写在了代码中) a). 覆盖validate方法,完成对Action的业务方法 数据校验,在jsp中 通过 <s:fieldError/> 显示错误信息 通过代码逻辑判断参数是否有效,如果参数非法 , this.addFieldError (ActionSupport提供) workflow拦截器 跳转回 input页面 b). 针对指定的动作进行校验 方式一:写了一个validate方法,可以在不需要验证的动作方法前,使用@SkipValidation带有此注解的表示会被忽略验证 方式二:validate方法有一定的书写规范。public void validate动作方法名(首字母大写) 总结:所有验证不通过或转换不同的过的,框架都会转向name=”input”的结果视图。要显示错误提示,使用<s:fieldError/>,显示字段有关的错误提示 # 声明式校验:通过xml配置文件 a). 针对动作类中的所有动作进行校验 在动作类所在的包中,建立一个名称为:”动作类名-validation.xml”配置文件 **引入DTD--xwork-core-2.3.7.jar 中 /com/opensymphony/xwork2/validator/validators/default.xml b). 针对指定的动作进行校验 方式一:使用@SkipValidation 方式二:声明文件遵循一定的书写规范: 动作类名-动作名(struts.xml配置文件中的)-validation.xml c). struts2框架内置的声明式类型验证器 * required (必填校验器,要求被校验的属性值不能为null) * requiredstring (必填字符串校验器,要求被校验的属性值不能为null,并且长度大于0,默认情况下会对字符串去前后空格) * stringlength (字符串长度校验器,要求被校验的属性值必须在指定的范围内,否则校验失败,minLength参数指定最小长度,maxLength参数指定最大长度,trim参数指定校验field之前是否去除字符串前后的空格) * regex (正则表达式校验器,检查被校验的属性值是否匹配一个正则表达式,expression参数指定正则表达式,caseSensitive参数指定进行正则表达式匹配时,是否区分大小写,默认值为true) * int(整数校验器,要求field的整数值必须在指定范围内,min指定最小值,max指定最大值) * double(双精度浮点数校验器,要求field的双精度浮点数必须在指定范围内,min指定最小值,max指定最大值) * fieldexpression (字段OGNL表达式校验器,要求field满足一个ognl表达式,expression参数指定ognl表达式,该逻辑表达式基于ValueStack进行求值,返回true时校验通过,否则不通过) * email(邮件地址校验器,要求如果被校验的属性值非空,则必须是合法的邮件地址) * url(网址校验器,要求如果被校验的属性值非空,则必须是合法的url地址) * date(日期校验器,要求field的日期值必须在指定范围内,min指定最小值,max指定最大值) 3. 自定义声明式校验 a). 编写一个类:实现Validator接口或者继承ValidatorSupport。如果是验证表单字段有关,建议继承FieldValidatorSuppor b). 要注册校验器,在WEB-INF\classes目录下,建立一个固定名称为validators.xml的配置文件 c). 使用校验器在Action所在包 创建Action类名-validation.xml **** 实际开发中很少用到自定义校验器
Struts2的国际化
1. 配置全局国际化消息资源包 在struts.xml中 添加<constant name="struts.custom.i18n.resources" value="messages"></constant> messages.properties 在src根目录 <constant name="struts.custom.i18n.resources" value="cn.itcast.resources.messages"></constant> messages.properties 在 cn.itcast.resources 包中 在Action动作类中: 前提,动作类继承ActionSuppor/this.getText("msg"); 在jsp中使用 :<s:text name="msg" /> 在配置文件中(校验xml) : <message key="agemsg"></message> 2. 配置局部消息资源包 数据只能在对应Action中使用,在Action类所在包 创建 Action类名.properties --------- 无需配置 局部的比全局的优先级高 3. 包范围的消息资源包 数据对包 (包括子包)中的所有Action 都有效 , 在包中创建 package.properties ----- 无需配置 书写有规范的,名称为package_zh_CN.properties,放在类的包中。可以被包中及子包的所有动作类来访问 4. 临时信息文件 (主要在jsp中 引入国际化信息 ) 在jsp指定读取 哪个properties文件 <s:i18n name="cn.itcast.struts2.demo7.package"> <s:text name="customer"></s:text> </s:i18n> 向信息中传递参数 {0} {1} ------------ MessageFormat 动态消息文本 this.getText("required", new String[] { "用户名" });
struts2中的拦截器(框架功能核心)
拦截器 的使用 ,源自Spring AOP(面向切面编程)思想 拦截器 采用 责任链 模式 * 在责任链模式里,很多对象由每一个对象对其下家的引用而连接起来形成一条链。 * 责任链每一个节点,都可以继续调用下一个节点,也可以阻止流程继续执行 在struts2 中可以定义很多个拦截器,将多个拦截器按照特定顺序 组成拦截器栈 (顺序调用 栈中的每一个拦截器 ) 1、 struts2 所有拦截器 都必须实现 Interceptor 接口 2、 AbstractInterceptor 类实现了 Interceptor 接口. 并为 init, destroy 提供了一个空白的实现 所有实际开发中,自定义拦截器 只需要 继承 AbstractInterceptor类, 提供 intercept 方法实现 3、 常用struts2 拦截器 <interceptor-ref name="modelDriven"/> 模型驱动 <interceptor-ref name="fileUpload"/> 文件上传 <interceptor-ref name="params"> 参数解析封装 <interceptor-ref name="conversionError"/> 类型转换错误 <interceptor-ref name="validation"> 请求参数校验 <interceptor-ref name="workflow"> 拦截跳转 input 视图
综合案例
案例 : 登陆,对其它Action访问 通过自定义拦截器 进行权限控制 导入jar包 (struts2 jar、c3p0、 dbutils、 mysql驱动) web.xml struts.xml JDBCUtils 工具类 第一步 : 编写index.jsp 提供 图书增删改查 四个功能 编写BookAction ,提供四个业务方法 第二步: 完成登陆功能 第三步 :必须要登陆 才能进行图书管理 使用Filter 进行权限控制 ---- 过滤所有web请求 (所有web资源访问) 使用拦截器 进行权限控制 ---- 主要拦截对Action访问 (不能拦截JSP) 定义拦截器 继承AbstractInterceptor 配置拦截器 方式一 <!-- 注册拦截器 --> <interceptors> <interceptor name="privilege" class="cn.itcast.interceptor.PrivilegeInterceptor"></interceptor> </interceptors> <action name="book_*" class="cn.itcast.action.BookAction" method="{1}" > <!-- 使用拦截器 --> <!-- 当使用自定义拦截器 后,默认拦截器 就会失效 --> <interceptor-ref name="defaultStack"></interceptor-ref> <interceptor-ref name="privilege"></interceptor-ref> </action> 方式二 <!-- 注册拦截器 --> <interceptors> <interceptor name="privilege" class="cn.itcast.interceptor.PrivilegeInterceptor"></interceptor> <!-- 自定义拦截器栈 --> <interceptor-stack name="privilegeStack"> <interceptor-ref name="defaultStack"></interceptor-ref> <interceptor-ref name="privilege"></interceptor-ref> </interceptor-stack> </interceptors> <!-- 设置当前包 所有Action 都使用 自定义拦截器栈 --> <default-interceptor-ref name="privilegeStack"></default-interceptor-ref>