ssh备考-05Struts2 Action类下的重要API(原生Servlet的API、跳转配置、框架自身的数据封装、自定义拦截器)
目录一、Struts框架中如何使用原生Servlet的API方法一、使用ActionContext类(完全解耦合的方式)(不好用,了解)demo1.jspdemo1Action.java ★struts.xmlsuc.jsp方法二、使用ServletActionContext类(原生Servlet的API的方式)(好用,掌握)★demo1.jsp里加上...
目录
方法一、使用ActionContext类(完全解耦合的方式)(不好用,了解)
方法二、使用ServletActionContext类(原生Servlet的API的方式)(好用,掌握)★
2.属性驱动方式(封装到action的类成员变量里 前端要写OGNL麻烦 )(了解即可)
3.模型驱动(前端name值不用写OGNL,也可封装到javaBean类对象中)★
struts框架环境如何搭建上篇已经介绍 今日资料下载: 直接下载struts2_2.zip 网盘备份下载
一、Struts框架中如何使用原生Servlet的API
案例需求:使用Struts2作为WEB层完成客户的新增功能
提供JSP的表单页面的数据,在Action中使用Servlet的API接收到,然后保存到三个域对象中,最后再显示到JSP的页面上。
* 提供JSP注册的页面
<h3>注册页面</h3>
<form action="${ pageContext.request.contextPath }/xxx.action" method="post">
姓名:<input type="text" name="username" /><br/>
密码:<input type="password" name="password" /><br/>
<input type="submit" value="注册" />
</form>
方法一、使用ActionContext类(完全解耦合的方式)(不好用,了解)
Struts2框架中提供了一个类,ActionContext类,该类中提供一些方法,通过方法获取Servlet的API
一些常用的方法如下:
static ActionContext getContext() -- 获取ActionContext对象实例(这么获取自己,不需要new)
Map<String,Object> getParameters() -- 获取请求参数,相当于request.getParameterMap();
Map<String,Object> getSession() -- 获取的代表session域的Map集合(原生的session被放到Map集合中了)
Map<String,Object> getApplication() -- 获取代表application域的Map集合
void put(String key,Object value) -- 注意:向request域中存入值 (没有getRequest,用起来反而不习惯了)

demo1.jsp
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>demo1</title>
</head>
<body>
<h1>使用ActionContext类使用原生Servlet的API(方法一,完全解耦合)</h1>
<h3>注册页面</h3>
<form action="${ pageContext.request.contextPath }/demo1Action.action" method="post">
姓名:<input type="text" name="username" /><br/>
密码:<input type="password" name="password" /><br/>
<input type="submit" value="注册" />
</form>
</body>
</html>
demo1Action.java ★
package cn.ahpu.action;
import java.util.Arrays;
import java.util.Map;
import java.util.Set;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionSupport;
public class demo1Action extends ActionSupport {
@Override
public String execute() throws Exception {
//完全解耦合方式获取servlet的api进而前台数据
ActionContext context = ActionContext.getContext();//先获取ActionContext
//getParameters会封装所有的请求参数
Map<String, Object> map = context.getParameters();//然后就可以通过context调用servlet的api获取数据了
//拿到map所有key,再通过key遍历map
Set<String> keys = map.keySet();
for (String key : keys) {
//通过key获取值
String[] vals = (String[]) map.get(key);
System.out.println(key+" : "+Arrays.toString(vals));
}
//其他api使用演示
context.getSession().put("msg", "Session成功!");
context.getApplication().put("msg", "Application成功!");
context.put("msg", "Resquest成功!");//直接put中间不写get默认getResquest了,因为太常用了,因此这么简单点设计
return SUCCESS;
}
}
struts.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
"http://struts.apache.org/dtds/struts-2.3.dtd">
<struts>
<package name="struts02" namespace="/" extends="struts-default">
<action name="demo1Action" class="cn.ahpu.action.demo1Action">
<result name="success">/demo1/suc.jsp</result>
</action>
<!-- 上两行决定了请求路径为 项目名/demo1Action.action 此处访问默认方法execute-->
</package>
</struts>
suc.jsp
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>sucess el表达式</title>
</head>
<body>
<h3>默认最小域(request)的msg:${msg }</h3>
<h3>requestScope:${requestScope.msg }</h3>
<h3>sessionScope:${sessionScope.msg }</h3>
<h3>applicationScope:${applicationScope.msg }</h3>
</body>
</html>
测试:

