各位老铁们好,相信很多人对深入剖析Struts2框架核心原理(第二部分)都不是特别的了解,因此呢,今天就来为大家分享下关于深入剖析Struts2框架核心原理(第二部分)以及的问题知识,还望可以帮助大家,解决大家的一些困惑,下面一起来看看吧!
提供获取/设置方法
以后页面传递这三个参数时,struts2框架会自动帮我们把这三个参数值放到action中的三个属性中。 (同时也做了类型转换)
注意:这个工作实际上是由defaultStack拦截器栈中的拦截器完成的。
传值完成后,我们只需要在execute方法中直接使用即可,不需要做任何其他事情。
第二种情况:(域模型)
当从页面接收值时,我们也可以让struts2框架直接帮我们将这些接收到的值封装成javabean对象。
在操作中定义一个User 类型变量user。 User类中有三个属性值,id name Age,User类中还有get/set方法。
为该用户属性提供获取/设置方法
当页面向action传递值时,参数名称应写为user.id=1 user.name=tom user.age=20
以后收到这个参数值后,struts2框架会帮我们创建一个User对象,将传入参数的三个值封装到该对象的三个属性中,最后将这个封装的对象放入到user属性中动作中间的
第三种情况:(模型驱动)
类TestAction 实现ModelDriven{
@覆盖
公共用户getModel() {
如果(用户==空){
用户=新用户();
}
返回用户;
}
}
action中跳转的方式
.
name属性指的是跳转的名称(默认值为success),即action返回的字符串。 type属性指的是跳转的类型(默认值为dispatcher)。常用的跳转类型有四种: 010 -59000 Dispatcher(action-jsp)
从操作跳转到服务器内的页面。这是type 属性的默认值。
链(动作-动作)
在服务器内从一个操作跳转到另一个操作。
方法测试1
或:
方法名称操作名称命名空间内部跳转重定向(action-jsp)
客户端从操作重定向到页面。
/成功.jsp
重定向动作(动作-动作)
将客户端从一个操作重定向到另一操作
同一个包下的action跳转到:
/test下的action跳转到/test下的actionmethodTest1或者methodTest1/test跳转的两个不同包下的action。
/test 下的动作跳转到/user外部跳转/success.jsp/error.jsp Functions : 下的动作mytest/user 。以后的任何其他动作中,如果需要返回成功字符串,则跳转到success.jsp 或return 错误字符串跳转到error.jsp 时,不需要单独定义,因为这两个跳转已经定义为全局跳转,会影响当前包中的所有动作。同时,你也可以在某个动作中重新定义这两个跳转,则全局跳转不会对该动作产生影响。
配置全局的跳转.Function : 如果在地址栏中访问当前包下不存在的动作,一般情况下会直接报错。错误信息显示找不到该action,但是一旦我们配置了这个默认action,那么访问不存在的action就不会报错,而是直接访问默认action。这个默认动作需要在当前包中定义并在标签中引用。
注意: 访问某个包下的操作时出现多个错误。
未找到操作。找到了Action,但是没有找到该Action对应的类。找到了Action,也找到了对应的类,但是没有找到类中要执行的方法。找到了动作,找到了对应的类,找到了类中要执行的方法,但是标签中没有定义该方法返回的字符串。找到了action,就找到了对应的类,找到了类中要执行的方法。方法返回的字符串也在标签中定义,但是没有找到要跳转的页面。
从action向页面传值
仍然可以像以前在servlet 中一样在操作中使用,
使用request、session、application来传输到页面。此外,
动作:ValueStack ActionContext中有两种独特的传值方法
ValueStack 是一个接口:com.opensymphony.xwork2.util.ValueStack
ActionContext 是一个类:com.opensymphony.xwork2.ActionContext
我们可以使用这两种类型的对象将值从操作带到页面。
ActionContext 上下文=ActionContext.getContext();
ValueStack vs=context.getValueStack();在页面中我们可以看到action通过一个struts2标签传递给页面的值(这里使用标签库时需要导入两个jar包):
页面引入标签库:%@taglib uri="/struts-tags" prefix="s" %
当当前action跳转时,struts2框架会自动将action对象本身放入两个对象:ValueStack和ActionContext。
然后struts2框架将这两个对象传递到页面中,那么我们只要在页面中传递这两个对象,就可以得到之前放入的值。 (在页面的debug标签中可以看到struts框架已经在这两个对象中放置了action)
除了struts框架自动将值放置在ValueStack和ActionContext中之外,
我们也可以手动给这两个对象赋值。
(在execute方法中拿到这两个对象后,就可以往里面放入值了)
如何获取ValueStack和ActionContext对象
获取ActionContext 对象:
ActionContext ac=ActionContext.getContext();
获取ValueStack对象:
`ValueStack vs=ac.getValueStack();` 自己主动将值放入ac和vs中
将值: 放入ActionContext 对象中
ac.put(字符串,对象);
ac.put("你好","世界");
将值: 放入ValueStack 对象中
用户用户=新用户();
与推送(用户);
ValueStack的特点(值栈)
将一个对象放入vs后,我们无法从vs中获取该对象,但可以直接获取该对象中的属性和属性值。
从vs中获取值时,是从vs中的属性名列中获取,然后获取的是属性值列的值。 (您可以在调试中的vs 视图中看到这些列)
所以如果我们通过vs向页面传递一个值,我们就不能直接把这个值放入vs中,因为我们获取不到。我们应该把值放入一个对象的属性中,然后将对象放入vs中,这时候,就可以通过vs获取这个对象的属性,这就是我们要传递的值。
浏览器每次发送新的请求,都会生成一个新的ValueStack对象。最后一个ValueStack 对象已经消失并且无法找到。 (类似于之前学过的request对象的特性)
每次创建一个新的ValueStack 对象时,该对象都会被放置在ActionContext 中。
ActionContext的特点
当向ac中放入一个值时,以key-value的形式存储。键是String类型,值是Object类型。 value也是通过key获取的。
struts框架默认在这个对象中存储了很多对象(数据),包括request、session、application、ValueStack、parameters等。
每个请求都会创建一个新的ActionContext对象(可以通过打印每个请求的ac的地址值来看到这一点)
注意:使用vs和ac传值时,必须使用服务器内部跳转方式。
配置package中默认的action:
ValueStack 对象和ActionContext 对象。当action执行并跳转时,struts2框架会将当前执行的action对象分别放入ValueStack对象和ActionContext对象中。可以通过页面上的debug标签放入这两个对象中。动作对象。所以最终我们可以通过页面上的ValueStack对象或者ActionContext对象来获取action中的属性值(get/set方法)
在action中访问web元素(request session application)
在struts2框架中,这三个对象各有两种类型: 原始类型Map类型(这个对象全部在ActionContext中)
原始类型:(指的是servlet中之前使用的对象类型)
HttpServletRequest 请求
HttpSession 会话
ServletContext applicationMap 类型:
地图请求
地图会话
在使用Mapapplication时,我们可以选择使用原始类型的请求,也可以选择使用Map类型的请求。 (session和application也是如此)
无论是original类型的对象还是Map类型的对象,struts2框架都默认存储在ActionContext对象中。 (可以使用debug标签查看)
原始类型和Map类型之间的关系。
Mapsession1=ActionContext.getContext().getSession();
HttpSession session2=ServletActionContext.getRequest().getSession();
使用Map类型对象可以减少代码中对servlet API的依赖(解耦)。大多数时候我们使用原始类型来存储和检索值。
并且原始类型本身也封装了Map对象。
因此,我们也可以使用Map类型对象来存储和检索值。 Map类型请求对象中的值(k-v)实际上是从原始类型复制的。
请求对象中的值(k-v)。当然,除了请求对象原始类型中的k-v类型的键值对之外,
还有其他属性和方法,因为它毕竟是HttpServletRequest类型的对象。因此,request的原始类型和request对象的Map类型,我们可以理解为它们里面的值(k-v)是相同的,都表示:对象里有什么值,那里面就有什么值目的
它将有什么价值?所以我们在action中的Map类型对象中存储一个值(k-v)。以后我们也可以在页面中使用原始类型的request对象来获取这个值(k-v)。
请注意, 会话和应用程序也是如此。 **原始类型和Map类型相当于下面的例子:** 张三手里有一个钱包。我们一般都是把钱给张三,张三把钱放在钱包里,我们拿到钱的时候,也是经过张三。张三从钱包里拿出钱,然后把钱给了我们。现在我们不想这样做,觉得很麻烦,就从张三手里抢过来了。钱包,我们存钱、取款的时候直接操作这个钱包。请求的原始类型就相当于这里的张三,Map类型的对象就相当于这个钱包。
如果您在操作中获取Map 类型和原始类型的对象
客户端发送一个请求到action,struts2框架会创建俩个对象第一种方式是在方法中自己获取:
ActionContext ac=ActionContext.getContext();
//获取Map类型请求
Maprequest=(地图) ac.get("请求");
//获取Map类型会话
Mapsession=ac.getSession();
//获取Map类型应用
地图应用程序=ac.getApplication();
第二种方法:允许struts2框架自动将Map类型对象放入action中(依赖注入)
第一种方式是主动获取对象,第二种方式是被动接受对象。
实现三个接口可以让struts2框架通过调用所实现的接口中的方法来将Map类型的request、session和application对象传递给我们的action。在action中,我们只需要接收这三个对象即可。然后,之后就可以直接使用了。三个接口依次为:
请求感知、会话感知、应用感知
例如:
公共类WebActionTest 扩展ActionSupport 实现RequestAware、SessionAware、ApplicationAware{
私人地图请求;
私人地图会话;
私人地图应用程序;
@覆盖
公共字符串execute()抛出异常{
//只需使用页面中的原始类型对象即可获取正常值。
request.put("我的名字", "汤姆");
session.put("你的名字", "zhansan");
application.put("她的名字", "莉莉");
返回成功;
}
公共无效setRequest(地图请求){
this.request=请求;
}
公共无效setSession(地图会话){
this.session=会话;
}
公共无效setApplication(地图应用程序){
this.application=应用程序;
}
}获取Map类型对象第一种方式是主动拨打:
获取原始类型请求对象
HttpServletRequest req=ServletActionContext.getRequest();
获取原始类型响应对象
HttpServletResponse res=ServletActionContext.getResponse();
获取原始类型session对象
HttpSession sess=req.getSession();
获取原始类型应用程序对象
ServletContext app1=sess.getServletContext();
或者
ServletContext app2=ServletActionContext.getServletContext();* 第二种方式: 自己被动接收
struts2框架提供了一个接口,可以用来获取请求对象的原始类型。
因为session对象的原始类型和request对象的原始类型都可以得到。
类型的应用程序对象
实现接口:ServletRequestAware,然后struts2框架会自动通过action实现的抽象方法将原始类型的request对象放入到action中。
还有一个类似的接口:ServletResponseAware,其作用和用法与上面相同。
页面中获得action传过来的值
struts2框架提供的页面取值方法中,需要用到两个东西:struts2框架标签和OGNL表达式
注: 同时我们还可以使用jsp内置对象获取值,使用jstl标签+EL表达式获取值。
struts2中可以使用的取值方式:
jsp内置对象值jstl标签+EL表达式值struts2标签+OGNL表达式注意:OGNL表达式只能写在struts2的tag属性中,这里我们首先使用struts2的这样一个标签:这个标签的用途就是向页面输出值。
例如
从ValueStack和ActionContext中取值
获取原类型对象//注意这个value属性中的值名称实际上是一个ongl表达式。
//这意味着从valueStack中取出一个名为name的属性值
注意,从ValueStack获取值时,如果Valuestack中有两个同名的值,我们只能获取最上面的值(从debug标签看vs中最上面的值)(其实,获取值的方式经过特殊处理仍然可以一次性获取以下属性值)
从ValueStack中取值.。
使用ognl表达式通过AC中的key获取相对值。取值时需要添加符号:#
从ActionContext中取值参数对应的值存储的是客户端传递过来的参数。
//接收客户端发送过来的名为name的参数值
`
`
//获取请求中的值
`
`
//获取session中的值
`
`
//获取应用程序中的值
`
`
//默认情况下,值按顺序从请求、会话、应用程序中获取。如果获取到则直接输出。如果没有获得,就算了。
`
`
还可以使用以前的方式从request、session、application中取值.
注意:如果我们使用request通过key获取value,我们会先在request中查找。如果在请求中没有找到,我们将在ValueStack中查找。因为ValueStack默认也是放在request里面的。但是session和application不具备request这样的功能。
ActionContext中的parameters、attr、request、session、application等key值.(这些都是AC中的key)%=request.getAttribute("名称") %
%=session.getAttribute("名称") %
%=application.getAttribute("名称") %
使用jsp脚本代码取值${requestScope.MyName}
${requestScope.name}
${sessionScope.MyName}
${applicationScope.MyName}
${我的名字}
${名称}
strut2框架中的拦截器(interceptor)
使用EL表达式取值:拦截器是strut2框架中提供的java类。
效果:
您可以拦截访问操作的请求,并向该操作添加新的丰富功能(上传、自动参数接收、自动类型转换等)。配置完之后,需要指定哪个拦截器拦截哪个动作或者哪些动作,这样这个拦截器才会拦截我们的动作。每个拦截器都可以向我们的操作添加一个新函数。拦截器如何工作?
有一个拦截器类(struts2框架自带的类或者我们自己定义的类)
在配置文件中配置这个拦截器类。
指示该拦截器应拦截哪些操作。
客户端发送请求访问被拦截器拦截的action
这个请求首先会被struts2过滤器拦截。过滤器首先会检查该请求是否是所请求的动作。如果是一个动作,它会检查该动作是否已被定义的拦截器拦截。如果是,则将这个请求交给拦截器处理。
如何自定义拦截器
struts2框架已经编写了很多拦截器(在struts2的核心jar包中),并且也在配置文件中(在struts-default.xml中)配置了这些拦截器。
除此之外,我们还可以编写自己的拦截器。
要编写拦截器,首先要实现一个接口:com.opensymphony.xwork2.interceptor.Interceptor
例如:
公共类MyInterceptor 实现拦截器{
公共无效销毁(){
System.out.println("在MyInterceptor的destroy()中");
}
公共无效初始化(){
System.out.println("在MyInterceptor的init()中");
}
//拦截访问action时调用该方法
公共字符串拦截(ActionInspiration ai)抛出异常{
System.out.println("之前.");
//ai.invoke()实际上帮助我们调用action中要执行的方法,比如execute方法
//ai.invoke()的返回值实际上是action中的方法执行后返回的字符串。
String s=ai.invoke();
System.out.println("之后.");
返回s;
}
}
然后在struts.xml文件中配置这个拦截器类: //既然我们提供了拦截器,那么系统不会自动提供拦截器。如果我们需要获取
Action中获取HttpServletRequest等对象时,需要加载系统拦截器代码如下: 最后指出该拦截器在哪个action中工作:/inde
x.jsp拦截器栈当前一个action需要被多个拦截器拦截的时候,正常情况下,我们需要在这个action中去引用要使用到的多个拦截器,但是我们可以使用一个拦截器栈去包含那几个拦截器,然后在action中直接引用这个拦截器栈就可以了. 一个拦截器栈可以包含多个拦截器 一个拦截器栈还可以包含其他拦截器栈 定义拦截器或者拦截器栈都要在标签中 例如:默认拦截器/拦截器栈在一个package中,我们可以把一个拦截器或者拦截器栈声明为一个默认的拦截器/拦截器栈 作用:将来这个package中所有的action都会被这个默认的拦截器/拦截器栈所拦截。 例如: myStack是一个拦截器或者拦截器栈 `` *注意:* 一般情况下,我们所写的任何action都会被一个叫做defaultStack的拦截器栈所拦截,这个拦截器栈中包含了十几个拦截器,这些拦截器给我们的action提供了很多丰富的功能.因为我们写所有的package都是直接或间接的继承了struts-default.xml文件中的一个名字叫struts-default的package,struts-default包中又把名字叫defaultStack的拦截器栈配置成了一个默认的拦截器栈,那么我们的package就把这个配置继承了过来,所有我们的action正常情况下都会被defaultStack所拦截 但是如果我们一旦指明了某一个action被我们所写的一个拦截器/拦截器栈所拦截,那么这个action就不会被defaultStack拦截了.所以我们可以在action中主动的再声明 这个action被defaultStack所拦截,或者把defaultStack加入到我们自定义的拦截器栈里面(拦截器栈可以包含拦截器栈)6.package之间的继承我们可以专门再定义一个package,在这个package里面我们只做拦截器/拦截器栈的定义: 然后我们可以让其他的package去继承我们这个MyInter包,这样一来,其他包中的action都会被我们这个MyInter包中的默认拦截器栈myStack所拦截了。 注意:一定要保证action至少是被defaultStack这个拦截器栈所拦截的.注意:在struts.xml中只定义出来一个拦截器,这个拦截器是不会被初始化和销毁的,在action中引用过以后才能让struts2框架帮我们去初始化这个拦截器,但是还是不能销毁,如果还想销毁的话,那么就要在一个拦截器栈中去引用一下这个拦截器才可以.拦截器(interceptor)和过滤器(filter)的比较相同点: 都是一种java类都能拦截客户端发给服务器端的请求拦截到请求之后都可以做一些相应的处理,最后还可以把这个请求放行.都需要实现各自相应的接口以及在相应的配置文件中配置.不同点: 拦截器(interceptor)是struts2框架中的定义的,过滤器(filter)是web里面的对象,是J2EE标准里面定义的. 拦截器(interceptor)只会拦截器访问action的请求,过滤器(filter)能够拦截所有请求. 拦截器(interceptor)定义在struts.xml文件中,过滤器(filter)定义在web.xml文件中. 拦截器(interceptor)对象的创建、调用、销毁是struts2框架负责的,过滤器(filter)对象的创建、调用、销毁服务器负责的.我们自己定义的filter能不能拦截Struts2框架中的action可以拦截 需要在web.xml文件中把我们自己的filter配置在struts2的filter的上面才可以. 因为web.xml文件中filter配置的先后顺序控制filter起作用的顺序,同时如果struts的filter先拦截到访问action的请求后,不会把这个请求交给下面的filter,而是交给了他它内部的拦截器(interceptor)了,但是如果我们自己filter拦截到请求之后,还是依然会交给下一个filter,也就是交给struts2的filter.Struts2 注解方式(Annotation)
引入 支持Struts2框架注解开发的jar包 struts2-convention-plugin-2.3.4.1struts.xml Struts2使用注解开发需要遵循一些规范:Action要必须继承ActionSupport父类; Action所在的包名必须以 Action 结尾。 package-info.java (在这里配置这个包下所有的类都可以用) @Namespace("/") @ParentPackage("struts-default") @DefaultInterceptorRef("authStack")//authStack自定义的拦截器 package com.briup.action.manager; import org.apache.struts2.convention.annotation.Namespace; import org.apache.struts2.convention.annotation.ParentPackage;action中常用的注解:
Namespace Annotation通过在ActionClass上定义 @Namespace("/custom")通过 package-info.java 定义@Namespace("/manager") @ParentPackage("default") @DefaultInterceptorRef("authStack") package com.example.actions;Action Annotation1. @Action(interceptorRefs={ @InterceptorRef("validation"), @InterceptorRef("defaultStack") }) 2. chain @Action("foo") public String foo() { return "bar"; } @Action("foo-bar") public String bar() { return SUCCESS; }例子: //配置了如下action之后就不需要在struts2.xml文件中不需要配置了。 //访问 http://localhost:8888/EStore_sh/toIndex.action; @Action(value = "toIndex", results = { @Result(name = SUCCESS,location = "/WEB-INF/jsp/index.jsp") }) public String toIndex() { System.out.println("Toindex"); return SUCCESS; }Result Annotation全局,整个类可以访问局部,某个方法可以访问@Results({ @Result(name="failure", location="fail.jsp") }) public class HelloWorld extends ActionSupport { @Action(value="/different/url",results={@Result(name="success", location="http://struts.apache.org", type="redirect")} ) public String execute() { return SUCCESS; } }可以传递参数: results={ @Result(name="success", type="httpheader",【深入剖析Struts2框架核心原理(第二部分)】相关文章:
2.米颠拜石
3.王羲之临池学书
8.郑板桥轶事十则
用户评论
终于到了 Struts2 的第二篇文章了,看这标题感觉要继续深入讲解
有8位网友表示赞同!
之前第一篇没看完,现在看到第二篇准备好好补补习
有10位网友表示赞同!
Struts2 框架我学了一段时间,希望能从总结中吸取更多精华
有13位网友表示赞同!
学习 Javaee 的小伙伴们,这篇文章肯定能帮到你们的
有18位网友表示赞同!
Struts2 的具体应用我还不太了解,期待看到这篇总结的实战案例
有16位网友表示赞同!
框架总是需要不断总结和实践才能真正掌握
有20位网友表示赞同!
不知道作者会从哪些方面进行总结呢?期待惊喜!
有12位网友表示赞同!
这篇文章能把 Struts2 的核心概念解释清楚吗?
有13位网友表示赞同!
希望能看到一些最新的发展趋势,比如与spring的结合
有17位网友表示赞同!
最近在用 Struts2 开发项目,这篇总结正好派上用场
有18位网友表示赞同!
学习框架最重要的是理解其设计理念,希望这篇文章能解释清楚
有18位网友表示赞同!
分享一下自己对Struts2 的心得体会吗?
有10位网友表示赞同!
期待看到一些代码示例,更直观地学习
有15位网友表示赞同!
感觉 Struts2 框架的应用场景还是挺广泛的
有7位网友表示赞同!
总结的文章能帮助我更好地复习和巩固知识
有13位网友表示赞同!
希望文章能涵盖一些常用的组件和功能
有17位网友表示赞同!
看标题就知道要进入更深入的内容了,继续学习!
有20位网友表示赞同!
分享一下您使用 Struts2 的成功经验吗?
有12位网友表示赞同!
期待作者的分享,不断提升自己
有6位网友表示赞同!
Struts2 框架的优点和缺点有哪些?
有8位网友表示赞同!