Struts2(二)

2017-10-18  本文已影响26人  贾里

1.访问ServletApi三种方式


1).在Action访问Servlet API:

在Action类中操作Servlet中相关的对象(request,repsonse,session,cookie等)

2).Action访问Servlet API,有三种方式:

1.通过Action实现感知接口.

操作步骤:

原理:拦截器.
常用的感知接口:
ServletRequestAware ---->感知request对象.
ServletResponseAware---->感知response对象.
ServletContextAware----->感知application对象.

2.使用ServletActionContext类.

好比是一个工具类,封装当前请求的对象和响应对象信息.
ServletActionContext类提供了很多静态方法,可以直接获取request/response等对象.

常用的方法:
static HttpServletRequest getRequest() :获取请求对象
static HttpServletResponse getResponse() :获取响应对象
static ServletContext getServletContext() :获取应用对象

Paste_Image.png
3.使用ActionContext类.

ActionContext:Action的上下文对象(环境).封装了当前请求/响应的所有的数据.

获取ActionContext对象:

    ActionContext ctx = ActionContext.getContext();
Paste_Image.png Paste_Image.png Paste_Image.png

3).Action访问Servlet API,有三种方式对比和选择:

在开发中,使用方式2和方式3比较多,Struts2官方建议使用方式3.先使用方式3,搞不定再使用方式2.

2.Action获取请求参数三种方式


J2EE的最佳实践:按照功能职责,分层开发:
表现层:
职责:
1.接受请求数据
2.把数据封装Model对象
3.调用业务逻辑方法处理请求
4.控制界面跳转

MVC思想:
M:数据对象.
V:JSP
C:StrutsPrepareAndExecuteFilter(前端控制器.)
问题:Action到底充当什么角色?

Action获取请求参数三种方式:

1).第一种:Action本身作为Model对象,通过setter方法封装(属性注入)

JSP(注意表单参数的名字):

Paste_Image.png

Action:

Paste_Image.png

注意:表单中的参数名称要和Action中的setter方法的属性名相同.

2).第二种:创建独立Model对象,页面通过ognl表达式封装(属性注入)

1):创建Model对象,封装参数数据信息.

Paste_Image.png

2):JSP(注意表单参数的名字):

Paste_Image.png

给当请求Action中的user属性对应的对象中,设置username和password值.

Action中的:user属性.--->对应一个对象.
user属性对应对象的:username/password属性

:先从Action中获取是否有user对象(getUser方法),
如果有,就直接在该对象中设置其他参数值.
如果没有:创建新的User对象.

User user = Struts2框架通过getUser方法来获取User对象.
if(uesr ==null){
   user = new User();
}
把参数设置到user对象中去.

3):Action代码:

Paste_Image.png

方式1:同时提供getter/setter.
方式2:在生命对象的时候,new出来,再提供getter方法即可.

Paste_Image.png

3).第三种:使用ModelDriven接口,对请求数据进行封装(模型驱动)

1):JSP(注意表单参数的名字):

Paste_Image.png

username和password对应:
Model中的属性:

2):Action类:

Paste_Image.png

4).Action获取请求参数三种方式对比:

第一种:Action本身作为Model对象,通过setter方法封装(属性注入)
1:如果参数比较多,此时Action中将提供大量字段和setter方法,Action很臃肿.
2:我们还得手动把数据封装到对象中去.
第二种:创建独立Model对象,页面通过ognl表达式封装(属性注入)
1:表单参数的name属性值,不是很清晰.
第三种:使用ModelDriven接口,对请求数据进行封装(模型驱动)
1:不能为多个对象封装数据.

一般的,我们在开发中使用第二种较多.
但是,修改密码的操作:
在User对象中,只有密码这个属性.
有时候,我们是方式1+方式2或者方式1+方式3.

3.Interceptor(拦截器)的美


拦截器:Interceptor

拦截器:
Struts2拦截器是在访问某个Action的某个方法之前或之后实施拦截,并且Struts2拦截器是可插拔的,拦截器是AOP的一种实现.

AOP:
面向切面编程.其实现原理:动态代理模式--->留给Spring

WebWork中文文档解释:
拦截器是动态拦截Action调用的对象。它提供了一种机制可以使开发者可以定义在一个Action执行的前后执行的代码,也可以在一个action执行前阻止其执行。同时也提供了一种可以提取Action中可重用的代码的方式。

拦截器栈(Interceptor Stack):
Struts2拦截器栈就是将拦截器按一定的顺序连接成一条链。在访问被拦截的方法或字段时,Struts2拦截器链中的拦截器就会按其之前定义的顺序被调用。

拦截器的"美":

DRY原则:Dont't Repeat Yourself.

