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,浏览器访问,输出结果正常,说明我们的配置是正确的。

  • 相关阅读:
    使用 Dockerfile 定制镜像
    UVA 10298 Power Strings 字符串的幂(KMP,最小循环节)
    UVA 11090 Going in Cycle!! 环平均权值(bellman-ford,spfa,二分)
    LeetCode Best Time to Buy and Sell Stock 买卖股票的最佳时机 (DP)
    LeetCode Number of Islands 岛的数量(DFS,BFS)
    LeetCode Triangle 三角形(最短路)
    LeetCode Swap Nodes in Pairs 交换结点对(单链表)
    LeetCode Find Minimum in Rotated Sorted Array 旋转序列找最小值(二分查找)
    HDU 5312 Sequence (规律题)
    LeetCode Letter Combinations of a Phone Number 电话号码组合
  • 原文地址:https://www.cnblogs.com/Code-Rush/p/4659815.html
Copyright © 2011-2022 走看看