一、简介
Apache Struts 2 是一种流行的MVC框架,成功地结合了 WebWork和Struts1.x 两种 web 框架。它的核心功能是使用拦截实现“值栈”的概念,OGNL表达式和Struts2标签来解决应用程序数据,很多注解和约定,使这个框架更加易于使用。
Struts2框架官网下载地址:
https://struts.apache.org/download.cgi#struts25
二、基础jar包
asm-3.3.jar (操作java字节码的类库)
asm-commons-3.3.jar (提供了基于事件的表现形式)
asm-tree-3.3.jar (提供了基于对象的表现形式)
commons-fileupload-1.2.2.jar (Struts文件的上传下载)
commons-io-2.0.1.jar (处理io流的工具)
commons-lang3-3.1.jar (为java.lang包提供扩展)
commons-loggin-1.1.1.jar (Jakarta的通用日志记录包)
freemarker-2.3.19.jar(FreeMarker是一个模板引擎,一个基于模板生成文本输出的通用工具)
javassist-3.11.0.GA.jar (开源Java字节码的类库)
ognl-3.0.5.jar (支持ognl表达式)
strut2-core-2.3.4.jar (struts2的核心包)
xwork-core-2.3.4.jar(xwork核心包)
注:基础jar包可从apps文件夹里的示例项目里找到
三、web.xml
在项目web.xml内的<web-app>标签内添加Struts2过滤器
<filter> <filter-name>Struts2Filter</filter-name> <filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class> </filter> <filter-mapping> <filter-name>Struts2Filter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
四、配置文件struts.xml
<!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN" "http://struts.apache.org/dtds/struts-2.0.dtd" >
<struts>
<!-- bean 标签 用于创建一个JavaBean实例-->
<!-- constant标签 用于Struts2 默认行为标签-->
<!-- 配置web默认编码集,相当于 HttpServletRequest.setChartacterEncoding用法 -->
<constant name="struts.i18n.encoding" value="UTF-8"></constant>
<!-- 默认我们Struts2的请求后缀是.action,也就是说我们不配置该元素,action/do都可以 -->
<constant name="struts.action.extension" value="action,do"></constant>
<!-- 设置浏览器是否缓存静态内容,默认值为true,在开发阶段建议关闭,防止修改后测试不到 -->
<constant name="struts.serve.static.browserCache" value="false"></constant>
<!-- 当struts 配置文件修改后,系统是否自动重新加载该文件,默认为false -->
<constant name="struts.configuration.xml.reload" value="true"></constant>
<!-- 开发模式下使用,这样可以打印出更加详细的错误信息 -->
<constant name="struts.devMode" value="true"></constant>
<!-- 默认视图主题 -->
<constant name="struts.ui.theme" value="simple"></constant>
<!-- include标签 用于引入其他的xml配置文件-->
<include file="struts-default.xml"></include>
<!-- package标签 包标签,用于区分不同的请求文件的标签,比方说:网站前台请求和网站后台请求
package的名字必须是唯一的 package可以扩展 当一个package扩展自另一个package时该package会在本身配置的基础上加入扩展的package的配置父package必须在子package前配置
name:package名称
extends:继承的父package名称
abstract:设置package的属性为抽象的 抽象的package不能定义action 值true:false
namespace:定义package命名空间 该命名空间影响到url的地址,例如此命名空间为/test那么访问是的地址为http://localhost:8080/struts2/test/XX.action
-->
<package name="com.kay.struts2" extends="struts-default" namespace="/test">
<interceptors>
<!-- 定义拦截器 -->
<interceptor name="拦截器名称" class="拦截器类路径"></interceptor>
<interceptor name="logger" class="com.kay.logger"></interceptor>
<!-- 定义拦截器栈 -->
<interceptor-stack name="mystack">
<interceptor-ref name="拦截器名称"></interceptor-ref>
<interceptor-ref name="logger"></interceptor-ref>
</interceptor-stack>
</interceptors>
<!-- 定义默认的拦截器 每个Action都会自动引用
如果Action中引用了其它的拦截器 默认的拦截器将无效 -->
<default-interceptor-ref name="mystack"></default-interceptor-ref>
<!-- 全局results配置 -->
<global-results>
<result name="input">/error.jsp</result>
</global-results>
<!-- Action配置 一个Action可以被多次映射(只要action配置中的name不同)
name:action名称
class: 对应的类的路径
method: 调用Action中的方法名
-->
<action name="hello" class="com.kay.struts2.Action.LoginAction">
<!-- 引用拦截器
name:拦截器名称或拦截器栈名称
-->
<interceptor-ref name="timer"></interceptor-ref>
<!-- 节点配置
name : result名称 和Action中返回的值相同
type : result类型 不写则选用superpackage的type struts-default.xml中的默认为dispatcher
-->
<result name="success" type="dispatcher">/talk.jsp</result>
<!-- 参数设置
name:对应Action中的get/set方法
-->
<param name="url">http://www.ziry.me</param>
</action>
<!--
通配符方式:
Name中第一个*代表CRUD操作的名字,第二个*代表类的名字。所以访问链接地址举例如下:
.../del_User.action将访问到User类的del方法,成功后跳到del_User.jsp页面。补充说明{0}是代表name中所有的*组合。
-->
<action name="*_*" class="me.ziry.{2}Action" method="{1}">
<result name="success">.../{1}_{2}.jsp</result>
</action>
</package>
</struts>五、OGNL表达式
#符号:
#符号的三种用法
1)访问非根对象属性,由于Struts 2中值栈被视为根对象,所以访问其他非根对象时,需要加#前缀。实际上,#相当于ActionContext.getContext();#session.msg表达式相当于ActionContext.getContext().getSession().getAttribute("msg")。
2)用于过滤和投影(projecting)集合,如示例中的persons.{?#this.age>20}。
3) 用来构造Map,例如示例中的#{'foo1':'bar1', 'foo2':'bar2'}2. %符号:
%符号的用途是在标志的属性为字符串类型时,计算OGNL表达式的值。
如下面的代码所示:
<h3>构造Map</h3>
<s:set name="foobar" value="#{'foo1':'bar1', 'foo2':'bar2'}" />
<p>The value of key "foo1" is <s:property value="#foobar['foo1']" /></p>
<p>不使用%:<s:url value="#foobar['foo1']" /></p>
<p>使用%:<s:url value="%{#foobar['foo1']}" /></p>
运行界面如下所示。
he value of key "foo1" is bar1
不使用%:#foobar['foo1']
使用%:bar13. $符号:
$符号主要有两个方面的用途。
1) 在国际化资源文件中,引用OGNL表达式,例如国际化资源文件中的代码:reg.agerange=国际化资源信息:年龄必须在${min}同${max}之间。
2) 在Struts 2框架的配置文件中引用OGNL表达式,例如下面的代码片断所示:
<validators>
<field name="intb">
<field-validator type="int">
<param name="min">10</param>
<param name="max">100</param>
<message>BAction-test校验:数字必须为${min}为${max}之间!</message>
</field-validator>
</field>
</validators>3. 其他用法
1.访问值栈中的action的普通属性:
username = <s:property value="username"/>
2.访问值栈中对象的普通属性(get set方法):
<s:property value="user.age"/> |
<s:property value="user['age']"/> |
<s:property value="user[\"age\"]"/> |
wrong: <%--<s:property value="user[age]"/>--%>
3.访问值栈中对象的普通属性(get set方法):
<s:property value="cat.friend.name"/>
4.访问值栈中对象的普通方法:
<s:property value="password.length()"/>
5.访问值栈中对象的普通方法:
<s:property value="cat.miaomiao()" />
6.访问值栈中action的普通方法:
<s:property value="m()" />
7.访问静态方法:
<s:property value="@com.bjsxt.struts2.ognl.S@s()"/>
8.访问静态属性:
<s:property value="@com.bjsxt.struts2.ognl.S@STR"/>
9.访问Math类的静态方法:
<s:property value="@@max(2,3)" />
10.访问普通类的构造方法:
<s:property value="new com.bjsxt.struts2.ognl.User(8)"/>
11.访问List:
<s:property value="users"/>
12.访问List中某个元素:
<s:property value="users[1]"/>
13.访问List中元素某个属性的集合:
<s:property value="users.{age}"/>
14.访问List中元素某个属性的集合中的特定值:
<s:property value="users.{age}[0]"/> |
<s:property value="users[0].age"/>
15.访问Set:
<s:property value="dogs"/>
16.访问Set中某个元素:
<s:property value="dogs[1]"/>
17.访问Map:
<s:property value="dogMap"/>
18.访问Map中某个元素:
<s:property value="dogMap.dog101"/> |
<s:property value="dogMap['dog101']"/> |
<s:property value="dogMap[\"dog101\"]"/>
19.访问Map中所有的key:
<s:property value="dogMap.keys"/>
20.访问Map中所有的value:
<s:property value="dogMap.values"/>
21.访问容器的大小:
<s:property value="dogMap.size()"/> |
<s:property value="users.size"/>
22.投影(过滤):
<s:property value="users.{?#this.age==1}[0]"/>
23.投影:
<s:property value="users.{^#this.age>1}.{age}"/>
24.投影:
<s:property value="users.{$#this.age>1}.{age}"/>
25.投影:
<s:property value="users.{$#this.age>1}.{age} == null"/>
26.[]:
<s:property value="[0].username"/>六、struts2标签库
<%@ taglib prefix="s" uri="/struts-tags" %> 就能使用struts2.0的标签库 A: <s:a href=""></s:a>-----超链接,类似于html里的<a></a> <s:action name=""></s:action>-----执行一个view里面的一个action <s:actionerror/>-----如果action的errors有值那么显示出来 <s:actionmessage/>-----如果action的message有值那么显示出来 <s:append></s:append>-----添加一个值到list,类似于list.add(); <s:autocompleter></s:autocompleter>-----自动完成<s:combobox>标签的内容,这个是ajax B: <s:bean name=""></s:bean>-----类似于struts1.x中的,JavaBean的值 C: <s:checkbox></s:checkbox>-----复选框 <s:checkboxlist list=""></s:checkboxlist>-----多选框 <s:combobox list=""></s:combobox>-----下拉框 <s:component></s:component>-----图像符号 D: <s:date/>-----获取日期格式 <s:datetimepicker></s:datetimepicker>-----日期输入框 <s:debug></s:debug>-----显示错误信息 <s:div></s:div>-----表示一个块,类似于html的<div></div> <s:doubleselect list="" doubleName="" doubleList=""></s:doubleselect>-----双下拉框 E: <s:if test=""></s:if> <s:elseif test=""></s:elseif> <s:else></s:else>-----这3个标签一起使用,表示条件判断 F: <s:fielderror></s:fielderror>-----显示文件错误信息 <s:file></s:file>-----文件上传 <s:form action=""></s:form>-----获取相应form的值 G: <s:generator separator="" val=""></s:generator>----和<s:iterator>标签一起使用 H: <s:head/>-----在<head></head>里使用,表示头文件结束 <s:hidden></s:hidden>-----隐藏值 I: <s:i18n name=""></s:i18n>-----加载资源包到值堆栈 <s:include value=""></s:include>-----包含一个输出,servlet或jsp页面 <s:inputtransferselect list=""></s:inputtransferselect>-----获取form的一个输入 <s:iterator></s:iterator>-----用于遍历集合 L: <s:label></s:label>-----只读的标签 M: <s:merge></s:merge>-----合并遍历集合出来的值 O: <s:optgroup></s:optgroup>-----获取标签组 <s:optiontransferselect doubleList="" list="" doubleName=""></s:optiontransferselect>-----左右选择框 P: <s:param></s:param>-----为其他标签提供参数 <s:password></s:password>-----密码输入框 <s:property/>-----得到'value'的属性 <s:push value=""></s:push>-----value的值push到栈中,从而使property标签的能够获取value的属性 R: <s:radio list=""></s:radio>-----单选按钮 <s:reset></s:reset>-----重置按钮 S: <s:select list=""></s:select>-----单选框 <s:set name=""></s:set>-----赋予变量一个特定范围内的值 <s:sort comparator=""></s:sort>-----通过属性给list分类 <s:submit></s:submit>-----提交按钮 <s:subset></s:subset>-----为遍历集合输出子集 T: <s:tabbedPanel id=""></s:tabbedPanel>-----表格框 <s:table></s:table>-----表格 <s:text name=""></s:text>-----I18n文本信息 <s:textarea></s:textarea>-----文本域输入框 <s:textfield></s:textfield>-----文本输入框 <s:token></s:token>-----拦截器 <s:tree></s:tree>-----树 <s:treenode label=""></s:treenode>-----树的结构 U: <s:updownselect list=""></s:updownselect>-----多选择框 <s:url></s:url>-----创建url
七、在Action获取Scope对象
引言:在前面的Action操作中,关键就是Action中的exectue方法,但是此方法并没有request、session、application等对象作为参数,自然就不能利用这些对象来操作。下面我们建立struts2scope项目,并用四种方式来获取这些对象:
方式一、与Servlet解耦合的非IOC方式
获取的scope对象与容器无关,通过ActionContext获取。
LoginAction代码如下:
package com.asm;
public class LoginAction extends ActionSupport {
private String username;
ActionContext context;
Map request;
Map session;
Map application;
public String execute() throws Exception {
context=ActionContext.getContext();
request=(Map) context.get("request");
session=context.getSession();
application=context.getApplication();
request.put("req", "requst属性");
session.put("ses", "sesion属性");
application.put("app", "application属性");
return SUCCESS;
}
...省略username的get/set方法
}
struts.xml配置如下:
<struts>
<package name="scope" extends="struts-default">
<action name="login" class="com.asm.LoginAction">
<result>/loginSuc.jsp</result>
</action>
</package>
</struts>
login.jsp内容如下:
<form action="<%=request.getContextPath() %>/login.action">
用户名:<input type="text" name="username"><br>
<input type="submit" value="login">
</form>
loginSuc.jsp的主要内容如下:
${requestScope.req}
${sessionScope.ses}
${applicationScope.app}
<h4>以下使用scope.getAttribute的形式来接受</h4>
request: <%=request.getAttribute("req") %><br>
session: <%=session.getAttribute("ses") %><br>
application:<%=application.getAttribute("app") %><br>
分析:通过ActionContext的getContext静态方法得到ActionContext对象,然后ActionContext对象调用get方法来获取一个存储在request范围中的对象。我们使用el或通过request.getAttribute这样的方式均可以获取对象值,这说明了这些Map request对象实际是存储在request范围内的对象。
方式二、与Servlet解耦合的IOC方式
我们建立Login2Action,主要代码如下:
package com.asm;
public class Login2Action extends ActionSupport implements RequestAware,SessionAware,ApplicationAware {
private String username;
Map request;
Map session;
Map application;
public String execute() throws Exception {
request.put("req", "requst属性");
session.put("ses", "sesion属性");
application.put("app", "application属性");
return SUCCESS;
}
public void setRequest(Map<String, Object> request) {
this.request=request;
}
public void setSession(Map<String, Object> session) {
this.session=session;
}
public void setApplication(Map<String, Object> application) {
this.application=application;
}
...省略username的get/set方法
}
注册此Action的name为login2,随后修改登录提交为.../login2.action。便可以发布测试。说明:此方法其实和方式一很相似,只是在方式一中我们需要手动的为Map request赋值,但是在方式二中它是通过实现接口,在重写接口中的方法中完成对Map requset的赋值,所以称之IOC方式。借助此例,略谈下依赖注入与控制反转:所谓依赖注入就是一个对象自己本身的初始化是依赖其它对象。比如这里Map request这些对象会依赖struts2来给其初始化,称为依赖注入,而依赖注入的就表示,这些对象的控制权不再由此类本身掌握,而是交给了别的对象,即是控制权反转了。 强调:方式二是开发中主要用的方式,应重点掌握
方式三、与Servlet耦合的非IOC方式
建立Login3Action,代码如下:
package com.asm;
public class Login3Action extends ActionSupport {
private String username;
HttpServletRequest request;
HttpSession session;
ServletContext application;
public String execute() throws Exception {
request = ServletActionContext.getRequest();
session = request.getSession();
application = ServletActionContext.getServletContext();
request.setAttribute("req", "requst属性");
session.setAttribute("ses", "sesion属性");
application.setAttribute("app", "application属性");
return SUCCESS;
}
...省略username的get/set方法。
}
此方法获取的纯粹的Scope对象,它与容器相关,这些Scope对象操作更强。同样只需要注册此Action并修改登录页面便可进行测试。
方式四、与Servlet耦合的IOC方式
建立Login4Action,代码如下:
package com.asm;
public class Login4Action extends ActionSupport implements ServletRequestAware,ServletContextAware{
private String username;
ActionContext context;
HttpServletRequest request;
HttpSession session;
ServletContext application;
public String execute() throws Exception {
context=ActionContext.getContext();
session=request.getSession();
request.setAttribute("req", "requst属性");
session.setAttribute("ses", "sesion属性");
application.setAttribute("app", "application属性");
return SUCCESS;
}
public void setServletRequest(HttpServletRequest request) {
System.out.println("测试:"+request);
this.request=request;
}
public void setServletContext(ServletContext application) {
System.out.println("测试:"+application);
this.application=application;
}
...省略username的get/set方法
}
同样只需要注册此Action并修改登录页面便可发布测试八、struts2注解
1) @ParentPackage 指定父包 2) @Namespace 指定命名空间 3) @Results 一组结果的数组 4) @Result(name="success",location="/msg.jsp") 一个结果的映射 5) @Action(value="login") 指定某个请求处理方法的请求URL。注意,它不能添加在Action类上,要添加到方法上。 6) @ExceptionMappings 一级声明异常的数组 7) @ExceptionMapping 映射一个声明异常
以上只是简略总结,详细学习可参考:
http://wenku.baidu.com/view/8b29fa125f0e7cd184253638
注意:本文归作者所有,未经作者允许,不得转载

