一、简介
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'] 使用%:bar1
3. $符号:
$符号主要有两个方面的用途。 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
注意:本文归作者所有,未经作者允许,不得转载