方法二、使用ServletActionContext类(原生Servlet的API的方式)(好用,掌握)★
jsp+servlet基础学得比较熟的,此方法比较简单直接,推荐
Struts2框架提供了一个类,ServletActionContext,该类中提供了一些静态的方法
具体的方法如下
getPageContext()
getRequest()
getResponse()
getServletContext()
可以直接获取未封装的原生的request/response等api,获取后用起来很顺手,用来接收或传递简单几个参数时很方便
demo1.jsp里加上
<h1>使用ServletActionContext类使用原生Servlet的API(方法二,比较简单顺手,常用)</h1>
<h3>注册页面</h3>
<form action="${ pageContext.request.contextPath }/demo2Action.action" method="post">
姓名:<input type="text" name="username" /><br/>
密码:<input type="password" name="password" /><br/>
<input type="submit" value="注册" />
</form>
demo2Action.java
package cn.ahpu.action;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.struts2.ServletActionContext;
import com.opensymphony.xwork2.ActionSupport;
public class demo2Action extends ActionSupport {
private static final long serialVersionUID = 1L;
@Override
public String execute() throws Exception {
//似乎不封装数据 也默认会帮你放到session中 只要传递了
HttpServletRequest request = ServletActionContext.getRequest();
String name = request.getParameter("username");
String pwd = request.getParameter("password");
System.out.println("name:"+name+"\npwd:"+pwd);
request.setAttribute("msg", "request值");
request.getSession().setAttribute("msg", "session值");
request.getServletContext().setAttribute("msg", "application值");//可还记得getServletContext()就是application
//ServletActionContext.getServletContext().setAttribute("msg", "application值");//可以直接拿
//找不到的api就写ServletActionContext. 根据提示肯定能找到
HttpServletResponse response = ServletActionContext.getResponse();
//response.getWriter().print("<br>response.getWriter打印值<br>");
//一调用response.getWriter前端就乱码,所以不要这么用了 好不容易框架自动处理了乱码,可别给破坏了
return SUCCESS;
}
}
小插曲:页面的跳转result的配置总结
1. 结果页面存在两种方式
* 全局结果页面
> 条件:如果<package>包中的一些action都返回success,并且返回的页面都是同一个JSP页面,这样就可以配置全局的结果页面。
> 全局结果页面针对的当前的包中的所有的Action,但是如果局部还有结果页面,会优先局部的。使用的标签是
<global-results>
<result>/demo3/suc.jsp</result>
</global-results>
* 局部结果页面
<action ..>
<result>/demo3/suc.jsp</result>
</action ..>2. 结果页面的类型
* 结果页面使用<result>标签进行配置,包含两个属性
> name -- 逻辑视图的名称 就是匹配返回值
> type -- 跳转的类型,值一些,需要掌握一些常用的类型。常见的结果类型去struts-default.xml中查找。
* dispatcher -- 转发.默认值.Action--->JSP
* redirect -- 重定向.Action--->JSP
* chain -- 多个action之间跳转.Action---转发---Action
* redirectAction -- 多个action之间跳转.Action---重定向---Action
* stream -- 文件下载时候使用的
1.全局结果页面配置
删掉上例子中两个action中同样的result配置,外面加一个global-results
<global-results>
<result name="success">/demo1/suc.jsp</result>
</global-results><?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.3//EN" "http://struts.apache.org/dtds/struts-2.3.dtd"> <struts> <package name="struts02" namespace="/" extends="struts-default"> <!-- 下面两个action的跳转一模一样,删除,在外面配置一个全局的即可 --> <global-results> <result name="success">/demo1/suc.jsp</result> </global-results> <action name="demo1Action" class="cn.ahpu.action.demo1Action"> <!-- <result name="success">/demo1/suc.jsp</result> --> </action> <action name="demo2Action" class="cn.ahpu.action.demo2Action"> <!-- <result name="success">/demo1/suc.jsp</result> --> </action> </package> </struts>依然正常运行,效果一样!
2.跳转类型设置
dispatcher
默认值 请求转发 action->jsp

修改(就是加个type="dispatcher")上例后 正常执行
redirect
重定向 action->jsp

改成转发,再次运行,request域中的值就传递不了了

redirectAction
重定向到Action Action->Action Action之间跳转路径不能写太详细 写匹配好的Action的name即可
演示重Demo3Action_save方法跳到Demo3Action_update
Demo3Action.java
package cn.ahpu.action;
import com.opensymphony.xwork2.ActionSupport;
public class Demo3Action extends ActionSupport {
public String save() {
System.out.println("save方法执行...");
return "saveOK";
}
public String update() {
System.out.println("update方法执行...");
return NONE;
}
}
struts.xml
<!-- 演示Action之间的跳转
注意:跳转路径写匹配好的Action的name即可
-->
<action name="Demo3Action_*" class="cn.ahpu.action.Demo3Action" method="{1}">
<result name="saveOK" type="redirectAction">Demo3Action_update</result>
</action>
index.jsp
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>My JSP 'index.jsp' starting page</title>
</head>
<body>
<a href="${ pageContext.request.contextPath }/demo1/demo1.jsp">demo1</a><br>
<a href="${ pageContext.request.contextPath }/Demo3Action_save.action">Action之间跳转测试</a>
</body>
</html>
访问 ${ pageContext.request.contextPath }/Demo3Action_save.action

