1. Struts2 框架中使用 Servlet 的 API 来操作数据

1.1 完全解耦合的方式

  1. Struts2 框架中提供了一个 ActionContext 类,该类中提供了一些方法:

    • static ActionContext getContext(): 获取 ActionContext 对象实例;
    • Map<Object> getParameters(): 获取请求参数, 相当于 request.getParameterMap();
    • Map<Object> getSession(): 获取代表 session 域的 Map 集合, 就相当于操作 session 域;
    • Map<Object> getApplication(): 获取代表 application 域的 Map 集合;
    • void put(String key, Object value): 向 request 域中存入值;

1.2 使用原生 Servlet 的API方式

  1. Struts2 框架提供了一个 ServletActionContext 类,该类中提供了一些静态的方法:

    • static getPageContext()
    • static getRequest()
    • static getResponse()
    • static getServletContext()
// 需求: 使用 Struts2 作为 Web 层完成客户的新增功能
// regist.jsp
<h1>注册</h1>
<form action="{pageContext.request.contextPath}/registAction" method="post">
用户名: <input type="text" name="username"/><br/>
密 码: <input type="password" name="password"/><br/>
<input type="submit" value="注册"/>
</form> // 完全解耦合的方式,操作数据 com.opensymphony.xwork2.ActionContext 包
ActionContext context = ActionContext.getContext();
// 获取到请求参数
Map<String,Object> map = context.getParameters();
// 遍历map, 获取数据
Set<String> keys = map.keySet();
for(String key : keys){
// Object 是数组
String[] val = (String[])map.get(key);
System.out.println(key+":"+Arrays.toString(val));
} // 向 request 域中存入数据
context.put("msg","request域中数据"); // 向 session 域中存入数据
context.getSession().put("msg","session域中数据"); // 向 application 域中存入数据
context.getApplication().put("msg","application域中数据"); // 使用原生 Servlet 的 API 方式 org.apache.struts2.ServletActionContext 包
// 获取 request 对象
HttpServletRequest request = ServletActionContext.getRequest();

2. 结果页面的跳转

2.1 结果页面存在两种方式

1. 全局结果页面
  • 如果 <package> 包中的一些action都返回 success,并且返回的页面都是同一个JSP页面,这样就可以配置全局的结果页面;
  • 全局结果页面针对当前包中的所有 Action, 如果局部还有结果页面,会优先局部的.
<package name="demo" extends="struts-default" namespace="/">

    // 添加图书和删除图书成功后,都会跳转到 suc.jsp 页面
<global-results>
<result>/demo2/suc.jsp</result>
</global-results> // 添加图书
<action name="addBook" class="cn.itcast.demo2.BookAction" method="add"/> // 删除图书
<action name="deleteBook" class="cn.itcast.demo2.BookAction" method="delete"/>
</package>
2. 局部结果页面
  • <result>/demo3/suc.jsp</result>

2.2 结果页面的类型

  1. <result>标签包含两个属性:

    • name: 逻辑视图的名称;
    • type: 跳转的类型; 常见的结果类型,可以从 struts-default.xml中查找;
      • dispatcher: 转发, 默认值;
      • redirect: 重定向;
      • chain: 多个 action 之间跳转, 从一个 Action 转发到另一个 Action;
      • redirectAction: 多个 action 之间跳转,从一个 Action 重定向到另一个 Action;
      • stream: 文件下载时,使用;
// 重定向到 Action
// Action 类的编写
public class Demo3Action extends ActionSupport{ public String save(){
System.out.println("save....");
return SUCCESS;
} public String update(){
System.out.println("update...");
return NONE;
}
} // struts.xml
<action name="demo3Action_*" class="com.itheima.demo.Demo3Action" method="{1}">
// 注意路径的编写方式
<result name="success" type="redirectAction">demo3Action_update</result>
</action>

3. Struts 框架的数据封装

3.1 概述

  1. Struts2 提供了两类数据封装的方式

    • 属性驱动;
    • 模型驱动(使用较多);

3.2 属性驱动

3.2.1 提供对应属性的 set 方法进行数据的封装(使用较多)
  1. 表单的哪些属性需要封装数据,那么在对应的 Action 类中提供该属性的 set 方法即可;
  2. 表单中提交的数据,最终调用 Action 类中的 setXxx 方法,赋值给全局变量;
  3. 注意点:
    • Struts2 的框架采用拦截器完成数据的封装;
    • 如果属性特别多,需要提供特别多的 set 方法,而且还需要手动将数据存入到对象中;
    • 这种情况下, Action 类就相当于一个 JavaBean. Action类既封装数据,又接收请求数据,耦合性较高,

      没有体现出 MVC 思想;
