什么是框架 ?代码架构,应用软件半成品,在框架基础上 进行软件开发
什么是类库、组件? commons-fileupload javamail c3p0 这些组件实现特定功能,直接拿来使用
什么是struts2?
struts2 是一个优秀的MVC框架 , struts1 开发流程,webwork框架核心
struts2 基于webwork ,webwork基于xwork ,struts2很多特性都是xwork提供
MVC 诞生与web开发,将web程序分为三个部分 Model模型 View视图 Controller控制器
View 视图: JSP web层
Model 模型: JavaBean 业务逻辑层、持久层
Controller控制器: Servlet web层
Strust2 核心功能
1、允许POJO(Plain Old Java Objects)对象作为Action
2、Action的execute 方法不再与Servlet API耦合,更易测试
3、支持更多视图技术(JSP、FreeMarker、Velocity)
4、基于Spring AOP思想的拦截器机制,更易扩展
5、更强大、更易用输入校验功能
6、整合Ajax支持
一、struts2 开发快速入门(简单的环境搭建的步骤)
1、导入开发包
下载struts-2.3.7-all.zip 解压 目录结构
apps 该文件夹包含了基于struts2 的示例应用,这些示例应用对于学习者是非常有用的
docs 该文件夹下包含了struts2 相关文档,包括struts2 快速入门、struts2的文档以及API文档等
lib 该文件夹下包含了Struts2框架和核心类库,以及struts2第三方插件类库
src 该文件夹下包含了Struts2框架的全部源代码
struts2 和 struts1 在app目录中都提供struts2_blank.war 该war 包中存放struts2 开发最基本的jar包
l Struts运行必要jar包
l struts2-core-2.3.1.1.jar:Struts 2框架的核心类库
l xwork-core-2.3.1.1.jar:Command模式框架,WebWork和Struts2都基于xwork
l ognl-3.0.3.jar:对象图导航语言(Object Graph Navigation Language), struts2框架通过其读写对象的 属性
l freemarker-2.3.18.jar:Struts 2的UI标签的模板使用FreeMarker编写
l commons-logging-1.1.x.jar:ASF出品的日志包,Struts 2框架使用这个日志包来支持Log4J和JDK 1.4+的日志记录。
l commons-fileupload-1.2.2.jar:文件上传组件,2.1.6版本后需要加入此文件
l commons-io-2.0.1.jar:传文件依赖的jar包
l commons-lang-2.5.jar:对java.lang包的增强
2、编写jsp 发起web请求
hello.jsp
<ahref="${pageContext.request.contextPath }/hello.action">访问struts2 快速入门</a>
3、配置web.xml 将请求配置到核心控制器
struts2核心的拦截器StrutsPrepareAndExecuteFilter首先必须配置
<!-- 配置struts2 核心控制器 -->
<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>
4、配置struts2框架核心配置文件 struts.xml
在src目录创建struts.xml
<package name="mystruts"extends="struts-default" namespace="/">
<!--默认值 会 调用 Action 的 execute方法 -->
<actionname="hello" class="cn.itcast.action.HelloAction">
<!--将逻辑视图abcd 映射 success.jsp 物理页面 -->
<resultname="abcd">/success.jsp</result>
</action>
</package>
5、建立一个HelloAction进行业务的处理
需要编写一个方法签名为public String execute()的方法。
publicString execute(){
return "abcd"; // 对应struts.xml配置result 结果 ------ success.jsp
}
在Action执行后,自动跳转到 success.jsp 页面
6、 struts2处理流程中StrutsPrepareAndExecuteFilter 会调用一组前端拦截器,完成请求处理大部分功能
Interceptor机制可以在Action访问前执行
Interceptor可以在Action 访问前后执行,功能类似 Filter
在strust2-core 核心jar包中struts-default.xml 定义了拦截器 列表
每个Action访问, 在Action的execute方法执行前,会调用 defaultStack 中定义拦截器
7、配置struts dtd myeclipse 提示
注:struts.xml配置文件中的名称空间中的dtd文件是网上的文件,如果想在编写配置文件中有提示,那么必须得联网,否则就指定一个本地文件进行关联。
window-preferences--- xml catalog --- add
添加DTD时,将key type 设置 URI
8、关联源码与反编译
学习框架,经常阅读框架源码,阅读源码有两种方式: 1 关联源码 2 在myeclipse加入反编译插件
反编译 将.class文件 编译 .java 文件
文件夹中插件基于eclipse 3.x
第一步: 将jad 文件夹 复制 myeclipse/dropins 目录
第二步: 将jad.exe 复制 jdk/bin 目录
第三步: 重启myeclipse (发现插件安装不上,在myeclipse快捷方式, 添加-clean参数 )
windows-preferences -- java -- jadClipse
第四步: 配置jad.exe位置
=============================================================================================
二、struts2 框架配置
1、 Struts2框架按照如下顺序加载struts2配置文件
1) default.properties 该文件保存在 struts2-core-2.3.7.jar中 org.apache.struts2包里面
* 定义struts2属性信息 key-value
2) struts-default.xml 该文件保存在 struts2-core-2.3.7.jar
* 定义默认package 拦截器interceptor结果集类 result-type
3) struts-plugin.xml 该文件保存在struts-Xxx-2.3.7.jar
* 插件自定义配置文件
4) struts.xml 该文件是web应用默认的struts配置文件 (重要!!!!)
* 创建在src下,struts2框架核心配置文件,主要配置Action,也可以配置struts2属性
5) struts.properties 该文件是Struts的默认配置文件
* 在src下创建
6) web.xml 该文件是Web应用的配置文件
* 都是用来配置struts2属性
注:绿色为系统自带的,红色与蓝色为自己写的,但是蓝色很少写,红色很重要。
注:如果多个文件配置了同一个struts2 常量,则后一个文件中配置的常量值会覆盖前面文件配置的常 量值
2、 Action的配置
struts2 引入package概念,用package管理Action, 在package中定义结果集类型、拦截器列表
struts-default.xml 定义 abstract 的 package "struts-default"
用户编写package通常extends="struts-default" 使用struts-default 定义结果集类型 和 拦截器列表
每个package 都提供namespace属性,该属性与Action的name一起决定Action的访问路径
Action的访问路径 = 包名称空间 namespace + Actionname属性
每个package,可以定义一个namespace属性,默认值 "/"
<packagename="xxx" extends="struts-default"namespace="/abc">
<action name="def"class="xxx" /> ----------- 该action访问路径 /abc/def.action
Action名称的搜索顺序
1.获得请求路径的URI,例如url是:
http://server/struts2/path1/path2/path3/test.action
2.首先寻找namespace为/path1/path2/path3的package,
如果存在这个package,则在这个package中寻找名字为test的action,
如果不存在这个package则转步骤3;
3.寻找namespace为/path1/path2的package,
如果存在这个package,则在这个package中寻找名字为test的action,
如果不存在这个package,则转步骤4;
4.寻找namespace为/path1的package,
如果存在这个package,则在这个package中寻找名字为test的action,
如果仍然不存在这个package,就去默认的namaspace的package下面去找名
字为test的action(默认的命名空间为空字符串“/” ),
如果还是找不到,页面提示找不到action。
3、缺省Action default-action 和默认处理类 default-class的区别
1) 默认处理类,指在struts.xml 中,找到action的name,但是<action> 没有配置 class属性
在struts-default.xml 中 定义
<default-class-refclass="com.opensymphony.xwork2.ActionSupport" />
所谓的ActionSupport就是默认的执行类
在struts.xml 中如果<action>没有class属性 ,将会执行默认的 ActionSupport类的execute方法
<action name="index">
<resultname="success">/index.jsp</result> “/”代表web应用
</action>
2) 缺省Action ,如果访问路径,没有找到对应<action>元素,将执行缺省Action的execute
配置缺省Action后,就不会出现Action找不到错误
<default-action-refname="error"></default-action-ref>
4、常量属性配置
l default.properties定义了struts2 框架的大量常量,开发者可以通过改变这些常量来满足应用的需求
l 修改struts2 的配置常量,可以通过以下三种方式配置
l 1. 配置src/struts.xml
<constantname="struts.devMode" value="true" /> 配置为true后,当服务器改动了配置文件后不用重 新启动服务器
l 2. 配置src/struts.properties
struts.devMode = false
l 3. 配置web.xml
常用属性
1)struts.i18n.encoding=UTF-8 等价于request.setCharacterEncoding("utf-8"); 处理post请求乱码
* struts2 开发程序 post请求没有乱码问题, get请求需要手动处理 newString(xxx.getBytes("ISO-8859-1"),"utf-8");
2)struts.action.extension=action,, 配置Action访问请求扩展名,默认值action , 没有扩展名的访问默认也是访问Action
3)struts.devMode = false 设置为true ,修改struts.xml 无需重启服务器
5、 <include> 元素, 将struts2 配置文件分离 ,分模块便于维护
<includefile="struts1.xml" /> 读取src下struts1.xml 配置文件
三、 Action的访问
每次客户端请求,struts2框架中 提供Action 进行处理
1、定义Action 有三种格式
第一种:自定义Action类可以是 POJO类简单的javabean
好处: 与任何API解耦合, 没有依赖struts2 API ,没有依赖Servlet API
publicclass RequestAction1 {
public String execute() {
System.out.println("action1....");
return "success";
}
}
第二种:自定义Action类可以实现 Action接口
好处: 使用Action接口定义 逻辑视图常量
这些常量有以下几种,分别代表处理请求完成后是否跳转,并且跳转到哪个页面。
SUCCESS :Action执行成功后,跳转页面
ERROR : Action执行过程中,发生错误, 跳转页面
INPUT : Action 执行时,发现输入数据有问题,跳转到 请求提交页面(数据输入页面)
LOGIN : Action执行需要登录,身份认证,而用户没有登陆(或者权限不足) ,跳转登陆页面
NONE : Action执行后,不发生页面跳转 return null ; 效果一样
public class RequestAction2 implements Action {
@Override
// 该注解,在JDK5 版本时 只能用于覆盖,在JDK6 版本 才能用于 接口方法实现
public String execute() throws Exception {
System.out.println("action2....");
return INPUT;
}
}
第三种 : 自定义Action类可以继承 ActionSupport这种比较常用
好处: 扩展了请求数据校验、错误信息设置、国际化信息文件读取三个功能
* 在实际开发中,主要用第三种
public class RequestAction3 extends ActionSupport {
@Override
public String execute() throws Exception {
System.out.println("action3....");
return SUCCESS;
}
}
2、 Action的方法调用
通过 method属性,执行该请求执行Action中 哪个方法,不指定默认执行execute方法
<actionname="request3_regist"class="cn.itcast.action.RequestAction3" method="regist">
* request3_regist.action 会执行 RequestAction3中 regist方法
3、通配符 * 的使用
通配符 主要应用在一个Action中 存在多个业务方法的情况下
使用通配符 简化 Action的配置
<action name="user_*"class="cn.itcast.action.UserAction2" method="{1}">
<result>/success.jsp</result>
</action>
此处{1}就代表第一个*
4、动态方法调用
不需要配置 method属性, 指定执行 Action中除了execute的其它业务方法
配置时 无需指定method
<actionname="usermanage" class="cn.itcast.action.UserAction3" >
<result>/success.jsp</result>
</action>
在页面编写Action访问路径时,通过!方法名指定调用Action的哪个方法
<ahref="${pageContext.request.contextPath }/usermanage.action">添加用户</a> 执行 execute方法
<ahref="${pageContext.request.contextPath}/usermanage!addUser.action">添加用户</a> 执行addUser
在default.properties 提供struts.enable.DynamicMethodInvocation = true 值为true支持动态方法调用,值为false,不支持动态方法调用
5、 config browser插件
第一步: 将struts2 解压目录 / lib /struts2-config-browser-plugin-2.3.7.jar 复制 WEB-INF/lib
重启web服务器
第二步 :在网页中http://localhost:8080/struts2_day1/config-browser/index.action
=============================================================================================
四 、在Action的业务方法中,使用Servlet API
第一种:与Servlet API解耦合的操作方式
通过其他API 间接完成Servlet API 执行效果
ActionContext 理解为 Action的上下文对象,完成struts2大部分常规操作
方法:
getContext() 返回ActionContext实例对象 (每次必须使用)
get(key) 相当于 HttpServletRequest的getAttribute(Stringname)方法
put(String,Object) 相当于HttpServletRequest的setAttribute方法
getApplication() 返回一个Map对象,存取ServletContext属性
getSession() 返回一个Map对象,存取HttpSession属性
getParameters() 类似调用HttpServletRequest的getParameterMap()方法
setApplication(Map) 将该Map实例里key-value保存为ServletContext的属性名、属性值
setSession(Map) 将该Map实例里key-value保持为HttpSession的属性名、属性值
好处解耦合,通过操作map的api 间接调用Servlet API
缺点就是无法对response进行处理
例:public class ServletAPIAction1 extends ActionSupport {
@Override
public String execute() throws Exception {
// 1、 获得请求参数 , 通过parameterMap 间接操作 request.getParameter
Map<String, Object> parameterMap = ActionContext.getContext()
.getParameters();
// 获得name 的参数值
System.out.println(((String[]) parameterMap.get("name"))[0]);
// 2、 向request session ServletContext 三个范围 保存数据
// request.setAttribute()
ActionContext.getContext().put("info", "request");
// session.setAttribute()
ActionContext.getContext().getSession().put("info", "session");
// ServletContext.setAttribute()
ActionContext.getContext().getApplication().put("info", "application");
// 3 从request session application 三个范围取值
System.out.println(ActionContext.getContext().get("info")); // 获取request
System.out.println(ActionContext.getContext().getSession().get("info")); // 获取session
System.out.println(ActionContext.getContext().getApplication()
.get("info")); // 获取application
return SUCCESS;
}
}
第二种 :耦合Servlet API
1)采用接口注入方式使用 Servlet API
ServletContextAware向Action中注入 ServletContext对象
ServletRequestAware向Action中注入 ServletRequest对象
ServletResponseAware向Action中注入 ServletResponse对象
例:public class ServletAPIAction2 extends ActionSupport implements
ServletContextAware, ServletRequestAware, ServletResponseAware {
// 三个Servlet 常用 API对象,可以被注入 Action 对象中
private ServletContext context;
private HttpServletRequest request;
private HttpServletResponse response;
@Override
public String execute() throws Exception {
// 获得请求参数
System.out.println(request.getParameter("name"));
// 向三个范围 存放数据
request.setAttribute("info", "request2");
request.getSession().setAttribute("info", "session2");
context.setAttribute("info", "application2");
return SUCCESS;
}
@Override
public void setServletResponse(HttpServletResponse response) {
this.response = response;
}
@Override
public void setServletRequest(HttpServletRequest request) {
this.request = request;
}
@Override
public void setServletContext(ServletContext context) {
this.context = context;
}
}
2) 使用ServletActionContext
ServletActionContext 理解为Servlet的Action上下文,通过该对象可以直接获得Servlet API对象
static PageContext getPageContext()
static HttpServletRequest getRequest()
static HttpServletResponse getResponse()
static ServletContext getServletContext()
例:
public class ServletAPIAction3 extends ActionSupport {
@Override
public String execute() throws Exception {
// 获取参数
System.out.println(ServletActionContext.getRequest().getParameter(
"name"));
// 向三个范围保存数据
ServletActionContext.getRequest().setAttribute("info", "request3");
ServletActionContext.getRequest().getSession()
.setAttribute("info", "session3");
ServletActionContext.getServletContext().setAttribute("info",
"application3");
return SUCCESS;
}
}
五、结果集类型使用
<resultname="success">/success.jsp </result> 这配置中 name="success" 这是逻辑视图名, /success.jsp 物理视图(真实页面 )
<result>元素使用有两个位置
1、<action> 内部 (局部结果集)
2、 <global-results> 内部 (全局结果集,当前package中所有Action都可以使用)
<global-results>
<resultname="success">/success.jsp</result>
</global-results>
<result>元素有两个属性 name和type : name默认值success, type默认值 dispatcher (转发)
struts-default.xml定义了十个结果集类型
常用的有以下几种:
chain : Action的连续执行 ,chain使用转发方式,将请求转发给另一个Action
<resulttype="chain">
<paramname="actionName">hello</param>
<paramname="namespace">/</param>
<paramname="method">execute</param>
</result>
dispatcher :转发给目标jsp页面
注:chain是作为action中的转发,而dispatcher作为页面中的转发。
redirect : 重定向 jsp页面
redirectAction :重定向到Action
<resulttype="redirectAction">
<paramname="actionName">hello</param>
<paramname="namespace">/</param>
<paramname="method">execute</param>
</result>
注:redirectAction是作为action中的重定向,而redirect作为页面中的重定向。
简化写法 <result type="redirectAction">hello</result> , namespace必须为/ method必须为execute
stream : 用于文件下载,向客户端范围html之外文件
plainText :用于向客户端返回纯文本字符串 (Ajax开发中)
=============================================================================================
六、 使用注解开发 struts2应用
1、 convention插件 约定 ,进行零配置(xml和注解都不需要写 )struts2 开发
struts2注解基于 convention插件
导入必须11个jar包外,必须导入 struts2-convention-plugin-2.3.7.jar
开发struts2程序,使用xml 和注解两种方式,xml开发struts时不要导入jar包,否则会有冲突
要求有三个
1、struts-plugin.xml文件中
<constantname="struts.convention.package.locators"value="action,actions,struts,struts2"/> 配置自动扫描包
2、将Action 放到action,actions,struts,struts2 包或者它们子包中,就可以被struts2框架扫描到 (无需xml配置)
3、所有实现了com.opensymphony.xwork2.Action的Java类
所有类名以Action结尾的Java类
以下包不被扫描到
<constantname="struts.convention.exclude.packages"value="org.apache.struts.*,org.apache.struts2.*,org.springframework.web.struts.*,org.springframework.web.struts2.*,org.hibernate.*"/>
<constant name="struts.convention.action.suffix"value="Action"/> 扫描以Action 结尾的类
<constantname="struts.convention.result.path"value="/WEB-INF/content/"/> 结果result页面存放位置
<constantname="struts.convention.classes.reload" value="false" />Action类文件重新自动加载
Action 约定访问路径
cn.itcast.actions.RegistAction 访问路径 /regist.action
cn.itcast.struts.basic.UserManageAction访问路径 /basic/user-manage.action
结果页面result的约定
约定: actionName + resultCode + suffix
访问cn.itcast.struts.user.UserAction返回success
Convention优先使用 WEB-INF/content/user/user-success.jsp
约定可以实现真正意义上零配置 (解决Action映射和 result映射
2、 struts2 注解 是基于约定的
使用默认名称空间例子
public class HelloAction2 extends ActionSupport {
@Override
@Action(value = "hello2", results = { @Result(name = "success", location = "/success.jsp") })
public String execute() throws Exception {
System.out.println("使用注解开发Action");
return SUCCESS;
}
}
使用指定名称空间
@ParentPackage("struts-default")
@Namespace("/basic")
@Result(name = "success", location = "/success.jsp")
public class HelloAction3 extends ActionSupport {
@Override
@Action(value = "hello3")
public String execute() throws Exception {
return super.execute();
}
}
注解会覆盖约定的效果 !!!!!!!