Struts2之Action接收请求参数和拦截器详解
技术分析之在struts2框架中使用servlet的api
1. 在action类中也可以获取到servlet一些常用的api
需求:提供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>
2. 完全解耦合的方式
如果使用该种方式,struts2框架中提供了一个类,actioncontext类,该类中提供一些方法,通过方法获取servlet的api
一些常用的方法如下
- static actioncontext getcontext() -- 获取actioncontext对象实例
- java.util.map<java.lang.string,java.lang.object> getparameters() -- 获取请求参数,相当于request.getparametermap();
- java.util.map<java.lang.string,java.lang.object> getsession() -- 获取的代表session域的map集合,就相当于操作session域。
- java.util.map<java.lang.string,java.lang.object> getapplication() -- 获取代表application域的map集合
- void put(java.lang.string key, java.lang.object value) -- 注意:向request域中存入值。
3. 使用原生servlet的api的方式(常用到)
struts2框架提供了一个类,servletactioncontext,该类中提供了一些静态的方法
具体的方法如下
- getpagecontext()
- getrequest()
- getresponse()
- getservletcontext()
技术分析之结果页面的跳转
1. 结果页面存在两种方式
全局结果页面
> 条件:如果<package>包中的一些action都返回success,并且返回的页面都是同一个jsp页面,这样就可以配置全局的结果页面。
> 全局结果页面针对的当前的包中的所有的action,但是如果局部还有结果页面,会优先局部的。使用的标签是
<global-results> <result>/demo3/suc.jsp</result> </global-results>
局部结果页面
<result>/demo3/suc.jsp</result>
2. 结果页面的类型
结果页面使用<result>标签进行配置,包含两个属性
> name -- 逻辑视图的名称
> type -- 跳转的类型,值一些,需要掌握一些常用的类型。常见的结果类型去struts-default.xml中查找。
- dispatcher -- 转发.type的默认值.action--->jsp
- redirect -- 重定向. action--->jsp
- chain -- 多个action之间跳转.从一个action转发到另一个action. action---action
- redirectaction -- 多个action之间跳转.从一个action重定向到另一个action. action---action
- stream -- 文件下载时候使用的
技术分析之struts2框架的数据封装
1. 为什么要使用数据的封装呢?
- 作为mvc框架,必须要负责解析http请求参数,并将其封装到model对象中
- 封装数据为开发提供了很多方便
- struts2框架提供了很强大的数据封装的功能,不再需要使用servlet的api完成手动封装了!!
2. struts2中提供了两类数据封装的方式?
第一种方式:属性驱动
> 提供对应属性的set方法进行数据的封装。
表单的哪些属性需要封装数据,那么在对应的action类中提供该属性的set方法即可。
表单中的数据提交,最终找到action类中的setxxx的方法,最后赋值给全局变量。
注意0:struts2的框架采用的拦截器完成数据的封装。
注意1:这种方式不是特别好:因为属性特别多,提供特别多的set方法,而且还需要手动将数据存入到对象中.
注意2:这种情况下,action类就相当于一个javabean,就没有体现出mvc的思想,action类又封装数据,又接收请求处理,耦合性较高。
> 在页面上,使用ognl表达式进行数据封装。
在页面中使用ognl表达式进行数据的封装,就可以直接把属性封装到某一个javabean的对象中。
在页面中定义一个javabean,并且提供set方法:例如:private user user;
页面中的编写发生了变化,需要使用ognl的方式,表单中的写法:<input type="text" name="user.username">
注意:只提供一个set方法还不够,必须还需要提供user属性的get和set方法!!!
> 先调用get方法,判断一下是否有user对象的实例对象,如果没有,调用set方法把拦截器创建的对象注入进来,
/** 属性驱动方式,把数据封装到javabean的对象中 @author administrator */ public class regist2action extends actionsupport{ private static final long serialversionuid = 6556880331550390473l; // 注意二:属性驱动的方式,现在,要提供是get和set方法 private user user; public user getuser() { system.out.println("getuser..."); return user; } public void setuser(user user) { system.out.println("setuser..."); this.user = user; } public string execute() throws exception { system.out.println(user); return none; } }
第二种方式:模型驱动
> 使用模型驱动的方式,也可以把表单中的数据直接封装到一个javabean的对象中,并且表单的写法和之前的写法没有区别!
> 编写的页面不需要任何变化,正常编写name属性的值
> 模型驱动的编写步骤:
手动实例化javabean,即:private user user = new user();
必须实现modeldriven<t>接口,实现getmodel()的方法,在getmodel()方法中返回user即可!!
/** 模型驱动的方式 实现modeldriven接口 必须要手动实例化对象(需要自己new好) @author administrator */ public class regist3action extends actionsupport implements modeldriven<user>{ private static final long serialversionuid = 6556880331550390473l; // 必须要手动实例化 private user user = new user(); // 获取模型对象 public user getmodel() { return user; } public string execute() throws exception { system.out.println(user); return none; } }
技术分析之struts2把数据封装到集合中
1. 封装复杂类型的参数(集合类型 collection 、map接口等)
2. 需求:页面中有可能想批量添加一些数据,那么现在就可以使用上述的技术了。把数据封装到集合中
3. 把数据封装到collection中
因为collection接口都会有下标值,所有页面的写法会有一些区别,注意:
<input type="text" name="products[0].name" />
在action中的写法,需要提供products的集合,并且提供get和set方法。
4. 把数据封装到map中
map集合是键值对的形式,页面的写法
<input type="text" name="map['one'].name" />
action中提供map集合,并且提供get和set方法
代码:
/** 属性驱动的方式,把数据封装到map集合中 @author administrator */ public class regist5action extends actionsupport{ private static final long serialversionuid = 6556880331550390473l; private map<string, user> map; public map<string, user> getmap() { return map; } public void setmap(map<string, user> map) { this.map = map; } public string execute() throws exception { system.out.println(map); return none; } }
案例总结之struts2的拦截器技术
1. 拦截器的概述
拦截器就是aop(aspect-oriented programming)的一种实现。(aop是指用于在某个方法或字段被访问之前,进行拦截然后在之前或之后加入某些操作。)
过滤器:过滤从客服端发送到服务器端请求的
拦截器:拦截对目标action中的某些方法进行拦截
- 拦截器不能拦截jsp
- 拦截到action中某些方法
2. 拦截器和过滤器的区别
1)拦截器是基于java反射机制的,而过滤器是基于函数回调的
2)过滤器依赖于servlet容器,而拦截器不依赖于servlet容器
3)拦截器只能对action请求起作用(action中的方法),而过滤器可以对几乎所有的请求起作用(css jsp js)
拦截器 采用 责任链 模式
> 在责任链模式里,很多对象由每一个对象对其下家的引用而连接起来形成一条链
> 责任链每一个节点,都可以继续调用下一个节点,也可以阻止流程继续执行
在struts2 中可以定义很多个拦截器,将多个拦截器按照特定顺序 组成拦截器栈 (顺序调用 栈中的每一个拦截器 )
3. struts2的核心是拦截器,看一下struts2的运行流程
自定义拦截器和配置
1. 编写拦截器,需要实现interceptor接口,实现接口中的三个方法
protected string dointercept(actioninvocation invocation) throws exception { // 获取session对象 user user = (user) servletactioncontext.getrequest().getsession().getattribute("existuser"); if(user == null){ // 说明,没有登录,后面就不会执行了 return "login"; } return invocation.invoke(); }
2. 需要在struts.xml中进行拦截器的配置,配置一共有两种方式
<!-- 定义了拦截器 第一种方式 <interceptors> <interceptor name="demointerceptor" class="com.itheima.interceptor.demointerceptor"/> </interceptors> --> <!-- 第二种方式:定义拦截器栈 --> <interceptors> <interceptor name="demointerceptor" class="com.itheima.interceptor.demointerceptor"/> <!-- 定义拦截器栈 --> <interceptor-stack name="mystack"> <interceptor-ref name="demointerceptor"/> <interceptor-ref name="defaultstack"/> </interceptor-stack> </interceptors> <action name="useraction" class="com.itheima.demo3.useraction"> <!-- 只要是引用自己的拦截器,默认栈的拦截器就不执行了,必须要手动引入默认栈 <interceptor-ref name="demointerceptor"/> <interceptor-ref name="defaultstack"/> --> <!-- 引入拦截器栈就ok --> <interceptor-ref name="mystack"/> </action>
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。