struts2.0(一)

        • Struts2.0 action地址转化
        • 配置Struts的核心过滤器
        • 创建struts.xml
        • 编写Action
        • Struts流程
        • Struct常量配置
        • struts.xml模块化
        • Struts的Action类
        • Action访问ServletAPI
        • Action直接访问Servlet API
        • 使用ServletActionContext访问Servlet API
        • Struts2.0的动态方法
          • 采用动态方法
          • 通配符方法
        • Struts2的通配符
          • 通配符优先原则
        • Struts2的默认Action
          • Action默认处理类
        • 配置处理结果
          • 配置处理结果
          • 处理结果类型
        • PreResultListener
        • Struts的异常处理
          • Struts异常处理机制
          • 申明式异常捕捉

首先进入struct官网,下载资料。这里写链接内容

添加相应的jar包到项目工程下的lib目录:

在这里添加jar包,你也可以去Struts官网,它提供了最核心的jar包,下载之后导入即可,最基本的功能都包含了,以后需要什么,在添加即可。

Struts2.0 action地址转化

我们都知道用户的请求,被Struct框架过滤,之后交由action,请求栏的地址也变成xxxx.action。

http://localhost:8889/Struct/xxx.action

配置Struts的核心过滤器

在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.xml


//这句话必须,否则标签不能自动补全,很麻烦的
<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下。

编写Action

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 的实例呢?

有两种解决方案:

  • 利用配置文件: 例如,我们可以配置login.action 对应使用LoginAction 类。这就可 以让MVC
    框架知道创建哪个Action 的实例了。
  • 利用约定: 这种用法可能是受Rails 框架的启发,例如,我们可以约定xxx.action 总是对应XxxAction 类。如 果核心控 制器 收到registaction 请求后,将会调用 RegistAction类来处理用户请求,这一点在本书所介绍的Sturts 2 版本中已有对应 的实现,就是它提供的Convention (约定) 插件。

Struts流程

struts2.0(一)_第1张图片

StrutsPrepareAndExecutei 和XxxAction 共同构成了Struts 2 的控制器,常常把StrutsPrepareAndExecuteFi 称为核心控制器,把XxxAction 称为业务控制器。

业务控制器XxxAction 通常并不与物理视图关联,这种做法提供了很好的而该处理结果与怎样的视图关联,依然由解耦。业务控制器只负责返回处理结果,StrutsPrepareAndExecuteFit 来决定。这样做的好处是:如果有一天需要将某个视图名映射到不同视图资源,这就无须修改XxxAction 的代码,而是只需修改配置文件即可。

Struct常量配置

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管理,最终全部汇总到struts.xml中。

<include file="struts1.xml ">include>

Struts的Action类

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。

Action访问ServletAPI

Struts 2 提供了一个ActionContext 类,Struts 2 的Action 可以通过该类来访问Servlet API。

ActionContext 类中包含的几个常用方法。

  • Object get(Object key): 该方法类似于调用HttpServletRequest的getAttribute(String name) 方法。
  • Map getApplication(): 返回一个Map 对象,该对象模拟了该应用的ServletContext 实例。
  • static ActionContext getContext(): 静态方法,获取系统的ActionContext 实例。
  • Map getParameters() :获取所有的请求参数。类似于调用HttpServletRequest
    对象的getParameterMap() 方法。
  • Map getSession(): 返回- 一个Map 对象,该Map 对象模拟了HttpSession 实例。
  • void setApplication(Map application); 直接传入- 一个Map实例,将该Map 实例里的key-value对转换成application 的属性名、属性值。
  • void setSession(Map session); 直接传入- 一个Map 实例,将该Map 实例里的key-value对转换成session 的属性名、属性值。
  • put(name,value) ,将该value存入当前的ActionContext中。(在表达式中可以使用$(requestScope.name去获取))

Action直接访问Servlet API

  • ServletContextAware: 实现该接口Action 可以直接访问Web 应用的ServletContext 实例。
  • Se rvletRequestAware :实现该接口的Action 可以直接访问用户请求的HttpServletRequest实例。
  • ServletResponseAware :实现该接口Action 可以直接访问服务器响应的。

实现上述的三个接口,都需要重写相应的方法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 中没有任何实际意义。

使用ServletActionContext访问Servlet API

该工具类中提供一些静态方法以便使用,其实和之前使用没啥区别,换了个马甲,我还认识你。

