Struts2的ServletAPI的获取和各种类型的数据获取(三)

勿以恶小而为之,勿以善小而不为--------------------------刘备

劝诸君,多行善事积福报,莫作恶

上一章简单介绍了Action的实现方式和struts.xml配置的详细解释,Struts2的简单执行过程(二),如果没有看过,请观看上一章

Struts2是web层框架,主要有两个方面的作用:

1 . 获取前端的客户端输入

2 . 响应后端输出

常常使用到 Servlet API 中相应的方法。

通常有以下三种方式获取 request,response,session,application 对象信息。

1 . Action 通过 ActionContext() 类访问Servlet API

2 . Action 通过实现 XxxAware 接口直接访问 Servlet API

3 . 使用 ServletActionContext 直接访问 Servlet API

所有的Struts2 文章,都已经在web.xml 中添加了StrutsPrepareAndExecuteFilter 过滤器

<!-- 配置struts2的过滤器 -->
<filter>
  		<filter-name>struts</filter-name>
  		<filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
</filter>
<filter-mapping>
  		<filter-name>struts</filter-name>
  		<url-pattern>/*</url-pattern>
</filter-mapping>

一. 获取Servlet API 对象

一.一 通过 ActionContext() 类访问 Servlet API

一.一.一 ActionContext 类的主要方法

方法作用
static ActionContext getContext()静态方法, 获取ActionContext 对象实例
void put(String key,Object value)设置request范围的属性值,类似于request.setAttribute(String key,Object value)
Object get(Object key)获取 request 范围的属性值,类似于 request.getAttribute(String name)
Map getSession()返回Map 对象,模拟了 session对象
Map getApplication()返回map对象,模拟了application 对象
Map getParameters()获取所有的请求参数,类似调用 request.getParameterMap() 方法

一.一.二 写Demo验证一下

一.一.二.一 编写Action 类 ActionContextDemo
	public class ActionContextDemo extends ActionSupport{
	private static final long serialVersionUID = 1L;
	// 前端传入一个参数 为 name 
	private String name;
	
	/*
	 * 通过此方法,展示一下,将数据放置到 request域,session域,application域的用法。
	 * */
	public String showData(){
		
		ActionContext actionContext=ActionContext.getContext();
		
		//获取 application 作用域
		Map<String, Object> applicationData=actionContext.getApplication();
		
		//获取application的值
		Integer count=(Integer)applicationData.get("count");
		if(count==null){	
			count=1;
		}else{
			count=count+1;
		}
		//设置application的值
		applicationData.put("count", count);
		
		//获取session 作用域
		
		Map<String,Object> sessionData=actionContext.getSession();
		
		//放置到session域 
		sessionData.put("loginName",name);
		if("两个蝴蝶飞".equals(sessionData.get("loginName"))){
			
			//放置到request域
			actionContext.put("msg","第一种方式 :欢迎您,"+sessionData.get("loginName"));
			//返回success 
			return SUCCESS;
		}
		//放置到request域
		actionContext.put("msg","服务器提示:登录失败");
		return ERROR;
		
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}
}
一.一.二.二 配置 struts.xml 文件
	<package name="hello" extends="struts-default" namespace="/">
		
		<!-- 配置第一种方式 -->
		<action name="actionContextDemo" class="com.yjl.web.action.ActionContextDemo"
		method="showData">
			<result name="success">/WEB-INF/content/success1.jsp</result>
			<result name="error">/WEB-INF/content/error.jsp</result>
		</action>
	</package> 
一.一.二.三 编写前端文件

success1.jsp 里面的内容为:

<body>
	本站访问次数:${applicationScope.count} <br/>
	${sessionScope.loginName},您已经成功登录<br/>
	${requestScope.msg}<br/>
</body>

error.jsp 里面的内容为:

<body>
	${requestScope.msg}<br/>
</body>
一.一.二.四 重启服务器,进行验证

当输入网址为: http://localhost:8080/Struts_API/actionContextDemo 时,没有name值,提示登录失败

有图片

