<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ taglib prefix="s" uri="/struts-tags" %>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<base href="<%=basePath%>"> <title>My JSP 'index.jsp' starting page</title> <meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">
<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
<meta http-equiv="description" content="This is my page">
<!--
<link rel="stylesheet" type="text/css" href="styles.css">
--> </head> <body>
<h3>输入坐标值,格式为x,y,x和y的类型是int类型</h3>
<s:form method="post" action="point" namespace="/">
<!-- 输入坐标值,格式为x,y,x和y的类型是int类型 -->
<s:textfield label="point" name="point"></s:textfield>
<s:submit value="submit"></s:submit>
</s:form>
</body>
</html>

index.jsp代码

  Struts2的自定义类型转换可以通过重写继承DefaultTypeConverter类来完成,也可以通过Struts2提供的模版重写方法来完成。并且有局部类型转换和全局类型转换两种,首先来看一下通过继承DefaultTypeConverter类来实现类型转换的方法。建立一个页面,其中有一个文本框,需要输入坐标值,用','来分割x和y,如图:

  代码如下:

index.jsp代码

  接着,编写一个Point类,有x和y两个字段,用int表示,代码如下:

package cn.net.bysoft.lesson3;

public class Point {
public Point() {
} public Point(int x, int y) {
super();
this.x = x;
this.y = y;
} public int getX() {
return x;
} public void setX(int x) {
this.x = x;
} public int getY() {
return y;
} public void setY(int y) {
this.y = y;
} private int x;
private int y;
}

Point类

  然后开始编写继承DefaultTypeConverter类的转换类,这里命名为PointConverter.java,代码如下:

package cn.net.bysoft.lesson3;

import java.util.Map;

import ognl.DefaultTypeConverter;

public class PointConverter extends DefaultTypeConverter {

    @Override
public Object convertValue(Map context, Object value, Class toType) {
if (Point.class == toType) {
// 用实体的类型与toType比较,等于客户端传递到服务端数据。
Point point = new Point();
// 客户端传递过来的数据为String数组,因为控件的(比如input空间)name可以有多个。
// 此处其实和HttpServletRequest.getParameterValues(String name)方法效果相同。
String[] strArray = (String[]) value;
// 解析字符串。
String[] paramValues = strArray[0].split(",");
int x = Integer.parseInt(paramValues[0]);
int y = Integer.parseInt(paramValues[1]);
point.setX(x);
point.setY(y); return point;
} if (String.class == toType) {
// 用String类型与toType比较,等于服务器发送到客户端数据。
Point point = (Point) value;
int x = point.getX();
int y = point.getY();
StringBuffer sb = new StringBuffer();
sb.append("[x = ");
sb.append(x);
sb.append(", y = ");
sb.append(y);
sb.append("]"); return sb.toString();
} return null;
} }

PointConverter

  其中重写convertValue方法进行类型转换,这个方法参数,toType类型若等于"某某类名".class则代表要将Object value转换成Java实体类,也就是客户端传递到服务端的数据需要进行类型转换。假如toType类型等于String.class则等于服务器像客户端发送数据,需要将对象转换成字符串。具体的转换方法可根据实际情况编写。

  接下来可以创建一个Action用于控制服务端与客户端的请求了,代码与配置如下:

package cn.net.bysoft.lesson3;

import com.opensymphony.xwork2.ActionSupport;

public class PointAction extends ActionSupport {
/**
*
*/
private static final long serialVersionUID = -2035413550978816228L; @Override
public String execute() throws Exception {
return SUCCESS;
} public Point getPoint() {
return point;
} public void setPoint(Point point) {
this.point = point;
} private Point point;
}

PointAction代码

