首先进入struct官网,下载资料。这里写链接内容
添加相应的jar包到项目工程下的lib目录:
在这里添加jar包,你也可以去Struts官网,它提供了最核心的jar包,下载之后导入即可,最基本的功能都包含了,以后需要什么,在添加即可。
我们都知道用户的请求,被Struct框架过滤,之后交由action,请求栏的地址也变成xxxx.action。
http://localhost:8889/Struct/xxx.action
在web.xml
<filter>
<filter-name>strutfilter-name>
<filter-class>org.apache.struts2.dispatcher.filter.StrutsPrepareAndExecuteFilterfilter-class>//这个需要基于Struts版本的变化,我的是2.5,所以和之前的不是一样。
filter>
<filter-mapping>
<filter-name>strutsfilter-name>
<url-pattern>/*url-pattern>//过滤整个应用的所有请求
filter-mapping>
//这句话必须,否则标签不能自动补全,很麻烦的
<struts>
<constant name="struts.custom.i18n.resources" value="mess">constant>
<constant name="struts.i18n.encoding" value="GBK">constant>
<package name="default" extends="struts-default">
<action name="LoginAction" class="com.example.test.action.LoginAction" >
<result name=""success"">/scuess.jspresult>
<result name ="error">/error.jspresult>
action>
package>
struts>
虽然Struts 2 提供了Convention 插件来管理Action、结果映射,但对于大部分实际开发来说,通常还是会考虑使用XML 文件来管理Struts 2 的配置信息。
Struts 2 的默认配置文件名为struts.xml,该文件应该放在Web应用的类加载路径下,通常就是放
在WEB-INF/classes 路径下,所以你放到src,编译之后会自动到WEB-INF/classes 路径下。
配置处理结果和物理视图资源之间的对应关系
当Action 处理用户请求结束后,通常会返回一个处理结果(通常使用简单的字符串就可以了),我们可以认为该名称是逻辑视图名,这个逻辑视图名需要和指定物理视图资源关联才有价值。所以我们还需要配置处理结果之间的对应关系。
写好之后,一定要struts.xml命名正确,而且要将该文件放在src,以便编译之后到WEB-INF/classes下。
package com.example.test.action;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionSupport;
public class LoginAction extends ActionSupport {
private String username;
private String userpass;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getUserpass() {
return userpass;
}
public void setUserpass(String userpass) {
this.userpass = userpass;
}
@Override
public String execute() throws Exception {
// TODO Auto-generated method stub
System.out.println("ssadasdas");
if(getUsername().equals("laoqiang")&&getUserpass().equals("123")){
ActionContext.getContext().getSession().put("user", getUsername());
return SUCCESS;
}
else{
return ERROR;
}
}
}
Jsp
"LoginAction">
"username" key="username"/>
"userpass" key="userpass"/>
"login"/>
首先编写的Action类必须继承于ActionSupport,Struts1.0 要求处理业务逻辑,必须在execute方法中,而Struts 2.0则可以在任何方法中。
Action 并未接收到用户请求啊,它怎么能处理用户请求呢?MVC 框架的底层机制是: 核心Servlet 或Filter接收到用户求后,通常会对用户请求进行简单预处理,例如解析、封装参数等,然后通过反射来创建Action 实例,并调用Action的指定方法(Struts 1通常是execute,Struts 2 可以是任意方法) 来处理用户请求。
这里又产生了一个问题:
当Servlet 或Filter 拦截用户请求后,它如何知道创建哪个Action 的实例呢?
有两种解决方案:
StrutsPrepareAndExecutei 和XxxAction 共同构成了Struts 2 的控制器,常常把StrutsPrepareAndExecuteFi 称为核心控制器,把XxxAction 称为业务控制器。
业务控制器XxxAction 通常并不与物理视图关联,这种做法提供了很好的而该处理结果与怎样的视图关联,依然由解耦。业务控制器只负责返回处理结果,StrutsPrepareAndExecuteFit 来决定。这样做的好处是:如果有一天需要将某个视图名映射到不同视图资源,这就无须修改XxxAction 的代码,而是只需修改配置文件即可。
struts.i18n.encoding: 指定Web 应用的默认编码集。该常量对于处理中文请求参数非常有用,对于获取中文请求参数值,应该将该常量值设置为GBK 或者GB2312。该常量的默认值为UTF-8。当设置该参数为GBK 时,相当于执行了HttpServletRequest 的setCharacterEncoding(“GBK”)方法。
struts.papper.class指定将HTTP 请求映射到指定Action 的映射器,Struts 2 提供了默认struts.mapper.class:的映射器:org.apache.struts2.dpcperefi 默认的映射器根据请求的前缀与Action 的name 常量完成映射。
struts.action.extenso 该常量指定需要Struts 2 处理的请求后缀,该常量的默认值是action,即所有匹配*.action 的请求都由Struts 2 处理。如果用户需要指定多个请求后缀,则多个后缀之间以英文逗号(,) 隔开。
struts.custom.properties 该常量指定Struts 2 应用加载用户自定义的常量文件,该自定义常量文件指定的常量不会覆盖struts.properties 文件中指定的常量。如果需要加载多个自定义常量文件,则多个自定义常量文件的文件名以英文逗号(,) 隔开。
总之,struts常量配置很多,现在一下子也说不清,用到哪就在记吧。
随着工程量的变大,struts.xml会变得很臃肿,我们可以采用多个struts.xml管理,最终全部汇总到struts.xml中。
<include file="struts1.xml ">include>
Struts2 通常直接使用Action 来封装HTTP 请求参数,因此,Action 类里还应该包含与请求参数对应的属性,并且为这些属性提供对应的setter 和getter 方法。
Action 类里的属性,不仅可用于封装请求参数,还可用于封装处理结果。直接定义一个字段,在jsp输出它的值,就ok。
系统不会严格区分Action 里哪个属性是用于封装请求参数的属性,哪个属性是封装处理结果的属性。对系统而言,封装请求参数的属性和封装处理结果的属性是完全平等的。如果用户的HTTP 请求里包含了名为tip 的请求参数,则系统会调用Action 类的void setTip(String tip)方法,通过这种方式,名为tip 的请求参数就可以传给Action 实例; 如果Action 类里没有包含对应的方法,则名为tip 的请求参数无法传入该Action。同样,在JSP 页面中输出Action 属性时,它也不会区分该属性是用于封装请求参数的属性,还是用于封装处理结果的属性。因此,使用Struts 2 的标签既可以输出Action 的处理结果,也可以输出HTTP。
Struts 2 提供了一个ActionContext 类,Struts 2 的Action 可以通过该类来访问Servlet API。
ActionContext 类中包含的几个常用方法。
实现上述的三个接口,都需要重写相应的方法set方法,并提供属性。
private HttpServletResponse re;//举其中一个例子
@Override
public void setServletResponse(HttpServletResponse arg0) {
// TODO Auto-generated method stub
re = arg0;
}
必须指出的是,虽然可以在Action 类中获取HttpServletResponse,但如果希望通过HttpServletResponse 来生成服务器响应是不可能的,因为Action 只是业务控制器。即如果在Action 中书写如下代码:
//用于在Servlet 中直接生成响应的代码
response.getWriter ().println (“Hello World”) ;
则在标准Servlet 中会生成对客户端的响应,但在Struts 2 的Action 中没有任何实际意义。
该工具类中提供一些静态方法以便使用,其实和之前使用没啥区别,换了个马甲,我还认识你。
static PageContext getPageContext() :取得Web 应用的PageContext 对象。
static HttpServletRequest getRequest():取得Web 应用的HttpServletRequest 对象。
static HttpServletResponse getResponse(): 取得Web 应用的HttpServletResponse 对象。
static ServletContext getServletContext() :取得Web 应用的ServletContext 对象。
我们如何在一个action处理多个控制处理逻辑。
可以采用DMI (Dynamic Method Invocation,动态方法调用) 来处理这种请求。动态方法调用是指表单元素的action 并不是直接等于某个Action 的名字,而是以如下形式来指定表单的action属性。其中ActionName 指定提交到哪个Action,而methodName 指定提交到指定方法–>
action="ActionName !methodName"
var form;
function register1(){
form = document.forms[0];
form.action = "LoginAction!register";
}
function login(){
form = document.forms[0];
form.action = "LoginAction!execute";
}
需要注意:
开启系统的动态方法调使用动态方法调用前必须设置Struts2 允许动态方法调用。设置该常量的值为用是通过设置struts.enable.DynamicMethodInvocation 常量完成的,true,将开启动态方法调用; 否则将关闭动态方法调用。
代表一个或多个在配置
name="*Action" class="com.example.test.action.LoginAction" method="{1}" >
<result name="success">/scuess.jspresult>
<result name ="error">/error.jspresult>
register1
上面的元素不是定义了一个普通Action,只要用户请求的URL 是Action.action 的模式,都可使用该Action 来处理。配置该action元素时,还指定method 属性(method 属性用于指定处理用户请求的方法),但该method 属性使用了属性值中第一个的值。例如,该表达式的值就是name如果用户请求的URL 为个表达式{1},
loginAction.action,则调用lee.LoginRegistAction 类的login 方法; 如果请求URL 为registAction.action,
则调用lee.LoginRegistAction 类的regist 方法。
var form;
function register1(){
form = document.forms[0];
form.action = "register1Action";
}
function login(){
form = document.forms[0];
form.action = "executeAction";
}
该类方法,版本在2.5的时候会出现问题,需要在配置的时候action添加一个标签:
<allowed-methods>register1allowed-methods>
没有该标签,自定义处理逻辑的方法无法执行,需要注意一下。
实际上,Struts 2 不仅允许在class 属性、name 属性中使用表达式,还可以在
<action name="*"
< !-- 使用表达式定义Result-->
<result>/{ 1}.jspresult>
action>
因为除非请求的URL 与Action 的name 属性绝对相同,则一定由该Action处理,否则将按先后顺序来决定由哪个Action 来处理用户请求。因此,我们应该将name=”*”的Action 配置在最后,否则Struts 2 将使用该Action 来处理所有希望使用模式匹配的请求。
<default-action-ref name="defaultAction">default-action-ref>
"defaultAction" class="xxxxxxxx">
开发者可以自己编写默认action处理类,也可以直接使用Struts提供的。
<default-class-ref class="com.opensymphony.xwork2.ActionSupport">default-class-ref>
Action 只是Struts2 控制器的一部分,所以它不能直接生成对浏览者的响应。Action 只负责处理请求,负责生成响应的视图组件,通常就是JSP 页面,而Action 会为JSP 页面提供显示的数据。当Action处理用户请求结束后,控制器应该使用哪个视图资源生成响应呢? 这就必须使用
配置
name="*Action" class="com.example.test.action.LoginAction" >
<result name="success">/${filename}.jspresult>
private String filename;
public String getFilename() {
return filename;
}
public void setFilename(String filename) {
this.filename = filename;
}
@Override
public String execute() throws Exception {
// TODO Auto-generated method stub
return SUCCESS;
}
<s:form action="LoginAction">
<s:textfield name="filename" key="filename"/>
<s:submit key="login"/>
s:form>
以上的功能就可以去实现通过你输入的值,跳转到不同的Jsp页面,这种方式也是比较灵活。
在action下,可以有多个结果。
result下param可以最常用携带参数:
因为此处指定的参数将由结果解析器负责处理,不同类型的结果解析器所需要的参数是不同的。
首先先让我们看看result的type值,有如下的几种:
- dispatcher 默认的类型,一般用于跳转到jsp页面。(这种是基于转发)
<result name="success" type="dispatcher" >
<param name="location">/scuess.jspparam>//转发的真正的视图
result>
<result name ="success" type="redirect">
name="location">/error.jsp
result>
<result name ="success" type="redirectAction">
<param name="actionName">sssparam>
<param name="namespace">/param>
result>
actionName:该参数指定重定向的Action 名。
namespace :该参数指定需要重定向的Action 所在的命名空间。
注意哦:重定向会生成新的请求,之前的参数什么的,都会丢失,地址栏地址不在原先那个action。
<result name ="success" type="plainText">
name="location">/error.jsp
result>
json
其实全局结果,就是我定义了几个结果,如果你没有,就使用我的,如果你有,还用你自己的。
<global-results>
<result name="success">/error.jspresult>
global-results>
上面的配置片段配置了一个Action,但在该Action 内没有配置任何的结果但这不会影响系统的运转,因为提供了一个名为success 的全局结果,而这个全局结果的作用范围对所有的Action 都有效。
如果一个Action 里包含了与全局结果里同名的结果,则Action 里的局部Result 会覆盖全局Result.也就是说,当Action 处理用户请求结束后,会首先在本Action 里的局部结果里搜索逻辑视图对应的结果,只有在Action 里的局部结果里找不到逻辑视图对应的结果,才会到全局结果里搜索。
PreResultListener 是- 一个监听器接口,它可以在Action 完成控制处理之后,系统转入实际的物理视图之间被回调。Struts 2 应用可由Action、拦截器添加PreResultListener 监听器,添加PreResultListener 监听器通过ActionInvocation 的addPreResultListener()方法完成。一旦为Action 添加了PreResultListener 监听器,该监听器就可以在应用转入实际物理视图之前回调该监听器的beforeResult0方法;一旦为拦截器添加了PreResultListener 监听器,该监听器会对该拦截器所拦截的所有Action 都起作用。
ActionContext.getContext().getActionInvocation().addPreResultListener(new PreResultListener() {
@Override
//String参数是视图名
public void beforeResult(ActionInvocation arg0, String arg1) {
// TODO Auto-generated method stub
System.out.println("我是视图前的");
}
});
对Struts框架的异常,我们可以在execute中进行处理,但是这样的话造成了大量的try…..catch…在execute方法中,很显然这样的处理方式是不好的。而Struts给我们提供的是声明式的方法管理异常。
通过上面这样图,我们发现Struts对异常的处理,有点视图名和结果集之间的关系。
Struts 2 的异常处理机制是通过在struts.xml 文件中配置