当输入网址为: http://localhost:8080/Struts_API/actionContextDemo?name=两个蝴蝶飞,name正确,提示登录成功

有图片

当输入网址为: http://localhost:8080/Struts_API/actionContextDemo?name=老蝴蝶,name值错误,提示登录失败

有图片

可以正常的传输数据。

这种方式,只能往request,session和applicaiton中进行存数据,取数据,只能对数据进行维护,不能像真正的request,response对象提供的那些方法一样强大。 如获取客户端ip,添加cookie 等, 用这种方法就无法实现了。

一.二 通过实现XxxAware 接口实现Servlet API 对象

Struts2针对Servlet 的API 对象,提供了三种接口, HttpServletRequestAware 接口,HttpServletResponseAware接口, ServletContextAware 接口。 其中,session对象可以通过request对象进行获取,所以就没有提供关于session的接口。

一.二.一 XxxAware 接口提供的方法

ServletRequestAware 接口提供了一个 setServletRequest() 方法,用于获取request对象

public abstract interface ServletRequestAware
{
  public abstract void setServletRequest(HttpServletRequest paramHttpServletRequest);
}

ServletResponseAware 接口提供了一个 setServletResponse() 方法,用于获取response对象

public abstract interface ServletResponseAware
{
  public abstract void setServletResponse(HttpServletResponse paramHttpServletResponse);
}

ServletContextAware 接口提供了一个 setServletContext()方法,用于获取application对象

public abstract interface ServletContextAware
{
  public abstract void setServletContext(ServletContext paramServletContext);
}

一.二.二 写Demo验证一下

一.二.二.一 编写Action 类 AwareDemo
	public class AwareDemo extends ActionSupport 
implements ServletRequestAware,ServletResponseAware,ServletContextAware{
	private static final long serialVersionUID = 1L;
	
	private String name;
	
	//接收 application
	private ServletContext application;
	//接收request
	private HttpServletRequest request;
	//接收response
	private HttpServletResponse response;
	//session可以通过 request 进行获取
	private HttpSession session;
	
	@Override
	public void setServletContext(ServletContext application) {
		this.application=application;
	}

	@Override
	public void setServletResponse(HttpServletResponse response) {
		this.response=response;
	}

	@Override
	public void setServletRequest(HttpServletRequest request) {
		this.request=request;
		this.session=request.getSession();
	}
	
	public String showData(){

		//获取application的值
		Integer count=(Integer)application.getAttribute("count"); 
		if(count==null){	
			count=1;
		}else{
			count=count+1;
		}
		//设置application的值
		application.setAttribute("count",count);
		
		
		//放置到session域 
		session.setAttribute("loginName",name);
		if("两个蝴蝶飞".equals(session.getAttribute("loginName"))){
			
			//放置到request域
			request.setAttribute("msg","第二种方式:欢迎您,"+session.getAttribute("loginName"));
			//展示ip 地址
			request.setAttribute("ip",request.getLocalAddr());
			
			//通过response 对象,设置cookie 
			
			Cookie cookie=null;
			try {
				cookie = new Cookie("userName",
						URLEncoder.encode(session.getAttribute("loginName").toString(),"UTF-8"));
			} catch (UnsupportedEncodingException e) {
				// TODO 自动生成的 catch 块
				e.printStackTrace();
			}
			cookie.setMaxAge(60*60);
			cookie.setPath("/");
			response.addCookie(cookie);
			
			//返回success 
			return SUCCESS;
		}
		//放置到request域
		request.setAttribute("msg","服务器提示:登录失败");
		return ERROR;
	}
	
	
	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

}

里面多提供了 request获取客户端ip和 response添加 cookie的操作

一.二.二.二 配置struts.xml 文件
<!-- 配置第二种方式 -->
<action name="awareDemo" class="com.yjl.web.action.AwareDemo"
method="showData">
	<result name="success">/WEB-INF/content/success2.jsp</result>
	<result name="error">/WEB-INF/content/error.jsp</result>
</action>
一.二.二.三 编写前端界面