<!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.3//EN" "http://struts.apache.org/dtds/struts-2.3.dtd">
<struts>
<package name="struts2_3_24_1" extends="struts-default">
<action name="helloWorld" class="cn.net.bysoft.lesson1.HelloWorldAction">
<result>lesson1/hello.jsp</result>
</action>
<action name="login" class="cn.net.bysoft.lesson2.LoginAction">
<result name="success">/lesson2/success.jsp</result>
<result name="input">/lesson2/login.jsp</result>
</action>
<action name="point" class="cn.net.bysoft.lesson3.PointAction">
<result name="success">/lesson3/output.jsp</result>
<result name="input">/lesson3/index.jsp</result>
</action>
</package>
</struts>

PointAction的struts.xml配置

  最后,最关键的是要编写一个配置文件来声明转换的信息,使用局部转换需要在Action的包下建立一个同名的加-conversion.properties属性文件,如PointAction-conversion.properties。内容如下:

point=cn.net.bysoft.lesson3.PointConverter

  等号左侧是Action中的字段名称,右侧是使用我们的PointConverter类进行转换。以上工作完成后,可以进行类型转换,编写一个输出页面测试类型转换,代码如下:

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ taglib prefix="s" uri="/struts-tags" %>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<base href="<%=basePath%>"> <title>My JSP 'output.jsp' starting page</title> <meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">
<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
<meta http-equiv="description" content="This is my page">
<!--
<link rel="stylesheet" type="text/css" href="styles.css">
--> </head> <body>
point:<s:property value="point"/>
</body>
</html>

output.jsp代码

  有一点需要注意的是,在PointConverter.java类中,在客户端向服务端请求类型转换时,参数Object value是一个字符串数组(String[]),因为页面中控件的name属性可以有多个,一次向服务端发送多个Point对象存放到数组中,请看如下代码:

<h3>输入坐标值,格式为x,y,x和y的类型是int类型</h3>
<s:form method="post" action="point" namespace="/">
<!-- 输入坐标值,格式为x,y,x和y的类型是int类型 -->
<s:textfield label="point" name="point"></s:textfield>
<s:textfield label="point" name="point"></s:textfield>
<s:textfield label="point" name="point"></s:textfield>
<s:submit value="submit"></s:submit>
</s:form>

  所以,在处理类型转换时,可以一次进行多个对象的类型转换,新创建一个局部类型转换类,实现转换客户端传递过来多个Point并放到集合中,代码如下:

package cn.net.bysoft.lesson3;

import java.util.ArrayList;
import java.util.List;
import java.util.Map; import ognl.DefaultTypeConverter; public class PointConverter2 extends DefaultTypeConverter { @Override
public Object convertValue(Map context, Object value, Class toType) {
if (List.class == toType) {
// 用实体的类型与toType比较,等于客户端传递到服务端数据。
List<Point> points = new ArrayList<Point>();
// 客户端传递过来的数据为String数组,因为控件的(比如input空间)name可以有多个。
String[] strArray = (String[]) value;
for (String str : strArray) {
// 解析字符串。
String[] paramValues = str.split(",");
int x = Integer.parseInt(paramValues[0]);
int y = Integer.parseInt(paramValues[1]);
Point point = new Point();
point.setX(x);
point.setY(y);
points.add(point);
}
return points;
} if (String.class == toType) {
// 用String类型与toType比较,等于服务器发送到客户端数据。
List<Point> points = (List<Point>) value;
int count = 0;
StringBuffer sb = new StringBuffer();
sb.append("[");
for (Point point : points) {
count++;
int x = point.getX();
int y = point.getY(); sb.append("point").append(count).append(":").append("{x = ")
.append(x).append(", y=").append(y).append("}");
}
sb.append("]");
return sb.toString();
} return null;
}
}

PointConverter2.java的代码

  在Struts2中添加相关字段和get/set方法,并配置属性文件:

    public List<Point> getPoints() {
return points;
} public void setPoints(List<Point> points) {
this.points = points;
} private List<Point> points;
points=cn.net.bysoft.lesson3.PointConverter2

  结果如下:

  如果有很多Action中都有一个Poin,那局部转换就麻烦,因为要为每一个Action都编写一个属性文件,Struts2提供了全局的转换方 式,可以编写全局属性文件实现效果。属性文件命名为固定的xwork- conversion.properties,属性值等号左侧是实体类的全名,右侧是制定的转换类。例如:

