zoukankan      html  css  js  c++  java
  • 第十一部分_Struts2.1类型转换精析

    首先,我们用第一种方式:继承ognl包下面的DefaultTypeConverter类,做一个类型转换:

    新建一个input.jsp:

    <%@ page language="java" import="java.util.*" pageEncoding="GBK"%>
    <%
    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 'input.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>
        
        <h1>请输入一个点的坐标(使用逗号分隔)</h1>
        <form action="converterAction.action" method="post">
        	坐标:<input type="text" name="point" size="20"><br>
        	坐标2:<input type="text" name="point2" size="20"><br>
        	用户名:<input type="text" name="username" size="20"><br>
        	年龄:<input type="text" name="age" size="20"/><br/>
        	出生日期:<input type="text" name="birthday" size="20"/><br/>
        	<input type="submit" value="submit"/>"
        
        
        </form>
        
        
      </body>
    </html>
    

    接下来编写处理类,在com.test.action包下建立一个PointAction类:

    package com.test.action;
    
    import java.util.Date;
    
    import com.opensymphony.xwork2.ActionSupport;
    import com.test.bean.Point;
    
    public class PointAction extends ActionSupport
    {
    	private Point point;
    	
    	private Point point2;
    	
    	private String username;
    	
    	private int age;
    	
    	private Date birthday;
    
    	public Point getPoint2()
    	{
    		return point2;
    	}
    
    	public void setPoint2(Point point2)
    	{
    		this.point2 = point2;
    	}
    
    	public Point getPoint()
    	{
    		return point;
    	}
    
    	public void setPoint(Point point)
    	{
    		this.point = point;
    	}
    
    	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 Date getBirthday()
    	{
    		return birthday;
    	}
    
    	public void setBirthday(Date brithday)
    	{
    		this.birthday = brithday;
    	}
    	
    	public String execute() throws Exception
    	{
    		return "success";
    	}
    }
    

    对于坐标的赋值,需要新建一个类,在com.test.bean包下新建一个类Point:

    package com.test.bean;
    
    public class Point
    {
    	private int x;
    	
    	private int 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;
    	}
    	
    	
    }
    

    然后再com.test.converter包下面建立一个点坐标的转换类PointConverter(该类需要继承ognl包下面的DefaultTypeConverter类):

    package com.test.converter;
    
    import java.util.Map;
    
    import ognl.DefaultTypeConverter;
    
    import com.test.bean.Point;
    
    public class PointConverter extends DefaultTypeConverter
    {
    	@Override
    	public Object convertValue(Map context, Object value, Class toType)
    	{
    		if(Point.class==toType)
    		{
    			String[] str = (String[])value;
    			
    			String firstValue = str[0];
    			
    			String[] resultValue = firstValue.split(",");
    			
    			Point point = new Point();
    			point.setX(Integer.parseInt(resultValue[0]));
    			point.setY(Integer.parseInt(resultValue[1]));
    			
    			return point;
    		}
    		else if(String.class == toType)
    		{
    			Point point = (Point)value;
    			
    			int x = point.getX();
    			int y = point.getY();
    			
    			String result = "X: " + x + " Y: " + y;
    			
    			return result;
    		}
    		
    		return null;
    	}
    }
    

    此外,我们需要做一些相关的配置让struts2找到这个处理类,在com.test.action下建立一个文件:PointAction-conversion.properties,注意到这个文件在'-'后的字符都是固定的,只用前面是可以变化的,此外他必须和PointAction放在同一个包下面:

    point=com.test.converter.PointConverter
    point2=com.test.converter.PointConverter
    

    然后配置struts.xml:

    <?xml version="1.0" encoding="UTF-8" ?>
    <!DOCTYPE struts PUBLIC
        "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
        "http://struts.apache.org/dtds/struts-2.0.dtd">
    	
    	<struts>
    		
    		<package name="struts2" extends="struts-default">
    		
    			<action name="helloworld" class="com.test.action.HelloWorld">
    				<result name="success">/helloworld.jsp</result>
    			</action>
    			
    			<action name="login" class="com.test.action.LoginAction">
    				<result name="success">/result.jsp</result>
    			</action>
    			
    			<action name="converterAction" class="com.test.action.PointAction">
    				<result name="success">/output.jsp</result>
    			</action>
    		</package>
    	
    	
    	</struts>
    

    最后写一个output.jsp,输出有几种选择:JSP脚本;EL;Struts2的标签库。这里我们使用后者:

    <%@ page language="java" import="java.util.*" pageEncoding="GBK"%>
    <%@ taglib uri="/struts-tags" prefix="s"%>
    <%
    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> 
      	坐标:<s:property value="point"/><br/>
      	坐标2:<s:property value="point2"/><br/>
      	用户名:<s:property value="username"/><br>
      	年龄:<s:property value="age"/><br>
      	出生日期:<s:property value="birthday"/>
    
      </body>
    </html>
    

    下面是运行结果的一个截图:

    其次,我们用Struts2提供的StrutsTypeConverter(它也继承了ognl包下面的DefaultTypeConverter类,如何在MyEclipse中查看其源代码?MyEclipse中找到struts2-core-2.1.6.jar,展开,找到org.apach.struts2.util,找到旗下的Struts TypeConverter.class,打开,点击Attach Source->External Folder,找到struts-2.1.6的解压缩目录,找到目录下的src,在src下面展开core,展开main,main下面有一个java,选择java,确定,这样就把硬盘上的源码和MyEclipse关联起来了)抽象类:

    在com.test.converter包下面新建一个类PointConverter2:

    package com.test.converter;
    
    import java.util.Map;
    
    import org.apache.struts2.util.StrutsTypeConverter;
    
    import com.test.bean.Point;
    
    public class PointConverter2 extends StrutsTypeConverter
    {
    
    	@Override
    	public Object convertFromString(Map context, String[] values, Class toClass)
    	{
    		Point point = new Point();
    		
    		String value = values[0];
    		
    		String[] result = value.split(",");
    		
    		point.setX(Integer.parseInt(result[0]));
    		point.setY(Integer.parseInt(result[1]));
    		
    		return point;
    	}
    
    	@Override
    	public String convertToString(Map context, Object o)
    	{
    		Point point = (Point)o;
    		
    		int x =point.getX();
    		int y = point.getY();
    		
    		String result = "x: " + x + " y: " + y;
    		
    		return result;
    	}
    
    }
    

    修改PointAction-conversion.properties:

    point=com.test.converter.PointConverter2
    point2=com.test.converter.PointConverter2
    

    浏览器访问http://localhost:8080/struts2/input.jsp,运行结果和用第一种方式实现的结果一样。

    一个问题:如何进行批量处理(假如有100个point,难道要从point1定义到point100)?

    我们假设有三个坐标表示"很多个坐标",在input.jsp中,注意到这些点的name属性都是相同的:

    <form action="converterAction.action" method="post">
        	坐标:<input type="text" name="point" size="20"><br>
        	坐标2:<input type="text" name="point" size="20"><br>
        	坐标3:<input type="text" name="point" size="20"><br>
        	用户名:<input type="text" name="username" size="20"><br>
        	年龄:<input type="text" name="age" size="20"/><br/>
        	出生日期:<input type="text" name="birthday" size="20"/><br/>
        	<input type="submit" value="submit"/>"
        
        
        </form>
    

    修改PointAction类:

    package com.test.action;
    
    import java.util.Date;
    import java.util.List;
    
    import com.opensymphony.xwork2.ActionSupport;
    import com.test.bean.Point;
    
    public class PointAction extends ActionSupport
    {
    	/*private Point point;
    	
    	private Point point2;*/
    	
    	private List<Point> point;
    	
    	private String username;
    	
    	
    
    	private int age;
    	
    	private Date birthday;
    	
    	public List<Point> getPoint()
    	{
    		return point;
    	}
    
    	public void setPoint(List<Point> point)
    	{
    		this.point = point;
    	}
    	/*public Point getPoint2()
    	{
    		return point2;
    	}
    
    	public void setPoint2(Point point2)
    	{
    		this.point2 = point2;
    	}
    
    	public Point getPoint()
    	{
    		return point;
    	}
    
    	public void setPoint(Point point)
    	{
    		this.point = point;
    	}*/
    
    	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 Date getBirthday()
    	{
    		return birthday;
    	}
    
    	public void setBirthday(Date brithday)
    	{
    		this.birthday = brithday;
    	}
    	
    	public String execute() throws Exception
    	{
    		return "success";
    	}
    }
    

    然后编写转换类PointConverter3:

    package com.test.converter;
    
    import java.util.ArrayList;
    import java.util.List;
    import java.util.Map;
    
    import org.apache.struts2.util.StrutsTypeConverter;
    
    import com.test.bean.Point;
    
    public class PointConverter3 extends StrutsTypeConverter
    {
    
    	@Override
    	public Object convertFromString(Map context, String[] values, Class toClass)
    	{
    		List<Point> list = new ArrayList<Point>();
    		
    		for(String value : values)
    		{
    			String[] result = value.split(",");
    			Point point = new Point();
    			
    			point.setX(Integer.parseInt(result[0]));
    			point.setY(Integer.parseInt(result[1]));
    			
    			list.add(point);
    		}
    		
    		return list;
    	}
    
    	@Override
    	@SuppressWarnings("unchecked")
    	public String convertToString(Map context, Object o)
    	{
    		List<Point> list = (List<Point>)o;
    		
    		StringBuffer sb = new StringBuffer();
    		
    		int number = 0;
    		
    		for(Point point : list)
    		{
    			number++;
    			
    			int x = point.getX();
    			int y = point.getY();
    			
    			// 这里不要使用以前PointConverter里那种直接拼接的方式,字符串太多,效率太低
    			sb.append(number).append(".x=").append(x).append(" y=").append(y).append(" ");
    			
    			
    		}
    		
    		return sb.toString();
    	}
    
    }
    

    更改配置文件PointAction-conversion.properties:

    #point=com.test.converter.PointConverter2
    #point2=com.test.converter.PointConverter2
    point=com.test.converter.PointConverter3
    

    最后更改output.jsp:

     <body> 
      	坐标:<s:property value="point"/><br/>
      	用户名:<s:property value="username"/><br>
      	年龄:<s:property value="age"/><br>
      	出生日期:<s:property value="birthday"/>
    
      </body>
    

    下面是运行结果的一个截图:

      

     此外,还用一种类型转换的方式(要求用户输入坐标分别在两个输入框中):

    修改input.jsp:

    <body>
        
        <h1>请输入一个点的坐标(使用逗号分隔)</h1>
        <form action="converterAction.action" method="post">
        <!-- 
        	坐标:<input type="text" name="point" size="20"><br>
        	坐标2:<input type="text" name="point" size="20"><br>
        	坐标3:<input type="text" name="point" size="20"><br>
         -->
         	x:<input type="text" name="point.x" size="20"/><br/>
         	y:<input type="text" name="point.y" size="20"/><br/>
        	用户名:<input type="text" name="username" size="20"><br>
        	年龄:<input type="text" name="age" size="20"/><br/>
        	出生日期:<input type="text" name="birthday" size="20"/><br/>
        	<input type="submit" value="submit"/>"
        
        
        </form>
    

    PointAction类内容如下:

    package com.test.action;
    
    import java.util.Date;
    import java.util.List;
    
    import com.opensymphony.xwork2.ActionSupport;
    import com.test.bean.Point;
    
    public class PointAction extends ActionSupport
    {
    	private Point point;
    	
    	private String username;
    
    	private int age;
    	
    	private Date birthday;
    
    	public Point getPoint()
    	{
    		return point;
    	}
    
    	public void setPoint(Point point)
    	{
    		this.point = point;
    	}
    
    	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 Date getBirthday()
    	{
    		return birthday;
    	}
    
    	public void setBirthday(Date brithday)
    	{
    		this.birthday = brithday;
    	}
    	
    	public String execute() throws Exception
    	{                
                    // 两行测试语句,输出到控制台
    		System.out.println("X: " + point.getX());
    		System.out.println("Y: " + point.getY());
    
    
    		return "success";
    	}
    }
    

    更改Point类,重写其toString方法:

    package com.test.bean;
    
    public class Point
    {
    	private int x;
    	
    	private int 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;
    	}
    	
    	@Override
    	public String toString()
    	{
    		String result = "x: " + x + " y: " + y;
    		return result;
    	
    	}
    }
    

    注释掉PointAction-conversion.properties:

    #point=com.test.converter.PointConverter2
    #point2=com.test.converter.PointConverter2
    #point=com.test.converter.PointConverter3
    

    output.jsp如下:

    <body> 
      	坐标:<s:property value="point"/><br/>
      	用户名:<s:property value="username"/><br>
      	年龄:<s:property value="age"/><br>
      	出生日期:<s:property value="birthday"/>
    
      </body>
    

    浏览器运行结果:

    坐标:x: 1 y: 2
    用户名:name
    年龄:20
    出生日期:93-3-30

    此外,附送一个小知识点:如果我们的Action有多个,比如增删查改,那么类就有点多了,我们可以用同一个action来处理多个业务需求,如下修改PointAction(增加了一个test方法,struts2要求这个方法除了方法名和execute不同外,其他签名包括public修饰符、抛出异常等必须完全一致):

    package com.test.action;
    
    import java.util.Date;
    import java.util.List;
    
    import com.opensymphony.xwork2.ActionSupport;
    import com.test.bean.Point;
    
    public class PointAction extends ActionSupport
    {
    	private Point point;
    	
    	private String username;
    
    	private int age;
    	
    	private Date birthday;
    
    	public Point getPoint()
    	{
    		return point;
    	}
    
    	public void setPoint(Point point)
    	{
    		this.point = point;
    	}
    
    	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 Date getBirthday()
    	{
    		return birthday;
    	}
    
    	public void setBirthday(Date brithday)
    	{
    		this.birthday = brithday;
    	}
    	
    	public String test() throws Exception
    	{
    		System.out.println("test invoked");
    		
    		System.out.println("X: " + point.getX());
    		System.out.println("Y: " + point.getY());
    		
    		return SUCCESS; // 读过Action的源代码,就知道它定义了一个叫做SUCCESS的常量,其值就是“success”,因此这里的效果和 return "success"相同
    	}
    	
    	public String execute() throws Exception
    	{
    		System.out.println("X: " + point.getX());
    		System.out.println("Y: " + point.getY());
    		return "success";
    	}
    }
    

    那么如何让我们的程序不执行默认的execute而是执行test方法呢?方法就是修改对应的struts.xml文件:

    <action name="converterAction" class="com.test.action.PointAction" method="test">
    				<result name="success">/output.jsp</result>
    			</action>
    

    可以看到在原有的基础上我们为其增加了一个method属性,并将其赋值为test,这样浏览器中访问http://localhost:8080/struts2/input.jsp,输出依旧,回到控制台可以看到test invoked,说明我们的做法成功了。

    补充:注意到上面程序中我给return SUCCESS语句添加了注释,提到了Action源码,其源码不在Struts2中,需要根据版本单独下载,比如我们这里是xwork-2.1.2,下载XWork源代码,找到对应的目录,比如我下载完成后,解压放到了struts2下面的D:ProgramFilesstruts-2.1.6xwork-2.1.2srcjava。MyEclipse中关联起来即可。

    我们怎么知道这个类的呢?

    因为我们的PointAction继承了ActionSupport,而ActionSupport实现了Action。

    再补充:如果我们要转换的Point在除了PointAction中还有其他的Action类需要对同样地Point转换,我们是不是针对每一个Action都得在它对应的包下面写一个同样的配置文件呢?答案是不需要,struts考虑到这点,给我们提供了一个全局转换的功能,在src(不要定义在某个包里,否则这个全局转换就失效了)下面新建一个文件命名为xwork-conversion.properties,注意到这里每个字符都是固定的。内容如下:

    #要转换的对象的类的全名=右边是转换器的名字
    com.test.bean.Point=com.test.converter.PointConverter2
    

    将input.jsp的坐标部分更改为:坐标:<input type="text" name="point" size="20"/><br/> 

    注释掉PointAction-conversion.properties,浏览器访问,输出结果正常,说明我们的配置是正确的。

  • 相关阅读:
    chart控件多个ChartArea
    winform chart画折线,波形图,多条数据
    C# Chart 折线图 多条数据展示
    task一个任务结束后执行另一个操作
    C#多线程同步 读写锁ReaderWriterLock的用法
    C# 多线程文件读写整理总结
    vue解决跨域问题
    接前端页面
    使用vue+zrender绘制体温单 三测单(2)
    使用vue+zrender绘制体温单 三测单(1)
  • 原文地址:https://www.cnblogs.com/Code-Rush/p/4659815.html
Copyright © 2011-2022 走看看