success2.jsp, 内容主要是:

<!--引入jquery文件,网络版的 -->
<script src="http://code.jquery.com/jquery-latest.js"></script>

<body>
	本站访问次数:${applicationScope.count} <br/>
	${sessionScope.loginName},您已经成功登录<br/>
	${requestScope.msg}<br/>
	ip:${requestScope.ip}<br/>
	cookie值:<span id="cookieValue"></span>
	
	<script>
		$(function(){
			var username = decodeURIComponent("${cookie.userName.value}");//如果为空,使用解码后为空字符串
			if(!username.length==0){
				$("#cookieValue").text(username);
			}
		})
	</script>
</body>	
一.二.二.四 重启服务器,进行验证

输入网址: http://localhost:8080/Struts_API/awareDemo?name=两个蝴蝶飞

有图片

ip地址和cookie 均可以正常获取。

用js 脚本,解决了 cookie 中文乱码的问题。

这种方式,还需要实现接口,重写里面的方法,如果需要同时获取request,response,application对象,那么需要实现三个接口,太复杂。

一.三 使用 ServletActionContext 工具类获取ServletAPI

一.三.一 ServletActionContext 提供方法

方法名作用
static HttpServletRequest getRequest()取得request对象
static HttpServletResponse getResponse()取得response 对象
static ServletContext getServletContext()取得application 对象

session依旧是通过 request 进行获取的。

一.三.二 编写Demo 验证一下

一.三.二.一 编写Action 类 ServletActionContextDemo
public class ServletActionContextDemo extends ActionSupport{

	private static final long serialVersionUID = 1L;
	private String name;
	public String showData(){
		//获取application对象
		ServletContext application=ServletActionContext.getServletContext();
		//获取request对象
		HttpServletRequest request=ServletActionContext.getRequest();
		//获取response对象
		HttpServletResponse response=ServletActionContext.getResponse();
		//获取session对象
		HttpSession session=request.getSession();
		
		//获取application的值
		Integer count=(Integer)application.getAttribute("count"); 
		if(count==null){	
			count=1;
		}else{
			count=count+1;
		}
		//设置application的值
		application.setAttribute("count",count);
		
		
		//放置到session域 
		session.setAttribute("loginName",name);
		if("两个蝴蝶飞".equals(session.getAttribute("loginName"))){
			
			//放置到request域
			request.setAttribute("msg","第三种方式:欢迎您,"+session.getAttribute("loginName"));
			//展示ip 地址
			request.setAttribute("ip",request.getLocalAddr());
			
			//通过response 对象,设置cookie 
			
			Cookie cookie=null;
			try {
				cookie = new Cookie("userName",
						URLEncoder.encode(session.getAttribute("loginName").toString(),"UTF-8"));
			} catch (UnsupportedEncodingException e) {
				// TODO 自动生成的 catch 块
				e.printStackTrace();
			}
			cookie.setMaxAge(60*60);
			cookie.setPath("/");
			response.addCookie(cookie);
			
			//返回success 
			return SUCCESS;
		}
		//放置到request域
		request.setAttribute("msg","服务器提示:登录失败");
		return ERROR;
	}
	
	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}
}
一.三.二.二 配置struts.xml 文件
<!-- 配置第三种方式 -->
<action name="servletDemo" class="com.yjl.web.action.ServletActionContextDemo"
method="showData">
	<result name="success">/WEB-INF/content/success2.jsp</result>
	<result name="error">/WEB-INF/content/error.jsp</result>
</action>	
一.三.二.三 编写 jsp文件

用的是上面的 success2.jsp 文件,不需要重复编写。

一.三.二.四 重启服务器,进行验证

输入网址: http://localhost:8080/Struts_API/servletDemo?name=两个蝴蝶飞

有图片

通过 ServletActionContext 工具类,获取request,response,session,application 对象,比较好,一般采用这种方式。

但是不通过这种方式来获取前端传递过来的数据,获取数据,struts2框架提供了更简单的方式。

二. 获取前端数据

