概述
1. JavaEE中有三层结构,struts2框架应⽤在JavaEE三层结构中的Web层的框架。2. struts2框架是在struts1和webwork基础之上发展的⼀个全新的框架。(完全脱胎换⾻)
3. struts2可以解决问题:
需要的jar包
依赖
创建action
我们之前的Servlet,Servlet本⾝就是⼀个类,⽽action本⾝也是⼀个类,所以我们现在就可以创建⼀个action。
配置Action路径的访问路径
struts.xml
\"-//Apache Software Foundation//DTD Struts Configuration 2.3//EN\" \"http://struts.apache.org/dtds/struts-2.3.dtd\">
web.xml
Struts2执⾏的基本过程
当我们从地址栏输⼊⼀个地址,点击回车,他相当于发送了⼀个请求给服务器,发送请求之后,它⾸先会到过滤器中,当我们从地址栏输⼊⼀个地址,点击回车,他相当于发送了⼀个请求给服务器,发送请求之后,它⾸先会到过滤器中,其实我们的这个过程都是由这个过滤器都是由这个过滤器帮我们决定的。过滤器会在启动服务器的时候,被创建过滤器⼀旦创建会做很多的事情帮我们决定的。过滤器会在启动服务器的时候,被创建过滤器⼀旦创建会做很多的事情:如下图五个步骤:如下图五个步骤
Struts2源代码的查看
这⾥本⾝是个过滤器,StrutsPrepareAndExecuteFilter这个过滤器的名称,防⽌⾯试的时候问起。
-① 过滤器会在服务器启动的时候被创建,他会执⾏⾥⾯的init()⽅法
-② 在init⽅法⾥⾯会加载很多的配置⽂件
- 有些是struts2⾃带的,也会加载我们⾃⼰写的struts.xml。我们可以通过源代码来查看⼀下:第⼀步是进⼊过滤器init⽅法,然后找到init.initDispatcher(config); 按住Ctrl键点击进去,然后找到⼀、在init⽅法中,调⽤了init的initDispatcher的⽅法来加载配置⽂件,进⼊该代码中……
⼆、我们发现这个⽅法有调⽤了dispatcher的init⽅法,进⼊init⽅法内部……
三、下⾯这些[1]、[2]、[3]、[5]、[6]、[7]就是⽤来加载Struts2配置⽂件的。
init_DefaultProperties(); // [1]
- 加载org.apache.struts2.default.properties配置的是struts2的所有的常量init_TraditionalXmlConfigurations(); // [2]- 加载struts-default.xml、struts-plugin.xmlinit_LegacyStrutsProperties(); // [3]-加载⽤户⾃定义的struts.propertiesinit_CustomConfigurationProviders(); // [5]-加载⽤户配置的提供对象init_FilterInitParameters() ; // [6]-加载web.xml
init_AliasStandardObjects() ; // [7]
-加载标准对象
四、
五、
加载顺序:
* default.properties* struts-default.xml* struts-plugin.xml
* struts.xml ------配置action以及常量* struts.properties ------配置常量
* web.xml ------配置核⼼过滤器及常量
前三个配置⽂件我们不⽤关⼼,是struts2的内部配置⽂件,我们⽆法修改,能修改的⽂件就是struts.xml、struts.properties、web.xml配置⽂件,这⼏个配置⽂件的加载是有⼀定的顺序的,这三个配置⽂件都可以修改struts2的常量的值,要记住的是,加载配置⽂件中的常量的值会将先加载的配置⽂件中的常量的给覆盖。
Struts2核⼼配置⽂件
⼀、 这个核⼼配置⽂件的名称和位置是固定的。
⼆、 在配置⽂件中有三个标签 package、action、result标签⾥⾯的属性
package标签
1. package类似与代码中的包的概念,区别不同的action,要配置action,必须先写package标签,在package⾥⾯才能写action
2. package标签⾥⾯的属性
- ① name:该属性值跟程序功能本⾝没有什么关系, 在⼀个配置⽂件中, 可以写多个package但是name属性值不能相同。
-② extends:该属性表⽰继承,这个属性的值是固定的,写了这个属性之后,package⾥⾯配置的类,就具有了action的功能,就表⽰让我们的类具有action的功能
- ③ namespace:名称空间,namespace属性值和我们action标签⾥⾯的name属性值构成访问路径。namespace有⼀个默认值,默认值就是‘/’,如下图:
action标签
1. 作⽤:配置action的访问的路径2. Action标签⾥⾯的属性
- ① name属性:namespace属性值和我们action标签⾥⾯的name属性值构成访问路径,注意:在package标签⾥⾯,可以写多个action,但是他的name属性
的值不能相同。
- ② class属性:
- Action类的全路径,他的底层是需要通过反射来解析类的,所以要提供全路径- ③ method属性:
- ⽐如在Action类⾥⾯,默认执⾏的是execute⽅法,但是我在action⾥⾯,可以写其他的⼀些⽅法.- 让action⾥⾯的多个⽅法进⾏执⾏,可以使⽤method属性来进⾏配置
result标签
1. 作⽤:根据Action⽅法的返回值,配置到不同路径中去,跳转不⼀定是页⾯,也可以跳转到另外的action中去。2. result标签⾥⾯的属性
- ① name属性:name属性的值要与action⽅法的返回值对应,路径/表⽰根路径,hello.jsp表⽰action⽅法返回的是字符串OK要跳转到的页⾯名称。
- ② type属性:⽤来配置如何到⼀个路径中去,可以转发,也可以重定向,该属性的默认值是是转发。
Struts2常量的配置
在Struts2中的这些常量,⼤多数在默认配置⽂件中已经配置好了,但根据⽤户需求的不同,开发的要求也不同,可能需要修改这些常量的值,修改⽅法就是在配置⽂件对常量进⾏重新配置。
在Struts2中常量配置共有三种⽅式,分别如下:- ① 在struts.xml中使⽤ - ③ 在web.xml中,通过 - 为了让⼤家更好地掌握着三种Struts2常见配置⽅式,接下来,分别对他们进⾏讲解,具体如下:- ① 在struts.xml⽂件中通过 - 在struts.xml⽂件中通过 性name和value。- name : 该属性指定了常量的常量名。- value : 该属性指定了常量的常量值。- 在struts.xml⽂件中配置⽰例代码如下: - 在上述⽰例代码中,配置了常量struts.i18n.encoding和struts.devMode,⽤于指定struts2应⽤程序的默认编码集为UTF-8,并使⽤开发模式。值得⼀提的是,struts.properties⽂件能配置的常量都可以在struts.xml中使⽤ - ② 在struts.properties⽂件中配置常量 struts.properties ⽂件是⼀个标准的properties⽂件, 其格式是key-value对, 即每个key对应⼀个value,key表⽰的是struts2框架中的常量,⽽value则是其常量值。 在struts.properties⽂件中配置常量的⽅式具体如下: - 在上述代码⽚段中,“=”号左边的是key,右边的是每个key对应的value,另外,代码⽚段中的### 表⽰properties⽂件中的注释信息,⽤于解释说明。 - ③ 在web.xml⽂件中通过初始化参数配置常量 - 在web.xml⽂件中,配置核⼼过滤器StrutsPrepareAndExecuteFilter时,通过初始化参数来配置常量。通过 个 在上述web.xml⽂件的代码⽚段中,当配置StrutsPrepareAndExecuteFilter时,还是通过 Struts2所⽀持的常量众多,在struts2-core-2.3.24.jar压缩⽂件的org.apache.struts2路径下有⼀个default.properties⽂件,该⽂件⾥⾯为struts2的所有的常量都指定了默认的值,读者可以通过查看该⽂件来了解struts2所⽀持的常量。 之前我们就已经介绍过了struts2的配置⽂件的加载顺序,后加载的配置⽂件的常量的值会覆盖先加载的配置⽂件中的常量的值。所以⼤家这个要注意。1. struts2框架中,帮我们实现⼀部分功能,struts2⾥⾯有常量,在常量⾥⾯封装了⼀部分功能2. struts2默认的常量的位置(记住) 1. 修改struts2默认常量值 - ① 常⽤⽅式:在struts.xml中进⾏配置 - ② 还有两种⽅式(了解) - ⼀、在src下创建⼀个struts.properties,进⾏修改- ⼆、在web.xml中进⾏配置 - 这两种⼤家了解即可,不需要掌握,掌握第⼀种⽅式就可以了。1. 最常⽤的常量 - (1)表单提交数据到action中去,在action中可以获取到表单提交数据, - (2)表单提交数据有中⽂,有乱码问题,之前解决: - post提交,直接设置request.setChara….Encoding(“UTF-8”)- get提交,需要做编码的转换 (3)如果在action获取表单数据是通过post⽅式提交的中⽂,中⽂乱码问题struts会帮我们解决乱码问题,不需要我们⾃⼰处理这个问题,这是常量帮我们封装的功能 分模块开发的配置 在实际开发过程中,我们都是协同开发,我们通常很多⼈需要修改通过⼀个配置⽂件就是struts.xml。因为这个⽂件是Struts2的核⼼配置⽂件,⽽且这个⽂件⼀旦改错了⼀点,那么会导致整个项⽬都出现问题,所以Struts2提供了 在上述代码⽚段中,struts.xml⽂件包含了四个配置⽂件,这个4个配置⽂件都包含在 Action的编写⽅式 在Struts2中,Action编写⽅式⼀共有三种⽅式。 第⼀种:创建普通类,这个类不继承任何类,不实现任何的接⼝;- ① 刚才我们创建的就是这个第⼀种的⽅式- ② 第⼆种:创建⼀个类,这个类实现接⼝Action; 第三种:创建类,让它继承⾃ActionSupport(主要⽤这种⽅式,⼀般都使⽤这种⽅式); 观察源码 - 我们发现他也实现了Action接⼝ Action的访问(重点) Action 的访问不是难题,因为之前已经访问过,但是出现⼀个问题⼀次请求现在对应⼀个Action类,那么如果请求很多,对应的很多的Action,现在要处理的问题就是要让⼀个模块的操作提交到⼀个Action中。 其实我们学过在 - ① method:使⽤action标签的method属性,在这个属性⾥⾯写要执⾏的action的⽅法 【解决Action的访问问题的⽅式⼀:通过配置method属性完成】编写页⾯: - 编写Action import com.opensymphony.xwork2.ActionSupport;public class UserAction extends ActionSupport { public String save(){ System.out.println(\"UserAction中save⽅法被执⾏了....\"); return NONE; } public String update(){ System.out.println(\"UserAction中update⽅法被执⾏....\"); return NONE; } public String delete(){ System.out.println(\"UserAction中delete⽅法被执⾏...\"); return NONE; } public String find(){ System.out.println(\"UserAction中find⽅法被执⾏......\"); return NONE; }} - 配置Action - 但是这种⽅式我们会发现,同⼀个Action类就被配置了很多次,只 是 修 改 了method属性的值,那么能不能简化呢?也就是说⼀个Action类,只配置⼀次就好 了,这个时候我们就需要使⽤通配符的配置⽅式了。 - ② 使⽤通配符的⽅式(使⽤的最多的) - 编写页⾯ 【解决Action的访问访问的问题的⽅式⼆:通过通配符完成】 - 编写Action import com.opensymphony.xwork2.ActionSupport;public class UserAction extends ActionSupport { public String save(){ System.out.println(\"UserAction中save⽅法被执⾏了....\"); return NONE; } public String update(){ System.out.println(\"UserAction中update⽅法被执⾏....\"); return NONE; } public String delete(){ System.out.println(\"UserAction中delete⽅法被执⾏...\"); return NONE; } public String find(){ System.out.println(\"UserAction中find⽅法被执⾏......\"); return NONE; } - 配置Action - 在Action的name属性中使⽤ * 号代替任意字符,method中的{1}代表name属性中出现的第⼀个 * 所代替的字符。- 这个时候我们发现只配置⼀个就可以了,在上述代码中,当客户端发送: - /users_save.action的时候,method的属性就被设置成了save。当客户端发送的请求是: /users_update.action的时候,method的属性就被设置成了update。 【解决Action的访问问题的⽅式三:动态⽅法访问】 动态⽅法访问在Struts2中默认是不开启的,如果想要使⽤需要先去开启⼀个常量。 动态⽅法访问,主要的控制是在页⾯端,所以编写Action和配置Action都很简单,关键是访问路径的编写。 - ③ 动态访问的⽅式(很少⽤或者不⽤) - 编写Action import com.opensymphony.xwork2.ActionSupport;public class UserAction extends ActionSupport { public String save(){ System.out.println(\"UserAction中save⽅法被执⾏了....\"); return NONE; }} - 配置Action 页⾯路径的写法 错误演⽰ - 1.如果说我们的Action的⽅法的返回值,再配置⽂件中没有进⾏配置,会出现如下错误:没有结果的定义 1. 在action⾥⾯的⽅法可以有返回值,但是如果有返回值的时候,类型必须是String类型 2. Action⾥⾯的⽅法也可以没有返回值,没有返回值的时候,就不需要配置result标签-可以把⽅法的返回值写成void -⼀般做法是:让⽅法的返回值是String,但最终返回的是:NONE. 这种情况也不需要配置result。 结果页⾯的配置 全局结果页⾯ 1. 2. result标签配置action⽅法的返回值,到不同的路径⾥⾯ 3. 业务:创建两个action,执⾏默认的⽅法:execute⽅法,让两个action⽅法都返回⼀个值:success,配置都到同⼀个页⾯⾥⾯去4. 具体实现步骤: 创建⼀个⼯程,⾥⾯有两个Action类 struts.xml配置⽂件如下: - 如果说我们有多个Action,他的Action⽅法⾥⾯返回值是相同的,他们到的页⾯也是相同的,这个时候,我们就可以使⽤全局结果页⾯ 局部结果页⾯ ① 如果你配置了全局的结果页⾯,有配置了局部结果页⾯,那么它局部结果页⾯的优先级要⾼于全局结果页⾯,也就是说,他会跳转到你在局部配置的结果页 ⾯⾥⾯去 result标签中的type属性 在result标签⾥⾯,除了name属性之外,还有⼀个属性叫:type- ① 表⽰我们如何到路径⾥⾯去的(转发还是重定向)- ② type的属性值: - 默认值:dispatcher 转发是⼀次请求,浏览器地址栏不发⽣改变。- 重定向:redirect 这是两次请求,浏览器地址栏发⽣改变。 - 默认:默认的是 type=”dispatcher” - 当我们改成重定向的时候 - 配置⽂件: - ③ 上⾯两个值dispatcher、redirect,这两个值⼀般针对到页⾯中配置,配置到其他Action的action⽅法⾥⾯: - (1) chain:转发到Action (⼀般不⽤)会有缓存问题,可能得不到最新数据- (2) redirectAction:重定向到Action Action获取表单提交的数据 1. 之前在Web阶段,提交表单都是到Servlet,在Servlet⾥⾯,使⽤request对象的⽅法获取。request.getParameter(“表单元素的名称”); getParameterMap2. 现在我们要把表单填写的数据提交到Action,但Action本⾝没有request,不能直接使⽤request。3. Action中获取表单提交的数据主要有如下三种⽅式:- ① 使⽤ActionContext类- ② 使⽤ServletActionContext类 - ③ 使⽤接⼝注⼊的⽅式实现(基本不⽤) 使⽤ActionContext类获取 Struts2框架提供了ActionContext类来访问ServletAPI,ActionContext是Action执⾏上下⽂对象,在ActionContext中保存了Action执⾏所需要的所有对象,包括parameters,request,session,application等下⾯列举ActionContext类访问Servlet API 的⼏个常⽤⽅法,具体如表所⽰: 1. Map 2. 这个ApplicationContext类对象不是new出来的,是通过下⾯这个静态⽅法获取 3. 具体演⽰: ① 创建表单提交表单到action⾥⾯ - ② 配合struts.xml⽂件 - ③ 在action⾥⾯使⽤ActionContext获取到数据 控制台输出 使⽤ServletActionContext来访问 (程序员⽐较喜欢⽤) 为了直接访问Servlet API,Struts2框架还提供了ServletActionContext类,该类包含了⼏个常⽤的静态⽅法具体如下: static HttpServletRequest getRequest():获取Web应⽤的HttpServletRequest对象static HttpServletResponse getResponse():获取Web应⽤的HttpServletResponse static ServletContext getServletContext():获取Web应⽤的ServletContextstatic PageContext getPageContext():获取Web应⽤的PageContext对象 接下来,讲解如何通过ServletActionContext来访问Servlet API1. 调⽤类⾥⾯的静态的⽅法,得到Request对象,login2.jsp如下 - struts.xml - LoginAction2 - 控制台结果: 通过特定接⼝访问⼀般不⽤ Struts2框架提供了ActionContext类来访问Servlet API,虽然这种⽅法可以访问Sservlet API,但是⽆法直接获取Servlet API 实例,为了在Action中直接访问ServletAPI,Strus2还提供了⼀系列的接⼝,具体如下: ServletRequestAware : 实现该接⼝的Action可以直接访问Web应⽤的HttpServletRequest实例ServletResponseAware : 实现该接⼝的Action可以直接访问Web应⽤的HttpServletResponse实例SessionAware:实现该接⼝的Action 可以直接访问Web应⽤的HttpSession实例 ServletContextAware:实现该接⼝的Action可以直接访问web应⽤的ServletContext实例。 login3.jsp struts.xml LoginAction3,实现接⼝ServletRequestAware,实现接⼝⾥⾯的⽅法setServletRequest。 在Action⾥操作域对象 1. Request域对象,session域对象,ServletContext域对象2. 使⽤ServletActionContext类操作 Struts2的数据的封装 原始的⽅式获取表单封装到实体对象 配置struts.xml LoginAction4.java 在Struts2中,可以直接在Action中定义各种Java基本数据类型的字段,使这些字段 与表单数据相对应,并利⽤这些字段进⾏数据传递。【属性驱动⽅式⼀:提供属性的set⽅法的⽅式】1. 直接把表单提交属性封装到action属性⾥⾯2. 实现步骤 - ① 在action成员变量位置定义变量 - ② ⽣成变量的set⽅法(为了⽅便记忆,我们把get和set都⽣成) // 使⽤ServletActionContext获取表单数据封装到实体类的对象⾥⾯去public class LoginAction5 extends ActionSupport { // 1、定义变量 // 变量的名称要与表单元素的name属性值保持⼀致 private String username; private String password; private String address; @Override public String execute() throws Exception { System.out.println(username + \" : \" + password + \" : \" + address); return NONE; } // ⽣成get and 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 getAddress() { return address; } public void setAddress(String address) { this.address = address; 模型驱动封装(重点,最常⽤的⽅式) 1. 使⽤模型驱动⽅式,可以直接把表单数据封装到实体类对象⾥⾯2. 实现步骤 - ① action类要实现⼀个接⼝ModelDriven - ② 实现接⼝⾥⾯的⽅法,getModel,把创建对象返回- ③ ⼿动创建实体类对象- 实体类: - 前提条件:表单输⼊项的name属性值要与实体类属性保持⼀致1. 使⽤模型驱动和属性封装需要注意的问题: - ① 在⼀个action中,获取表单数据,可以使⽤属性封装,也可以使⽤模型驱动封装,但是不能同时使⽤属性封装和模型驱动封装获取通过⼀个表单数据,如果同时使⽤,它只会执⾏模型驱动。 表达式封装 1. 实现过程 - 使⽤表达式封装(有些书本也叫属性封装) - 使⽤表达式封装可以把表单数据封装到实体类对象⾥⾯- ① 在action⾥⾯⽣命实体类- ② ⽣成实体类变量的set和get⽅法 - ③ 在表单输⼊项的name属性值⾥⾯写表达式形式具体过程如下: ⽐较表达式封装和模型驱动封装 1. 使⽤表达式封装和模型驱动封装,都可以把数据封装到实体类对象2. 不同点 - ① 使⽤模型驱动只能把数据封装到⼀个实体类对象⾥⾯,在⼀个Action⾥⾯不能把数据封装到不同的实体类对象⾥⾯- ② 使⽤表达式封装可以把数据封装到不同的实体类对象⾥⾯ Struts2中封装到集合类型的数据 在实际开发过程中,有些时候我们需要批量插⼊⽤户或者批量插⼊其他的对象,在Action中需要接受到多个Action中封装的对象,然后传递给业务层,那么这个时候需要将表单数据封装到集合中,⼀般我们通常使⽤的集合⽆⾮是List或者Map集合,下⾯就以这两种集合进⾏数据封装的实例演⽰: 封装数据到list⾥⾯ 编写页⾯ 编写Action public class LoginAction8 extends ActionSupport { private List public List public void setList(List @Override public String execute() throws Exception { for (User user : list) { System.out.println(user.getUsername()+\" : \" +user.getPassword()+\" : \" +user.getAddress()); } return NONE; }} 配置⽂件struts.xml 封装数据到Map⾥⾯ 1. 声明⼀个Map集合2. ⽣成get 和 set ⽅法 3. 在表单输⼊项的name属性值⾥⾯写表达式页⾯代码: 配置⽂件:struts.xml Action⾥⾯的代码:LoginAction9.java public class LoginAction9 extends ActionSupport { private Map public void setMap(Map @Override public String execute() throws Exception { for (Map.Entry return NONE; } OGNL概述 OGNL的全称是对象图导航语⾔(Object-Graph Navigation Language),他是⼀种功能强⼤的开源表达式语⾔,使⽤这种表达式语⾔,可以通过某种表达式语法,存取Java对象的任意属性,调⽤Java对象的⽅法,同时能够⾃动实现必要的类型转换。如果把表达式看做是⼀个带有语义的字符串,那么OGNL⽆疑成为了这个语义字符串与Java对象之间沟通的桥梁。 【OGNL的作⽤】 Struts2默认的表达式语⾔就是OGNL,它具有⼀下特点♥ ⽀持对象⽅法调⽤。例如:objName.methodName(). ♥ ⽀持类静态⽅法调⽤和值访问,表达式的格式为:@[类全名(包括包路径)]@[⽅法名 | 值名]。例如:@java.lang.String@format(‘foo%s’,’bar’);♥ ⽀持赋值操作和表达式串联 例如:price=100,discount=0.8,calculatePrice(),在⽅法中进⾏乘法计算会返回90. ♥ 访问OGNL上下⽂(OGNL context)和 ActionContext♥ 操作集合对象 1. 之前在Web阶段学过EL表达式,EL表达式,是在JSP中获取域对象⾥⾯的值2. OGNL也是⼀种表达式,功能更加强⼤,很多功能是EL表达式做不到的- ① struts2⾥⾯操作值栈数据 - ② ⼀般把ognl在struts2操作:和struts2标签⼀起使⽤操作值栈 3. OGNL不是struts2的⼀部分,他是⼀个单独的项⽬,经常和Struts2⼀起使⽤。- ① 使⽤OGNL时候⾸先导⼊jar包,Struts2提供jar包 OGNL⼊门案例 了解了什么是OGNL及其特点之后,接下来,分析⼀下OGNL的结构,OGNL的操作实际上是围绕OGNL结构的三个要素⽽进⾏的,分别是表达式(Expression),根对象(Root Object),上线⽂环境(Context)。♥ ⽀持对象⽅法调⽤ 使⽤OGNL+Struts2的标签,计算字符串的长度- ① 在Java代码中,调⽤字符串.length()- ② 要使⽤到Struts2的标签 - ③ 使⽤JSTL时候,我们除了导⼊jstl的jar包之外,在jsp页⾯引⼊标签库,- 使⽤Struts2的时候,也需要在页⾯中引⼊Struts2的标签库。- ④ 使⽤Ognl+Struts2标签实现计算字符串长度 什么是值栈 1. 之前在Web阶段,在Servlet⾥⾯进⾏操作,把数据放到域对象⾥⾯ , 在页⾯中使⽤ EL表达式获取到,域对象是在⼀定范围内,存值和取值。2. 在Struts2⾥⾯,它提供了⼀种存储的这种机制,类似于我们之前学的那个域对象,叫做值栈,可以存值和取值。- ① 在action⾥⾯,我们可以把数据存到值栈⾥⾯,在页⾯中获取值栈的⾥⾯的数据 3. Servlet跟Action的区别 - ① Servlet:在第⼀次访问的时候创建,只创建⼀次,它是⼀个单实例对象。 - ② Action:在访问的时候创建,每次访问Action的时候,都会创建⼀个新的Action对象,Action是⼀个多实例对象。- 验证Action是⼀个多实例的对象: 创建⼀个Action类,把构造器写出来,然后再构造器⾥⾯写⼀句输出语句: - 配置Struts2核⼼配置⽂件:struts.xml - 每刷新⼀次,控制台都会打印构造器⾥⾯的信息,说明每次访问Action,都会实例化Action实例。 1. 值栈存储的位置 - ① 每次访问Action的时候,都会创建⼀个Action的对象- ② 在每个Action对象⾥⾯,都有⼀个值栈的对象(只有⼀个)- 获取值栈对象 1. 获取值栈对象⼀共有多种⽅式 - ① 常⽤的⽅式:使⽤ActionContext类⾥⾯的⽅法得到值栈对象 - 栈的概念: 值栈的内部结构 1. 值栈分为两部分: - ① 第⼀部分 root,结构是list集合 - (1)⼀般操作都是root⾥⾯数据,通过调试可以查看 - ② 第⼆部分 context ,结构map集合 1. struts2⾥⾯有标签 - ① 访问action,执⾏action的⽅法的返回值,配置返回值到jsp的页⾯中,在jsp中,使⽤这个标签。- 具体实现:ValueStackAction.java - Struts.xml - 浏览器访问该Action,然后看到了超级链接:Debug,点击超级链接可以看到结构 - 点击页⾯中的Debug,我们看到了两部分:第⼀部分就是root,第⼆部分是键值对的,context; - 在Action⾥⾯没有做任何的操作,栈顶的元素就是Action的引⽤,Action如上图所⽰; - Action⾥⾯会有值栈对象 - 值栈对象⾥⾯有action引⽤,存的不是真正的Action的对象,⽽是⼀个Action的引⽤ 向值栈放数据 1. 向值栈中存放数据多种⽅式 - ① 获取到值栈对象,调⽤值栈对象⾥⾯的set⽅法- ② 获取到值栈对象,调⽤值栈对象⾥⾯的push⽅法 - ③ 最常⽤的⽅式,在Action⾥⾯定义⼀个变量,⽣成这个变量的get⽅法2. 具体实现:- ♥ 第⼀种⽅式:set - 浏览器查看【Debug】,多了⼀个HashMap对象 - ♥ 第⼆种⽅式:push - - 浏览器查看【Debug】,多了⼀个String对象- - ♥ 第三种⽅式:这是我们最常⽤的⽅式:定义变量,然后⽣成get⽅法- - 浏览器查看【Debug】,多了⼀个String对象 1. 总结:我们使⽤set是分配了⼀个Map空间,push,他分配了⼀个字符串的空间,第三种⽅式,他就直接存到Action⾥⾯进⾏存储,这么做可以减少空间的分配。 从值栈中存放对象 1. 实现的步骤: - ① 在成员变量的位置,定义⼀个对象的变量- ② ⽣成这个对象变量的get⽅法 - ③ 在执⾏的⽅法⾥⾯,向这个对象中设置值 - 具体操作: - 查看浏览器:【Debug】,可以看到Action⾥⾯就有了user对象 向值栈存放list对象 场景:⽐如我们从表中查询⼀些记录,在Java⾥⾯我们把查询到的数据存⼊集合,然后集合要传递到JSP页⾯,这个时候,我们就可以使⽤到值栈的List对象1. 定义⼀个list集合的变量2. ⽣成变量的get⽅法 3. 在执⾏的⽅法⾥⾯,给设置集合的值4. 具体实现 - 查看浏览器,就可以看到存储的数据: 从值栈中获取数据 Ognl是根据Struts2标签⼀起来获取值栈的数据。使⽤Struts2的标签+ognl表达式获取值栈数据- ① 从值栈中获取字符串 具体实现: 在ValueStackAction⾥⾯定义成员变量username: 在核⼼配置⽂件 struts.xml配置访问 在valuestack.jsp⾥⾯进⾏获取字符串数据 浏览器访问,测试,得到数据:“⽆崖⼦” 从值栈中获取对象 集体实现步骤:在实体类⾥⾯⽣命user对象变量 Struts2核⼼配置⽂件,如下配置 在页⾯中获取对象⾥⾯的数据: 从值栈中获取List集合 实现步骤:1. 声明Action - 核⼼配置⽂件:struts.xml - valuestack3.jsp,使⽤两种⽅式来获取list集合⾥⾯的数据: - 观察浏览器效果:两种⽅式都获取到了集合⾥⾯的数据: - 第三种⽅式: 其他操作 1. 使⽤set⽅法向值栈中放数据,如何取出 1. 使⽤push⽅法向值栈中放数据,如何取出 - ① 使⽤push⽅法设置值,没有名称,只有设置的值 - ② 向值栈中存放数据,他会把值栈放数据存到数组⾥⾯去,数组的名称:top,根据数组来获取值- 取出数组中的第⼀个值,栈顶的值,如下: - 查看浏览器:栈顶的值,如下图所⽰: EL表达式获取值栈数据 1. 具体实现⽅式: - EL表达式可以获取值栈数据,为什么呢? - ① EL表达式是获取域对象⾥⾯的值 - ② 向域对象⾥⾯放值使⽤setAttribute()⽅法,获取值是:getAttribute()⽅法- ③ 底层增强request对象⾥⾯的⽅法:getAttribute()⽅法- (1)⾸先从request域⾥⾯获取值,如果获取到,直接返回 - (2)如果从request域⾥⾯没有获取到值,他会到值栈⾥⾯去获取值,然后把值放⼊我们的域对象⾥⾯,然后返回1. 查看源代码: 继续点击 - 在这个类⾥⾯,他主要增强了getAttribute() ⽅法 - 最终: OGNL#、%的使⽤#使⽤ 1. 使⽤#获取context⾥⾯的数据 1. 演⽰#的使⽤ - 向request域中放值- 在页⾯中使⽤ognl获取- ValueStackAction4.java - 核⼼配置⽂件struts.xml - valuestck4.jsp - 查看浏览器:值已经取出来 %的使⽤ 1. 在Struts2标签⾥⾯表单标签 - % : 在struts2标签⾥⾯使⽤ognl表达式,如果直接在struts2表单标签⾥⾯使⽤ognl表达式不识别,只有使⽤%之后才能识别。 Struts2概述 1. 只是Struts2⾥⾯的⼀个概念,在其他⾥⾯没有,Struts2是⼀个框架中封装了很多的功能,Struts2⾥⾯封装的很多功能都是在⾥⾯的,⽐如,之前⽤过的功能,⽐如说在Struts2⾥⾯的到表单数据,有属性封装,还有模型驱动封装。这些功能都是封装在Struts2的⾥⾯的,我们可以直接⽤⾥⾯的内容完成我们的操作。⼀句话,Struts2的帮我们封装了很多的功能。 2. Struts2⾥⾯封装了很多的功能,有很多,不是每次这些都运⾏,每次只会执⾏⼀些默认的。3. Struts2⾥⾯默认的的位置 1. 在什么时候执⾏ - ♡ 在action对象创建之后,action的⽅法执⾏之前执⾏- ♡ 通过调试查看源代码,来分析执⾏的时机: - ♡ 选择这⼀⾏代码,按Ctrl、Shift、T,跳转到源代码,到了这个模型驱动的类⾥⾯,我们设置⼀个断点,然后调试查看执⾏时机: - 具体实现: - ♡ InterAction.action.java - 核⼼配置⽂件struts.xml - 通过调试,我们发现,⾸先:执⾏我们定义的构造函数,然后:程序会执⾏到⾥⾯去,最后:会执⾏我们的Action⽅法。 的底层的原理 1. 底层使⽤到了两个原理- ① AOP的思想- ② 责任链模式 AOP的思想 - ① AOP本⾝是⼀种开发的思想: - ⾯向切⾯编程(⾯向⽅⾯编程):假如我有⼀个功能,我需要扩展这个功能,按照我们之前的写法是,改写我们的源代码,但是AOP的模式是不通过修改源 代码的⽅式就可以扩展我们的功能,⽐如:通过配置⽂件扩展。- ② AOP理解图:不需要修改源代码,就可以扩展功能 责任链模式 1. 在Java⾥⾯有很多的设计模式,责任链模式是其中的⼀种。 2. 之前过滤器,我们说过过滤器链,责任链模式跟这个过滤器链是很相似的 - 过滤链:⼀个请求可以有多个过滤器进⾏过滤,每个过滤器只有做放⾏的操作才能到下⼀个过滤器。 3. 责任链模式:要执⾏有多个操作,假如有添加、修改、删除,⾸先执⾏添加操作,添加操作执⾏完毕之后,他要做⼀个类似过滤器放⾏的操作,然后执⾏修 改,修改操作执⾏完毕之后,然后执⾏类似过滤器放⾏的操作,最后执⾏删除操作。 AOP的思想和责任链应⽤到⾥ 1. 在action对象创建之后,action的⽅法执⾏之前被执⾏。 2. 在action⽅法执⾏之前,会执⾏默认,执⾏的过程使⽤到的是AOP的思想 。在action⾥⾯,并没有直接调⽤的⽅法,它是使⽤配置⽂件的⽅式进 ⾏操作,这就是AOP 的思想,不改源代码,实现功能。3. 执⾏的时候,会执⾏到很多的,这个过程使⽤到的就是责任链模式。 - 假如有三个,先执⾏1,执⾏完1之后,做⼀个类似与放⾏的操作,在执⾏2,执⾏2之后,放⾏,再执⾏3,当拦截 器3放⾏,执⾏Action⾥⾯的⽅法。- 执⾏过程如下图: - - 接线来,我们来查看⼀下源代码:- 第⼀步:在9⾏,按住Ctrl 点击进去 - 第⼆步:在99⾏,按住Ctrl 点击进去 - 第三步:在81⾏,按住Ctrl键点击进去 -第四步:观察代码565⾏:创建Action代理对象,在575⾏,执⾏Action⽅法, - 第五步:我们在575⾏,按住Ctrl点击下⾯的第⼆个选项:Open Implementation,查看接⼝的实现类:然后,双击StrutsActionProxy,进去: 第六步: 在⾏,按住Ctrl键,选择第⼆个选项,点击进去查看代码 - 最后,我们就看到了执⾏的代码了: 过滤器和的区别 1. 过滤器 - 过滤器:理论上可以过滤任意的内容,⽐如:HTML,JSP,servlet,图⽚。2. - :只会拦截Action。 Servlet和Action的区别 Servlet:默认是第⼀次访问的时候创建,它会创建⼀次,是⼀个单实例对象。 Action:每次访问的时候创建,会创建多次,是⼀个多实例对象。 ⾃定义 1. 在Struts2⾥⾯有很多的,这些都是Struts2封装的功能,但是在实际的开发中,有的时候,Struts2⾥⾯封装的没有我们需要的功能,这个时候, 需要我们⾃⼰写来实现功能:2. 关于的⼀个基本的结构:- 查看源代码,来查看的结构 - 在导⼊的jar包中,找到struts-default.xml中,选择如下代码,按 Ctrl + Shift + T - 到源代码中,看到如下:该继承了 AbstractInterceptor - 实现了Intercepter接⼝: - 在如下接⼝⾥⾯,有三个⽅法,分别是:destory()销毁的操作;init()⽅法是初始化操作,和intercept() 拦截逻辑的的操作。 1. 在实际开发过程中,我们就⾃定义⼀个类,让这个⾃定义的类继承⾃ - MethodFilterInterceptor来实现,实现这个类的好处:可以让我们的Action⾥⾯的某个⽅法不进⾏拦截。- 让跟我们的Action有关系(AOP的应⽤): - ① 不是在Action⾥⾯调⽤的⽅法,⽽是通过配置⽂件的⽅式来建⽴这种关系。 ⾃定义登录 1. 需求:在项⽬中,有很多的Action的超链接,每个Action的超链接都对应着⼀个功能,实现只有是登录的状态,你才能点击这些超链接实现功能,如果说你不 是登录状态,点击Action的超链接,返回到登录页⾯。2. 登录的状态:使⽤session的域对象来实现 - ① 登录成功之后,客户把登录这的信息存⼊session⾥⾯- ② 判断session⾥⾯是否有值,可以知道是否是登录的状态3. 实现基本的登录的功能 - ① 查询数据库,判断⽤户名和密码(我就直接写固定的了)4. 具体实现:- 登录页⾯: - 核⼼配置⽂件struts.xml LoginAction.java - index.jsp 1. 添加 - ① 判断是否登录,判断session⾥⾯是否有你存⼊的值- ② 的具体的实现 - (1)创建⼀个类,继承⾃MethodFilterInterceptor类- - (2)重写⽅法:doIntercept,实现拦截逻辑 - (3)配置Action和的关系,其实就是:注册 - 第⼀步:在要拦截的Action标签所在的package标签⾥⾯先声明 - 第⼆步:在具体的Action标签⾥⾯使⽤我们声明的 - 第三步: 在Struts2⾥⾯,会执⾏很多的默认的,但是如果我们在Action⾥⾯配置了⾃定义的,这时候会有⼀个问题:默认的就不会执⾏了,只会执⾏你配置的,这样以来,Struts2的很多功能我们就不能使⽤,因为Struts2⾥⾯的功能都是通过配置来实现的;解决⽅案:把默认的⼿动使⽤⼀次。 - ** 配置的,会对Action⾥⾯的所有的⽅法都进⾏拦截 1. 通过调试发现,对Action⾥⾯所有的⽅法都进⾏了拦截 - ① 在Action⾥⾯有⼀个登录的⽅法,⽽这个登录的⽅法不能拦截,如果这个⽅法也拦截,他永远没有登录的机会,还没有到Action的登录的⽅法,页⾯有转到 登录页⾯去了。- ② 解决⽅案:让登录的⽅法不进⾏拦截 - ③ 我们继承的是MethodFilterInterceptor类,好处就是直接通过配置的⽅式,让Action⾥⾯的某些⽅法不进⾏拦截,在实际开发过程中,都 是继承⾃MethodFilterInterceptor Struts2的标签库 对于⼀个MVC框架⽽⾔,重点是实现两部分:业务逻辑控制器部分和视图页⾯部分。Struts2作为⼀个优秀的MVC框架,也把重点放在了这两个部分上。控制器主要由Action来提供⽀持,⽽视图则是有⼤量的标签来提供⽀持。 Struts2标准标签库概述 1. Struts标签库概述 - 在JavaWeb中,Struts2标签库是⼀个⽐较完善,⽽且功能强⼤的标签库,它将所有标签都统⼀到⼀个标签库中,从⽽简化了标签的使⽤,它还提供主题和模 板的⽀持,极⼤的简化了视图页⾯代码的编写,同时它还提供对Ajax的⽀持,⼤⼤的丰富了视图的表现效果。与JSTL(JSP Standard Library,JSP标准标签库)相⽐,Struts2标签库更加易⽤和强⼤。 Struts2标签库的分类 早期的JSP页⾯需要嵌⼊⼤量的Java脚本来进⾏输出,这样使得⼀个简单的JSP页⾯加⼊了⼤量的代码,不利于代码的可维护性和可读性,随着技术的发展,逐渐的采⽤标签库来进⾏JSP页⾯的开发,这使得JSP页⾯能够在很短的时间内开发完成,⽽且代码通俗易懂,⼤⼤的⽅便了开发者,Struts2的标签库就是这样发展起来的。 Struts2框架对整个标签库进⾏了分类,按照功能⼤体可以分为两类,如图所⽰: 由图中可以看出,Struts2标签库主要分为两类,普通标签和UI标签。普通标签主要是在页⾯⽣成的时,控制执⾏的流程。UI标签则是以丰富⽽可复⽤的HTML⽂件来显⽰数据。 普通标签⼜分为控制标签(Control Tags)和数据标签(Data Tags)。控制标签⽤来完成条件逻辑,循环逻辑的控制,也可⽤来做集合的操作。数据标签⽤来输出后台的数据和完成其他数据访问功能。 UI标签⼜分为表单标签(Form Tags)、⾮表单标签(Non-Form Tags)和Ajax标签,表单标签主要⽤来⽣成HTML页⾯中的表单元素,⾮表单标签主要⽤来⽣成HTML的 Struts标签的使⽤ Struts2标签库被定义在struts-tags.tld⽂件中,我们可以在struts2-core-2.3.34.jar中的META-INF⽬录下找到它。要使⽤Struts2的标签库,⼀般只需要在JSP⽂件使⽤taglib指令导⼊Struts2标签库,具体代码如下: <%@taglib uri=\"/struts-tags\" prefix=\"s\" %> 在上述代码中,taglib指令的uri属性⽤于指定引⼊标签库描述符⽂件的URI,prefix属性⽤于指定引⼊标签库描述符⽂件的前缀。需要注意的是,在JSP⽂件中,所有的Struts2标签都使⽤ ’s’ 前缀。 Struts2的控制标签 在Struts2开发中,经常要⽤流程控制语句实现分⽀,循环操作,为此,Struts2标签库中提供了控制标签,常⽤的逻辑控制标签主要包括: - 与多数编程语⾔中的if、elseif、和else语句功能类似, ⽤,⽽ - 上述语句表达式中, - Iterator 标签的属性 - 在表中,如果在 过status属性获取信息的⽅法如下表所⽰: status 获取状态信息 <%@ page language=\"java\" contentType=\"text/html; charset=UTF-8\" pageEncoding=\"UTF-8\"%> <%@ taglib uri=\"/struts-tags\" prefix=\"s\" %> 在⽂件的table标签内,⾸先使⽤ 从图中运⾏结果可以看出,表格的奇数⾏变为了⽩⾊,偶数⾏变成了灰⾊。这是因为⽂件中,使⽤ 的奇偶数来决定表格的颜⾊。 Struts2的数据标签 在Struts2标签中,数据标签主要⽤于各种数据访问相关的功能以及Action的调⽤等。常⽤的数据标签有 - - - default : 可选属性,如果要输出的属性值为null,则显⽰default属性指定的值- escape : 可选属性,指定是否忽略HTML代码 - value : 可选属性,指定需要输出的属性值 , 如果没有指定该属性 , 则默认输出ValueStack栈顶的值- propertyTags.jsp <%@ page language=\"java\" contentType=\"text/html; charset=UTF-8\" pageEncoding=\"UTF-8\"%> <%@ taglib uri=\"/struts-tags\" prefix=\"s\" %> 输出字符串: 忽略HTML代码: 不忽略HTML代码: - 在⽂件中, 定义了四个不同属性的 了value和escape两个属性,其中value属性值包含了HTML标签,但其escape属性值为true,表⽰忽略HTML代码,所以会直接输出value的值;第三个标签,同样使⽤了value和default两个属性,其value值依然包括了HTML标签,但其escape的属性值为false,表⽰不能忽略HTML代码,所以输出的value值为3号标题的值,最后⼀个标签,使⽤了value和default两个属性,但是value值为空,指定了default属性的值为:defaultValue , 所以最后会输出defaultValue,如下图所⽰: 2. - a 标签的常⽤属性以及描述 3. - Struts2的表单标签 Struts2的表单标签⽤来向服务器提交⽤户输⼊的信息,绝⼤多数的表单标签都有其对应的HTML标签,通过表单标签可以简化表单的开发,还可以实现HTML中难以实现的功能,我们可以结合HTML的标签对⽐学习Struts2的表单标签。 表单标签的公共属性 Struts2的表单标签⽤来向服务器提交⽤户输⼊信息,在org.apache.struts2.components包中都有⼀个对应的类,所有表单标签对应的类都继承⾃UIBean类,UIBean类提供了⼀组公共的属性,这些属性是完全通⽤的。 表单标签的通⽤属性 除了这些常⽤的通⽤属性外,还有很多其它属性。由于篇幅有限,这⾥就不⼀⼀列举。需要注意的是,表单标签的name和value属性基本等同于HTML组件 的name和value,但是也有些不同的地⽅:表单标签在⽣成HTML的时候,如果标签没有设置value属性的话,就会从值栈中按照name获取响应的值,把这个值设置成HTML组件的value。简单的说,就是表单标签的value在⽣成HTML的时候会⾃动设置值,其值从值栈中获取。 1. Form 标签常⽤的属性及描述 在使⽤ 2. 3. < s:textarea label=”描述” name=”description” /> name属性⽤来指定单⾏/多⾏⽂本框的名称,在Action中,通过该属性获取单⾏/多⾏⽂本框的值。其value属性⽤来指定单⾏/多⾏⽂本框当前值。 此外,⽤户的管理
⽤户的管理
⽤户的管理
输出默认值:
Copyright © 2019- sceh.cn 版权所有 湘ICP备2023017654号-4
违法及侵权请联系:TEL:199 1889 7713 E-MAIL:2724546146@qq.com
本站由北京市万商天勤律师事务所王兴未律师提供法律服务