static PageContext getPageContext() :取得Web 应用的PageContext 对象。
static HttpServletRequest getRequest():取得Web 应用的HttpServletRequest 对象。
static HttpServletResponse getResponse(): 取得Web 应用的HttpServletResponse 对象。
static ServletContext getServletContext() :取得Web 应用的ServletContext 对象。

Struts2.0的动态方法

我们如何在一个action处理多个控制处理逻辑。

采用动态方法

可以采用DMI (Dynamic Method Invocation,动态方法调用) 来处理这种请求。动态方法调用是指表单元素的action 并不是直接等于某个Action 的名字,而是以如下形式来指定表单的action属性。其中ActionName 指定提交到哪个Action,而methodName 指定提交到指定方法–>

action="ActionName !methodName"
   
type="text" name="username"/> type="text" name="userpass"/> type="submit" value="注册" onclick="register1()"/> type="submit" value="登录" onclick="login()"/>
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> 

没有该标签,自定义处理逻辑的方法无法执行,需要注意一下。

Struts2的通配符

实际上,Struts 2 不仅允许在class 属性、name 属性中使用表达式,还可以在


<action name="*"
< !-- 使用表达式定义Result-->
<result>/{ 1}.jspresult>
action>
通配符优先原则

因为除非请求的URL 与Action 的name 属性绝对相同,则一定由该Action处理,否则将按先后顺序来决定由哪个Action 来处理用户请求。因此,我们应该将name=”*”的Action 配置在最后,否则Struts 2 将使用该Action 来处理所有希望使用模式匹配的请求。

Struts2的默认Action

<default-action-ref name="defaultAction">default-action-ref>
"defaultAction" class="xxxxxxxx">
Action默认处理类

开发者可以自己编写默认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页面,这种方式也是比较灵活。

处理结果类型
  1. 局部结果

在action下,可以有多个结果。

result下param可以最常用携带参数:

  • location: 该参数指定了该逻辑视图对应的实际视图资源。
  • parse: 该参数指定是否允许在实际视图名字中使用OGNL 表达式,该参数值默认为true。如果设置该参数值为false,
    则不允许在实际视图名中使用表达式。通常无须修改该属性值。

因为此处指定的参数将由结果解析器负责处理,不同类型的结果解析器所需要的参数是不同的。

首先先让我们看看result的type值,有如下的几种:
- dispatcher 默认的类型,一般用于跳转到jsp页面。(这种是基于转发)

<result name="success" type="dispatcher" >
<param name="location">/scuess.jspparam>//转发的真正的视图
result>
  • redirect、redirect-action 前者用于跳转到jsp页面,后者用于跳转到action。(这种是基于重定向)
<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。

  • chain 将请求转发到一个action。
  • stream 一般用于下载文件用。
  • PlainText 普通文本。主要用来显示源资源文件Jsp的源代码
<result name ="success" type="plainText">
name="location">/error.jsp
result>
  • Velocity(Velocity)  用于与Velocity技术的集成 。
  • XSLT(xslt) 用于与XML/XSLT技术的集成。
  • HttpHeader 返回报文头给用户。
  • json

    1. 全局结果

其实全局结果,就是我定义了几个结果,如果你没有,就使用我的,如果你有,还用你自己的。

<global-results>
<result name="success">/error.jspresult>
global-results>

上面的配置片段配置了一个Action,但在该Action 内没有配置任何的结果但这不会影响系统的运转,因为提供了一个名为success 的全局结果,而这个全局结果的作用范围对所有的Action 都有效。

如果一个Action 里包含了与全局结果里同名的结果,则Action 里的局部Result 会覆盖全局Result.也就是说,当Action 处理用户请求结束后,会首先在本Action 里的局部结果里搜索逻辑视图对应的结果,只有在Action 里的局部结果里找不到逻辑视图对应的结果,才会到全局结果里搜索。

PreResultListener

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的异常处理

对Struts框架的异常,我们可以在execute中进行处理,但是这样的话造成了大量的try…..catch…在execute方法中,很显然这样的处理方式是不好的。而Struts给我们提供的是声明式的方法管理异常。

Struts异常处理机制

struts2.0(一)_第2张图片

通过上面这样图,我们发现Struts对异常的处理,有点视图名和结果集之间的关系。

申明式异常捕捉

Struts 2 的异常处理机制是通过在struts.xml 文件中配置

你可能感兴趣的:(struct)