二.一. 通过原始的 request 对象进行获取数据

二.一.一 编写Action

public class RequestData extends ActionSupport{
	private static final long serialVersionUID = -477463776005071632L;
	Logger logger=Logger.getLogger(RequestData.class);
	public String getData() {
		//有一个ServletActionContext对象来获取底层的HttpServletRequest
		HttpServletRequest request=ServletActionContext.getRequest();
		//如果获取的是单个数据,如text框,password,hidden,radio性别框,select单选框等。
		String userName=request.getParameter("userName");
		//如果获取的是checkbox,select多选框.
		String []hobbys=request.getParameterValues("hobbys");
		logger.info("姓名是:"+userName);
		if(hobbys!=null) {
			for (String hobby : hobbys) {
				logger.info("爱好有:"+hobby);
			}
		}
		return NONE;
	}
}

二.一.二 配置struts.xml

<!-- 通过获取request来获取前端数据 -->
<action name="requestData" class="com.yjl.web.action.RequestData"
method="getData">

</action>

<!-- 配置跳转页面,要把它放置到最后 -->
<action name="*">
	<result>/WEB-INF/content/{1}.jsp</result>
</action>

二.一.三 编写前端界面

要配置跳转页面的 action

在 /content 文件夹下,创建一个 request.jsp 页面

<body>
  <form action="requestData" method="post">
		用户名:<input type="text" name="userName"><br/>
		爱好: <input type="checkbox" name="hobbys" value="读书"> 读书
		<input type="checkbox" name="hobbys" value="编程"> 编程
		<input type="checkbox" name="hobbys" value="写小说">写小说<br/>
		<input type="submit" value="提交">
	  </form>
</body>

二.一.四 重启服务器,进行验证

输入网址: http://localhost:8080/Struts_API/request , 会跳转到 /WEB-INF/content/request.jsp 页面,

有图片

名称填写 两个蝴蝶飞,爱好是编程和写小说

有图片

前端正常跳转,后端控制台打印输出:

有图片

ServletActionContext类可以直接获取request对象,response对象,application 对象,可以通过request.getSession()来获取session对象,

但是这种方式获取数据与Servlet产生了高度耦合,若非一些特殊数据需求,如客户端的ip地址,端口号等,不建议使用这种方式。而是采用 struts2框架提供的方式,来获取数据。

下面的例子,都可以正常访问,就不一 一 贴运行效果图了。struts.xml 的配置也很简单,也不一个一 个贴配置文件了。

二.二 通过 Struts2 框架提供的方式进行获取数据

二.二.一 Struts2获取单个普通的单值,如字符串和Integer 值

二.二.一.一 Demo展示
public class SimpleData extends ActionSupport{
	private static final long serialVersionUID = -477463776005071632L;
	Logger logger=Logger.getLogger(SimpleData.class);
	//name为单个值
	private String name;
	public void setName(String name) {
		this.name=name;
	}
	//多个值,用数组或者是List集合
	private String []hobbys;
	public void setHobbys(String[] hobbys) {
		this.hobbys = hobbys;
	}
	public String single() {
		logger.info("获取的姓名为:"+name);
		if(hobbys!=null) {
			for (String hobby : hobbys) {
				logger.info("爱好有:"+hobby);
			}
		}
		return NONE;
	}
}

前端页面为:

​​​​<form action="simpleData" method="post">
		用户名:<input type="text" name="name"><br/>
		爱好: <input type="checkbox" name="hobbys" value="读书"> 读书
		<input type="checkbox" name="hobbys" value="编程"> 编程
		<input type="checkbox" name="hobbys" value="写小说">写小说<br/>
		<input type="submit" value="提交">
</form>
二.二.一.二 注意事项

其中前端的表单的name值要与Action中属性的值相同,并且还需要在Action中实现相应的setter方法,只有这样,才可以进行封装数据。

如果是单个值,用普通的基本类型进行封装(Struts2自动处理了包装类,所以建议用包装类进行接收。String–>String,int—>Integer. 这样当输入年龄的数字时,可以直接将age转换成数字了。不用Integer.parseInt(age)进行转换了)