3.2.2 在页面上,使用 OGNL 表达式进行数据封装
  1. 在页面中使用OGNL表达式进行数据的封装,就可以直接把属性封装到某一个 JavaBean 的对象中;
  2. 在页面中定义一个 JavaBean, 并且提供 set 方法;
  3. 表单的写法: <input type="text" name="user.username"/>
  4. 注意:
    • 只提供一个 set 方法还不够,还需要提供 user 属性的 get 方法;
    • 先调用 get 方法,判断一下是否有 user 对象的实例对象;如果没有,就先创建 user 对象,并封装一个数据,

      然后调用set方法把拦截器创建的对象注入进来; 再调用 getUser 来封装数据;

3.3 模型驱动

  1. 手动实例化 JavaBean, 即: private User user = new User();
  2. 必须实现 ModelDriven 接口,实现 getModel() 的方法, 在 getModel() 方法中返回 user 即可!
// 属性驱动
// regist.jsp
<form action="{pageContext.request.contextPath}/regist.action" method="post">
用户名: <input type="text" name="username"/><br/>
密 码: <input type="password" name="password"/><br/>
<input type="submit" value="注册"/>
</form> // 属性驱动方式一, Action 类中提供对应属性的 set 方法
public class RegistAction extends ActionSupport{ // 定义属性
private String username;
private String password; // 只需要提供对应属性的 set 方法
// 拦截器调用 setXxx 方法,将属性封装,赋值给全局变量 username,password
public void setUsername(String username){
this.username = username;
}
public void setPassword(String password){
this.password = password;
} // regist 方法
public String regist(){ // 输出打印
System.out.println(username+"::"+password);
return NONE;
}
} // 属性驱动方式二, OGNL 表达式
// regist.jsp, 页面中使用 OGNL 表达式
<form action="{pageContext.request.contextPath}/regist.action" method="post"> // 此处 user.username 与 Action 类中的属性 user 一致
用户名: <input type="text" name="user.username"/><br/>
密 码: <input type="password" name="user.password"/><br/>
<input type="submit" value="注册"/>
</form> // 需要提供 JavaBean
// User.class
public class User{
private String username;
private String password; // 提供 get 和 set 方法
public String getUsername(){
return username;
}
public void setUsername(String username){
this.username = username;
} public String getPassword(){
return password;
}
public void setPassword(String password){
this.password = password;
} public String toString(){
....
}
} // Action 类
public class RegistAction extends ActionSupport{ // 定义属性
private User user; // 提供 get 和 set 方法
public User getUser(){
return user;
}
public void setUser(User user){
this.user = user;
} public String regist(){
System.out.println(user);
return NONE;
}
} // 模型驱动
// regist.jsp
<form action="{pageContext.request.contextPath}/regist.action" method="post">
用户名: <input type="text" name="username"/><br/>
密 码: <input type="password" name="password"/><br/>
<input type="submit" value="注册"/>
</form> // User.class
同上 // Action 类, 需要实现 ModelDriven 接口
public class RegistAction extends ActionSupport implements ModelDriven<User>{ // 手动实例化
private User user = new User(); // 实现 getModel() 方法
// 即获取模型对象
public User getModel(){
return user;
} public String regist(){
System.out.println(user);
return NONE;
}
}

3.4 Struts2 把数据封装到集合中

  1. 把数据封装到 Collection 中

    • 因为 Collection 接口都会有下标值,所有页面的写法会有一些区别,

      <input type="text" name="products[0].name"/>;
    • 在 Action 类中,需要提供 products 集合,并且提供 get 和 set 方法;
  2. 把数据封装到 Map 中
    • Map 集合是键值对的形式,页面的写法:

      <input type="text" name="map['one'].name"/>
    • Action 类中提供 map 集合,并且提供 get 和 set 方法;
