如何查看网站源代码defaulttypeconverter源码

JAVA_WEB(34)
Action接受请求参数
作为MVC框架,必须要负责解析HTTP请求参数,并将其封装到Model对象中
Struts2提供了非常强大的类型转换机制用于请求数据 到 model对象的封装
Struts2和MVC定义关系
StrutsPrepareAndExecuteFilter:控制器
在Struts2中action是什么?(Struts2是一个MVC框架)
C:action StrutsPrepareAndExecuteFilter
Struts2提供了三种数据封装方式:
Action本身作为model对象,通过成员setter封装。(属于属性驱动)创建独立model对象,页面通过ognl表达式封装。(属于属性驱动)使用ModelDrivern接口,对请求数据进行封装。(属于模型驱动)
具体使用如下:
1.属性驱动
&属性驱动方式(一):直接将action作为一个model,就可以得到请求参数
action类成员变量setter接收参数如下图所示:
问题1:action封装请求参数,会不会存在线程安全问题?
& &是不会的,因为每一次请求,都是一个新的action
优点:使用简单
缺点:需要单独定义JavaBean,将action中属性copy到JavaBean中(不能将Action作为model传给service层)
这种方式,底层是通过反射进行实现的。
属性驱动方式(二):创建一个单独的Model类,在action类中引用model作为成员变量。(页面使用ognl)
具体操作:
在action类中声明一个mdoel,private U&
提供对应的setter和getter方法。
在页面上使用ognl来进行描述
&input type=&text& name=&user.username&& 如下图所示:
这种方式的优点:简单易使用,解决了第一种封装的问题。
缺点:在页面上使用了ognl表达式,页面不通用了。
问题:这种方式,数据是怎样封装的?
是通过Struts2中name为params的interceptor拦截器进行的数据封装(Struts的核心core包下struts-default.xml中定义)&interceptor name=&params& class=&com.opensymphony.xwork2.interceptor.ParametersInterceptor&/&
2.模型驱动(在开发中应用比较多)
模型驱动的步骤:
1.让action 类实现ModelDrivern接口。
2.重写getModel方法
3.在action中实例化一个model对象,让getModel方法返回这个对象。
& public class Login3Action extends ActionSupport implements ModelDriven&User& {
private User user = new User();
public User getModel() {
如下图所示:
优点:解决了属性驱动存在的问题
缺点:一次只能封装一个model对象
Struts2有很多围绕模型驱动的属性(在struts-default.xml中的拦截器中定义)
&interceptor name=&modelDriven& class=&com.opensymphony.xwork2.interceptor.ModelDrivenInterceptor&/&
(1)将数据封装到List集合。类型转换与Collection配合使用。
&Struts2还允许填充Collection里的对象,这常见于需要快速录入批量数据的场合。
&username1:&input type=&text& name=&users[0].username&&&br&
&password1:&input type=&password& name=&users[0].password&&&br&
&username2:&input type=&text& name=&users[1].username&&&br&
&password2:&input type=&password& name=&users[1].password&&&br&
&private List&User&
&get/set方法
(2)将数据封装到Map集合(类型转换与Map配合使用)
username1:&input type=&text& name=&map['aaa'].username&&&br&
password1:&input type=&password& name=&map['aaa'].password&&&br&
username2:&input type=&text& name=&map['bbb'].username&&&br&
password2:&input type=&password& name=&map['bbb'].password&&&br&
private Map&String, User&
提供get/set
1.将action作为model(属性驱动方式一)
Login1Action
package cn.itcast.
import javax.servlet.http.HttpServletR
import org.apache.struts2.ServletActionC
import com.opensymphony.xwork2.ActionS
// 获取请求参数
属性驱动 第一种,直接将action作为model
public class Login1Action extends ActionSupport {
public String getUsername() {
public void setUsername(String username) {
this.username =
public String getPassword() {
public void setPassword(String password) {
this.password =
public String execute() throws Exception {
HttpServletRequest request = ServletActionContext.getRequest();
// 2.判断用户名与密码是否正确
if (&tom&.equals(username) && &123&.equals(password)) {
request.getSession().setAttribute(&username&, username);
return SUCCESS;
request.setAttribute(&login.message&, &用户名或密码错误&);
return &failer&;
login1.jsp
&%@ page language=&java& contentType=&text/ charset=UTF-8&
pageEncoding=&UTF-8&%&
&!DOCTYPE html PUBLIC &-//W3C//DTD HTML 4.01 Transitional//EN& &http://www.w3.org/TR/html4/loose.dtd&&
&meta http-equiv=&Content-Type& content=&text/ charset=UTF-8&&
&title&Insert title here&/title&
${requestScope[&login.message&]}
&form action=&${pageContext.request.contextPath}/login1& method=&POST&&
username:&input type=&text& name=&username&&&br&
password:&input type=&password& name=&password&&&br&
&input type=&submit& value=&登录&&
&/html&2.将model对象作为Action类成员(属性驱动模式二)
封装Model类
package cn.itcast.
public class User {
public String getUsername() {
public void setUsername(String username) {
this.username =
public String getPassword() {
public void setPassword(String password) {
this.password =
public String toString() {
return &User [username=& + username + &, password=& + password + &]&;
Login2Action
package cn.itcast.
import javax.servlet.http.HttpServletR
import org.apache.struts2.ServletActionC
import cn.itcast.domain.U
import com.opensymphony.xwork2.ActionS
// 获取请求参数
属性驱动 第二种,直接在action上声明一个model
public class Login2Action extends ActionSupport {
public User getUser() {
public void setUser(User user) {
this.user =
public String execute() throws Exception {
HttpServletRequest request = ServletActionContext.getRequest();
// 2.判断用户名与密码是否正确
if (&tom&.equals(user.getUsername())
&& &123&.equals(user.getPassword())) {
request.getSession().setAttribute(&username&, user.getUsername());
return SUCCESS;
request.setAttribute(&login.message&, &用户名或密码错误&);
return &failer&;
login2.jsp
&%@ page language=&java& contentType=&text/ charset=UTF-8&
pageEncoding=&UTF-8&%&
&!DOCTYPE html PUBLIC &-//W3C//DTD HTML 4.01 Transitional//EN& &http://www.w3.org/TR/html4/loose.dtd&&
&meta http-equiv=&Content-Type& content=&text/ charset=UTF-8&&
&title&Insert title here&/title&
${requestScope[&login.message&]}
&form action=&${pageContext.request.contextPath}/login2& method=&POST&&
username:&input type=&text& name=&user.username&&&br&
password:&input type=&password& name=&user.password&&&br&
&input type=&submit& value=&登录&&
&/html&3.模型驱动(action类实现ModelDrivern接口)
Login3Action
package cn.itcast.
import javax.servlet.http.HttpServletR
import org.apache.struts2.ServletActionC
import cn.itcast.domain.U
import com.opensymphony.xwork2.ActionS
import com.opensymphony.xwork2.ModelD
// 获取请求参数 模型驱动
public class Login3Action extends ActionSupport implements ModelDriven&User& {
private User user=new User();
public User getModel() {
public String execute() throws Exception {
HttpServletRequest request = ServletActionContext.getRequest();
// 2.判断用户名与密码是否正确
if (&tom&.equals(user.getUsername())
&& &123&.equals(user.getPassword())) {
request.getSession().setAttribute(&username&, user.getUsername());
return SUCCESS;
request.setAttribute(&login.message&, &用户名或密码错误&);
return &failer&;
login3.jsp
&%@ page language=&java& contentType=&text/ charset=UTF-8&
pageEncoding=&UTF-8&%&
&!DOCTYPE html PUBLIC &-//W3C//DTD HTML 4.01 Transitional//EN& &http://www.w3.org/TR/html4/loose.dtd&&
&meta http-equiv=&Content-Type& content=&text/ charset=UTF-8&&
&title&Insert title here&/title&
${requestScope[&login.message&]}
&form action=&${pageContext.request.contextPath}/login3& method=&POST&&
username:&input type=&text& name=&username&&&br&
password:&input type=&password& name=&password&&&br&
&input type=&submit& value=&登录&&
success.jsp
&%@ page language=&java& contentType=&text/ charset=UTF-8&
pageEncoding=&UTF-8&%&
&!DOCTYPE html PUBLIC &-//W3C//DTD HTML 4.01 Transitional//EN& &http://www.w3.org/TR/html4/loose.dtd&&
&meta http-equiv=&Content-Type& content=&text/ charset=UTF-8&&
&title&Insert title here&/title&
${username }
4.将数据封装到List集合
&%@ page language=&java& contentType=&text/ charset=UTF-8&
pageEncoding=&UTF-8&%&
&!DOCTYPE html PUBLIC &-//W3C//DTD HTML 4.01 Transitional//EN& &http://www.w3.org/TR/html4/loose.dtd&&
&meta http-equiv=&Content-Type& content=&text/ charset=UTF-8&&
&title&Insert title here&/title&
&form action=&${pageContext.request.contextPath}/list& method=&POST&&
username:&input type=&text& name=&users[0].username&&&br&
password:&input type=&password& name=&users[0].password&&&br&
username:&input type=&text& name=&users[1].username&&&br&
password:&input type=&password& name=&users[1].password&&&br&
&input type=&submit& value=&登录&&
&/html&ListAction
package cn.itcast.
import java.util.L
import cn.itcast.domain.U
import com.opensymphony.xwork2.ActionS
public class ListAction extends ActionSupport {
private List&User&
public List&User& getUsers() {
public void setUsers(List&User& users) {
this.users =
public String execute() throws Exception {
System.out.println(users);
5.将数据封装到Map集合
&%@ page language=&java& contentType=&text/ charset=UTF-8&
pageEncoding=&UTF-8&%&
&!DOCTYPE html PUBLIC &-//W3C//DTD HTML 4.01 Transitional//EN& &http://www.w3.org/TR/html4/loose.dtd&&
&meta http-equiv=&Content-Type& content=&text/ charset=UTF-8&&
&title&Insert title here&/title&
&form action=&${pageContext.request.contextPath}/map& method=&POST&&
username:&input type=&text& name=&map['aaa'].username&&&br&
password:&input type=&password& name=&map['aaa'].password&&&br&
username:&input type=&text& name=&map['bbb'].username&&&br&
password:&input type=&password& name=&map['bbb'].password&&&br&
&input type=&submit& value=&登录&&
&/html&MapAction
package cn.itcast.
import java.util.M
import cn.itcast.domain.U
import com.opensymphony.xwork2.ActionS
public class MapAction extends ActionSupport {
private Map&String, User&
public Map&String, User& getMap() {
public void setMap(Map&String, User& map) {
this.map =
public String execute() throws Exception {
System.out.println(map);
配置struts.xml
&?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&&
&constant name=&struts.enable.DynamicMethodInvocation& value=&false& /&
&constant name=&struts.devMode& value=&true& /&
&package name=&default& namespace=&/& extends=&struts-default&&
&action name=&login1& class=&cn.itcast.action.Login1Action&&
&result name=&failer&&/login1.jsp&/result&
&result type=&redirect&&/success.jsp&/result&
&action name=&login2& class=&cn.itcast.action.Login2Action&&
&result name=&failer&&/login2.jsp&/result&
&result type=&redirect&&/success.jsp&/result&
&action name=&login3& class=&cn.itcast.action.Login3Action&&
&result name=&failer&&/login3.jsp&/result&
&result type=&redirect&&/success.jsp&/result&
&action name=&list& class=&cn.itcast.action.ListAction&&&/action&
&action name=&map& class=&cn.itcast.action.MapAction&&&/action&
&/package&
验证属性驱动方式一:
验证属性驱动方式二:
验证模型驱动:
验证封装数据到List集合
验证封装数据到Map集合
2自定义类深入剖析属性驱动模式一和模型驱动
首先导入DOM4J、XPATH、BeanUtils的相关jar包
在src下新建struts.xml
新建自定义的ModelDrivern接口MyModelDrivern
package cn.
public interface MyModelDriven&T& {
public T getModel();
创建User类(和上面的一样)
创建Action类
package cn.itcast.
import cn.itcast.MyModelD
import cn.itcast.U
public class HelloAction implements MyModelDriven&User& {
// 剖析模型驱动
private User user = new User();
public User getModel() {
属性驱动模式一
public String getUsername() {
public void setUsername(String username) {
this.username =
public String getPassword() {
public void setPassword(String password) {
this.password =
public String say() {
System.out.println(user.getUsername() + &
& + user.getPassword());
return &good&;
自定义拦截器(模仿Struts中的params拦截器)
StrutsFilter
package cn.itcast.
import java.io.F
import java.io.IOE
import java.lang.reflect.InvocationTargetE
import java.lang.reflect.M
import javax.servlet.F
import javax.servlet.FilterC
import javax.servlet.FilterC
import javax.servlet.ServletE
import javax.servlet.ServletR
import javax.servlet.ServletR
import javax.servlet.http.HttpServletR
import javax.servlet.http.HttpServletR
import mons.beanutils.BeanU
import org.dom4j.D
import org.dom4j.DocumentE
import org.dom4j.E
import org.dom4j.io.SAXR
import cn.itcast.MyModelD
public class StrutsFilter implements Filter {
public void init(FilterConfig filterConfig) throws ServletException {
public void doFilter(ServletRequest req, ServletResponse resp,
FilterChain chain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest)
HttpServletResponse response = (HttpServletResponse)
// 2.1 得到请求资源路径
String uri = request.getRequestURI();
String contextPath = request.getContextPath();
String path = uri.substring(contextPath.length() + 1);
// System.out.println(path); // hello
// 2.2 使用path去struts.xml文件中查找某一个&action name=path&这个标签
SAXReader reader = new SAXReader();
// 得到struts.xml文件的document对象。
Document document = reader.read(new File(this.getClass()
.getResource(&/struts.xml&).getPath()));
Element actionElement = (Element) document
.selectSingleNode(&//action[@name='& + path + &']&); // 查找&action
// name='hello'&这样的标签
if (actionElement != null) {
// 得到&action&标签上的class属性以及method属性
String className = actionElement.attributeValue(&class&); // 得到了action类的名称
String methodName = actionElement.attributeValue(&method&);// 得到action类中的方法名称。
// 2.3通过反射,得到Class对象,得到Method对象
Class actionClass = Class.forName(className);
Method method = actionClass.getDeclaredMethod(methodName);
// 处理请求参数封装:
Object actionObj = actionClass.newInstance();
// 2.模型驱动
if (actionObj instanceof MyModelDriven) {
MyModelDriven mmd = (MyModelDriven) actionO
BeanUtils.populate(mmd.getModel(),
request.getParameterMap());
// 1.属性驱动
BeanUtils.populate(actionObj, request.getParameterMap());//
// 2.4 让method执行.
String returnValue = (String) method.invoke(actionObj); // 是让action类中的方法执行,并获取方法的返回值。
// 使用returnValue去action下查找其子元素result的name属性值,与returnValue做对比。
Element resultElement = actionElement.element(&result&);
String nameValue = resultElement.attributeValue(&name&);
if (returnValue.equals(nameValue)) {
// 2.6得到了要跳转的路径。
String skipPath = resultElement.getText();
// System.out.println(skipPath);
request.getRequestDispatcher(skipPath).forward(request,
response);
} catch (DocumentException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvocationTargetException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InstantiationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
chain.doFilter(request, response);
public void destroy() {
编辑自定义的struts.xml
&?xml version=&1.0& encoding=&UTF-8& ?&
&action name=&hello& class=&cn.itcast.action.HelloAction&
method=&say&&
&result name=&good&&/hello.jsp&/result&
在web.xml中配置拦截器
创建jsp进行测试:
&%@ page language=&java& import=&java.util.*& pageEncoding=&UTF-8&%&
&!DOCTYPE HTML PUBLIC &-//W3C//DTD HTML 4.01 Transitional//EN&&
&title&My JSP 'index.jsp' starting page&/title&
&h1&hello Struts2&/h1&
&%@ page language=&java& import=&java.util.*& pageEncoding=&UTF-8&%&
&!DOCTYPE HTML PUBLIC &-//W3C//DTD HTML 4.01 Transitional//EN&&
&title&My JSP 'index.jsp' starting page&/title&
&a href=&${pageContext.request.contextPath}/hello?username=tome&password=123&&第一次使用struts2&/a&
测试结果如下:
Struts2内置的类型转换器
类型转换:即在web中 使用Servlet时,使用BeanUtils直接将表单数据封装到JavaBean中。
对于大部分常用类型,开发者根本无需创建自己的转换器,Struts2内置了常见数据类型的多种转换器。
boolean和Booleanchar和Characterint和Integerlong和Longfloat和Floatdouble和DoubleDate可以接收yyyy-MM-dd格式字符串(浏览器语言首选项为中文时)数组 &可以将多个同名参数转换到数组中集合 & 支持将数据保存到List或者Map集合
例如:日期类型,我们传递yyyy-MM-dd yyyy年MM月dd日 格式都可以,但是如果是yyyy/MM/dd就会出现问题。
关于Struts2中的类型转换器:
Struts2中的类型转换器根接口是:com.opensymphony.xwork.conversion.TypeConverter
自定义类型转换器
Struts2提供常规类型转换器,可以实现常用类型的转换,但是如果目标类型是一个特殊类型,则需要自定义转换器
Struts2 类型转换器实际上都是基于OGNL实现的,在OGNL项目中,有一个TypeConverter接口
自定义类型转换器必须实现 ongl.TypeConverter接口
相关的关键源代码如下:
TypeConverter接口关键源代码:
DefaultTypeConverter类实现了TypeConverter接口:
StrutsTypeConverter直接继承自DefaultTypeConverter:
自定义转换器的的步骤:
& &1.创建一个类实现TypeConverter接口
& &2.重写接口中方法,实现类型转换操作
& &3.注册类型转换器
详细说明:
1.创建一个自定义类型转换器(有三种方式)
方式一:实现TypeConverter需要重写
& &public Object convertValue(Map&String, Object& context, Object target, Member member, String propertyName, & & & &Object value, Class toType);
& &如果实现接口,这个方法参数太多(6个)
方式二:不推荐实现接口,可以继承DefaultTypeConverter类
& &优点:重写的方法参数没有那么多
& &&public Object convertValue(Map&String, Object& context, Object value, Class toType) {
return convertValue(value, toType);
方式三:(推荐使用)继承DefaultTypeConverter类的一个子类StrutsTypeConverter& &
& &public abstract Object convertFromString(Map context, String[] values, Class toClass);——请求封装
& &public abstract String convertToString(Map context, Object o);——数据回显
& &类型转换器一直都是双向转换:
& &页面提交的请求参数,封装到model——需要转换
& &model数据 &需要在页面上回显——需要转换
2.怎样注册一个自定义类型转换器
& 注册方式有三种类型:
方式一:局部—针对于action
& 配置文件所在的位置及名称:在Action类所在包下,创建 Action类名-conversion.properties
& 配置文件书写:格式 &属性名称=类型转换器的全类名
方式二:局部—针对于Model(属性驱动模式二)
& 配置文件所在位置以及名称:在Model类所在包,创建 Model类名-conversion.properties
& 配置文件书写:格式 &属性名称=类型转换器的全类名
方式三:全局
& 配置文件所在位置以及名称:在src下创建一个 xwork-conversion.properties
& 配置文件书写 &格式:要转换的类型全名=类型转换器的全类名
对于struts2中类型转换器,如果表单数据提交时,将数据向model封装,出现了问题,会报错:
No result defined for action cn.itcast.action.RegistAction and result input
上面的意思是说,在RegistAction的配置中没有配置input结果视图.
&action name=&regist& class=&cn.itcast.action.RegistAction&&
&result name=&input&&/success.jsp&/result&
如果配置了,出现类型转换问题,就会跳转到input指定的视图。
问题:为什么会向input视图跳转?
是因为struts2中的拦截器(interceptor).
在struts2中的conversionError拦截器用于记录类型转换问题
&&interceptor name=&conversionError& class=&org.apache.struts2.interceptor.StrutsConversionErrorInterceptor&/&
在struts2中的workflow拦截器用于得到问题,向input视图跳转。
&interceptor name=&workflow& class=&com.opensymphony.xwork2.interceptor.DefaultWorkflowInterceptor&/&
类型转换中的错误处理:
Struts2提供了一个名为conversionError的拦截器,查看struts-default.xml&interceptor name=&conversionError& class=&org.apache.struts2.interceptor.StrutsConversionErrorInterceptor&/&如果Struts2的类型转换器执行类型转换时出现错误,该拦截器将负责将对应错误封装成表单域错误(FieldError),并将这些错误信息放入ActionContext中使用类型转换中的错误处理用户定义Action必须继承ActionSupport在自定义类型转换器中,异常必须抛出不能捕获,conversionError会处理该异常,然后转入名为input的逻辑视图在Action所在包中,创建 ActionName.properties,在局部资源文件中配置提示信息 :invalid.fieldvalue.属性名= 错误信息在input逻辑视图所对应jsp页面中,通过&s:fielderror/& 输出类型转换信息
程序示例如下:
首先新建自定义转换类MyDateConverter (通过继承自DefaultTypeConverter)
package cn.itcast.
import java.text.ParseE
import java.text.SimpleDateF
import java.util.D
import java.util.M
import ognl.DefaultTypeC
public class MyDateConverter extends DefaultTypeConverter {
public Object convertValue(Map context, Object value, Class toType) {
SimpleDateFormat dateFormat = new SimpleDateFormat(&yyyy/MM/dd&);
if (toType == Date.class) {// 当字符串向Date类型转换时
String[] params = (String[])
return dateFormat.parse(params[0]);
} else if (toType == String.class) {// 当Date转换成字符串时
Date date = (Date)
return dateFormat.format(date);
} catch (ParseException e) {
throw new RuntimeException(&日期转换错误&);
再新建一个日期转换类(使用另外一种方式继承自StrutsTypeConverter)
MyDateConverter2
package cn.itcast.
import java.text.ParseE
import java.text.SimpleDateF
import java.util.D
import java.util.M
import org.apache.struts2.util.StrutsTypeC
public class MyDateConverter2 extends StrutsTypeConverter {
// 接收页面传递的数据封装到JavaBean
public Object convertFromString(Map context, String[] values, Class toClass) {
String value = values[0];
SimpleDateFormat sdf = new SimpleDateFormat(&yyyy/MM/dd&);
Date date =
date = sdf.parse(value);
} catch (ParseException e) {
// e.printStackTrace();
throw new RuntimeException();
public String convertToString(Map context, Object o) {
具体代码如下:
RegistAction
package cn.itcast.action1;
import cn.itcast.domain.U
import com.opensymphony.xwork2.ActionS
import com.opensymphony.xwork2.ModelD
public class RegistAction extends ActionSupport implements ModelDriven&User& {
private User user = new User();
public User getModel() {
public String execute() throws Exception {
System.out.println(user);
Regist2Action
package cn.itcast.action2;
import java.util.A
import java.util.D
import com.opensymphony.xwork2.ActionS
public class Regist2Action extends ActionSupport {
private String[]
public String toString() {
return &Regist2Action [username=& + username + &, password=& + password
+ &, age=& + age + &, birthday=& + birthday + &, hobby=&
+ Arrays.toString(hobby) + &]&;
public String getUsername() {
public void setUsername(String username) {
this.username =
public String getPassword() {
public void setPassword(String password) {
this.password =
public int getAge() {
public void setAge(int age) {
this.age =
public Date getBirthday() {
public void setBirthday(Date birthday) {
this.birthday =
public String[] getHobby() {
public void setHobby(String[] hobby) {
this.hobby =
public String execute() throws Exception {
System.out.println(this);
Regist2Action-conversion.properties
birthday=cn.itcast.utils.MyDateConverter2
package cn.itcast.
import java.util.A
import java.util.D
public class User {
private String[]
public String getUsername() {
public void setUsername(String username) {
this.username =
public String getPassword() {
public void setPassword(String password) {
this.password =
public int getAge() {
public void setAge(int age) {
this.age =
public Date getBirthday() {
public void setBirthday(Date birthday) {
this.birthday =
public String[] getHobby() {
public void setHobby(String[] hobby) {
this.hobby =
public String toString() {
return &User [username=& + username + &, password=& + password
+ &, age=& + age + &, birthday=& + birthday + &, hobby=&
+ Arrays.toString(hobby) + &]&;
User-conversion.properties
birthday=cn.itcast.utils.MyDateConverter
struts.xml
&?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&&
&package name=&default& namespace=&/& extends=&struts-default&&
&action name=&regist& class=&cn.itcast.action1.RegistAction&&
&result name=&input&&/success.jsp&/result&
&action name=&regist2& class=&cn.itcast.action2.Regist2Action&&
&result name=&input&&/success.jsp&/result&
&/package&
regist.jsp
&%@ page language=&java& contentType=&text/ charset=UTF-8&
pageEncoding=&UTF-8&%&
&!DOCTYPE html PUBLIC &-//W3C//DTD HTML 4.01 Transitional//EN& &http://www.w3.org/TR/html4/loose.dtd&&
&meta http-equiv=&Content-Type& content=&text/ charset=UTF-8&&
&title&Insert title here&/title&
&form action=&${pageContext.request.contextPath}/regist& method=&POST&&
username:&input type=&text& name=&username&&&br&
password:&input type=&password& name=&password&&&br&
hobby:&input type=&checkbox& name=&hobby& value=&eat&&吃
&input type=&checkbox& name=&hobby& value=&drink&&喝
&input type=&checkbox& name=&hobby& value=&play&&玩&br&
age:&input type=&text& name=&age&&&br&
birthday:&input type=&text& name=&birthday&&&br&
&input type=&submit& value=&注册&&
&/html&regist2.jsp
&%@ page language=&java& contentType=&text/ charset=UTF-8&
pageEncoding=&UTF-8&%&
&!DOCTYPE html PUBLIC &-//W3C//DTD HTML 4.01 Transitional//EN& &http://www.w3.org/TR/html4/loose.dtd&&
&meta http-equiv=&Content-Type& content=&text/ charset=UTF-8&&
&title&Insert title here&/title&
&form action=&${pageContext.request.contextPath}/regist2& method=&POST&&
username:&input type=&text& name=&username&&&br&
password:&input type=&password& name=&password&&&br&
hobby:&input type=&checkbox& name=&hobby& value=&eat&&吃
&input type=&checkbox& name=&hobby& value=&drink&&喝
&input type=&checkbox& name=&hobby& value=&play&&玩&br&
age:&input type=&text& name=&age&&&br&
birthday:&input type=&text& name=&birthday&&&br&
&input type=&submit& value=&注册&&
&/html&success.jsp
&%@ page language=&java& contentType=&text/ charset=UTF-8&
pageEncoding=&UTF-8&%&
&%@ taglib prefix=&s& uri=&/struts-tags& %&
&!DOCTYPE html PUBLIC &-//W3C//DTD HTML 4.01 Transitional//EN& &http://www.w3.org/TR/html4/loose.dtd&&
&title&Insert title here&/title&
&s:fielderror/&
Struts2的输入校验
校验的分类 : 客户端数据校验 和 服务器端数据校验&
客户端数据校验 ,通过JavaScript 完成校验 (改善用户体验,使用户减少出错 )
服务器数据校验 ,使用框架内置校验功能 (struts2 内置校验功能 ) ----- 必须的
struts2 支持校验方式&
代码校验 :在服务器端通过编写java代码,完成数据校验&
配置校验 :XML配置校验(主流) 和 注解配置校验
代码校验(手动校验)了解
要求:action类必须继承自ActionSupport。需要重写一个validate方法
通过测试发现在action中的validate方法执行了。并且是在请求处理方法(execute)之前执行的。
对于struts2提供的校验,它也是通过拦截器实现的。
问题1:在validate方法中怎样存储错误校验信息?
& 在validate方法中 &this.addFieldError(String name,String value);
问题2:在页面上怎样获取错误信息?(在Input视图上)
&&s:fielderror& 展示所有的错误信息
&s:fielderror fieldName=&&& 展示特定名称的错误信息
问题3:在同一个Action中有多个请求处理方法(login,regist) ,那么有些方法是需要校验的,有些是不需要的,如何处理?
解决方案:创建一个名称叫 validate+请求方法处理名(首字母大写) &例如:请求处理方法叫 &regist() &校验 的方法名 validateRegist().会发现不管定义多少validateXxx方法 执行时都会走validate方法,所以可以将一些公共的校验放在validate方法中,可以把针对于特定方法的检验放在validateXxx方法下(xxx请求方法处理名)
手动校验的流程如下:
第一步:类型转换器对请求参数执行类型转换,并将转换后的值赋给action中的属性。
第二步:如果在执行转换的过程中出现异常,系统会将异常信息保存到ActionContext,conversionError拦截器将异常信息封装到fieldErrors里,然后执行第三步。如果类型转换没有出现异常,则直接进入第三步。
第三步:系统通过反射技术调用action中的ValidateXxx()方法,xxx为请求方法处理名。
第四步:调用action中的validate方法。
第五步:经过上面4步,如果系统中的fieldErrors存在错误信息(即存放错误信息的集合的size大于0),系统自动将请求转发至名称为input的视图。如果系统中的fieldErrors没有任何错误信息,系统将执行action中的处理方法。
手动校验示例如下:
导入Strutsjar包 配置好struts.xml
在WebRoot下新建login.jsp和regist.jsp
&%@ page language=&java& import=&java.util.*& pageEncoding=&UTF-8&%&
&%@taglib prefix=&s& uri=&/struts-tags&%&
&!DOCTYPE HTML PUBLIC &-//W3C//DTD HTML 4.01 Transitional//EN&&
&title&My JSP 'index.jsp' starting page&/title&
&s:fielderror/&
&form action=&${pageContext.request.contextPath}/login& method=&post&&
username:&input type=&text& name=&username&&&s:fielderror fieldName=&username.message&/&&br&
password:&input type=&password& name=&password&&&s:fielderror fieldName=&password.message&/&&br&
repassword:&input type=&password& name=&repassword&&&br&
hobby:&input type=&checkbox& name=&hobby& value=&eat&&吃&input
type=&checkbox& name=&hobby& value=&drink&&喝&input
type=&checkbox& name=&hobby& value=&play&&玩&br& age:&input
type=&text& name=&age&&&br& birthday:&input type=&text&
name=&birthday&&&br&
email:&input type=&text& name=&email&&&br&
url:&input type=&text& name=&url&&&br&
telphone:&input type=&text& name=&telphone&&&br&
&input type=&submit& value=&注册&&
regist.jsp
&%@ page language=&java& import=&java.util.*& pageEncoding=&UTF-8&%&
&%@taglib prefix=&s& uri=&/struts-tags&%&
&!DOCTYPE HTML PUBLIC &-//W3C//DTD HTML 4.01 Transitional//EN&&
&title&My JSP 'index.jsp' starting page&/title&
&s:fielderror/&
&form action=&${pageContext.request.contextPath}/regist& method=&post&&
username:&input type=&text& name=&username&&&s:fielderror fieldName=&username.message&/&&br&
password:&input type=&password& name=&password&&&s:fielderror fieldName=&password.message&/&&br&
repassword:&input type=&password& name=&repassword&&&br&
hobby:&input type=&checkbox& name=&hobby& value=&eat&&吃&input
type=&checkbox& name=&hobby& value=&drink&&喝&input
type=&checkbox& name=&hobby& value=&play&&玩&br& age:&input
type=&text& name=&age&&&br& birthday:&input type=&text&
name=&birthday&&&br&
email:&input type=&text& name=&email&&&br&
url:&input type=&text& name=&url&&&br&
telphone:&input type=&text& name=&telphone&&&br&
&input type=&submit& value=&注册&&
新建model类User
package cn.itcast.
import java.util.A
import java.util.D
public class User {
private String[]
public String getRepassword() {
public void setRepassword(String repassword) {
this.repassword =
public String getUrl() {
public void setUrl(String url) {
this.url =
public String getEmail() {
public void setEmail(String email) {
this.email =
public String getTelphone() {
public void setTelphone(String telphone) {
this.telphone =
public String[] getHobby() {
public void setHobby(String[] hobby) {
this.hobby =
public String getUsername() {
public void setUsername(String username) {
this.username =
public String getPassword() {
public void setPassword(String password) {
this.password =
public int getAge() {
public void setAge(int age) {
this.age =
public Date getBirthday() {
public void setBirthday(Date birthday) {
this.birthday =
public String toString() {
return &User [username=& + username + &, password=& + password
+ &, age=& + age + &, birthday=& + birthday + &, hobby=&
+ Arrays.toString(hobby) + &]&;
接着使用手动校验创建Action类UserAction
package cn.itcast.
import cn.itcast.domain.U
import com.opensymphony.xwork2.ActionS
import com.opensymphony.xwork2.ModelD
// 采用手动的方式
public class UserAction extends ActionSupport implements ModelDriven&User& {
private User user = new User();
public User getModel() {
public String execute() throws Exception {
System.out.println(user);
public String login() throws Exception {
System.out.println(&login method ......&);
public String regist() throws Exception {
System.out.println(&regist method ......&);
public void validate() {
System.out.println(&validate method ......&);
public void validateRegist() {
if (user.getUsername() == null
|| user.getUsername().trim().length() == 0) {
// 说明用户名为空
this.addFieldError(&username.message&, &用户名不能为空&);
if (user.getPassword() == null
|| user.getPassword().trim().length() == 0) {
this.addFieldError(&password.message&, &密码不能为空&);
if (!(user.getAge() &= 10 && user.getAge() &= 40)) {
this.addFieldError(&age.message&, &年龄必须在10-40之间&);
System.out.println(&validateRegist......&);
配置struts.xml
&?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&&
&package name=&default& namespace=&/& extends=&struts-default&&
&action name=&regist& class=&cn.itcast.action.UserAction&
method=&regist&&
&result name=&input&&/regist.jsp&/result&
&action name=&login& class=&cn.itcast.action.UserAction&
method=&login&&
&result name=&input&&/login.jsp&/result&
&/package&
输入http://localhost/mystruts2_day02_3/login.jsp 直接提交
发现首先调用了validate方法载调用了login请求处理方法
接着调试注册方法(提供了注册校验)
本地调试 http://localhost/mystruts2_day02_3/regist.jsp &直接提交
发现首先调用了validateRegist方法 再调用了validate方法
因此 只要重写了validate方法,不管怎样都会执行校验。所以可以把公共部分抽取到validate方法内。
Struts2的校验框架已经完成了校验操作(做了很多校验法)而我们在使用时只需要调用它们即可(通过配置文件)
基于XML配置方式实现输入校验:
要求:Action类必须继承自ActionSupport或实现了Validateable接口。
& & & & & 在struts.xml中添加type为input的视图结果集。
& & & & & &添加配置文件。
关于配置文件的配置方式:
配置文件位置: xml文件要与Action类在同一包下。
配置文件名称:Action简单类名-validation.xml
配置文件约束:xwork-core-2.3.7.jar 中 xwork-validator-1.0.3.dtd 下
&!DOCTYPE validators PUBLIC
&-//Apache Struts//XWork Validator 1.0.3//EN&
&http://struts.apache.org/dtds/xwork-validator-1.0.3.dtd&&
配置文件的书写:
1.根元素:&validators&
2.子元素:&field name=&属性名称&&&/field&
& & & & & & 指定action中要校验的属性,name属性指定将被验证的表单字段的名称。
3.&field&的子元素
& &&field-validator &type=&校验器&& &是用于指定校验器
& &问题:校验器有哪些?
& &xwork-core-2.3.7.jar 中 /com/opensymphony/xwork2/validator/validators/default.xml下
&validator name=&required& class=&com.opensymphony.xwork2.validator.validators.RequiredFieldValidator&/&
&validator name=&requiredstring& class=&com.opensymphony.xwork2.validator.validators.RequiredStringValidator&/&
&validator name=&int& class=&com.opensymphony.xwork2.validator.validators.IntRangeFieldValidator&/&
&validator name=&long& class=&com.opensymphony.xwork2.validator.validators.LongRangeFieldValidator&/&
&validator name=&short& class=&com.opensymphony.xwork2.validator.validators.ShortRangeFieldValidator&/&
&validator name=&double& class=&com.opensymphony.xwork2.validator.validators.DoubleRangeFieldValidator&/&
&validator name=&date& class=&com.opensymphony.xwork2.validator.validators.DateRangeFieldValidator&/&
&validator name=&expression& class=&com.opensymphony.xwork2.validator.validators.ExpressionValidator&/&
&validator name=&fieldexpression& class=&com.opensymphony.xwork2.validator.validators.FieldExpressionValidator&/&
&validator name=&email& class=&com.opensymphony.xwork2.validator.validators.EmailValidator&/&
&validator name=&url& class=&com.opensymphony.xwork2.validator.validators.URLValidator&/&
&validator name=&visitor& class=&com.opensymphony.xwork2.validator.validators.VisitorFieldValidator&/&
&validator name=&conversion& class=&com.opensymphony.xwork2.validator.validators.ConversionErrorFieldValidator&/&
&validator name=&stringlength& class=&com.opensymphony.xwork2.validator.validators.StringLengthFieldValidator&/&
&validator name=&regex& class=&com.opensymphony.xwork2.validator.validators.RegexFieldValidator&/&
&validator name=&conditionalvisitor& class=&com.opensymphony.xwork2.validator.validators.ConditionalVisitorFieldValidator&/&
4.&field-validator&的子元素
& & &message&错误信息&/message&
& &&如果需要国际化,可以为message指定key属性,key的值为属性文件中的key。
5.&field-validator&的子元素
& & &param name=&&&值&/param&
& & &用于指定校验器中的参数
关于配置校验中的校验器:
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指定最大值)
注意:关于param的name属性 要到指定校验器对应的类中找到属性的setter方法setXxx 其xxx就是要设置的name属性
问题配置校验,怎样处理在同一个action中存在多个请求处理方法校验问题?
只需要将校验xml文件名称修改即可:
Action简单类名-valication.xml
&现在要对action类西红某一个方法校验,
就改为:Action简单类名-action名称-validation.xml
将上面手动配置校验的代码进行修改。
屏蔽UserAction中的所有校验的方法
在同一包下新建UserAction-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&
&!-- 对username属性进行校验 --&
&field name=&username&&
&!-- 指定username不能为空 --&
&field-validator type=&requiredstring&&
&!-- 错误信息 --&
&message&用户名不能为空---&/message&
&/field-validator&
&!-- 长度校验,规定用户名必须在6-10位之间 --&
&field-validator type=&stringlength&&
&param name=&maxLength&&10&/param&
&param name=&minLength&&6&/param&
&message&用户名必须在${minLength}-${maxLength}位之间&/message&
&/field-validator&
&!-- 对age进行校验,规定年龄必须在10-40之间 --&
&field name=&age&&
&field-validator type=&int&&
&param name=&min&&10&/param&
&param name=&max&&40&/param&
&message&年龄必须在${min}--${max}之间&/message&
&/field-validator&
&!-- 对birthday进行校验 --&
&field name=&birthday&&
&field-validator type=&date&&
&param name=&min&&&/param&
&param name=&max&&&/param&
&message&生日必须在${min}--${max}年之间&/message&
&/field-validator&
&!-- 校验邮箱 --&
&field name=&email&&
&field-validator type=&email&&
&message&邮箱格式不正确&/message&
&/field-validator&
&!-- url校验 --&
&field name=&url&&
&field-validator type=&url&&
&message&url不合法,应类似于&/message&
&/field-validator&
&!-- 使用正则 --&
&field name=&telphone&&
&field-validator type=&regex&&
&param name=&regexExpression&&&![CDATA[^135[0-9]{8}$]]&&/param&
&message&电话号码必须是135xxxxxxxx&/message&
&/field-validator&
&field name=&repassword&&
&field-validator type=&fieldexpression&&
&param name=&expression&&&![CDATA[(password==repassword)]]&&/param&
&message&两次密码输入不一致&/message&
&/field-validator&
&/validators& 调试结果如下:
登录/login,会有同样的校验
如果要只对regist的action方法进行校验,需要做如下修改
将UserAction-validation.xml修改为UserAction-regist-validation.xml即可
修改后调试如下:
发现login方法没有做校验,而regist方法做了校验
当然 也可以自定义校验器,不过很少自定义校验器
基于XML校验的一些特点:
当为某个action提供了ActionClassName-validation.xml和ActionClassName-ActionName-validation.xml两种规则的校验文件时,系统按下面顺序寻找校验文件:
1。AconClassName-validation.xml
2。ActionClassName-ActionName-validation.xml
系统寻找到第一个校验文件时还会继续搜索后面的校验文件,当搜索到所有校验文件时,会把校验文件里的所有校验规则汇总,然后全部应用于处理方法的校验。如果两个校验文件中指定的校验规则冲突,则只使用后面文件中的校验规则。
当action继承了另一个action,父类action的校验文件会先被搜索到。假设UserAction继承BaseAction, UserAction在struts.xml的配置如下:
&action name=&user& class=&cn.itcast.action.UserAction& method=&{1}&&
访问上面名为user的action,系统先搜索到BaseAction-validation.xml, BaseAction-user-validation.xml,接着搜索到UserAction-validation.xml, UserAction-user-validation.xml。校验规则是这四个文件的总和。
编写校验文件时,不能出现提示(帮助信息)解决方案:
在编写ActionClassName-validation.xml校验文件时,如果出现不了帮助信息,可以按下面方式解决:
windwos-&preferences-&myeclipse-&files and editors-&xml-&xmlcatalog
点“add”,在出现的窗口中的location中选“File system”,然后在xwork-2.1.2解压目录的src\java目录中选择xwork-validator-1.0.3.dtd,回到设置窗口的时候不要急着关闭窗口,应把窗口中的Key Type改为URI 。Key改为/xwork/xwork-validator-1.0.3.dtd
约定访问提供Struts2的零配置
从struts2.1开始,struts2 引入了Convention插件来支持零配置
使用约定无需struts.xml或者Annotation配置
需要 struts2-convention-plugin-2.3.7.jar 、asm-*.jar(三个)
插件会自动搜索action、actions、struts、struts2包下所有Java类
所有实现了com.opensymphony.xwork2.Action的Java类
所有类名以Action结尾的Java类
下面类名都符合Convention插件
cn.itcast.struts2.HelloAction
cn.itcast.actions.books.BookSearchAction
cn.itcast.struts.user.UserAction
cn.itcast.estore.action.test.LoginAction
struts2-convention-plugin-2.3.7.jar 中struts-plugin.xml重要常量
&constant name=&struts.convention.package.locators& value=&action,actions,struts,struts2&/& &默认扫描包
&constant name=&struts.convention.exclude.packages& value=&org.apache.struts.*,org.apache.struts2.*,org.springframework.web.struts.*,org.springframework.web.struts2.*,org.hibernate.*&/& 不扫描
&constant name=&struts.convention.action.suffix& value=&Action&/& 默认扫描以Action结尾的类
&constant name=&struts.convention.result.path& value=&/WEB-INF/content/&/& 结果result页面存放位置
&constant name=&struts.convention.classes.reload& value=&false& /& Action类文件重新自动加载
如果Action类名包含Action后缀,将Action后缀去掉
将Action类名的驼峰写法,转成中划线写法
cn.itcast.struts2.HelloAction 映射到 /hello.action
cn.itcast.actions.books.BookSearchAction &映射到 /books/book-search.action
cn.itcast.struts.user.UserAction 映射到 /user/user.action
cn.itcast.estore.action.test.LoginAction 映射到 /test/login.action
默认情况下,Convention总会到Web应用的WEB-INF/content路径下定位结果资源
&constant name=&struts.convention.result.path& value=&/WEB-INF/content/&/&
约定: actionName + resultCode + suffix&
访问cn.itcast.struts.user.UserAction返回success
Convention优先使用 WEB-INF/content/user/user-success.jsp
如果user-success.jsp不存在,会使用user-success.html
如果user-success.html不存在,会使用user.jsp
&&相关文章推荐
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:180318次
积分:5363
积分:5363
排名:第4516名
原创:364篇
转载:24篇
评论:25条
(8)(7)(8)(11)(5)(1)(1)(1)(18)(21)(9)(7)(7)(2)(6)(17)(64)(44)(68)(38)(2)(2)(24)(17)

我要回帖

更多关于 defaulttypeconverter 的文章

 

随机推荐