如果是多个值,如多选框和多选的select框,那么需要用数组 String []hobbys或者 集合 List []hobbys进行相应的接收。

通过这种setter() 方法的封装,叫做属性驱动。

当前端属性数目小时,可以通过这种方式进行封装, 当属性数目过多时,如员工档案数据,有name,age,email,phone 等大量数据时,就不建议用这种方式了。

二.二.二 表达式封装Bean实体类对象

在一个表单里面,如果表单的元素值过多,如一个注册页面,要传递很多的属性数据,如果都写成setter方法,对每一个属性,单独进行封装,那么在Action中会有很多setter() 方法,导致Action 类 会很麻烦。我们希望Struts2可以直接将表单数据封装成Java Bean对象。

二.二.二.一 Demo 展示

先新建一个User.java对象,里面封装一些基本的属性

	 /**
	 * @param id 主键编号
	 * @param name 姓名
	 * @param sex 性别
	 * @param age 年龄
	 * @param relation 关系
	 */
	private Integer id;
	private String name;
	private String sex;
	private Integer age;
	private String relation;
 
    //重写toString()方法,方便查看
    @Override
	public String toString() {
		return "User [id=" + id + ", name=" + name + ", sex=" + sex + ", age=" + age + ",     relation=" + relation + "]";
	}
	...
		封装相应的setter 和 getter 方法。
	...

在User.java 里面,提供封装setter和getter方法,重写toString()方法

新建UserAction类, 在里面封装User user 的属性,实现setter方法

/**
* @description 处理多个数据提交封装Java Bean的类
*/
public class UserAction extends ActionSupport{
	private static final long serialVersionUID = 5018178953781239408L;
	private Logger logger=Logger.getLogger(UserAction.class);
	private User user;
	public void setUser(User user) {
		this.user = user;
	}
	public User getUser() {
		return user;
	}
	public String setData() {
		logger.info("获取信息:"+user.toString());
		return NONE;
	}
}

前端form表单 /content/user.jsp

<body>
	<form action="Request_setData" method="post">
			姓名:<input type="text" name="user.name"><br/>
			性别:<input type="radio" name="user.sex" value="男">男
			<input type="radio" name="user.sex" value="女">女<br/>
			年龄:<input type="text" name="user.age"><br/>
			关系: <select name="user.relation">
					<option>父子</option>
					<option>母子</option>
					<option>姐弟</option>
					<option>妻弟</option>
				</select>
			<br/>
			<input type="submit" value="提交">
	</form>
</body>

运行Tomcat服务器,填写基本的数据后,控制台可以正常的打印前端输入的数据。

二.二.二.二 注意事项
  1. 实体类中属性值要与前端表单中的值相同(去除user.后),

  2. UserAction中user 只是private User user,并没有将其实例化成private User user=new User(), Struts2会自动将其实例化。

  3. input框中name=“对象.属性”, 这个对象指的是要将数据封装到哪个实体类对象。如果是private User a; 那么这个时候就是name=“a.name”

  4. 在Action中,必须要实现user的setter和getter()方法,只单独实现setter方法是不行的。

  5. 如果在Action中有 user 类和 teacher类,其中 user中有name属性,teacher 类也有name属性,那么 用 user.name 表达员工的姓名,teacher.name 表示教师的名称, 可以很方便的进行区分。

二.二.三 模型驱动封装 Java Bean对象。

需要Action 实现ModelDriven接口

二.二.三.一 ModelDriven 接口定义
public interface ModelDriven<T> {
    T getModel();
}

需要重写里面的 getModel() 方法。

二.二.三.二 Action实现
/
* @description 处理多个数据提交封装Java Bean的类
*/
public class UserAction2 extends ActionSupport
implements ModelDriven<User>{
	private static final long serialVersionUID = 5018178953781239408L;
	private Logger logger=Logger.getLogger(UserAction.class);
	// 需要直接实例化,不然会返回NPE 异常
	private User user=new User();
	@Override
	public User getModel() {
		return user;
	}
	public String setData() {
		logger.info("获取信息:"+user.toString());
		return NONE;
	}
}

