第一节 Struts2简介:
(1)Struts2的前世今生:
1.早期开发模型Servlet+JSP+JavaBean(Model2)显得力不从心:
流程凌乱、数据传递无序、缺乏辅助功能。
2.MVC模式的轻量级Web应用框架:Apache Struts1很快风靡全球。
代码结构划分合理,实用工具框架(如验证框架、国际化框架)等,搞J2EE必会Struts。
3.时间推移,Struts1的缺点:
线程不安全、灵活性低、和ServletAPI耦合、页面传值麻烦等。
4.异军突起,SpringMVC和OpenSymphony的WebWork等。
5.Apache Struts + OpenSymphony WebWork2 = Struts2
Struts2:基于MVC的轻量级的Web应用框架,
来源于Webwork2, 与Struts1.x完全不兼容
Struts2 是一个非常优秀的MVC框架,基于Model2 设计模型.
由传统Struts1和WebWork两个经典框架发展而来:
Struts2框架=Struts2+XWork
Strust2 核心功能:
允许POJO(Plain Old Java Objects)对象 作为Action.
Action的execute 方法不再与Servlet API耦合,更易测试
支持更多视图技术(JSP、FreeMarker、Velocity)
基于Spring AOP思想的拦截器(感觉在Struts2中,使用数据的封装和国际化等等功能非常容易,)机制,更易扩展
更强大、更易用输入校验功能
整合Ajax支持
(2)struts2目录结构:
apps:该文件夹包含了基于struts2 的示例应用,这些示例应用对于学习者是非常有用的
docs:该文件夹下包含了struts2 相关文档,包括struts2 快速入门、struts2的文档以及API文档等
lib:该文件夹下包含了Struts2框架和核心类库,以及struts2第三方插件类库
src: 该文件夹下包含了Struts2框架的全部源代码
第二节 第一个Struts2程序:
①新建一个项目:
②配置项目路径:
③设置jar包位置:
④配置tomcat服务器:
⑤拷贝/apps/struts2-blank/WEB-INF/lib中的jar到项目的lib中.
注意:
开发Struts2依赖的jar,不需要挨个去挑选:
找到根下apps目录,找到struts2-blank(Struts2提供的空白项目),里面整合了Struts2的依赖环境和配置.
struts2-core-2.3.1.1.jar:Struts 2框架的核心类库
xwork-core-2.3.1.1.jar:Command模式框架,WebWork和Struts2都基于xwork
ognl-3.0.3.jar:对象图导航语言(Object Graph Navigation Language), struts2框架通过其读写对象的属性
freemarker-2.3.18.jar:Struts 2的UI标签的模板使用FreeMarker编写
commons-logging-1.1.x.jar:ASF出品的日志包,Struts 2框架使用这个日志包来支持Log4J和JDK 1.4+的日志记录。
commons-fileupload-1.2.2.jar: 文件上传组件,2.1.6版本后需要加入此文件
commons-io-2.0.1.jar:传文件依赖的jar包
commons-lang-2.5.jar:对java.lang包的增强
⑥.2.在web.xml中配置Struts2的前端控制器-StrutsPrepareAndExecuteFilter.
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
version="3.1">
<filter>
<filter-name>struts2</filter-name>
<filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>
⑦定义一个POJO类:HelloAction,并提供一个公共无参数的execute方法.
public class HelloAction {
public String excute(){
System.out.println("hello action");
return "hello";
}
}
⑧.在struts.xml文件中,配置HelloAction.(把HelloAction交给Struts2框架管理).
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
"http://struts.apache.org/dtds/struts-2.0.dtd">
<struts>
<package name="helloPkg" extends="struts-default" namespace="/pss">
<action name="hello" class="com.fym.action.HelloAction" method="excute">
<result name="hello">/index.jsp</result>
</action>
</package>
</struts>
启动tomcat即可.
第三节 struts2的简单执行流程
第四节 Struts2框架和应用的配置文件以及常见的常量
(1)Struts2中的6大配置文件:
Struts2框架按照如下顺序加载struts2配置:
1.default.properties 该文件保存在 struts2-core-2.3.7.jar 中 org.apache.struts2包里面:包含了Struts2的默认常量配置
2.struts-default.xml 该文件保存在 struts2-core-2.3.7.jar:包含了框架依赖的对象配置和结果类型,拦截器等配置.
3.struts-plugin.xml 该文件保存在Struts2框架的插件中:struts-Xxx-plugin-2.3.7.jar.由插件提供
上述三个文件是框架自带的,我们不能修改,只能使用.
4.struts.xml 该文件是web应用默认的struts配置文件.重点.配置自定义的Action和其他信息.
5.struts.properties 该文件是Struts的默认配置文件–>可以修改default.properties 的常量配置.
6.web.xml 该文件是Web应用的配置文件
上述三个文件是我们可以修改操作的.
如果多个文件配置了同一个struts2 常量,则后一个文件中配置的常量值会覆盖前面文件配置的常量值.
注意:一般的,我们只在struts.xml中做常量配置.
(2)Struts2中常见常量:
1):指定默认编码集,作用于HttpServletRequest的setCharacterEncoding方法和 freemarker、velocity的输出
2):该属性指定需要Struts 2处理的请求后缀,该属性的默认值是action,即所有匹配 *.action的请求都由Struts2处理。
如果用户需要指定多个请求后缀,则多个后缀之间以英文逗号(,)隔开
3):设置浏览器是否缓存静态内容,默认值为true(生产环境下使用),开发阶段最好关闭
4):当struts的配置文件修改后,系统是否自动重新加载该文件,默认值为false(生产环境下 使用),开发阶段最好打开
5):开发模式下使用,这样可以打印出更详细的错误信息
:修改struts.xml之后,不要重启Tomcat.
6):默认的视图主题
7):是否支持动态方法调用
第五节 package,action,result的相关配置
package元素: 是struts根元素的子元素.
用来对多个action元素分类管理,和Java中的package没有关系.
常见的属性:
<package name="" extends="" namespace="" abstract=""></package>
name: 表示package的名字,但是要保证不同的package元素的name不同. 可以通过该名字被其他的包所指代.
extends: 表示当前package继承哪一个package,一般都是:struts-default.
而struts-default其实就是struts-default.xml中package元素的名字.
继承struts-default之后,就拥有了该package定义的所有资源.(结果返回类型,拦截器…)
namespace: 表示命名空间,一般的以"/"打头,命名一般以模块名.如: /crm, /oa. 和action的name决定了一个Action类的访问路径.
abstract: 抽象的,缺省值是false. 若一个package的abstract=“true”,那么该package中就不能再定义action元素,只能用来继承.
企业中的最佳实践:
action元素:是package元素的子元素.
专门用来配置Action对象的.
<action name="" class="" method=""/>
常见的属性:
name: action的名称,在同一个package中,action的名字必须唯一. 和package的namespace共同决定了一个Action类的访问路径.
注意:action的name值不能以"/"打头.
class:一个Action类的全限定名. 缺省值:ActionSupport类.
method:当前Action动作访问的方法, 缺省值:execute.
result元素:配置结果视图.
<result name="" type=""></result>
局部结果视图: result定义在action中.
全局结果视图: result定义在global-results中,而global-results在package中
如右图:
逻辑视图寻找顺序:先从当前的Action中去选择局部结果视图,找到就跳转,找不到,再找当前action所在package中找全局的结果视图,找到,跳转,找不到,报错.No result defined.
常见的属性:
name:Action方法返回的逻辑视图名称. 缺省值:success
type:结果的跳转类型.该类型的值在struts-default.xml中已经预定义好了. 缺省值:dispatcher
常见的type值(结果类型):
dispatcher: 表示从Action请求转发到页面(JSP).缺省值
redirect: 表示从Action重定向到页面(JSP).
chain: 表示从Action请求转发到另一个Action.
redirectAction: 表示从Action重定向到另一个Action.
stream: 表示返回流. 文件下载时使用.
<param name="">表示参数:name缺省值:location(地址)
第六节 Action类的编写方式
第三种.定义一个类,继承于com.opensymphony.xwork2.ActionSupport类.(推荐)
public class ActionSupport implements Action, Validateable, ValidationAware, TextProvider, LocaleProvider, Serializable {}
真实开发中,我们却往往再提供一个BaseAction类.
–BaseAction extends ActionSupport
-----AAction extends BaseAction
-----BAction extends BaseAction
第七节 Action中多方法调用
方案: 使用通配符的方式类配置: 通配符:*
<action name="emp_*" class="com.manymethod.EmployeeAction" method="{1}">
Action的名字: emp_Action方法: 比如:emp_list,那么{1}的值就是list
emp_edit,那么{1}的值就是edit
两个通配符:
<action name="*_*" class="com.manymethod.{1}Action" method="{2}">
Action名字:Action类名_Action方法. 比如:Employee_list,表示调用的EmployeeAction中的list方法
比如:Department_edit,表示调用DepartmentAction中的edit方法.
第八节 Action获取请求参数三种方式
Action获取请求参数三种方式,归功于拦截器(ParametersIntercepter):
第一种:Action本身作为Model对象,通过setter方法封装(属性注入)
第二种:创建独立Model对象,页面通过ognl表达式封装(属性注入)(首选)
第三种:使用ModelDriven接口,对请求数据进行封装(模型驱动)
方式2:创建独立Model对象,页面通过ognl表达式语法来封装对象.
Model:
Action:
JSP:
- List类型参数的封装(了解)
页面中的OGNL表达式的书写:
users[0].name = xxx
users[0].age = 19
users[1].name = ooo
users[1].age = 20
Action中的属性的定义:
private List<User> users = new ArrayList<>();
Getter/Setter方法
* Map类型参数的封装
页面中的OGNL表达式的书写:
map [‘a’].name = “xxx”
map [‘a’].age = 19
map [‘b’].name = ooo
map [‘b’].age = 20
Action中的属性的定义:
private Map<String, User> map = new HashMap<>();
Getter/Setter方法
第九节 访问ServletApi三种方式
Action访问Servlet API:
在Action类中操作Servlet中相关的对象.
request,repsonse,session,cookie等.
获取请求参数: request.getParameter(String name)
设置/获取共享数据: 域对象.setAttribute(String name,Object value);
操作Cookie: response.addCookie(Cookie cookie);
依赖servlet-api.jar-
解决上述问题的方式:
访问ServletApi方式1:让Action类实现感知接口.(不建议使用)
ServletRequestAware:感知HttpServletRequest对象;
ServletResponseAware:感知HttpServletResponse对象;
SessionAware:感知HttpSession对象;
存在的问题,和ServletAPI藕合严重;
问题:Action中感知接口的方法是谁在调用?----->servletConfig拦截器(优先于Action执行)
访问ServletApi方式2:通过ServletActionContext工具类.
通过ServletActionContext类中的静态方法,得到Servlet相关的Api;
这种方式直接通过ServletActionContext的静态方法就可以获取Servlet的API对象,操作和理解非常简单.
在开发中很多人都喜欢使用,但是依然Action与ServletAPI有耦合.
访问ServletApi方式3:通过ActionContext工具类,
理解ActionContext:从字面上分析,表示Action的上下文对象.就在一次请求中
ActionContext封装每一次请求的相关信息.和之前使用的HttpServletRequest作用一致
获取ActionContext对象:
ActionContext ctx = ActionContext.getContext();获取请求对象
在ActionContext中把request,session,application三大作用域都作为Map对象.
1):获取请求参数.
原始:Map<String,String[]> params = request.getParameterMap();
现在:Map<String,String[]> params = ctx.getParameters();
2):操作request作用域:
原始:request.setAttribute(String name, Object value);
Object val = request.getAttribtue(String name);
现在:ctx.put(String key,Object value);
Object val = ctx.get(String name);
3):操作session作用域:
原始:HttpSession session =request.getSession();
现在:Map<String,Object> session = ctx.getSession(); 接下来就是操作Map对象
4):操作servletContext(application)作用域:
原始:ServletContext servletContext = request.getServletContext();
现在:Map<String,Object> app = ctx.getApplication();