果然先执行save再执行update
暂时就演示3个
二、struts2专门的数据封装 ★
在Action类中写属性,提供get/set,框架自动帮你封装数据,还用得着啥子servlet api? 强大!!
1.属性驱动方式(封装到Action内定义的属性里)★
Action中定义属性 只用给属性添加set方法 然后框架的拦截器就自动帮你封装好了 属性name就是前端数据的name
demo2.jsp
<h3>属性驱动方式封装数据</h3>
<form action="${ pageContext.request.contextPath }/regist1.action" method="post">
姓名:<input type="text" name="username" /><br/>
密码:<input type="password" name="password" /><br/>
年龄:<input type="text" name="age" /><br/>
<input type="submit" value="注册" />
</form>
struts.xml
<!-- 新包 测试数据封装 一般一个项目一个包就够了 -->
<package name="demo2" namespace="/" extends="struts-default">
<action name="regist1" class="cn.ahpu.action.Regist1Action"/>
</package>
Regist1Action.java
package cn.ahpu.action;
import com.opensymphony.xwork2.ActionSupport;
/**
* 数据封装方式demo
* 属性驱动
*/
public class Regist1Action extends ActionSupport {
//设置属性 只用给属性添加set方法 然后框架的拦截器就自动帮你封装好了,封装到了这些属性中
private String username;
private String password;
private String age;
public void setUsername(String username) {
this.username = username;
}
public void setPassword(String password) {
this.password = password;
}
public void setAge(String age) {
this.age = age;
}
@Override
public String execute() throws Exception {
System.out.println("name:"+username+"\n"+"pwd:"+password+"\nage:"+age);
return NONE;
}
}


2.属性驱动方式(封装到action的类成员变量里 前端要写OGNL麻烦 )(了解即可)
action内定义个属性,属性本身是个javabean 提供get/set 自己new不用提供set
demo2.jsp 注意name写法
<h3>属性驱动方式封装数据(Action内new一个javabean 直接封装到javabean对象中)</h3>
<form action="${ pageContext.request.contextPath }/regist2.action" method="post">
<!-- 注意name写OGNL表达式 语法类似OGNL -->
姓名:<input type="text" name="user.username" /><br/>
密码:<input type="password" name="user.password" /><br/>
年龄:<input type="text" name="user.age" /><br/>
<input type="submit" value="注册" />
</form>
struts.xml
<action name="regist2" class="cn.ahpu.action2.Regist2Action"/>
User.java
package cn.ahpu.action2;
public class User {
private String username;
private String password;
private Integer age;
//省略get set
@Override
public String toString() {
return "User [username=" + username + ", password=" + password
+ ", age=" + age + "]";
}
}
Regist2Action.java
package cn.ahpu.action2;
import com.opensymphony.xwork2.ActionSupport;
/**
* 数据封装方式demo
* 属性驱动
*/
public class Regist2Action extends ActionSupport {
private User user=new User();//自己new了就不需要提供set了
public User getUser() {
return user;
}
@Override
public String execute() throws Exception {
System.out.println(user);
return NONE;
}
}

3.模型驱动(前端name值不用写OGNL,也可封装到javaBean类对象中)★
模型驱动 最简单常用 实现一个接口 前端正常写 后端Action实例化一个javabean对象为属性 不需要get/set
模型驱动的方式
1.实现ModelDriven接口
2.手动实例化对象(需要自己new好)
前端demo2.jsp 写法没啥特殊之处了
<h3>属性驱动方式封装数据(模型驱动方式 不用改前端,也可封装数据到对象中)</h3>
<form action="${ pageContext.request.contextPath }/regist3.action" method="post">
姓名:<input type="text" name="username" /><br/>
密码:<input type="password" name="password" /><br/>
年龄:<input type="text" name="age" /><br/>
<input type="submit" value="注册" />
</form>
struts.xml
<action name="regist3" class="cn.ahpu.action2.Regist3Action"/>
User.java同上
Regist3Action.java
package cn.ahpu.action2;
import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.ModelDriven;
/**
* 数据封装方式demo
* 模型驱动的方式
* 1.实现ModelDriven接口
2.手动实例化对象(需要自己new好)
*/
public class Regist3Action extends ActionSupport implements ModelDriven<User>{
private User user=new User();//必须自己new好
//不用提供get/set 但必须实现这个方法 拦截器会调用这个必须实现的方法获取user对象,帮助你封装数据 多简单
@Override
public User getModel() {
return user;
}
@Override
public String execute() throws Exception {
System.out.println("模型驱动"+user);
return NONE;
}
}