前端时,/conent/user2.jsp

<form action="User2_setData" method="post">
	姓名:<input type="text" name="name"><br/>
	性别:<input type="radio" name="sex" value="男">男
	<input type="radio" name="sex" value="女">女<br/>
	年龄:<input type="text" name="age"><br/>
	关系: <select name="relation">
			<option>父子</option>
			<option>母子</option>
			<option>姐弟</option>
			<option>妻弟</option>
		</select>
	<br/>
	<input type="submit" value="提交">
</form>

重启服务器,输入数据,可以正常的接收到数据。

二.二.三.三 注意事项
  1. 实现ModelDriven 接口时,T为具体要封装的类型, 封装到user中,为User. 封装到class中为Class.

  2. user对象需要实例化,必须自己手动实例化. private User user=new User(); 如果不实例,会空指向异常的.

  3. 不需要实现对象的setter和getter方法,只需要重写ModelDriven中的getModel()方法即可,返回相应的对象。

  4. 在前端时,去除封装对象前缀., 因为ModelDriven中只有一个类型,所以知道封装到哪个对象. 在前端jquery动态操作时,也方便使用。

  5. 表单中的属性值必须与类中的属性值完全保持一致。 开发时,为了简便开发,可以将表单数据与实体类属性完全一致,实体类属性与数据库数据基本一致, 数据库字段值最好为类名第一个字母小写+类中的属性。 表名为t+实体类名。

  6. 如果前端既传入user的name,也传入teacher的name, 那么将无法区分name的值。 故同一个表单中元素的name值必须保证唯一。

二.二.四 三种数据封装方式的比较

上面就是Struts2提供的三种数据封装的方式,

  1. setter和getter方法封装属性的属性驱动

  2. 对象.属性名的表达式封装方式

  3. 实现ModelDriven接口的模型驱动方式。

二.二.四.一 三种方式的区别与联系
  1. 表达式封装和模型驱动封装,都可以直接封装成Java Bean实体类对象,表达式封装时前端需要对象.属性,要有对象的前缀.,模型驱动不需要。

  2. 表达式封装,不需要将对象实例化,而模型驱动却必须将封装的对象显式实例化,否则会出现空指向异常。

  3. 表达式可以封装多个对象中相同的属性值

private User user;
private Teacher teacher;
//user和teacher的setter和getter方法

在前端时, user.name, user.age 表示封装到 user对象中
         teacher.name, teacher.age ,表示封装到teacher 对象中 
  1. 模型驱动并不能像表达式封装那样,明确指明哪一个属性属于哪一个对象。 如果有一个name属性,User 对象有,Teacher 对象也有, ModelDriven对象时,那么这个name即使想表示的是Teacher对象的,也会被封装成user对象的。

ModelDriven对象时,那么这个name即使想表示的是User对象的,也会被封装成 teacher 对象的。

  1. 模型驱动封装与属性驱动的顺序

当属性驱动与模型驱动同时存在时,name在User对象中, 进行了模型驱动封装,并且还实现了name的setter和getter方法,那么这个时候:

	private User user=new User();
	@Override
	public User getModel() {
		return user;
	}
    private String name;
	public void setName(String name) {
		this.name = name;
	}
 
	public String setData() {
		//为null
		logger.info("属性驱动:"+name);
		//获取前端传入的值 
		logger.info("模型驱动:"+user.getName());
		return NONE;
	}

模型驱动能够取到值。

二.二.五 提供Action公共代码,创建 BaseAction

在开发中,最常用的是模型驱动,因为这样方便一些。 但每一个类都是继承ActionSupport,实现ModelDriven 接口,太麻烦,一般会用一个BaseAction类来实现。

放置在 com.yjl.utils 包下。

BaseAction.java

