Struts2(二)之封装请求正文、数据类型转换、数据验证
一、封装请求正文到对象中(重点)
1.1、静态参数封装
在struts.xml文件中,给动作类注入值,使用的是setter方法
1.2、动态参数封装
通过用户表单封装请求正文参数
1.2.1、动作类作为实体模型
也就是说动作和实体模型写在一起。
实体模型:entity。对应数据库中表的记录(类对应的是表的结构,而对象对应的是一条记录)
1.2.2、数据模型和动作类分开写
数据模型:User 动作类:Demo2Action
原理:当我们在动作类中的SetUser和getUser分别输出时
所以我们可以自己实例化User对象也可以不用自己实例化。
1.2.3、模型驱动(开发中采用的方式)
要想使用模型驱动,数据模型和动作类必须分开写。
实现数据模型的步骤:
1.实现一个ModelDriven的接口
2.实现接口里的方法getModel()
3.在使用模型驱动的时候,数据模型必须由我们来完成实例化
是由一个ModelDriven的拦截器帮我们做的
二、基于数据模型封装请求正文编写一个demo
目录的总体结构
我编写的步骤是这样的先建立数据库表
根据数据库表写出User的实体类
写业务层service接口然后业务层的实现类serviceImpl
写dao层,记得在这里要配置数据库的jar包
然后写表单jsp,编写struts.xml,编写动作类
三、数据类型转换
3.1、开发中的情况
实际开发中用户输入的数据都是String或String[].
string/String[]——填充模型(set方法)——POJO(plain old java object)pojo中有java的数据类型
POJO——获取(get方法)——页面展示String
3.2、类型转换情况
写数据:(增、删、改)都是String或string[]转换成其他类型
读数据:(查)其他数据类型转换成String
3.3、Struts2提供的常用类型转换
A.基本数据类型自动转换
B.日期类型:默认按照本地日期格式转换(yyyy-MM-dd)
C.字符串数组:默认用逗号+空格,连接一个字符串
3.4、自定义类型转换器
从这张图可以看的出来如果你想要自定义一个类型转换器的话需要集成StrutsTypeConverter类
3.4.1、创建一个MyTypeConvertor继承StrutsTypeConverter类
package com.jxlg.web.converter; import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Map;
/**
* 需求:
* 把表单中的MM/dd/yyyy格式的数据转换成日期类型
* 把数据库的本地日期格式,转化成MM/dd/yyyy形式输出
*
* 自定义子类转换器:
* 1.编写一个类,继承自StrutsTypeConverter,实现convertFromString和convertToString抽象方法
*/ import org.apache.struts2.util.StrutsTypeConverter; public class MyTypeConvertor extends StrutsTypeConverter {
//定义一个类型转换器
private DateFormat format = new SimpleDateFormat("MM/dd/yyyy"); /**
* 把字符串数组中的数据转化成日期类型
*
* 方法参数详解:
* Map context:是OGNL的上下文对象,我们暂时不知道。
* String[] values:要转换的数据类型
* Class toClass:目标类型
*/
public Object convertFromString(Map context, String[] values, Class toClass) {
//1.先看看有没有数据
if(values==null ||values.length==0){
return null;
}
//2.取出数组中的第一个元素
String date = values[0];
//3.判断目标类型的字节码是不是日期类型
if(toClass == java.util.Date.class) {
//4.使用DateFormat进行转换,并返回转换后的结果
try {
return format.parse(date);
} catch (ParseException e) {
e.printStackTrace();
return null;
}
}
return null;
} /**
* 把日期类型转换成字符串
*/
public String convertToString(Map context, Object o) {
//1.判断object是不是日期类型
if(o instanceof Date){
Date date = (Date)o;
//2.是日期类型,使用转换器转成指定格式的字符串,并返回
return format.format(date);
}
return null;
} }
3.4.2、注册类型转换器
局部类型转换器:只能指定javabean中的属性来用
按照属性来注册,在属性所属的javaBean的包下建立一个.properties文件。
文件名称命名规范:javabean名称-conversion.properties。
全局类型转换器(开发中使用这种模式开发)
按照要转换的数据类型来注册
存放位置:at the top op classpath(类路径的根路径) ,建立一个固定名称xwork-conversion-properites的属性文件。
3.5、转换失败后的处理(重点)
当转换失败后,页面的提示
解决办法:配置回显结果试图
四、数据验证
用户的输入验证,必须做,且工作量巨大。
4.1、验证方式
客户端验证:javascript
服务端验证:逻辑验证
注意:如果客户端和服务端验证二选一,服务端必不可少。
实际开发中:服务端+客户端都需要验证
4.2、Struts2的服务端验证
在struts2的框架中,它也提供了一个Map<表单的字段名,错误提示>,我们要做的:往map中存放错误信息
4.2.1、编程式验证
前提:动作类必须继承ActionSupport
重写validate方法
注意:validate方法会在动作方法执行之前,进行验证。
举例
第一步:在动作类UserAction中继承AcctionSupport,重写Validate方法
备注:StringUtils是struts框架中org.apache.commons.lang3.StringUtils,jar包中的,增强了String的功能
第二步: register.jsp
第三步:配置struts.xml文件
第四步:测试(没有输入用户名直接按注册)
问题:当重写了validate方法,它会对动作类中的所用动作方法进行验证。
在UserAction中添加动作方法
testValidate.jsp
最后创建一个index.jsp用来测试
结果:
当我们注释掉Validate方法时。
解决验证所有动作方法的问题:
第一种方式:
使用@SkipValidation的注解
就是我们不需要去验证testValidate方法我们就在定义方法的上面进行注释
第二种方式:
定义验证方法的名称:validate+动作名称 动作名称的首字符还要大写
public void validateRegister(){
if(StringUtils.isEmpty(user.getUsername())){
//存入错误信息,直接调用父类的addFieldError方法,存入错误信息。第一个参数是表单name属性的值。第二个参数是错误提示
addFieldError("username", "请输入用户名");
}
编程式验证弊端:硬编码
4.2.2、声明式验证
Struts内置的常用声明式验证器位置:
通过编写验证规则的xml文件。需要验证时,编写xml文件,不要验证,就不要写。
优点:解决了编程式验证的弊端
A.针对动作类的所有动作进行验证:在动作类所在的包中,建立一个ActionClassName-validation.xml的文件
测试前要先把前面的validate方法注释和testValidate都注释
<?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">
<!-- 当使用ActionClassName-validation.xml来命名文件时,它是一个动作类验证器。会验证动作类中的所有动作方法 -->
<validators>
<!-- 基于字段的声明式验证 -->
<!-- field中name属性指定的是表单name属性的取值 -->
<field name="username">
<!-- struts2框架为我们集成了很多的内置验证器。requiredstring会验证输入内容是否为空,是否为空字符串。并且去掉左右空格-->
<field-validator type="requiredstring">
<message>请输入用户名</message>
</field-validator>
</field>
</validators>
这是一个会验证所有动作方法的,又回到了我们上面编程式验证所遇到的问题。那我们怎么去解决呢?
解决一:使用@SkipValidation的注解
解决二:定义一个针对验证动作类中某个动作方法的xml
B.针对动作类中的某个动作进行验证:在动作类所在的包中建立一个xml文件,名称为ActionClassName-ActionName-validaton.xml的文件
内容和上面的一样,只是修改一下名称。
test:访问index.jsp
基于验证器的验证
<?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">
<!-- 当使用ActionClassName-ActionName-validation.xml来命名文件时,它是一个指定动作方法的验证器。只会验证指定的动作方法 -->
<validators>
<field name="username">
<field-validator type="requiredstring">
<message>请输入用户名必须要输入</message>
</field-validator>
</field> <!-- 基于验证器的验证 -->
<validator type="requiredstring">
<!-- 以注入的方式,提供要验证的字段信息
setFieldName("password");
-->
<param name="fieldName">password</param>
<message>密码必须输入</message>
</validator>
</validators>
为什么param中的name是filedName呢
我们可以查看一下源码
查看的源码
找父类
五、基于声明式验证的demo
第一步:编写一个Student.java
package com.jxlg.domain; import java.io.Serializable;
/**
* URL:uniform resource locator 统一资源定位符
* http://localhost:6060/studentManagement/home.jsp
* 协议 主机 端口 URI
* URI:uniform resource identifier 统一资源标识符
* studentManagement/home.jsp
* @author Shinelon
*
*/
public class Student implements Serializable {
private String username;//不能为null和空字符串。要去空格
private int age;//整数,介于18-100之间
private String email;//按照邮箱的格式输入
private String password;//密码。长度3-8位
private String repassword;//确认密码,必须和密码一致。写在这里的目的,完全是为了演示验证器的使用。实际开发中根本不会保存确认密码。
private int score;//成绩,必须是自然数
private String url;//个人主页:必须符合url格式
private String gender;//性别
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getRepassword() {
return repassword;
}
public void setRepassword(String repassword) {
this.repassword = repassword;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
public int getScore() {
return score;
}
public void setScore(int score) {
this.score = score;
} }
第二步:编写一个student.jsp
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ taglib uri="/struts-tags" prefix="s" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
</head>
<body>
<s:actionerror/>
<%-- <s:fielderror />字段错误
动作错误 --%>
<%--struts2的form标签,它提供了和原始html表单标签几乎一致的属性
action:请求地址。直接写动作名称。不用写contextPath
method:请求方式。在这里可以不写,struts的form表单中默认是post
enctype:表单编码的MIME类型 --%> <s:form action="addStudent.action">
<s:textfield name="username" label="用户名" />
<s:textfield name="age" label="年龄" />
<s:textfield name="email" label="邮箱" />
<s:textfield name="password" label="密码"/>
<s:textfield name="repassword" label="确认密码"/>
<s:textfield name="score" label="成绩"/>
<s:textfield name="url" label="个人主页"/>
<%--list中的取值是生成一个list集合,并往集合中放入元素 --%>
<s:radio name="gender" list="{'男','女'}" label="性别"/>
<s:submit value="注册"/>
</s:form>
</body>
</html>
第三步:编写一个struts.xml,配置addStudent.action
<?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">
<struts>
<constant name="struts.devMode" value="true"></constant>
<package name="p1" extends="struts-default"> <!-- 声明式验证器的案例的动作类配置 -->
<action name="addStudent" class="com.jxlg.web.action.StudentAction" method="addStudent">
<result name="input">/student.jsp</result>
</action>
</package>
</struts>
第四步:编写StudentAction动作类继承ActionSupport类和实现modelDriven接口
package com.jxlg.web.action; import com.jxlg.domain.Student;
import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.ModelDriven; public class StudentAction extends ActionSupport implements ModelDriven<Student> { private Student stu = new Student();
public Student getModel() {
return stu;
} public String addStudent(){
return SUCCESS;
}
public Student getStu() {
return stu;
}
public void setStu(Student stu) {
this.stu = stu;
} }
第五步:编写UserAction-register-validation.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="username">
<field-validator type="requiredstring">
<message>请正确输入用户名</message>
</field-validator>
</field>
<field name="age">
<field-validator type="int">
<param name="min">18</param>
<param name="max">100</param>
<message>请输入18-100之间的整数</message>
</field-validator>
</field>
<field name="email">
<field-validator type="email">
<message>请输入正确的邮箱格式</message>
</field-validator>
</field>
<field name="password">
<field-validator type="requiredstring">
<!-- 注入取消使用trim -->
<param name="trim">false</param>
<message>请输入密码</message>
</field-validator>
<field-validator type="stringlength">
<param name="minLength">3</param>
<param name="maxLength">8</param>
<message>请输入3-8位的密码</message>
</field-validator>
</field> <!-- 确认密码和密码必须保持一致,是2个字段的事情,所以要使用基于验证器的声明方式 -->
<validator type="expression">
<param name="expression">
<!-- CDATA为了去掉特殊字符 -->
<![CDATA[
password == repassword
]]>
</param>
<message>两次密码必须一致</message>
</validator>
<field name="score">
<field-validator type="regex">
<param name="regex">
/d+
</param>
<message>请正确输入成绩</message>
</field-validator>
</field>
<field name="url">
<field-validator type="url">
<message>请正确输入url</message>
</field-validator>
</field>
<field name="gender">
<field-validator type="required">
<!-- required是一个只验证是否为null的内置验证器,不去除空格 -->
<message>请输入性别</message>
</field-validator>
</field>
</validators>
第六步:测试
开发中遇到的问题
1.在测试自己的student.jsp的页面中出现了错误
经过查看自己的score的标签中的name没有写导致的错误
2.在测试密码和确认密码的时候发现不一致也不报错
它属于动作错误,所以需要写上面的标签
Struts2(二)之封装请求正文、数据类型转换、数据验证的更多相关文章
- Struts2 03---数据封装+获取表单提交数据
Struts的数据封装分为三种:属性封装,模型驱动,表达式封装.下面以获取表单提交数据来简单介绍一下Struts的数据封装. <form action="loginlogin. ...
- struts2 二: 参数封装
封装请求正文到对象中(非常重要) 1.静态参数封装 在struts.xml配置文件中,给动作类注入值.调用的是setter方法. struts.xml的编写: <action name=&quo ...
- 04springMVC数据类型转换
数据类型转换简介 Spring Web MVC中的数据类型转换 内建的类型转换器 自定义类型转换器 1 数据类型转换简介 当从页面提交数据到后台Action的时候,通过请求发送的数据,通常都 ...
- JAVA学习(三):Java基础语法(变量、常量、数据类型、运算符与数据类型转换)
Java基础语法(变量.常量.数据类型.运算符与数据类型转换) 1.变量 Java中.用户能够通过指定数据类型和标识符来声明变量.其基本的语法为: DataType identifier; 或 Dat ...
- Struts2(接受表单参数)请求数据自动封装和数据类型转换
Struts2请求数据自动封装: (1)实现原理:参数拦截器 (2)方式1:jsp表单数据填充到action中的属性: 普通的成员变量,必须给set,get可以不给的. 注意点,A ...
- Android-Volley网络通信框架(二次封装数据请求和图片请求(包含处理请求队列和图片缓存))
1.回想 上篇 使用 Volley 的 JsonObjectRequest 和 ImageLoader 写了 电影列表的样例 2.重点 (1)封装Volley 内部 请求 类(请求队列,数据请求,图片 ...
- struts2数据类型转换详解
Web应用程序的交互都是建立在HTTP之上的,互相传递的都是字符串.也就是说服务器接收到的来自用户的数据只能是字符串或者是字符数组,而在Web应用的对象中,往往使用了多种不同的类型,如整数(int). ...
- Struts2中的数据类型转换
Struts2对数据的类型转换 一.Struts2中自带类型转换拦截器 Struts2内部提供了大量转换器,用来完成数据类型转换的问题,有如下 * boolean 和 Boolean * char和 ...
- 十一、Struts2封装请求参数的方式
十一.Struts2封装请求参数的方式 方式一.Action 本身作为model对象,通过成员setter封装(一个名字为params的拦截器干的) 注意:表单中的名称要和动作类中的名称一致(这是必须 ...
随机推荐
- Git 和 GitHub 使用
Git和GitHub的使用 Git是一款免费.开源的分布式版本控制系统. GitHub托管远程仓库,并提供一个web界面. 有2种协议支持从本地push代码到远程仓库. 一种是http,需要输入用户名 ...
- 在 Linux OpenVPN 服务端吊销客户端证书
OpenVPN服务器与 VPN 客户端之间的身份验证, 主要是通过证书来进行的.有时我们需要禁止某个用户连接 VPN 服务器,则将其证书吊销即可.要吊销(Revoke) OpenVPN 客户端证书, ...
- 学习 OpenStack 的方法论 - 每天5分钟玩转 OpenStack(150)
作为 OpenStack 的核心教程,我们已经到了最后总结的部分. OpenStack 目前已经有好几十个模块,本教程讨论的是最最重要的核心模块:Keystone,Nova,Glance,Cinder ...
- vue2重写饿了么
构建 vue有自己的脚手架构建工具vue-cli,使用起来非常方便,使用webpack来集成各种开发便捷工具,比如: 代码热更新,修改代码之后网页无刷新改变,对前端开发来说非常的方便 PostCss, ...
- 三层——vb.net版
经过不懈的努力,我的vb.net 版的三层登陆终于实现了.下面将我的成果向大家展示一下. 原则 vb.net的三层登陆跟C#的三层登陆的思想是一样的都是将系统分层--U层只负责与用户 ...
- ubuntu通过虚拟域名访问不了 502 / 网络错误
##之前把虚拟机的lamp环境搭建好,但是通过自己windows在浏览器访问一直不能正常运行. 简单说明一下我的相关设置: 1.设置windows的ip映射 C:\Windows\System32\d ...
- ArcGIS许可启动问题
前段时间,由于360常常删除重要文件终于发生在我身上.不得已换了电脑管家,清理后再次打开License Server Administrator时,发现启动项怎么也点不动了.而打开服务管理器,却发现A ...
- 响应式布局中的CSS相对量
一个响应式布局,要能够根据设备屏幕尺寸的改变,动态的调整页面内容,展现不同的设计风格. 在进行响应式的 CSS 代码编写过程中,经常会用到一些相对尺寸,以达到相对定位的目的.例如,常见的响应式布局中需 ...
- WP8.1开发中关于如何显示.gif格式动态格式图片方法
这几天又遇到个问题,就是如何显示动态图片,本来以为和显示静态图片一样,谁知不行,在网上一查才知道WP8.1不支持.gif格式动态图片的显示: 后来又在MSDN论坛上查找,也有人问类似的问题,后来就大概 ...
- 【前端】:jQuery下
前言: 接上一篇博客: [前端]:jQuery上 一.jQuery属性操作 ① attr(设置或返回自定义属性值) input.select.textarea框中的内容, 可以通过attr来获取,但是 ...