- 注:学习笔记,可能有些地方会有错误,仅供参考
Struts2的基本使用
由于我们使用Struts2代替了表现层的Servlet,同样我们也需要学习如果通过Struts2获取页面传来的数据,或者如何向页面传数据,同时还要学习如何转发或者重定向到一个逻辑页面(jsp或者action类)。
Struts2的域对象的使用
在Servlet时,我们是通过域对象向页面传数据,这些域对象都是Servlet为我们提供好的,在Struts2中也有这些域对象,但是需我们自己去创建或者访问,Struts2有三种方式可以去访问Serlvet的API。
- 访问Servlet的API的三种方式
- 实现接口的方式
package com.wzm.action;
import java.util.Map;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.struts2.interceptor.ServletRequestAware;
import org.apache.struts2.interceptor.ServletResponseAware;
import org.apache.struts2.util.ServletContextAware;
import com.opensymphony.xwork2.ActionSupport;
/*
* 使用ServletAPI的第一种方法,可以通过实现Struts提供的接口
* ServletRequestAware,ServletResponseAware,ServletContextAware
* 通过实现接口,会为我们提供ServletContext,HttpServletResponse,HttpServletRequest
* 我们需要定义全局变量来接这些对象,这样我们就可以在其他方法种使用这些对象
*/
public class ActionDemo1 extends ActionSupport implements ServletRequestAware,ServletResponseAware,ServletContextAware{
//定义全局变量
private ServletContext servletContext;
private HttpServletResponse response;
private HttpServletRequest request;
//ececute方法,在里边使用域对象
@Override
public String execute() throws Exception {
//获取页面传来的值
Map<String, String[]> map = request.getParameterMap();
//遍历输出
for (String key : map.keySet()) {
System.out.println(key+":"+map.get(key));
}
//往域对象中存值,操作方式与servlet时一样
servletContext.setAttribute("msg1", "实现接口方法,servletContext");
request.getSession().setAttribute("msg2", "实现接口方法,session");
return "success";
}
//Struts2提供的ServletContext,赋值给全局变量
public void setServletContext(ServletContext servletContext) {
this.servletContext = servletContext;
}
//Struts2提供的HttpServletResponse,赋值给全局变量
public void setServletResponse(HttpServletResponse response) {
this.response = response;
}
//Struts2提供的HttpServletRequest,赋值给全局变量
public void setServletRequest(HttpServletRequest request) {
this.request = request;
}
}
- 使用ActionContext的方式
package com.wzm.action;
import java.util.Arrays;
import java.util.Map;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.struts2.interceptor.ServletRequestAware;
import org.apache.struts2.interceptor.ServletResponseAware;
import org.apache.struts2.util.ServletContextAware;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionSupport;
/*
* 通过使用ActionContext来访问ServletAPI,
* 但是只能控制底层的Map对象,不能使用域对象的一些方法
*/
public class ActionDemo2 extends ActionSupport {
@Override
public String execute() throws Exception {
//获取actionCotext对象,该对象有点类似于request
ActionContext actionContext = ActionContext.getContext();
//通过actionContext获取servletContext
Map<String, Object> servletContext = actionContext.getApplication();
//通过actionContext获取session
Map<String, Object> session = actionContext.getSession();
//获取页面传来的值
Map<String, Object> map = actionContext.getParameters();
//遍历输出
for (String key : map.keySet()) {
System.out.println(key+":"+Arrays.toString((String[])map.get(key)));
}
//往域中存值,注意是直接操作map
servletContext.put("msg1", "ActionContext方法,servletContext");
session.put("msg2", "ActionContext方法,session");
return "success";
}
}
- 使用ServletActionContext的方式(常用)
package com.wzm.action;
import java.util.Arrays;
import java.util.Map;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.apache.struts2.ServletActionContext;
import org.apache.struts2.interceptor.ServletRequestAware;
import org.apache.struts2.interceptor.ServletResponseAware;
import org.apache.struts2.util.ServletContextAware;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionSupport;
/*
* 通过使用ServletActionContext来访问ServletAPI,
* 可以使用域对象的方法API
* 这种方法比较建议使用
*/
public class ActionDemo3 extends ActionSupport {
@Override
public String execute() throws Exception {
//通过ServletActionContext获取request
HttpServletRequest request = ServletActionContext.getRequest();
//通过ServletActionContext获取servletContext
ServletContext servletContext = ServletActionContext.getServletContext();
//通过request获取session
HttpSession session = request.getSession();
//获取页面传来的值
Map<String, String[]> map = request.getParameterMap();
//遍历输出
for (String key : map.keySet()) {
System.out.println(key+":"+Arrays.toString(map.get(key)));
}
//往域中存值,操作与servlet的类似
servletContext.setAttribute("msg1", "ServletActionContext方法,servletContext");
session.setAttribute("msg2", "ServletActionContext方法,session");
return "success";
}
}
result标签的type属性
在web开发中,当服务端接受到一个请求,会根据业务的不同来处理这请求,有时是转发请求,有时就是重定向,在Struts2中,这些操作是通过result标签的type属性来实现的。
- type的常见使用
<!-- result标签中的type属性介绍
-->
<package name="test4" extends="struts-default" namespace="/">
<action name="demo" class="com.wzm.action.ActionDemo">
<!-- dispatcher:这表示转发到jsp页面,默认不写就是这个类型 -->
<result name="add" type="dispatcher">/result.jsp</result>
<!-- chain:这表示转发到一个action,注意这里不需要有斜杆 -->
<result name="delete" type="chain">demo1</result>
<!-- redirect:表示重定向到jsp页面 -->
<result name="update" type="redirect">/result.jsp</result>
<!-- redirectAction:表示重定向到一个action中,注意不用斜杆 -->
<result name="find" type="redirectAction">demo1</result>
</action>
</package>
属性驱动和模型驱动
在Servlet时,我们需要自己手动的去一个个封装页面传来的数据,有时候数据多了就会变得比较繁琐,在Struts2中为我们提供了两种不同的封装方式:属性封装和模型封装。
- 属性驱动的封装
import java.util.List;
import com.opensymphony.xwork2.ActionSupport;
import com.wzm.entity.User;
public class ActionDemo4 extends ActionSupport {
/*
* 在servlet时期,如果我们要封装页面传来的属性的话,我们需要通过request获取参数,然后使用beanutils封装
* 在Struts2,封装数据不再需要我们自己封装,struts2会帮我们封装,有两种方式封装,一种为属性封装,一种为模型封装
* 属性封装又分为三种,封装基本类型和String类型,封装对象类型,封装复杂类型list.map等
*/
//第一种方式就是通过定义属性和属性的getter和setter方式来封装
//struts2会通过对比表单的name和属性名来进行封装
//定义属性,注意属性名要与页面表单中的name相对应
private String username;
private Integer age;
//定义setter方法,对于基本类型、包装类和String类型的封装,只需要有setter方法
public void setUsername(String username) {
this.username = username;
}
public void setAge(Integer age) {
this.age = age;
}
public String attr() throws Exception {
System.out.println(username+":"+age);
return null;
}
//第二种直接将参数封装到一个对象中,首先要有要封装的对象的类
//定义一个对象成员变量,注意名字要与表单的一致,对象内的属性名也要与表单的一致
private User user;
//定义user的getter和setter方式,封装对象的话,getter也要定义出来
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
public String obj() throws Exception {
System.out.println(user.getUsername()+":"+user.getAge());
return null;
}
//第三种直接将参数封装到一个复杂对象中
//定义一个对象成员变量,注意名字要与表单的一致,对象内的属性名也要与表单的一致
private List<User> list;
//定义list的getter和setter方式,封装复杂对象的话,getter也要定义出来
public List<User> getList() {
return list;
}
public void setList(List<User> list) {
this.list = list;
}
public String complex() throws Exception {
System.out.println(list.get(0).getUsername()+":"+list.get(0).getAge());
return null;
}
}
- 模型驱动的封装
package com.wzm.action;
import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.ModelDriven;
import com.wzm.entity.User;
/*
* 在servlet时期,如果我们要封装页面传来的属性的话,我们需要通过request获取参数,然后使用beanutils封装
* 在Struts2,封装数据不再需要我们自己封装,struts2会帮我们封装,有两种方式封装,一种为属性封装,一种为模型封装
* 模型封装需要实现一个模型驱动接口ModelDriven<T>,泛型要写自己想要封装进去的对象
*/
public class ActionDemo5 extends ActionSupport implements ModelDriven<User>{
//实现接口会让我们实现一个getModel()方法,返回值就我们要封装的对象
//如果要使用模型驱动封装,我们就要自己实例化出要的封装的对象
User user = new User();
public User getModel() {
//这里的方法要返回自己定义的对象
return user;
}
@Override
public String execute() throws Exception {
System.out.println(user.getUsername()+":"+user.getAge());
return null;
}
}
- form表单和Struts.xml的编写示例
form表单:
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
使用属性封装基本类型和String类型<br>
<form action="${pageContext.request.contextPath }/demo4_attr">
姓名:<input type="text" name="username"><br>
年龄:<input type="text" name="age"><br>
<input type="submit" value="提交"><br>
</form>
<!-- 如果封装的是一个对象,那么这里name就需要为
对象属性名.对象中的成员变量名
对象属性名与action类中定义的对象属性名相同
-->
使用属性封装对象类型<br>
<form action="${pageContext.request.contextPath }/demo4_obj">
姓名:<input type="text" name="user.username"><br>
年龄:<input type="text" name="user.age"><br>
<input type="submit" value="提交"><br>
</form>
<!-- 如果封装的是一个复杂类型,那么这里name就需要为
list[下标].list中的对象内的属性名,如list存储User对象,
list[0]代表第一个user对象,list[0].username代表user的username属性
复杂对象的属性名与action类中定义的对象属性名相同
-->
使用属性封装复杂对象类型<br>
<form action="${pageContext.request.contextPath }/demo4_complex">
姓名:<input type="text" name="list[0].username"><br>
年龄:<input type="text" name="list[0].age"><br>
<input type="submit" value="提交"><br>
</form>
<!--
使用模型封装的话,这里的name的写法就普通写法
-->
使用模型封装参数<br>
<form action="${pageContext.request.contextPath }/demo5">
姓名:<input type="text" name="username"><br>
年龄:<input type="text" name="age"><br>
<input type="submit" value="提交"><br>
</form>
</body>
</html>
struts.xml:
<!-- 封装页面传来的参数的方法:
第一种是属性引擎,也就是属性封装
第二种是模型引擎,也就是模型封装
-->
<package name="test5" extends="struts-default" namespace="/">
<!-- 属性引擎,也就是属性封装 -->
<action name="demo4_*" class="com.wzm.action.ActionDemo4" method="{1}">
<!-- 没有逻辑页面,返回值null -->
</action>
<!-- 模型引擎,也就是模型封装 -->
<action name="demo5" class="com.wzm.action.ActionDemo5">
<!-- 没有逻辑页面,返回值null -->
</action>
</package>