Struts2-part1
作者:禅楼望月(http://www.cnblogs.com/yaoyinglong)
1. Struts2应用的开发步骤:
① 在web.xml中配置核心的Filter来拦截用户的请求。
<web-app>
<!-- 配置Sturts2 -->
<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>*.do</url-pattern>
</filter-mapping>
</web-app>
其中<url-pattern>*.do</url-pattern>表示所有以.do结尾的url都要经过struts2。
②如果需要以POST方式提交请求,则需要定义包含表单数据的JSP页面,如果仅仅以GET方式发送请求,则无需定义JSP页面。
③定义处理请求的Action类。
④配置Action。即指定那个请求对应哪个Action进行处理。
⑤配置处理结果和物理视图资源的之间的对应关系。
⑥编写视图资源。需要借助OGNL表达式。
2. Struts2请求—响应完整流程

3. Struts2配置
3.1. 常量
在Struts2种可以使用Convertion插件来管理Action、结果映射,不过大多数还是使用XML文件来管理Struts2的配置信息。
Struts2默认配置文件为struts.xml,通常放在类加载路径下,也可以改变。Struts2默认会加载类路径下的struts.xml(开发者定义的默认配置文件)、struts-plugin.xml(struts2插件的默认配置文件)、struts-default.xml(Struts2自带的配置文件)文件。
struts2常量有3种配置方式:
①struts.properties文件
②struts.xml文件
③web.xml文件
如在struts.xml中定义常量:
<struts>
<!-- 通过 constant元素 配置Struts2常量-->
<constant name="struts.custom.il8n.resources" value="mess"/>
</struts>
在web.xml文件中定义常量:
<filter>
<filter-name>struts2</filter-name>
<filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
<init-param>
<param-name>struts.custom.il8n.resources</param-name>
<param-value>mess</param-value>
</init-param>
</filter>
以初始化参数的形式配置。
推荐使用Struts2.xml文件配置常量。
Struts2框架搜索Struts2常量的顺序:
①struts-default.xml:该文件在struts2-core-2.1.2.jar文件中。
②struts-plugin.xml:该文件保存在struts2-Xxx-2.1.2.jar等Struts2插件JAR文件中。
③struts.xml:该文件是web应用默认的Struts2配置文件。
④struts.properties.
⑤web.xml
顺序在后面的常量会覆盖顺序在前面的文件中的同名常量。
3.2. 分散配置
避免struts.xml文件过大,提高该文件的可读性。可以将struts.xml文件分解为多个配置文件,然后在struts.xml文件中包含其他配置文件即可:
<struts>
<!-- 通过include元素导入其他配置文件 -->
<include file="struts-part1.xml"/>
</struts>
这里的struts-part1.xml文件和struts.xml文件一样,没有任何的特殊之处。
4. Action
和struts1不同,struts2将struts1种的ActionForm和Action合并为Action。该Action只是一个普通的Java类,不需要继承任何接口和父类。只需配置即可使用。就想Hibernate中的domain(POJO)类一样。
4.1. Action接口与ActionSupport
为了开发者设计的Action更加规范,Struts2提供了Action接口:
public interface Action {
/**
* The action execution was successful. Show result
* view to the end user.
*/
public static final String SUCCESS = "success";
/**
* The action execution was successful but do not
* show a view. This is useful for actions that are
* handling the view in another fashion like redirect.
*/
public static final String NONE = "none";
/**
* The action execution was a failure.
* Show an error view, possibly asking the
* user to retry entering data.
*/
public static final String ERROR = "error";
/**
* The action execution require more input
* in order to succeed.
* This result is typically used if a form
* handling action has been executed so as
* to provide defaults for a form. The
* form associated with the handler should be
* shown to the end user.
* <p/>
* This result is also used if the given input
* params are invalid, meaning the user
* should try providing input again.
*/
public static final String INPUT = "input";
/**
* The action could not execute, since the
* user most was not logged in. The login view
* should be shown.
*/
public static final String LOGIN = "login";
/**
* Where the logic of the action is executed.
*
* @return a string representing the logical result of the execution.
* See constants in this interface for a list of standard result values.
* @throws Exception thrown if a system level exception occurs.
* <b>Note:</b> Application level exceptions should be handled by returning
* an error value, such as <code>Action.ERROR</code>.
*/
public String execute() throws Exception;
}
这个5个字符串常量是做为execute方法返回值来使用的。比如:在请求处理成功后,有人喜欢返回welcome,而有人喜欢银success,这样不利于项目同一管理。所以Struts2定义了这5个常量来规范。
为例大大简化开发者开发Action,Struts2提供了ActionSupport类。它是struts2默认的Action处理类(如果我们配置Action时没 有指定class属性,struts2会自动使用ActionSupport类作为Action处理类)。
5. Action访问Servlet API
5.1. ActionContext类
Struts2的Action没有与Servlet API耦合,这是一个很大的改善。但是作为一个Web框架,不访问Servlet API怎么可能?因此Struts2提供了ActionContext类,通过该类Struts2的Action便可以访问Servlet的API了。
ActionContext(com.opensymphony.xwork.ActionContext)是Action执行时的上下文,上下文可以看作是一个容器(其实我们这里的容器就是一个Map而已),它存放放的是Action在执行时需要用到的对象,比如:在使用WebWork时,我们的上下文放有请求的参数(Parameter)、会话(Session)、Servlet上下文(ServletContext)、本地化(Locale)信息等。
在每次执行Action之前都会创建新的ActionContext,ActionContext是线程安全的,也就是说在同一个线程里ActionContext里的属性是唯一的,这样我的Action就可以在多线程中使用。详见这里。
以一个登陆的Action为例:
package com.stbc.web.Action;
import com.opensymphony.xwork2.Action;
import com.opensymphony.xwork2.ActionContext;
public class LoginAction implements Action {
private String userName;
private String psw;
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getPsw() {
return psw;
}
public void setPsw(String psw) {
this.psw = psw;
}
@Override
public String execute() throws Exception {
ActionContext actionContext=ActionContext.getContext();
//通过ActionContext访问application范围的属性值。
Integer counter=(Integer)actionContext.getApplication().get("counter");
if(counter==null){
counter=1;
}else {
counter+=1;
}
actionContext.getApplication().put("counter", counter);
//通过ActionContext设置session属性
actionContext.getSession().put("username", getUserName());
if(getUserName().equals("hello") && getPsw().equals("123")){
//通过ActionContext设置request范围的属性。
actionContext.put("tip", "登陆成功");
return SUCCESS;
}else {
actionContext.put("tip", "登陆失败");
return ERROR;
}
}
}
5.2. Action直接访问Servlet API
Action通过继承如下几个接口便可以通过这些接口来访问Servlet API:
ServletContextAware:实现该接口的Action可以直接访问Web应用的ServletContext实例。
ServletRequestAware:实现该接口的Action可以直接访问用户请求的HttpServletRequest实例。
ServletResponseAware:实现该接口的Action可以直接访问服务器响应的HttpServletResponse实例。
package com.stbc.web.Action;
import javax.servlet.http.HttpServletRequest;
import org.apache.struts2.interceptor.ServletRequestAware;
import com.opensymphony.xwork2.Action;
import com.opensymphony.xwork2.ActionContext;
public class LoginAction implements Action,ServletRequestAware {
private HttpServletRequest request =null;
……
@Override
public void setServletRequest(HttpServletRequest request) {
//这里将HttpServletRequest传给request,其他的使用和Servlet中一样
this.request=request;
}
}
5.3. ServletActionContext
这是一个工具类它是ActionContext的子类,有如下静态方法供调用:

借助ServletActionContext,Action能以更简单的方式来访问Servlet API。该类详见这里。
6. 配置Action
配置Action就是让Struts2知道,那个请求是由那个Action来控制的。
6.1. 包和命名空间
Struts2使用包来组织Action。Action标签必须放在package标签下面。
Package标签的元素如下:
- name:必须,是引用该包的唯一标识;也指定了该Action所处理的请求的URL,相当于Struts1的path。
- extends:可选,表示该包继承其他包,可以继承其他包中的Action定义、拦截器定义等。
- namespace:可选,该包的命名空间
- abstract:可选,指该包是否是一个抽象包,抽象包中不能包含Action定义。
注意:Struts2的配置文件是从上往下处理的,所以父类应该在子类前面定义。
例:
<struts>
<package name="get" extends="struts-default" namespace="/book">
<!-- 配置一个名为getBooks的Action -->
<action name="getBooks" class="org.crazyit.app.action.GetBooksAction">
<result name="login">/login.jsp</result>
<result name="sucess">/showBook.jsp</result>
</action>
</package>
</struts>
除此之外,Struts2还指定根命名空间:
<package name="get" extends="struts-default" namespace="/">
当某个包指定了命名空间后,该包下所有的Action处理的URL应该是命名空间+Action名,如访问该Action的URL应该是:
http://localhost:8080/webappName/book/getBooks.action
访问的Action的命名空间为根命名空间则把上面的/book去掉即可。
对于上面的URL,Struts2首先会在book命名空间查找名为getBooks或者根命名空间的Action,找到则使用该Action处理用户的请求,否则Struts2会在默认命名空间中查找名为getBooks的Action,找到则使用该Action处理用户的请求,否则Struts2报错。
注意在URL中命名空间只能有一个,即book下面不能再有一个命名空间了。如:http://localhost:8080/webappName/book/sub/getBooks.action,则,Struts2会将当/book/sub成一个命名空间名称来对待。
注意:在action的name属性中不能出现“.”和中划线“-”。
6.2. Action的动态方法调用
这个代替Struts1的分派Action。使用动态调用方法前必须设置Struts2允许动态方法调用:设置struts.enable.DynamicMethodInvocation常量值为true来完成,该值默认为false。
URL为:action的name!action的方法名。如:
public class LoginAction{
public String regedit() throws Exception {
//业务逻辑
return SUCCESS;
}
}
配置action为:
<struts>
<constant name="struts.enable.DynamicMethodInvocation" value="true"/>
<package name="get" extends="struts-default" namespace="/">
<action name="regeditAndLogin" class="com.stbc.web.Action.LoginAction">
<result name="sucess">/welcome.jsp</result>
</action>
</package>
</struts>
则URL为:http://localhost:8080/webappName/regeditAndLogin!regedit
6.3. Action使用通配符
使用通配符可以是一个action处理一系列(一类)的请求。这时在配置<action>元素时,允许在name属性中使用模式字符(即用“*”代表一个或多个字符),接下来可以在class、method属性、result子元素中使用{N}的形式,来代表前面第N个星号(*)所匹配是字符串。如:
public class LoginAction extends ActionSupport{
public String regedit() throws Exception {
//业务逻辑
return SUCCESS;
}
public String Login() throws Exception {
//业务逻辑
return SUCCESS;
}
public String Logout() throws Exception {
//业务逻辑
return SUCCESS;
}
}
配置Action:
<constant name="struts.enable.DynamicMethodInvocation" value="true"/>
<package name="get" extends="struts-default" namespace="/">
<!-- 使用模式字符串定义Action的name,指定以regLog结尾的请求,都可以使用 LoginAction来处理
,method属性使用{1},这个{1}代表进行模式匹配时第一个*所代替的字符串-->
<action name="*regLog" class="com.stbc.web.Action.LoginAction" method="{1}">
<result name="sucess">/welcome.jsp</result>
</action>
</package>
</struts>
这时只要请求是*regLog.action的模式都可以使用该action来处理。如:URL为:http://localhost:8080/webappName/regeditregLog.action时则表示,调用LoginAction的regedit方法。
此外action的class属性也可以使用{N}表达式,含义与method的一样:
<action name="*regLog" class="com.stbc.web.Action.{1}LoginAction">
如果有需要,Struts2完全可以在class属性和method属性使用{N}表达式:
<action name="*_*" class="com.stbc.web.Action.{1}" method="{2}">
<result name="sucess">/{1}welcome.jsp</result>
</action>
如URL:http://localhost:8080/webappName/LoginAction_Login.action,则会调用LoginAction类中的Login方法。
如果只是简单的超链接请求可将action的name属性定义为“*”.
现在的问题是,如果一个URL与多个action匹配怎办?
如果URL与action名能完全匹配则请求由该action处理,否则struts2会寻找能和该URL匹配的第一个action(struts2寻找顺序是由上向下的),并用这个action来处理该请求。
如:有一个URL为abcAction.action与一下3个action都匹配:它们的name为:abcAction、*Action、*,则该url由name为abcAction的action处理。但是如果该struts.xml中没有name为:abcAction的action,只有name为*和*Action的action,并且它们在struts.xml中的配置顺序为:<action name="*"……>、<action name="*Action"……>,则该URL请求由name为*的action处理。Struts2并不觉得name为*Action的action与URL的匹配度高而选用它,Struts2只会由上向下寻找第一个匹配的action,并使用这个action。
因此在配置Action时,应该注意Action的顺序。最好将name为“*”的action放到最后。
6.4. 配置默认Action
当用户的请求找不到对应的Action时,则用默认的Action处理用户的请求。
<struts>
<package name="get" extends="action-default">
<default-action-ref name="someAction"/>
<actoin name="someAction" class="……"></actoin>
</package>
</struts>
注:将Action配置在默认命名空间中就可以让该Action处理所有用户请求,因为默认命名空间的Action可以处理任何命名空间的请求。
6.5. 配置Action的默认处理类
一个Action没有指定class属性,则Struts2默认使用ActionSupport作为该Action的处理类。
Struts2还允许开发人员自己配置自己的默认处理类:
<struts>
<package name="get">
<default-class-ref class="myClass"/>
</package>
</struts>
这样定义之后,没有指定class属性Action,将用myClass来处理。
7. 配置处理结果
Struts2提供了两种结果:
局部结果:
<action name="someAction" class="com.someclass">
<result name="sucess">/welcome.jsp</result>
</action>
全局结果:
<global-results>
<result name="globalResult">/welcome.jsp</result>
</global-results>
7.1. Struts2支持的结果类型
Struts2提供了一系列的结果类型。
- chain结果类型:Action链式处理的结果类型。
- dispatcher结果类型:用于指定使用JSP作为视图的结果类型
- freemarker结果类型:用于执行使用FreeMarker模板作为视图的结果类型
- httpheader结果类型:用于控制特殊的HTTP行为的结果类型
- redirect结果类型:用于直接跳转到其它URL的结果类型
- redirect-action结果类型:用与直接跳转到其它Action的结果类型
- stream结果类型:用于向浏览器返回一个InputStream(一般用于文件下载)
- velocity结果类型:用于指定使用Velocity模板作为视图的结果类型
- xslt结果类型:用于与XML/XSLT整合的结果类型
- plainText结果类型:用于显示某个页面的原始代码的结果类型
它们被定义在struts2-core-2.2.1.jar下的struts-default包下的<result-types>元素内:
<result-types>
<result-type name="chain" class="com.opensymphony.xwork2.ActionChainResult"/>
<result-type name="dispatcher" class="org.apache.struts2.dispatcher.ServletDispatcherResult" default="true"/>
<result-type name="freemarker" class="org.apache.struts2.views.freemarker.FreemarkerResult"/>
<result-type name="httpheader" class="org.apache.struts2.dispatcher.HttpHeaderResult"/>
<result-type name="redirect" class="org.apache.struts2.dispatcher.ServletRedirectResult"/>
<result-type name="redirectAction" class="org.apache.struts2.dispatcher.ServletActionRedirectResult"/>
<result-type name="stream" class="org.apache.struts2.dispatcher.StreamResult"/>
<result-type name="velocity" class="org.apache.struts2.dispatcher.VelocityResult"/>
<result-type name="xslt" class="org.apache.struts2.views.xslt.XSLTResult"/>
<result-type name="plainText" class="org.apache.struts2.dispatcher.PlainTextResult" />
</result-types>
dispatcher与redirect的区别:
dispatcher:表示forward(转发)请求。
redirect:重定向。
使用redirect结果类型的效果是,系统将调用HttpServletRespoe的sendRedirect(String)方法来重定向指定视图资源,这种重定向的效果就是一个请求,因此所有的请求参数、请求属性、Action实例和Action中封装的属性全部丢失。
7.2. PreResultListener
监听器接口,它在Action完成控制处理之后,struts2转入实际的物理视图之前被回调。Action、拦截器可添加PreResultListener监听器:
public class LoginAction extends ActionSupport{
//需要的Field
@Override
public String execute() throws Exception {
ActionInvocation invocation=ActionContext.getContext().getActionInvocation();
invocation.addPreResultListener(new PreResultListener() {
@Override
public void beforeResult(ActionInvocation invocation, String resultCode) {
// TODO 业务逻辑
}
});
return SUCCESS;
}
}
7.3. 配置Struts2的异常处理
可以在Action中使用try……catch来根据不同的异常返回不同的字符串,但是这样做使得异常与代码耦合,一旦要改变异常处理方式,就必须修改Action。
由Action的签名来看:public String execute() throws Exception,它声明了Exception,就说明该方法不必处理任何类型的错误,将所有类型的错误发给struts2即可。然后struts2会根据异常的类型寻找匹配的逻辑视图名,并使用他来处理异常。这样我们只需在struts.xml中配置异常处理即可。
为了使用Struts2的异常处理机制,必须打开struts2的异常映射功能:
<interceptors>
<!-- 执行异常处理的拦截器 -->
<interceptor name="exception" class="……"/>
<!-- Struts2默认的拦截器栈 -->
<interceptor-stack name="defaultStack">
<!-- 引用异常映射拦截器 -->
<interceptor-ref name="exception"/>
</interceptor-stack>
</interceptors>
上述代码来自struts-defaults.xml,在该文件中已经使用拦截器开启了Struts2的异常映射。接下来,我们需要做的只是在struts.xml文件中配置异常及其匹配的处理方式。
public class LoginAction extends ActionSupport implements Action{
//需要的Field
@Override
public String execute() throws Exception {
if(getName().equalsIgnoreCase("孙悟空")){
throw new MyException("自定义异常");
}
if(getName().equalsIgnoreCase("八戒")){
throw new java.sql.SQLException("用户名不能使用八戒");
}
我在struts.xml文件中便可以捕捉了:
<package name="global" extends="struts-default">
<global-results>
<result name="sqlException">/exception.jsp</result>
</global-results>
<global-exception-mappings>
<exception-mapping result="sqlException" exception="java.sql.SQLExcetion"/>
</global-exception-mappings>
</package>
<package name="goUi" extends="struts-default" namespace="/">
<action name="login" class="com.stbc.web.Action.LoginAction">
<!-- 异常映射,exception属性指的是所映射异常类型;result属性值的是当发生该 类型的异常是转入那个result标签锁映射的页面-->
<exception-mapping result="goMyExceptionHandle" exception="com.stbc.domain.MyException"/>
<result name="goMyExceptionHandle">/myExceptionHandler.jsp</result>
<result name="success">/welcome.jsp</result>
<result name="error">/error.jsp</result>
</action>
</package>
如上述代码 显示:根据<exception-mapping 标签出现的位置不同,可分为全局异常映射(<global-exception-mapping> 标签的子元素)和局部异常映射(<action 标签的子元素)。
Struts2-part1的更多相关文章
- Struts2 学习笔记 10 Result部分 part1
1.关于Result我们首先来学习一下结果类型 result type. 先来看struts.xml. struts.xml <?xml version="1.0" enco ...
- Struts2 学习笔记19 类型转换 Part1
现在来说一说类型转换,提到类型转换其实我们之前早已经用过了,在url传递参数的时候,我们传递过来的参数其实都是String类型的,在显示的时候都自动转换了,像这种简单的转换很好理解,我们要说的是,转换 ...
- Struts2 学习笔记15 Struts标签 part1
来说一下Struts标签,之前我们也很多地方用到了,还是来总结一下. 首先是property标签. <li>property:<s:property value="user ...
- Linux平台 Oracle 10gR2(10.2.0.5)RAC安装 Part1:准备工作
Linux平台 Oracle 10gR2(10.2.0.5)RAC安装 Part1:准备工作 环境:OEL 5.7 + Oracle 10.2.0.5 RAC 1.实施前准备工作 1.1 服务器安装操 ...
- 为什么做java的web开发我们会使用struts2,springMVC和spring这样的框架?
今年我一直在思考web开发里的前后端分离的问题,到了现在也颇有点心得了,随着这个问题的深入,再加以现在公司很多web项目的控制层的技术框架由struts2迁移到springMVC,我突然有了一个新的疑 ...
- 菜鸟学Struts2——Interceptors
昨天学习Struts2的Convention plugin,今天利用Convention plugin进行Interceptor学习,虽然是使用Convention plugin进行零配置开发,这只是 ...
- 菜鸟学Struts2——零配置(Convention )
又是周末,继续Struts2的学习,之前学习了,Struts的原理,Actions以及Results,今天对对Struts的Convention Plugin进行学习,如下图: Struts Conv ...
- 菜鸟学Struts2——Results
在对Struts2的Action学习之后,对Struts2的Result进行学习.主要对Struts2文档Guides中的Results分支进行学习,如下图: 1.Result Types(Resul ...
- 菜鸟学Struts2——Actions
在对Struts2的工作原理学习之后,对Struts2的Action进行学习.主要对Struts2文档Guides中的Action分支进行学习,如下图: 1.Model Driven(模型驱动) St ...
- 菜鸟学Struts2——Struts工作原理
在完成Struts2的HelloWorld后,对Struts2的工作原理进行学习.Struts2框架可以按照模块来划分为Servlet Filters,Struts核心模块,拦截器和用户实现部分,其中 ...
随机推荐
- oracle约束约束状态和设计习惯
oracle约束状态有几个项目,会让人迷惑,分别是: enable/disable--是否启用/禁用 validate/invalidate--确认/不确认 deferrable/not deferr ...
- vue js 保留小数
toFixed(number,fractionDigits ){ //number 保留小数数 //fractionDigits 保留小数位数 var times = Math.pow(10, fra ...
- 判断不同浏览器,加载不同的css和js文件
在低版本的IE中,条件注释还有效果,但是在ie9,10,11浏览器中,条件注释不起作用. 在网上找了个校验ie的方法. function isIE(){ if (window.ActiveXObje ...
- python应用:爬虫实例(静态网页)
爬取起点中文网某本小说实例: # -*-coding:utf8-*- import requests import urllib import urllib2 from bs4 import Beau ...
- ruby require的使用
引用单个文件 例: 引用当前rb同目录下的file_to_require.rb先介绍3种方法 require File.join(__FILE__, '../file_to_require') req ...
- 【Hadoop】配置环境-伪分布式
目录 1.Linux设置静态IP地址 2.修改主机名和映射文件 3.SSH免密码配置 4.Linux系统JDK的安装和配置 5.Hadoop伪分布式配置和测试 1.Linux设置静态IP地址 1.在L ...
- Python自动化运维——IP地址处理模块
Infi-chu: http://www.cnblogs.com/Infi-chu/ 模块:IPy 功能:辅助我们高效的完成IP的规划工作 安装: wget https://pypi.python.o ...
- Android: Requesting root access in your app
package com.certusnet.videomonitor; import java.util.List; import java.io.IOException; import java.i ...
- iOS下原生与JS交互(总结)
iOS开发免不了要与UIWebView打交道,然后就要涉及到JS与原生OC交互,今天总结一下JS与原生OC交互的两种方式. JS调用原生OC篇(我自己用的方式二,简单方便) 方式一 第一种方式是用JS ...
- 步骤:asp.net core中使用identifyserver4颁发令牌
使用IdentityServer4颁发令牌基本步骤如下: 在 Startup.Configure 方法调用 app.UseIdentityServer ,添加IdentityServer4到应用的 H ...