cn.net.bysoft.lesson3.Point=cn.net.bysoft.lesson3.PointConverter

  Struts2还提供了内置的转换类StrutsTypeConverter,他是一个抽象类,提供了两个抽象方法让我们重写:

  继承这个抽象类,并重写convertFormString方法和convertToString方法,顾名思义,convertFromString是将客户端请求传递过来的字符串转换成服务端对象,而convertToString是将服务端对象转换成字符串以备发送到客户端。具体代码如下:

package cn.net.bysoft.lesson3;

import java.util.ArrayList;
import java.util.List;
import java.util.Map; import org.apache.struts2.util.StrutsTypeConverter; public class PointConverter3 extends StrutsTypeConverter { @Override
public Object convertFromString(Map arg0, String[] values, Class toClass) {
// 用实体的类型与toType比较,等于客户端传递到服务端数据。
List<Point> list = new ArrayList<Point>();
System.out.println(list.getClass());
// 客户端传递过来的数据为String数组,因为控件的(比如input空间)name可以有多个。
for (String value : values) {
// 解析字符串。
Point point = new Point();
String[] paramValues = value.split(",");
int x = Integer.parseInt(paramValues[0]);
int y = Integer.parseInt(paramValues[1]); point.setX(x);
point.setY(y);
list.add(point);
}
return list;
} @Override
public String convertToString(Map arg0, Object o) {
// 用String类型与toType比较,等于服务器发送到客户端数据。
List<Point> points = (List<Point>) o;
int count = 0;
StringBuffer sb = new StringBuffer();
sb.append("[");
for (Point point : points) {
count++;
int x = point.getX();
int y = point.getY(); sb.append("point").append(count).append(":").append("{x = ")
.append(x).append(", y=").append(y).append("}");
}
sb.append("]");
return sb.toString();
} }

PointConverter3.java的代码

  这段代码相对于之前的代码,将两个if判断拆分成两个方法,更加优雅,并且由Starts来判断我们是从字符串转换成对象,还是从对象转换成字符串,使得代码更加健壮。

[Struts2学习笔记] -- 自定义类型转换的更多相关文章

  1. Struts2学习笔记(七)——类型转换

    1.自动类型转换 Struts2内部提供大量类型转换器,用来完成数据类型转换问题: String和boolean.Boolean:完成字符串与布尔值之间的转换 String和char.Characte ...

  2. Struts2 学习笔记19 类型转换 Part1

    现在来说一说类型转换,提到类型转换其实我们之前早已经用过了,在url传递参数的时候,我们传递过来的参数其实都是String类型的,在显示的时候都自动转换了,像这种简单的转换很好理解,我们要说的是,转换 ...

  3. Struts2 学习笔记20 类型转换part2 写自己的转换器

    之前说的是调用Struts2的默认转换器,现在我们来说以下写自己的转换器,这个一般不常用,在访问不是自己写的类中可能用到.我们一点点来,因为写自己的转换器需要注意的东西还是很多的. 我们还是用之前的项 ...

  4. Struts2 学习笔记(概述)

    Struts2 学习笔记 2015年3月7日11:02:55 MVC思想 Strust2的MVC对应关系如下: 在MVC三个模块当中,struts2对应关系如下: Model: 负责封装应用的状态,并 ...

  5. Struts2学习笔记⑧

    今天是Struts2学习笔记的最后一篇文章了.用什么做结尾呢,这两天其实还学了很多东西,没有记录下,今天就查漏补缺一下. 文件上传与下载.FreeMarker以及昨天没做完的例子 文件上传与下载 文件 ...

  6. Struts2学习笔记①

    Struts2 学习笔记① 所有的程序学习都从Hello World开始,今天先跟着书做一个HW的示例. Struts2是一套MVC框架,使用起来非常方便,接触到现在觉得最麻烦的地方是配置文件.我的一 ...

  7. Struts2学习笔记NO.1------结合Hibernate完成查询商品类别简单案例(工具IDEA)

    Struts2学习笔记一结合Hibernate完成查询商品类别简单案例(工具IDEA) 1.jar包准备 Hibernate+Struts2 jar包 struts的jar比较多,可以从Struts官 ...

  8. iOS学习笔记-自定义过渡动画

    代码地址如下:http://www.demodashi.com/demo/11678.html 这篇笔记翻译自raywenderlick网站的过渡动画的一篇文章,原文用的swift,由于考虑到swif ...

  9. [原创]java WEB学习笔记67:Struts2 学习之路-- 类型转换概述, 类型转换错误修改,如何自定义类型转换器

    本博客的目的:①总结自己的学习过程,相当于学习笔记 ②将自己的经验分享给大家,相互学习,互相交流,不可商用 内容难免出现问题,欢迎指正,交流,探讨,可以留言,也可以通过以下方式联系. 本人互联网技术爱 ...