4.数据封装到集合 list和map 能封装到List<User>和Map<String,User> 但是前端仍然要写OGNL,麻烦。不学了
三、拦截器
拦截器只能对Action请求起作用(Action中的方法),而过滤器可以对几乎所有的请求起作用(CSS JSP JS)
需要在struts.xml中进行拦截器的配置,配置一共有两种方式,学第一种即可
1.编写拦截器类,关键:继承
DemoInterceptor.java
package cn.ahpu.interceptor;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.AbstractInterceptor;
public class DemoInterceptor extends AbstractInterceptor {
/**
* 配置好后,执行action方法之前会执行intercept
*/
@Override
public String intercept(ActionInvocation invocation) throws Exception {
System.out.println("Action方法执行之前");
String invoke = invocation.invoke();//表示执行下一个拦截器(Struts2就是一大堆拦截器组成的)
System.out.println("Action方法执行之后");
return invoke;//返回值必须这么写 不放行就卡死在这了
}
}
2.编写一个新的action方法
UserAction.java
package cn.ahpu.action3;
import com.opensymphony.xwork2.ActionSupport;
public class UserAction extends ActionSupport{
@Override
public String execute() throws Exception {
System.out.println("我是UserAction的方法...");
return NONE;
}
}
3.配置拦截器(自定义拦截器,action引入自定义的拦截器) ★
struts.xml拦截
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
"http://struts.apache.org/dtds/struts-2.3.dtd">
<struts>
<package name="struts02" namespace="/" extends="struts-default">
<!-- 下面两个action的跳转一模一样,删除,在外面配置一个全局的即可
效果:此struts02包下所有action的方法return success; 都会根据此配置跳转
当然,若下面的action内还是自己配置了<result name="success"> 会覆盖掉全局的
-->
<global-results>
<result name="success" type="redirect">/demo1/suc.jsp</result>
</global-results>
<action name="demo1Action" class="cn.ahpu.action.Demo1Action">
<!-- <result name="success">/demo1/suc.jsp</result> -->
</action>
<action name="demo2Action" class="cn.ahpu.action.Demo2Action">
<!-- <result name="success">/demo1/suc.jsp</result> -->
</action>
<!-- 演示Action之间的跳转
注意:跳转路径写匹配好的Action的name即可
-->
<action name="Demo3Action_*" class="cn.ahpu.action.Demo3Action" method="{1}">
<result name="saveOK" type="redirectAction">Demo3Action_update</result>
</action>
</package>
<!-- 新包 测试数据封装 一般一个项目一个包就够了 -->
<package name="demo2" namespace="/" extends="struts-default">
<action name="regist1" class="cn.ahpu.action2.Regist1Action"/>
<action name="regist2" class="cn.ahpu.action2.Regist2Action"/>
<action name="regist3" class="cn.ahpu.action2.Regist3Action"/>
</package>
<!-- 新包,测试拦截器的使用 -->
<package name="demo3" namespace="/" extends="struts-default">
<!-- package内action外定义拦截器-->
<interceptors>
<!-- name随便写 class必须是你写的那个Interceptor类的全路径 -->
<interceptor name="DemoInterceptor" class="cn.ahpu.interceptor.DemoInterceptor"/>
</interceptors>
<action name="user" class="cn.ahpu.action3.UserAction">
<!-- 引入自定义拦截器 -->
<interceptor-ref name="DemoInterceptor">
<!-- 放行写法 中间可以写写此不拦截的此action的方法-->
<!-- <param name="excludeMethods">login,regist,checkCode</param> -->
</interceptor-ref>
<!-- 只要引入了自定义拦截器,默认栈的拦截器就不执行了,必须手动引入 -->
<interceptor-ref name="defaultStack"/>
</action>
</package>
</struts>
4.测试运行

今日重点:
使用ServletActionContext类(原生Servlet的API的方式)(好用,掌握)★ [ServletActionContext.getRequest()]
属性驱动方式(封装到Action内定义的属性里)★ [Action内定义基本属性,提供get/set自动封装]
模型驱动(前端name值不用写OGNL,也可封装到javaBean类对象中)★ [Action实现ModelDriven接口,实现getModel]
拦截器★ [写Interceptor类实现接口,xml内先定义拦截器,再action内引入拦截器]
更多推荐




所有评论(0)