package com.yjl.utils;
import java.lang.reflect.ParameterizedType;
import org.apache.log4j.Logger;
import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.ModelDriven;
/**
* @author 两个蝴蝶飞
* @version 创建时间:2018年8月23日 下午4:40:13
* @description BaseAction的工具类
*/
@SuppressWarnings(value= {"rawtypes","unchecked"})
public class BaseAction<T> extends ActionSupport implements ModelDriven<T>{
	private static final long serialVersionUID = -7180401147510521582L;
	private Logger logger=Logger.getLogger(BaseAction.class);
	private T t;
	private Class clazz;
	public BaseAction() {
		//得到当前的类
		Class class1=this.getClass();
		//得到运行中的父类
		ParameterizedType parameterizedType=(ParameterizedType) class1.getGenericSuperclass();
		clazz=(Class) parameterizedType.getActualTypeArguments()[0];
		try {
			t=(T) clazz.newInstance();
		} catch (InstantiationException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		logger.info("当前类的类:"+clazz.getName()+"完成初始化");
	}
	@Override
	public T getModel() {
		return t;
	}
	
}

然后UserAction类只需要继承BaseAction类即可

public class UserAction extends BaseAction<User>{
    //取user对象时,用 super.getModel()
}

TeacherAction 类只需要继承BaseAction 类即可

public class TeacherAction extends BaseAction<Teacher>{
    //取teacher对象时,用 super.getModel()
}

这样就可以了。

二.二.六 属性驱动封装List 集合

封装list集合,可以批量添加对象时使用,批量修改对象时使用。

/
* @description 处理多个对象数据提交封装List集合
*/
public class UserAction6 extends ActionSupport{
	private static final long serialVersionUID = 5018178953781239408L;
	private Logger logger=Logger.getLogger(UserAction.class);
	private List<User> userList;
	public List<User> getUserList() {
		return userList;
	}
	public void setUserList(List<User> userList) {
		this.userList = userList;
	}
	public String setData() {
		if(userList!=null) {
			for (User user : userList) {
				logger.info(user.toString());
			}
		}
		return NONE;
	}
}

其中前端表示为: /content/user6.jsp

<form action="User6_setData" method="post">
	姓名:<input type="text" name="userList[0].name"><br/>
	性别:<input type="radio" name="userList[0].sex" value="男">男
	<input type="radio" name="userList[0].sex" value="女">女<br/>
	年龄:<input type="text" name="userList[0].age"><br/>
	关系: <select name="userList[0].relation">
			<option>父子</option>
			<option>母子</option>
			<option>姐弟</option>
			<option>妻弟</option>
		</select>
	<br/>
	<hr/>
	姓名:<input type="text" name="userList[1].name"><br/>
	性别:<input type="radio" name="userList[1].sex" value="男">男
	<input type="radio" name="userList[1].sex" value="女">女<br/>
	年龄:<input type="text" name="userList[1].age"><br/>
	关系: <select name="userList[1].relation">
			<option>父子</option>
			<option>母子</option>
			<option>姐弟</option>
			<option>妻弟</option>
		</select>
	<br/>
	<input type="submit" value="提交">
</form>

list数据提交时, name=list属性名[下标].属性值。

二.二.七 属性驱动封装Map 集合

UserAction7.java 封装

/**
* @description 处理多个对象数据提交封装Map
*/
public class UserAction7 extends ActionSupport{
	private static final long serialVersionUID = 5018178953781239408L;
	private Logger logger=Logger.getLogger(UserAction.class);
	private Map<String,User> maps;
	public Map<String, User> getMaps() {
		return maps;
	}
	public void setMaps(Map<String, User> maps) {
		this.maps = maps;
	}
	public String setData() {
		if(maps!=null) {
			/* 
			 * 第一种遍历Map的方式  用keySet遍历
			 * Set<String> sets=maps.keySet();
			Iterator <String> iterator=sets.iterator();
			while(iterator.hasNext()) {
				String key=iterator.next();
				User value=maps.get(key);
				logger.info(key+"------>"+value.toString());
			}*/
			//用第二种方式 entrySet
		  Set<Entry<String,User>> sets=maps.entrySet();
		  for (Entry<String, User> entry : sets) {
			   String key=entry.getKey();
			   User value=entry.getValue();
			   logger.info(key+"------>"+value.toString());
		  	}
		}
		return NONE;
	}
}

前端时: /content/user7.jsp

<form action="User7_setData" method="post">
	姓名:<input type="text" name="maps['one'].name"><br/>
	性别:<input type="radio" name="maps['one'].sex" value="男">男
	<input type="radio" name="maps['one'].sex" value="女">女<br/>
	年龄:<input type="text" name="maps['one'].age"><br/>
	关系: <select name="maps['one'].relation">
			<option>父子</option>
			<option>母子</option>
			<option>姐弟</option>
			<option>妻弟</option>
		</select>
	<br/>
	<hr/>
	姓名:<input type="text" name="maps['two'].name"><br/>
	性别:<input type="radio" name="maps['two'].sex" value="男">男
	<input type="radio" name="maps['two'].sex" value="女">女<br/>
	年龄:<input type="text" name="maps['two'].age"><br/>
	关系: <select name="maps['two'].relation">
			<option>父子</option>
			<option>母子</option>
			<option>姐弟</option>
			<option>妻弟</option>
		</select>
	<br/>
	<input type="submit" value="提交">
</form>

运行输入数据:

二.二.八 属性封装到Set中

基本没有使用,简单写一下

UserAction8.java