// 向 List 集合中封装数据 (默认情况下, 采用属性驱动的方式)
// regist.jsp
<form action="{pageContext.request.contextPath}/regist.action" method="post">
用户名1: <input type="text" name="list[0].username"/><br/>
密 码1: <input type="password" name="list[0].password"/><br/> 用户名2: <input type="text" name="list[1].username"/><br/>
密 码2: <input type="password" name="list[1].password"/><br/>
<input type="submit" value="注册"/>
</form> // User.class
同上 // Action 类
public class RegistAction extends ActionSupport{ // 定义属性
private List<User> list; // 提供 get 和 set 方法
public List<User> getList(){
return list;
}
public void setList(List<User> list){
this.list = list;
} public String regist(){
for(User user : list){
System.out.println(user);
}
return NONE;
}
} // 向 Map 集合中封装数据
// regist.jsp
<form action="{pageContext.request.contextPath}/regist.action" method="post">
用户名1: <input type="text" name="map['one'].username"/><br/>
密 码1: <input type="password" name="map['one'].password"/><br/> 用户名2: <input type="text" name="map['two'].username"/><br/>
密 码2: <input type="password" name="map['two'].password"/><br/>
<input type="submit" value="注册"/>
</form> // User.class
同上 // Action 类
public class RegistAction extends ActionSupport{ // 定义属性
private Map<String,User> map; // 提供 get 和 set 方法
public Map<String,User> getMap(){
return map;
}
public void setMap(Map<String,User> map){
this.map = map;
} public String regist(){
System.out.println(map);
return NONE;
}
}

4. 拦截器技术

4.1 拦截器的概述

  1. 拦截器就是 AOP(Aspect-Oriented Programming)的一种实现. AOP 是指用于在某个方法或字段被访问之前,

    进行拦截,然后在之前或之后加入某些操作;
  2. 拦截器采用"责任链"模式
    • 在责任链模式里,很多对象由每一个对象对其下家的引用而连接起来形成一条链;
    • 责任链中每一个节点,都可以继续调用下一个节点,也可以组织流程继续执行;
  3. Struts2 中可以定义很多个拦截器,将多个拦截器按照特定顺序组成拦截器栈.

4.2 拦截器和过滤器的区别

  1. 拦截器是基于 java 反射机制的,而过滤器是基于函数回调的;
  2. 过滤器依赖于 Servlet 容器, 而拦截器不依赖于 Servlet 容器;
  3. 拦截器只能对 Action 请求起作用(即Action 中的方法),

    而过滤器是用于过滤从客户端发送到服务端请求的,其中包括CSS, JSP, JS等;

4.3 自定义拦截器和配置

4.3.1 自定义拦截器
  • 编写拦截器需要实现 interceptor 接口,实现接口中的三个方法;
  • 也可以继承 interceptor 接口的已知实现类 AbstractInterceptor;
  • 或者继承 interceptor 接口的已知实现类 MethodFilterInterceptor, 可以对指定方法放行;
// 编写拦截器
public String DemoInterceptor extends AbstractInterceptor { // intercept 方法: 在 action 执行之前,拦截
public String intercept(ActionInvocation invocation) throws Exception{ System.out.println("拦截器执行之前....."); // 执行下一个拦截器
String result = invocation.invoke(); System.out.println("拦截器执行之后....");
return result;
}
}
4.3.2 在 struts.xml 中配置拦截器
// 第一种方式:
// 在 <package> 包中定义拦截器,出现在 <package> 包的上方
<interceptors>
<interceptor name="loginInterceptor" class="cn.itcast.interceptor.LoginInterceptor"/>
</interceptors> // 在某个 action 中引入拦截器
<interceptor-ref name="loginInterceptor"/> // 注意:
// 如果引入了自定义的拦截器,Struts2 框架默认的拦截器就不会再执行了,所以需要引入 Struts2 默认的拦截器
<interceptor-ref name="defaultStack"/> // 第二种方式
// 在 <package> 包中定义拦截器的时候,自己直接定义一个拦截器栈
<interceptors>
<interceptor name="loginInterceptor" class="cn.itcast.interceptor.LoginInterceptor"/>
<interceptor-stack name="myStack">
<interceptor-ref name="loginInterceptor"/>
<interceptor-ref name="defaultStack"/>
</interceptor-stack>
</interceptors> // 在 action 中引入自定义拦截器栈
<action name="book_*" class="cn.itcast.action.BookAction" method="{1}">
<interceptor-ref name="myStack"/>
</action>

参考资料