随机推荐

  1. 关于STM32 定时器 PWM 实时调节占空比时,预装载特性

    最近在调试项目的时候遇到一个奇怪的现象:在调试状态下,给定时器捕获比较寄存器赋不同值,能产生不同占空比的波形(图1).反映到器件上也有不同的电压显示,但是在设备运行的时候,就不行了(图2). 图1 图 ...

  2. bzoj 1093 [ZJOI2007]最大半连通子图(scc+DP)

    1093: [ZJOI2007]最大半连通子图 Time Limit: 30 Sec  Memory Limit: 162 MBSubmit: 2286  Solved: 897[Submit][St ...

  3. [Java] Map / HashMap - 源代码学习笔记

    Map 1. 用于关联 key 和 value 的对象,其中 key 与 key 之间不能重复. 2. 是一个接口,用来代替 Java 早期版本中的 Dictionary 抽象类. 3. 提供三种不同 ...

  4. ltp工具使用配置

    ltp是一个比较全的自然语言处理工具,可以用它进行分词.词性标注.语法分析等任务. ---- 准备 下载 下载ltp和ltp4j,在cmake官网下载并安装相应版本的cmake,并且下载ant. 构建 ...

  5. 简单的FIRST+集演示程序

    /* * 该程序用于计算某个非终结符的 FIRST+ 集合 * RexfieldVon * 2013年6月30日16:02:47 */ #include <stdio.h> #includ ...

  6. React Native专题

    转载注明出处:地址:http://www.lcode.org本文出自:[江清清的技术专栏]本React Native讲解专题:主要讲解了React Native开发,由基础环境搭建配置入门,基础,进阶 ...

  7. Python Logging 模块研究

    背景在一个新的项目里面加入了日志功能,想自己写一个,但是一个偶然的机会,通过google发现Python内建了一个非常强大的日志(log)模块:l... 背景 在一个新的项目里面加入了日志功能,想自己 ...

  8. jquery ajaxform上传文件返回不提示信息的问题

    在使用jquery的ajaxform插件进行ajax提交表单并且上传文件的时候,返回类型datatype :json但是后台通过写出一个json对象后,在执行完以后没有进入success函数,而是直接 ...

  9. JDK5-枚举

    1. 使用普通类模拟枚举 public class Weekday { private Weekday() {} // 私有化 public static final Weekday MONDAY = ...

  10. 详谈typedef的用法

    我们都知道typedef是类型重定义,既然是重定义就不可能出现新的数据类型,只是将已有的数据类型进行换个名字而已,但是这有什么用呢?可能我们学的时候,给的例子都是:typedef int INT; 然 ...