	@KeyProperty("id")
    private Set<User> userSet=new HashSet<User>();
 
    public Set<User> getUserSet() {
        return userSet;
    }
 
    public void setUserSet(Set<User> userSet) {
        this.userSet = userSet;
    }
    public String setData() {
    	if(userSet!=null) {
    		System.out.println("不为空"+userSet.size());
            for (User user : userSet) {
                System.out.println(user.toString());
            }
    	}else {
    		System.out.println("为空");
    	}
        return NONE;
    }

jsp页面: /content/user8.jsp

<form action="Request_setData" method="post">
    姓名:<input name="userSet.makeNew[0].name" type="text"/><br/>
    姓名:<input name="userSet.makeNew[1].name" type="text"/><br/>
    <input type="submit" value="提交"/>
</form>

set集合比较特殊,没有顺序,所以不能用[0][1] 下标的方式进行,需要用 set名称.makeNew[下标].属性

并且Action中set需要添加一个注解 @keyProperty(“id”) 其中id为User类的唯一标识。(建议重写User 类的hashCode和equals()方法)

数据封装所配置的struts.xml 文件为:

<!-- 通过获取request来获取前端数据 -->
	<action name="requestData" class="com.yjl.web.action.RequestData"
	method="getData">
	</action>
	
	<!-- 通过setter 方法封装单值  -->
	<action name="simpleData" class="com.yjl.web.action.SimpleData"
	method="single">
	</action>
	
	<!-- 通过表达式封装java bean 对象 -->
	<action name="User_setData" class="com.yjl.web.action.UserAction"
	method="setData">
	</action>
	
	<!-- 通过模型驱动封装java bean 对象 -->
	<action name="User2_setData" class="com.yjl.web.action.UserAction2"
		method="setData">
	</action>
	
	<!-- 属性驱动封装List 集合 -->
	<action name="User6_setData" class="com.yjl.web.action.UserAction6"
		method="setData">
	</action>
	
	<!-- 属性驱动封装Map 集合 -->
	<action name="User7_setData" class="com.yjl.web.action.UserAction7"
		method="setData">
	</action>
	
	<!-- 属性驱动封装Set 集合 -->
	<action name="User8_setData" class="com.yjl.web.action.UserAction8"
		method="setData">
	</action>

本章节代码链接为:

链接:https://pan.baidu.com/s/1RK1RlGqoKKm51kruKJ5cqg 
提取码:l5d5

下一章简单介绍了两个小例子登录和显示全部用户信息的模块(四)

谢谢您的观看!!!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

两个蝴蝶飞

你的鼓励,是老蝴蝶更努力写作的

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值