拦截器在设计和程序结构上的优点:
拦截器能把很多功能从Action中独立出来,分散到不同的拦截器里面,减少了Action的代码。如此,拦截器和Action本身的功能都更单一了。当通用的功能代码被封装在拦截器里面(代码模块化),就可以对不同的Action,根据功能需要,来配置相应功能的拦截器了。提高了拦截器所实现的功能的重用性,也变相实现了装配式和可插拔式的体系结构,使得整个系统结构变得更灵活。
1.简化Action的实现
2.功能更单一
3.通用代码模块化
4.提高重用性

4.Struts2执行流程


1).Struts2的执行步骤:

在上述过程中所有的对象(Action、Interceptors、Results等)都由xwork容器中的ObjectFactory创建。

Paste_Image.png Paste_Image.png

2).Struts2中内置的拦截器:

在struts-core-2.3.x.jar--->struts-default.xml中

常见的拦截器:

Paste_Image.png

5.自定义拦截器


1).需求:

做一个登陆拦截器(LoginCheckInterceptor),拦截Action访问.
如果强行访问某一个需要登陆之后才能访问的Action,直接跳转到登录页面.

Paste_Image.png

2).操作步骤:

步骤1.定义拦截器类

方式1:实现com.opensymphony.xwork2.interceptor.Interceptor接口.

方式2:继承com.opensymphony.xwork2.interceptor.AbstractInterceptor类.

Paste_Image.png

步骤2.在struts.xml中注册拦截器

第一步:先在<package>中声明拦截器LoginInterceptor.

第二步:在<action>中来引用LoginInterceptor拦截器.

Paste_Image.png

上图的拦截器引用配置:
因为是在<action name="main">中引用了登录拦截器,所以只有当前Action才会做登录拦截功能.其他Action元素,没有这个功能.
如果其他多个action元素都做登录检查功能,那么所有action元素都得配置:
<interceptor-ref name="loginCheck" />
如此一来,重复配置.

3).可以通过全局配置拦截器:

Paste_Image.png

如果不拦截某一个Action:
1.方式一:代码中放行:

Paste_Image.png

2.方式二:默认拦截器

Paste_Image.png

6.OGNL和ValueStack(值栈)


1).什么是OGNL

OGNL是Object Graphic Navigation Language(对象图导航语言)的缩写,它是一个开源项目。

Struts2框架使用OGNL作为默认的表达式语言。

EL(表达式语言),OGNL就是EL的升级版.

作用:Action和视图(JSP)之间数据交互的桥梁.

讲解OGNL之前,先得学习ValueStack.

2).什么是ValueStack

值栈是对应每一个请求对象的轻量级的内存数据中心。

每一次请求的时候,都会创建一个新的ValueStack对象,该ValueStack对象封装了这一次请求相关的数据信息.

每一次的请求: 一个新的Action对象,新的ActionContext对象,新的ValueStack对象.

3).如何获取ValueStack.

         ValueStack vs = request.getAttribute("struts.valueStack");
         ValueStack vs = ServletActionContext.getRequest().getAttribute("struts.valueStack");
         ValueStack vs = ServletActionContext.getRequest().getAttribute(ServletActionContext.STRUTS_VALUESTACK_KEY);
         ValueStack vs = ActionContext.getContext().getValueStack();

以上两种方式获取的是同一个ValueStack对象.

Paste_Image.png

4).ValueStack内部结构

ValueStack对象中有两个很重要的属性,这两个属性就是ValueStack的主要内部结构:

属性 类型 数据储存类型 引用 获取数据
root CompoundRoot extends ArrayList : 栈的数据结构(后进先出) 主要存储Action对象相关的数据信息. - 从root中获取数据: 直接使用属性名获取. ---><s:property value="属性名"/>
context Map 上下文 主要存储映射关系数据.(key-value). 存在用root对象的引用(只要拿到context对象就可以获取到root对象);context中还存在request、session、application、attr、parameters对象的引用。 从context中获取数据: #key ---><s:property value="#key"/>
Paste_Image.png Paste_Image.png Paste_Image.png

5).把数据放入ValueStack.

1.把数据放入root中:(栈,ArrayList.每次都要压在栈顶)

此时:Action在栈顶,往Action中存储属性和属性值.

2).把数据放入context中:

一般的:把集合中的数据放入context中.

6).如何从JSP中取出ValueStack中的数据:

<%@ taglib uri="/struts-tags" prefix="s"%>
Paste_Image.png

EL可以访问ValueStack中的数据:
不建议这么做,为什么可以呢:
Struts2重新包装而来请求对象.${msg}---><%=pageContext.findAttribute("msg") %>
StrutsRequestWrapper:先从ValueStack中取出数据,再放入request中.

上一篇 下一篇

猜你喜欢

热点阅读