Struts2.0 封装请求数据和拦截器介绍的更多相关文章

  1. Struts2的运行流程以及关键拦截器介绍

    Struts2的运行流程 1.ActionProxy是Action的一个代理类,也就是说Action的调用是通过ActionProxy实现的,其实就是调用了ActionProxy.execute()方 ...

  2. Struts2之Action接收请求参数和拦截器

    技术分析之在Struts2框架中使用Servlet的API        1. 在Action类中也可以获取到Servlet一些常用的API        * 需求:提供JSP的表单页面的数据,在Ac ...

  3. [ SSH框架 ] Struts2框架学习之四(自定义拦截器)

    一.Struts2的拦截器 1.1 拦截器概述 拦截器,在AOP( Aspect-Oriented Programming)中用于在某个方法或字段被访问之前,进行拦截然后在之前或之后加入某些操作.拦截 ...

  4. struts2.1.6教程五、拦截器

    在前面我们已经初步使用过拦截器,下面继续细细探讨. 1.概述strust2中的拦截器 拦截器是Struts2框架的核心,它主要完成解析请求参数.将请求参数赋值给Action属性.执行数据校验.文件上传 ...

  5. springmvc-高级参数绑定-映射-异常-json数据交互-拦截器

    1.1. 高级参数绑定 1.1.1. 复制工程 把昨天的springmvc-web工程复制一份,作为今天开发的工程 复制工程,如下图: 粘贴并修改工程名为web2,如下图: 工程右键点击,如下图: 修 ...

  6. struts2框架学习笔记6:拦截器

    拦截器是Struts2实现功能的核心部分 拦截器的创建: 第一种: package interceptor; import com.opensymphony.xwork2.ActionInvocati ...

  7. Java过滤器处理Ajax请求,Java拦截器处理Ajax请求,拦截器Ajax请求

    Java过滤器处理Ajax请求,Java拦截器处理Ajax请求,拦截器Ajax请求 >>>>>>>>>>>>>>&g ...

  8. Java过滤器处理Ajax请求,Java拦截器处理Ajax请求,java 判断请求是不是ajax请求

    Java过滤器处理Ajax请求,Java拦截器处理Ajax请求,java 判断请求是不是ajax请求   Java过滤器处理Ajax请求,Java拦截器处理Ajax请求,拦截器Ajax请求 java ...

  9. AOP框架Dora.Interception 3.0 [5]: 基于策略的拦截器注册方式

    注册拦截器旨在解决如何将拦截器应用到目标方法的问题.在我看来,针对拦截器的注册应该是明确而精准的,也就是我们提供的注册方式应该让拦截器准确地应用到期望的目标方法上,不能多也不能少.如果注册的方式过于模 ...

随机推荐

  1. Xilinx资源优化问题

    资源优化问题:Xilinx ise 出现资源不够的问题(ERROR:Cpld:868 - Cannot fit the design into any of the specified devices ...

  2. gpg: symbol lookup error

    今天使用sudo apt-get 安装包的时候,出现gpg错误,如下: gpg: symbol lookup error: /usr/local/lib/libreadline.so.6: undef ...

  3. ajax发送请求时为url添加参数(使用函数)

    <script> // ajax的get请求,使用函数向其url添加参数 function addURLParam(url,name,value){ url+=(url.indexOf(' ...

  4. 文件io之——read/write

    read函数从打开的设备或文件中读取数据. #include <unistd.h>ssize_t read(int fd, void *buf, size_t count);返回值:成功返 ...

  5. Freemarker自定义方法

    在项目中有一个需求,每个物品有一个guid,存在数据库中,而在页面上需要显示一个对应的业务数据值,暂且叫做serverId,serverId是通过guid移位计算得来.serverId只需要显示,后台 ...

  6. JVM性能调优监控工具专题一:JVM自带性能调优工具(jps,jstack,jmap,jhat,jstat,hprof)

    性能分析工具jstatjmapjhatjstack 前提概要:         JDK本身提供了很多方便的JVM性能调优监控工具,除了集成式的VisualVM和jConsole外,还有jps.jsta ...

  7. 在grub的rescue模式修复linux引导

    今天在windows 10系统收到系统更新通知,没看清楚就手贱点了马上更新.以为只是像那些普通更新一样重启一下更新就完了,万万没想到这个是覆盖更新,也就是说这是一个全新的系统更新而不是系统补丁.在安装 ...

  8. javaweb项目配jdk

    1.首先在你的本地安装jdk1.6,并将之添加至myeclipse中:window--preferences--installed   jres,add添加,格式D:\program files\jd ...

  9. Unity3D GUI图形用户界面系统

    1.skin变量 using UnityEngine; using System.Collections; public class Skin : MonoBehaviour { public GUI ...

  10. XMLRPC 学习笔记(一)- Python 实现

    参考文章: http://baike.baidu.com/view/643379.htm http://docs.python.org/2/library/xmlrpclib.html http:// ...