Struts2
概述
- Struts2框架应用JavaEE三层结构中Controller层框架
- Struts2框架在struts1和webwork基础之上发展全新的框架
- Stru2解决问题
入门案例
1. 导入struts2的jar包
2. 创建action
3. 配置action类访问路径
(1)创建struts2核心配置文件
- 核心配置文件名称和位置是固定的
- 位置必须在src下面,名称struts.xml
(2)引入dtd约束
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.5//EN"
"http://struts.apache.org/dtds/struts-2.5.dtd">
(3)action配置
<struts>
<package name="" namespace="" extends="">
<action name="" class="" method="">
<!-- 配置方法的返回值到页面 -->
<result name="">/跳转的页面 </result>
</action>
</package>
</struts>
4. 配置struts2过滤器
<filter>
<filter-name>struts2</filter-name>
<filter-class>org.apache.struts2.dispatcher.filter.StrutsPrepareAndExecuteFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
Struts2底层执行过程
查看源代码
class StrutsPrepareAndExecuteFilter implements StrutsStatics, Filter
服务器启动时创建过滤器,过滤器执行init()方法
在init()方法中主要加载配置文件
-struts.xml
-web.xml
-struts.properties
-default.properties
-struts-default.xml
-struts-plugin.xml
常量配置
- struts.xml里配置
<!-- 常量配置 -->
<constant name="struts.i18n.encoding" value="UTF-8"></constant>
注:default.properties
2. struts.properties配置
3. web.xml配置
分模块开发
<include file="com/wzw/struts/action/hello.xml"></include>
Action的三种创建方式
1. 创建普通类
public class ActionDemo1 {
public String execute(){
return "ok";
}
}
2. 创建类,实现Action接口
public class ActionDemo2 implements Action{
@Override
public String execute() throws Exception {
return "ok";
}
}
3. 创建类,继承ActionSupport类
public class ActionDemo3 extends ActionSupport{
@Override
public String execute() throws Exception {
return SUCCESS;
}
}
动态action(访问action里的其他方法)
1. 使用action标签的method属性
<!-- 1 使用method属性 -->
<action name="addAction" class="com.wzw.struts.action.MoreAction" method="add">
<result name="ok">/MyJsp.jsp </result>
</action>
<action name="delAction" class="com.wzw.struts.action.MoreAction" method="del">
<result name="ok">/MyJsp.jsp </result>
</action>
2. 使用通配符方式
<!-- 2 使用通配符
执行action里add方法,访问moreAction_add
执行action里del方法,访问moreAction_del
-->
<action name="moreAction_*" class="com.wzw.struts.action.MoreAction" method="{1}">
<result name="ok">/MyJsp.jsp </result>
<!-- 只允许访问add,del方法 -->
<allowed-methods>add,del</allowed-methods>
</action>
3. 动态访问action
<!-- 3 动态action
- 无method属性
- moreAction!add访问
-->
<constant name="struts.enable.DynamicMethodInvocation" value="true"></constant>
<package name="more2" namespace="/" extends="struts-default">
<action name="moreAction_*" class="com.wzw.struts.action.MoreAction">
<result name="ok">/MyJsp.jsp </result>
<!-- 允许访问所有方法 -->
<allowed-methods>regex:.*</allowed-methods> </action>
</package>
结果页面配置
1. 全局结果页面
针对于两个不同的action
<package name="page" namespace="/" extends="struts-default">
<!-- 1 全局结果页面配置 -->
<global-results>
<result name="success">/MyJsp.jsp </result>
</global-results>
<action name="AAction" class="com.wzw.struts.action2.AAction" method="execute">
</action>
<action name="BAction" class="com.wzw.struts.action2.BAction" method="execute">
</action>
</package>
2. 局部结果页面
<action name="AAction" class="com.wzw.struts.action2.AAction" method="execute">
<result name="success">/index.jsp </result>
</action>
局部配置与全局配置共存情况下,以局部配置为主
3. result标签type属性
Type:如何到页面(转发(dispatcher)/重定向(redirect))
(1) 针对配置到其他页面
dispatcher(转发):默认值,转发一次请求,地址栏不变
<result name="success" type="dispatcher">/index.jsp </result>
redirect(重定向):转发两次请求,地址栏变化
<!-- 3 type属性 -->
<result name="success" type="redirect">/MyJsp.jsp </result>
(2)针对配置到其他action
- chain:转发(地址栏不变)到其他action,一般不用,存在缓存问题
<result name="success" type="chain">BAction</result>
- redirectAction:重定向(地址栏变化)到其他action
<result name="success" type="redirectAction">BAction</result>
Action获取表单提交数据方式
注:使用ServletActionContext类操作域对象
1. 使用ActionContext类获取
public String execute() throws Exception {
//1 获取ActionContext对象
ActionContext context = ActionContext.getContext();
//2 调用方法得到表单数据
Map<String,Parameter> map = context.getParameters();
//3 获取key集合
Set<String> keys = map.keySet();
//4 根据key获取value
for (String key : keys) {
Parameter parameter = map.get(key);
System.out.println(parameter);
}
return SUCCESS;
}
2. 使用ServletActionContext类获取
public String execute() throws Exception {
//1 使用ServletActionContext对象获取request对象
HttpServletRequest request = ServletActionContext.getRequest();
//2 获取表单提交数据
String name = request.getParameter("name");
String age = request.getParameter("age");
String birth = request.getParameter("birth");
System.out.println("name: " + name + ", age: " + age + ", birth: " + birth);
return SUCCESS;
}
3. 使用接口注入方式获取
public class Form3Action extends ActionSupport implements ServletRequestAware{
private HttpServletRequest request;
@Override
public void setServletRequest(HttpServletRequest request) {
this.request = request;
}
@Override
public String execute() throws Exception {
String name = request.getParameter("name");
String age = request.getParameter("age");
String birth = request.getParameter("birth");
System.out.println("name: " + name + ", age: " + age + ", birth: " + birth);
return SUCCESS;
}
}
Struts2获取表单数据
1. 属性驱动获取
2. 对象驱动获取
<form action="./login/LoginAction2" method="get">
<input type="text" name="user.name">
<input type="text" name="user.age">
<input type="text" name="user.birth">
<input type="submit" value="login">
</form>
public class LoginAction2 {
private User user;
public String execute() {
System.out.println("2: " + user);
return "ok";
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
}
3. 模型驱动获取
<form action="./login/LoginAction3" method="get">
<input type="text" name="name">
<input type="text" name="age">
<input type="text" name="birth">
<input type="submit" value="login">
</form>
public class Form4Action extends ActionSupport implements ModelDriven<User>{
//注:表单name属性值与实体类属性值一样
private User user = new User();
@Override
public User getModel() {
return user;
}
@Override
public String execute() throws Exception {
System.out.println(user);
return "success";
}
}
注:属性和模型同时获取同一个表单,只执行模型封装
4. 复杂数据类型获取(Struts2获取数据封装到集合)
(1)List
(2)Map
<form action="./login/LoginAction4" method="get">
<input type="text" name="list">
<input type="text" name="list[1]">
<input type="text" name="map['haha']">
<input type="submit" value="login">
</form>
public class LoginAction4 {
private List<String> list;
private Map<String, String> map;
public String execute() {
System.out.println(list);
System.out.println(map);
return "ok";
}
public List<String> getList() {
return list;
}
public void setList(List<String> list) {
this.list = list;
}
public Map<String, String> getMap() {
return map;
}
public void setMap(Map<String, String> map) {
this.map = map;
}
}
5. 对象封装和模型驱动封装区别
- 对象封装可以获取多个对象,而模型只能封装一个对象
Ognl
1. 入门案例
(1)准备jar包
ognl-3.1.15.jar
(2)在JSP中引入标签库
<%@ taglib uri="/struts-tags" prefix="s" %>
(3)配合struts2标签使用
<!-- 使用s:property标签
value属性值里写Ognl表达式
-->
<s:property value="'你好'.length()" />
2 值栈概念
(1)web阶段,在Servlet中进行操作,把数据放到域对象里,页面中使用EL表达式获取,域对象在一定范围内,存取值
(2)在struts2中,自身存在一种存储机制,类似于web阶段的域对象——值栈,在action中把数据放到值栈里,在页面中通过Ognl获取值栈里的值
(3)Servlet与action区别(两者都是访问时创建)
- servlet:默认在第一次访问时创建,只创建一次,线程不安全
- action:每次访问时,都会创建一个action对象
(4)值栈存储位置
- 每次访问action时候,都会创建一个action对象;每个action对象中都会只有一个值栈对象
3 获取值栈对象
通过ActionContext类获取
public class ValueStackAction1 extends ActionSupport{
@Override
public String execute() throws Exception {
//1 创建ActionContext对象
ActionContext context = ActionContext.getContext();
//2 获取值栈对象
ValueStack valueStack1 = context.getValueStack();
ValueStack valueStack2 = context.getValueStack();
System.out.println(valueStack1 == valueStack2);//true
return NONE;
}
}
4. 向值栈放数据的三种方式
第一种 获取值栈对象,调用值栈对象中的set方法
第二种 获取值栈对象,调用之战对象中的push方法
第三种 在action中定义变量,生成变量的get方法
public class ValueStackAction3 extends ActionSupport{
private String name;
private Integer age;
public String getName() {
return name;
}
public Integer getAge() {
return age;
}
/**
* 向值栈中存放对象的三种方式
*/
@Override
public String execute() throws Exception {
//1 创建ActionContext对象获取值栈对象
ActionContext context = ActionContext.getContext();
//2 获取值栈对象
ValueStack stack = context.getValueStack();
/*
* 第一种 set(key,value)
*/
stack.set("wzw", 18);
/*
* 第二种 push(Object o)
*/
stack.push("95237");
/*
* 第三种 get()
*/
name = "hhh";
age = 18;
return SUCCESS;
}
}
(1)s:debug标签
<%@ taglib prefix="s" uri="/struts-tags" %>
<s:debug></s:debug>
(2)向值栈放对象
(3)向值栈放list集合
5 从值栈获取数据
(1)从值栈中获取字符串
<!-- 1 获取字符串 -->
<s:property value="name"/>
通过struts2标签和ognl表达式获取
(2)获取对象
<!-- 2 从值栈中获取对象 -->
<s:property value="user.name"/>
<s:property value="user.age"/>
<s:property value="user.birth"/>
(3)获取list集合
<!-- 3 从值栈中获取list集合 -->
<!-- 3.1 第一种方式 -->
name:<s:property value="list[0].name"/><br/>
<!-- 3.2 第二种方式 s:iterator -->
<s:iterator value="list">
name:<s:property value="name"/>
age:<s:property value="age"/>
birth:<s:property value="birth"/>
</s:iterator>
<br/>
<!-- 3.3 第三种方式 -->
<s:iterator value="list" var="user">
<!--
遍历list集合,得到user对象
把每次遍历得到的user对象放到context中
通过ognl表达式,#获得
-->
<s:property value="#user.name"/>
</s:iterator>
注:EL表达式也可以从值栈中获取