zoukankan      html  css  js  c++  java
  • struts2框架学习之第一天

    day01

    Struts2概述

    1 什么是框架

    试想一下,人与人之间不同之处多,还是相同之处多呢?当然是相同之处多,不同之处少!人都有头,而且头都在脖子上面!

    软件之间也是相同之处多,不同之处少,框架就是把软件中相同的部分抽取出来而形成的。开发人员在框架的基础之上进行开发,那么只需要给出软件独有部分即可。

    软件相同之处称之为应用组件,不同之处称之为业务组件。框架就是已经完成了应用组件这部分的半成品软件。

    应用框架应该具有如下特征:

    1)       已经知道它们在其它程序上工作的很好;(经过良好的测试)

    2)       它们随时可以在下一个项目中使用;(可重用)

    3)       它们可以被组织的其它团队使用;(可扩展)

    2 什么是Struts2框架

    Struts2是MVC框架!使用Struts2可以更好的实现MVC模式。你可能会说,没有Struts2我们在开发时也使用MVC了。没错,但是你想一想:

    l  JSP传递参数给Servlet时,你是不是需要自己把数据再封装到JavaBean中呢?

    l  你是不是在对表单参数进行校验时很不方便呢?

    l  请求参数都是String类型,你需要亲自把String转换成不同的类型;

    l  如果希望Servlet不再转发到a.jsp,而是b.jsp,这是不是需要修改Servlet源代码呢;

    l  你在完成国际化时,是不是感觉到很麻烦呢?

    这些问题由Struts2来帮你处理吧!

    我们已经知道,Struts2是MVC框架,而MVC和Java三层模式又使我们的Java软件分为:页面、控制层、业务层,以及数据层,而Struts2就是处于页面和控制层的框架。

    Struts2、Struts1、JSF、SpringMVC都是MVC框架!

    3 Struts2核心功能

    Struts1是Apache的开源免费框架,也是最早的MVC框架,当时可以说风靡全球!Struts1拥有大量的客户群但是Struts1有自己的缺陷,导致无法再进一步升级!最终Apache决定与WebWork框架合作,即使用WebWork的技术,使用Apache的名字,生成一个新框架,即Struts2!

    所以Struts2基本上与Struts1没有任何关系,Struts2就是一个新的框架,它的内核是WebWork,如果开发人员对WebWork很了解,那么对学习Struts2很有帮助,但如果开发人员只会Struts1,那么学习Struts2就等于学习一个新的框架一样。

    Struts2的内核是WebWork,而WebWork的内核是Xwork,可以在非WEB环境下使用的框架。它的核心功能也就是Struts2的核心了:

    l  类型转换;

    l  输入校验;

    l  上传下载;

    l  拦截器;

    l  国际化;

      Struts2 = Struts名称 + WebWork + 杂七杂八

    4 Struts2处理流程分析

    在JavaWeb中,页面发出请求,由Servlet来做处理。

     

    在所有的MVC框架(包括Struts2)中,都会使用“前端控制器”来接收所有的请求,它会完成所有请求中“共性”的部分(你可以把“共性”的部分想象成编码转换之类的操作),然后再由“前端控制器”通过框架配置文件把请求“分发”给“业务控制器”。

     

    在Struts2中,前端控制器是一个Filter,名为StrutsPrepareAndExecuteFilter。通常它会过滤所有请求,然后完成共性操作,再通过struts.xml文件把请求分发给Action,Action就是Struts2中的业务控制器,等同与JavaWeb中的Servlet。

    前端控制器会接收所有的请求,然后为所有的请求完成共性的部分,再把请求分发给不同的Action对象来处理请求。Action处理的部分是请求中个性的部分!

    前端控制器是怎么找到Action的呢?前端控制器通过请求的URL,去struts.xml配置文件中查找匹配的Action。

    在Struts2中,前端控制器就是一个Filter。我们都知道Filter需要在web.xml文件中进行配置!既然要让前端控制器接收所有请求,那么这个Filter的<url-pattern>就应该是“/*”。

        <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>/*</url-pattern>

        </filter-mapping>

    5 下载Struts2

    这东西自己回去到http://struts.apache.org/去下载吧。我们已经下载了Sturts2的2.3.x版本,下面我们来了解一下struts2的目录结构。

    l  apps:官方的demo

    l  docs:文档

    l  lib:jar包

    l  src:源代码

    其实在开发中,我们不需要把lib下的所有jar包都导入到项目中。

    去apps目录下找到blank.war,然后使用解压缩软件打开它,把WEB-INFlib目录下的jar包copy出来,我们的项目中只需要这些jar包即可

    6 Hello Struts2
    1. 搭建Struts2项目的开发环境

    创建项目,把Struts2所需jar包导入到项目中。

    这里只需要专稿blank.war中的jar包即可。

     

    创建Struts2的配置文件,在src目录下创建struts.xml文件。

    因为配置文件都需要有一个头,即dtd等信息,所以我们最后去blank.war中找到classes下的struts.xml文件,把内容copy过来,然后再把其中的无用信息删除,只留下根元素<struts>,以及<package>元素。

    <?xml version="1.0" encoding="UTF-8" ?>

    <!DOCTYPE struts PUBLIC

        "-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"

        "http://struts.apache.org/dtds/struts-2.3.dtd">

    <struts>

        <package name="default" namespace="/" extends="struts-default">

        </package>

    </struts>

    1. 功能分析

    在index.jsp页面中访问hello.action(Struts2默认处理扩展名为action的请求)路径,转发到result.jsp页面。其中hello.action对应HelloAction类,再由HelloAction把请求转发到result.jsp页面。

    1. 创建index.jsp和result.jsp

      <body>

    <h1>主页</h1>

    <a href="<c:url value='/hello.action'/>">访问Struts2的Action</a>

      </body>

      <body>

    <h1>结果页面</h1>

      </body>

    1. 在web.xml文件中配置“前端控制器”

    前端控制器类是由Struts2提供的,它是一个Filter,我们只需要在web.xml文件中配置这个Filter即可,其他什么都不用做。

      <filter>

        <filter-name>struts</filter-name>

        <filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>

      </filter>

      <filter-mapping>

        <filter-name>struts</filter-name>

        <url-pattern>/*</url-pattern>

      </filter-mapping>

    1. 编写struts.xml配置文件

    前面我们已经讲过了,前端控制器会去完成“共性”的部分,然后通过struts.xml文件中的配置信息找到被请求的Action,然后把请求分发给这个Action来处理“个性”部分。

    <?xml version="1.0" encoding="UTF-8" ?>

    <!DOCTYPE struts PUBLIC

        "-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"

        "http://struts.apache.org/dtds/struts-2.3.dtd">

     

    <struts>

        <package name="default" namespace="/" extends="struts-default">

            <action name="hello" class="cn.itcast.demo1.action.HelloAction"></action>

        </package>

    </struts>

    在配置文件中,我们在<package>元素中添加一个<action>元素,我们需要指定<action>元素的两个属性:

    l  name:与访问路径对应,在index.jsp中的<a>元素中我们访问的是/hello.action路径,所以在name属性指定的值也要是hello.action,但这里不能带有扩展名,所以name=”hello”;

    l  class:指定用来处理请求的Action类。

    1. 编写请求处理类:HelloAction

    HelloAction不需要去继承或实现什么东西,但Struts要求Action必须要有请求处理方法,请求处理方法的格式为:public String execute(),即没有参数,返回值类型为String。返回逻辑视图,逻辑视图只是一个字符串,它需要有对应的物理视图。

    HelloAction.java

    package cn.itcast.demo1.action;

     

    public class HelloAction {

        public String execute() {

            System.out.println("Hello Sturts2...");

            return "succ ";

        }

    }

    1. 指定结果页面

    execute()方法的返回值可以随意给出,这里给出的返回值为“succ”,我们需要在struts.xml文件中把“succ”与返回的结果页面绑定到一起。

    <struts>

        <package name="default" namespace="/" extends="struts-default">

            <action name="hello" class="cn.itcast.demo1.action.HelloAction">

                <result name="succ">/result.jsp</result>

            </action>

        </package>

    </struts>

     这里定义了一个视图,其中succ是逻辑视图,与execute()方法的返回值相同。/result.jsp是物理视图,即真实的页面。

    OK,现在我们已经完成了这个Hello World项目。请在index.jsp页面中点击链接,查看结果吧。注意查看控制台上是否有输出。

    l  搭建环境:

    • 导包:struts2安装包appslank.warlib下所有包
    • 部署前端控制器:web.xml中配置过滤器:StrtusPrepareAndExecuteFilter
    • Struts2的配置文件:src下创建struts.xml

    l  请求三步

    • 超链接指向Action:要求请求URL的后缀是.action;
    • Action类的请求处理方法签名:public String execute();
    • struts.xml文件中配置请求url和Action的联系:<action name=”xxx” class=””/>;
    7 MyEclipse中配置Struts的DTD

      在使用MyEclipse开发环境时,我们在struts.xml文件中可以使用Alt+/来做补全,这是因为在xml文档中指定的DTD的原因。

    大家也可以看出来,这个dtd只有在连网时才能找到,如果你现在没有网可用,那么这个dtd可能就无法找到,这时你的alt + /可能就会“不听话”了。

    如果你需要在没有连网时也可以找到dtd文档,那么就需要在MyEclipse中进行配置。其实在我们下载的Struts2安装包的struts-2.3.7srccoresrcmain esourcesstruts-2.3.dtd路径下已经存在了这个DTD文档,我们只需要在MyEclipse中导入它即可。

     

    8 MyEclipse中导入Struts2源代码

    导入Struts2的源代码!

    选择一个Struts2中的类,然后点击

    点击Attach Source按钮

    点击External File,选中我们下载的Struts2安装包,然后点击OK按钮即可。

    9 Struts2流程图

     

    现在我们不需要把这张图全面了解了,我们现在只需要知道Struts2中完成请求的“共性”部分的组件是Interceptor(拦截器),它会在每个Action之前执行!

    Struts2中的系列拦截器我们会在后面来讲,今天先不讲,但你要知道,Interceptor就是对Action的增强。它是Struts2的核心部分!

    Struts2的基本配置

    1        Struts2的基本配置文件

    在学习Struts2时,你会感觉到Struts2的配置文件多的很!但其实真正重要的配置文件没有几个,现在对我们来说,只有一个配置文件很重要,它就是struts.xml。

    下面是Struts2配置文件,以优先级由低到高的顺序给出:

    l  default.properties:这个文件在struts-core.jarorg.apache.struts2default.properties位置,它内部是常量的默认值,我们不会去修改它;

    l  struts-default.xml:这个文件在struts-core.jarstruts-default.xml位置,它内部定义了拦截器、结果类型,以及bean。我们也不会去修改它;

    l  struts-plugin.xml:在安装插件时,插件的jar包中需要带有这个文件,我们也不会去修改它;

    struts.xml:这个文件不是默认存在的,而是需要我们自己在src目录下创建的,它是我们通常要编写的配置文件,最为重要!

    struts.properties:这个文件也不是默认存在的,也是需要在src目录下创建的,这个文件中用来配置常量,但是建议大家还是在strtus.xml文件中配置常量,而不是这个文件中,所以它也使用的比较少;

    web.xml:这个文件大家再熟悉不过了,也可以在这个文件中配置常量,但也不建议在这里去配置。但这个文件中配置的常量优先级最高!

    6个配置文件中前3个是配置自带的,我们不会去修改,后3个中2个是不建议去使用的,所以最为重要的就只有struts.xml文件一个。

    这里需要注意,后加载的文件优先级最高,也就是说在web.xml文件中配置的常量优先级最高。

    2        struts.xml入门
    <struts>
    
        <!--
    
        0~N个常量配置
    
        name: 常量名
    
        value: 常量值
    
        -->
    
        <constant name="struts.devMode" value="true" />
    
        <!--
    
        0~N个package
    
        name: 包名随便起,但必须是唯一名称
    
        namespace: 请求URL的前缀,例如当请求路径为/a/b/hello.action时,那么namespace应该为/a/b
    
        extends:指定父包!通常都是指定struts-default这个父包。父包中定义的东西等同于定义在当前包中。
    
         -->
    
        <package name="s1" namespace="/" extends="struts-default">
    
             <!--
    
            默认Action:在找不到请求的Action时,执行的Action。与404的友好页面相同
    
            name:指定<action>元素的name属性值。
    
             -->
    
             <default-action-ref name="error" />
    
            <!--
    
            默认Action处理类:对于<action>元素而言,它的class属性是可选的!
    
            在没有指定class时,执行的Action类为默认Action处理类。
    
            例如:<action name="xxx">时,其class默认为ActionSupport
    
            其实我们不指定<default-class-ref>默认也是ActionSupport,这是因为在
    
            父包struts-default中已经定义过<default-class-ref>元素了。
    
             -->
    
             <default-class-ref class="com.opensymphony.xwork2.ActionSupport" />
    
            <!--
    
            配置Action
    
            name:Action的配置名称,没有后缀.action。与namespace共同定位请求URL
    
            class:请求处理Action类。默认值由<default-class-ref>来指定。
    
            -->
    
            <action name="hello" class="cn.itcast.action.HelloAction">
    
                <!--
    
                结果处理类
    
                name:execute()方法返回的字符串匹配。默认值为success
    
                    内容:物理路径。即真实的页面路径!
    
                -->
    
                <result name="success">/demo1/hello.jsp</result>
    
             </action>
    
             <action name="error">
    
                <result>/error.jsp</result>
    
             </action>
    
        </package>
    
    </struts>

    2.1 <package>元素

    首先说一下struts.xml文件的基本结果,根元素是<struts>,在<struts>元素下可以有多个<package>元素,在<package>元素中可以配置多个<action>元素。

    对于<struts>元素,我们没有什么可说的,它就是struts.xml文件的根元素而已!

    <package>元素中可以存在多个<action>元素,在<package>元素中的配置会作用到它内部的所有<action>中,但你千万不要认为它与Java类中的package cn.itcast有什么关系!!!<package>只是一个XML元素,与Java类没什么关系。

    <package>中不只是可以<action>,还可以包含拦截器的定义,以及结果类型的定义!

    <package>元素有3个重要的属性:

    l  name:这个名字可以随便起,只要与其它<package>的name不相同即可;

    l  namespace:名称空间!通常该值为“/”,如果希望指定namespace也要以“/”开头。它与<action>的name属性共同决定访问路径。例如namespace的值为/admin,某个<action>的name为hello,那么在浏览器中访问这个Action时就需要使用/admin/hello.action来访问;

    l  extends:指定当前包的父包,用来继承父包中的东西。通常我们会去继承struts-default这个包,因为struts-default中定义了很多拦截器,以及结果类型,我们自定义的<package>就不用再去定义,而是直接继承过来。struts-default包在struts-default.xml文件中定义。

    2.2 <action>元素

    <action>元素最为重要的有两个属性:

    l  name:用来指定当前<action>的名字,它与<package>的namespace来共同决定当前Acton的访问路径;

    l  class:用来指定当前<action>的类型。

    <package namespace=”/” …>

      <action name=”foo” …/>

    <package>

    这个action foo的访问路径为:/foo.action;

    <package namespace=”/admin” …>

      <action name=”foo” …/>

    <package>

    这个action foo的访问路径为:/admin/foo.action

    当访问路径为/a/b/c/foo.action时,Struts2会按下面的顺序去查找Action

    l  查询namespace=”/a/b/c”,<actoin name=”foo”>的Action

    <package namespace=”/a/b/c” …>

      <action name=”foo” …/>

    <package>

    l  查询namespace=”/a/b”,<action name=”foo”>的Action

    <package namespace=”/a/b” …>

      <action name=”foo” …/>

    <package>

    l  查询namespace=”/a”,<action name=”foo”>的Action

    <package namespace=”/a” …>

      <action name=”foo” …/>

    <package>

    l  查询namespace=”/”,<action name=”foo”>的Action

    <package namespace=”/” …>

      <action name=”foo” …/>

    <package>

    l  查询namespace=””,<action name=”foo”>的Action

    <package namespace=”” …>

      <action name=”foo” …/>

    <package>

     <package>的namespace的默认值为””,在其它名称空间不存在时,会去””名称空间下去查找Action。

    2.3 <action>默认处理类

    <action>元素的class属性也有默认值:com.opensymphony.xwork2.ActionSupport,也就是说在没有给<action>元素指定class属性时,会执行ActionSupport类的execute()方法。也就是说,ActionSupport就是<action>的默认处理类!!!

    查看ActionSupport源代码可以知道,它的execute()方法返回值为”success”,所以这时你需要为<action>元素添加<result name=”success”>子元素!

    <action name=”hello”>

      <result name=”success”>/index.jsp</result>

    </aciton>

    其实每个<package>元素都可以指定一个<default-class-ref class=”…”/>元素,该元素的class指定的就是<action>的class的默认值。因为我们的<package>没有指定<default-class-ref>元素,所以是从父包sturts-default处继承而来,可以查看struts-default.xml文件中的<default-class-ref>元素的class指定的就是com.opensymphony.xwork2.ActionSupport。

    下面代码中,没有为<action>指定class属性值,但因为指定了Action默认值为HelloAction,所以就会访问HelloAction。

    <struts>

        <package name="b" namespace="/" extends="struts-default">

           <default-class-ref class="cn.itcast.demo1.action.HelloAction" />

            <action name="hello">

                <result name="succ">/result.jsp</result>

            </action>

        </package>

    </struts>

    2.4 默认<action>

    默认<action>需要<default-action-ref name="">来指定,通常用户在访问一个不存在的<action>时会报404,我们可以通过<default-action-ref name="">来指定默认的<action>,这样在用户访问不存在的路径时,就会去访问默认<action>。

    默认<action>是用来代替404页面的!

    <struts>

        <package name="b" namespace="/" extends="struts-default">

            <default-action-ref name="error"></default-action-ref>

            <action name="error">

                <result name="success">/404.jsp</result>

            </action>

        </package>

    </struts>

    注意,默认<action>与<action>默认处理类的区别:

    l  默认<action>:当用户访问一个不存在的路径时,会执行默认<action>;

    l  <action>默认处理类:当<action>没有指定class属性时,执行默认的处理类。

    2.5 <result>元素的name属性默认值

    <result>元素的name属性默认值为success,也就是说:

    <result>/index.jsp</result>

    等同于

    <result name=”success”>/index.jsp</result>

    3 Struts2常量

    Struts2常量就是给Struts2使用的一些参数,以键值对的形式出现。

    1. Struts2常量都配置在哪里?

    Struts2默认常量都是在default.properties中配置的,你可以打开这个文件看看!你会发现常量真的很多,我们不需要去背!

    1. 我们在哪里配置常量

    最佳位置:struts.xml文件中,在struts.xml文件中配置常量需要使用<constant>元素

    <struts>

        <constant name="struts.devMode" value="true" />

        …

    </struts>

    其次是struts.properites文件,你可以在src下创建struts.properites文件,在这里来创建常量,我们已经知道它的优先级高与struts.xml文件。

    最后的位置是web.xml文件中,即给<filter>元素添加<init-param>子元素,通常我们不会在这里配置常量。

    1. 常用常量了解一下:

    l  struts.i18n.encoding=UTF-8:相当于调用request.setCharacterEncoding(“utf-8”),即对POST请求做编码处理,但不包括GET请求;

    l  struts.action.extension=action,,:前端控制器会接收所有请求,但只有action后缀的请求才会分发给Action来处理,这时因为struts.action.extension指定了分发给action的后缀为action。也可以指定多种后缀名,然后用逗号分隔!大家仔细观察,struts.action.extension常量的值是“action,,”,后面有两个逗号,这表示后缀为action的请求,以及没有后缀的请求都会分发给action!如果你在struts.xml文件中指定:<constant name=” struts.action.extension” value=”action”/>,那么无后缀的请求就不会分发给actoin了;

    l  struts.serve.static.browserCache=false:该常量的值为false时,表示让浏览器不缓存,如果为true表示让浏览器缓存,在开发阶段,该常量通常设置为false;

    l  struts.devMode=true:该常量为true时,表示为开发模式,开发模式下Struts2会在修改了配置文件后无需重启Tomcat,而是自动加载,而且还会在出错时在页面提供详细的错误信息。

    4 Struts2配置文件分离

    在项目开发过程中,struts.xml文件的内容会越来越多,这时struts.xml就会变得勿阅读,这时我们希望可以把struts.xml文件分成多个配置文件!

    可以在struts.xml文件中使用<include>元素来包含其他配置文件:

    <struts>

        <include file="struts-part1.xml" />

        <include file="struts-part2.xml" />

        …

    </struts>


    Actoin处理请求

    1        Action的三种书写方式

    我们必须遵守Struts2对Action的要求,Struts2给出三种对Action的书写方法:

    l  无耦合(POJO);

    l  实现Action接口;

    l  继承ActionSupport。

    1.1 无耦合方式(POJO)

    Action可以是一个POJO,即不继承,也不实现类的普通Java类。但是要求Action必须要有一个execute()方法:

    l  访问修饰为public;

    l  返回值为String;

    l  名称为execute;

    l  没有参数的。

    这种方式用的很少,但我们要知道这种方式的存在!

    1.2 实现Action接口

    让我们的Action去实现com.opensymphony.xwork2.Action接口。

    package com.opensymphony.xwork2;

     

    public interface Action {

        public static final String SUCCESS = "success";

        public static final String NONE = "none";

        public static final String ERROR = "error";

        public static final String INPUT = "input";

        public static final String LOGIN = "login";

       

        public String execute() throws Exception;

    }

    这个类只给出一个方法,即execute()方法,这说明在实现Action接口后,如果没有给出execute()方法就会编译出错。这与第一种方式使用POJO不同,如果在使用POJO时没有给出execute()方法,那是不会编译出错的,而是在运行时会报错,说找不到execute()方法。

    Action接口中还提供了5个字符串常量,这5个常量用来作为execute()方法的返回值。这也是开发中最为常见的5种逻辑视图。

    l  SUCCESS:表示成功;

    l  NONE:不跳转,与return null相同;

    l  ERROR:表示出错,对应的物理视图应该是用来显示错误信息的;

    l  INPUT:表示表单数据的输入有错误,对应的物理视图应该是表单页面;

    l  LOGIN:表示访问了受限资源,需要登录后才能访问,对应的物理视图应该是登录页面。

      其实你不使用这些常量也一样,只要把<result>元素配置好即可。当然,这些Action常量地球人都认识,如果你的逻辑视图名称为a,它对应的物理视图为a.jsp,那么谁知道你是在表示什么啊。

      这种方式同样使用的很少,但我们要知道这种方式的存在!

    1.3 继承ActionSupport类

    这是最后一种编写Action的方式,也是我们最后最为常用的方式。让我们的Action类去继承com.opensymphony.xwork2.ActionSupport类。ActionSupport类实现了Action接口,我们的Action需要去覆盖ActionSupport的execute()方法。

    继承ActionSuppot类的好处:

    l  输入校验;

    l  错误信息的设置;

    l  获取国际化信息。

    2 Action的请求处理方法

    上面讲解了三种Action的书写方式,即Struts2如何找到Action类。下面要讲解的是Struts2如何找到Action中请求处理方法。

    2.1 指定请求处理方法名称

    上面我们已经了解到Action的请求处理方法名称为execute,其实这只是默认的请求处理方法的名称。也就是说Struts2允许我们来指定请求方法名称。这需要在<action>元素的method属性中指定请求处理方法的名称。

    当没有指定<action>元素的method属性时,那么请求处理方法名称为execute()。在指定method属性的值时,那么请求处理方法的名称就是method属性的值。

    但要注意,无论请求处理方法的名称是什么,返回值必须是String,而且不能有任何参数。

      <body>

        <a href="<c:url value='/Order_add.action'/>">添加订单</a><br/>

        <a href="<c:url value='/Order_mod.action'/>">修改订单</a><br/>

        <a href="<c:url value='/Order_del.action'/>">删除订单</a><br/>

      </body>

        <package name="s3" namespace="/" extends="struts-default">

            <action name="Order_add" class="cn.itcast.test.action.OrderAction" method="add[崔6] ">

                <result>/index.jsp</result>

            </action>

            <action name="Order_mod" class="cn.itcast.test.action.OrderAction" method="mod[崔7] ">

                <result>/index.jsp</result>

            </action>

            <action name="Order_del" class="cn.itcast.test.action.OrderAction" method="del[崔8] ">

                <result>/index.jsp</result>

            </action>

        </package>

    public class OrderAction extends ActionSupport {

        public String add() {

            System.out.println("add()");

            return SUCCESS;

        }

        public String mod() {

            System.out.println("mod()");

            return SUCCESS;

        }

        public String del() {

            System.out.println("del()");

            return SUCCESS;

        }

    }

    2.2 使用通配符减少<action>的配置

    通过指定<action>元素的method可以减少Action的个数,这样我们可以在一个Action中提供多个请求处理方法。但是,并没有减少<action>元素的配置个数。对每个请求我们都需要配置一个<action>元素。

    下面我们来使用通配符来减少<action>元素的配置。通配符就是“*”,它只能出现在<action>元素的name中。例如:

    <action name=”ABC*” …>

    这说明请求路径只要是以ABC开头,那么都会通过这个<action>。例如请求路径为:

    l  /ABChelllo.action,其中通配符匹配的是hello;

    l  /ABCworld.action,其中通配符匹配的是world;

    我们还可以在<action>元素的其他属性,或子元素中使用通配符匹配的文本,例如{!}表示通配符匹配的文本。

    <action name=”Order_*” class=”cn.itcast.action.OrderAction” method=”{1}”>

    当请求路径为“/Order_add.action”时,通配符匹配的文本就是add,而在method中的{1}表示通配符匹配的文本,即“add”。

    当请求路径为“/Order_mod.action”时,通配符匹配的文本就是mod,而在method中的{1}表示通配符匹配的文本,即“mod”。

    我们来修改2.1中的订单例子,只需要修改struts.xml文件中的配置,其他地方无需修改。

        <package name="s3" namespace="/" extends="struts-default">

            <action name="Order_*" class="cn.itcast.test.action.OrderAction" method="{1}">

                <result>/index.jsp</result>

            </action>

        </package>

    其中在<action>的name属性中可以使用多个通配符,即多个“*”,然后在method或class中可以使用{1}、{2}、…,其中{1}表示第一个通配符配置的文本,{2}表示第二个通配符配置的文本。

    我们再次来修改<action>的配置:

            <action name="*_*" class="cn.itcast.test.action.{1}Action" method="{2}">

                <result>/index.jsp</result>

            </action>

    当请求路径为“/Order_add.action”时,第一个通配符匹配的文本为Order,第二个通配符匹配的文本是add,所以{1}表示Order,而{2}表示add。即class指定的类为OrderAction,而method指定的方法是add方法。

    使用这种配置,我们甚至可以使用一个<action>就OK了!

    当请求路径为“/User_regist.action”时,第一个通配符匹配的文本是User,第二个通配符匹配的文本是regist,那么这就说明请求的是UserAction的regist方法。

    2.3 动态调用请求处理方法

    Struts2还提供了动态调用请求处理方法的方式,这种方式需要在请求路径中使用感叹号(!),然后在感叹号后给出要调用的方法:“/OrderAction!add.action”。这时在<action>元素中无需再指定method属性。

      <body>

        <a href="<c:url value='/OrderAction!add.action'/>">添加订单</a><br/>

        <a href="<c:url value='/OrderAction!mod.action'/>">修改订单</a><br/>

        <a href="<c:url value='/OrderAction!del.action'/>">删除订单</a><br/>

      </body>

            <action name="OrderAction" class="cn.itcast.test.action.OrderAction">

                <result>/index.jsp</result>

            </action>

    public class OrderAction extends ActionSupport {

        public String add() {

            System.out.println("add()");

            return SUCCESS;

        }

        public String mod() {

            System.out.println("mod()");

            return SUCCESS;

        }

        public String del() {

            System.out.println("del()");

            return SUCCESS;

        }

    }

    注意,这种方式需要开启动态请求调用对应的常量,这个常量的默认值可以在default.properties文件中找到:

      也就是说,默认Struts2是开启了动态请求方法调用的。

    Action与Servlet API

    1 Action中3种获取Servlet API方式

    l  ActionContext解耦方式获取Servlet API;

    l  通过感知接口获取Servlet API;

    l  ServletActionContext的静态方法获取Servlet API

    2 ActionContext解耦方式获取Servlet API

    首先需要获取ActionContext对象:ActionContext ac = ActionContext.getContext();

    1. 获取请求参数

    Map<String,Object> params = ac.getParameters();

    其中params中的数据就是请求参数,它等同与request.getParameterMap()。

    需要注意的是,返回的Map中键是字符串,而值其实是String[]类型。下面是获取参数username的值:

    String[] value = (String[])params.get(“username”);

    String username = value[0];

    1. 在request域中存取数据

    ac.put(“aa”, “aa”);//等同与request.setAttribute(“aa”,”aa”)

    String s = (String)ac.get(“aa”);//等同与request.getAttribute(“aa”)

    在页面中可以使用EL表达式来获取这个值:${requestScope.aa}

    1. 在session域中存取数据

    Map<String,Object> sessionMap = ac.getSesson();

    sessionMap.put(“aa”,”aa”);//等同与session.setAttribute(“aa”, “aa”);

    String s = (String)sessionMap.get(“aa”);//等同与session.getAttribute(“aa”)

    在页面中可以使用EL表达式${sessionScope.aa}来获取这个值

    1. 在application域存取数据

    Map<String,Object> appMap = ac.getApplication();

    appMap.put(“aa”,”aa”);//等同与application.setAttribute(“aa”,”aa”);

    String s = (String)appMap.get(“aa”);//等同与application.getAttribute(“aa”)

    在页面中可以使用EL表达式${applicationScope.aa}来获取这个值

      请注意,这种解耦方式只能对三个域对象进行存取数据的操作,如果你想调用request.getContextPath()方法,这是不可能的,也不能application.getRealPath()。如果你不知道使用这些操作,那么使用第一种方式是灰常理想的选择!因为你根本就看不到Servlet API,解耦已经到了最佳境界。

        public String execute() throws Exception {

            ActionContext ac = ActionContext.getContext();

           

            Map<String,Object> paramMap = ac.getParameters();

            String username = ((String[])paramMap.get("username"))[0];

            System.out.println(username);

           

            ac.put("aa", "aa");

            String s = (String) ac.get("aa");

            System.out.println(s);

           

            Map<String,Object> sessionMap = ac.getSession();

            sessionMap.put("aa", "aa");

            s = (String) sessionMap.get("aa");

            System.out.println(s);

           

            Map<String,Object> appMap = ac.getApplication();

            appMap.put("aa", "aa");

            s = (String) appMap.get("aa");

            System.out.println(s);

            return SUCCESS;

        }

    3 通过感知接口获取Servlet API

    Struts2提供了三个感知接口,Actoin可以去实现它们来获取Servlet API。

    l  ServletContextAware – setServletContext(ServletContext context);

    l  ServletRequestAware – setServletRequest(HttpServletRequest req);

    l  ServletResponseAware – setServletResponse(HttpServletResponse res)。

    当Action实现了感知接口后,Struts2会在创建Action对象后,调用感知方法把Servlet API传递给Action。也就是说,在请求处理方法执行之前,已经把Servlet API传递给了Action,所以在请求处理方法中使用Servlet API是没有问题的。

    public class AwareAction extends ActionSupport

            implements ServletContextAware,

            ServletRequestAware, ServletResponseAware {

        private ServletContext context;

        private HttpServletRequest request;

        private HttpServletResponse response;

     

        public void setServletContext(ServletContext context) {

            this.context = context;

        }

        public void setServletRequest(HttpServletRequest request) {

            this.request = request;

        }

        public void setServletResponse(HttpServletResponse response) {

            this.response = response;

        }

    }

      这种方式比较麻烦,所以很少被使用!

    4 ServletActoinContext获取Servlet API

    这种方式比较直接,可以直接通过ServletActionContext类的静态方法获取到Servlet API。当然,这种方式也会与Servlet API耦合在一起。

    HttpServletRequest request = ServletActionContext.getRequest();

    HttpServletResponse response = ServletActionContext.getResponse();

    ServletContext context = ServletActionContext.getServletContext();

      这种方式最为方便。所以也是最为常用的方式,第一种解耦方式也是很好,所以也很常用。

    Action返回值与<result>

    1 全局结果和局部结果

    在<action>中可以配置<result>元素,其中在<package>元素的<global-results>元素中也可以配置<result>。其中<action>中的<result>是局部结果,只有当前<action>自己可以使用,而在<global-results>中配置的<result>是全局结果,可以供当前<package>中所有的<action>使用。

        <package name="test" namespace="/" extends="struts-default">

        <global-results>

            <result name="a">/a.jsp</result>

        </global-results>

            <action name="MyAction1" class="cn.itcast.test.action.MyAction1">

                <result name="success">/my1/index.jsp</result>

            </action>

            <action name="MyAction2" class="cn.itcast.test.action.MyAction2">

                <result name="success">/my2/index.jsp</result>

            </action>

        </package>

      当局部和全局的<result>同名时,局部的<result>优先。

    2 结果类型

    <result>元素的type属性用来指定结果类型!如果没有指定type时,默认为dispatcher,下面介绍4种常用的结果类型:

    l  dispatcher:默认值,表示转发到页面;

    l  chain:表示转发到另一个Action,所以这时<result>元素的内容需要是另一个<action>的名字;

    l  redirect:表示重定向到页面;

    l  redirectAction:表示重定向到另一个Action。

    <result>/index.jsp</result>

    等同于

    <result type=”dispatcher”>/index.jsp</result>

    等同于

    <result type=”dispatcher” name=”success”>/index.jsp</result>

    其实结果类型都是在struts-default.xml文件中定义的。

    <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>

    登录练习

    1 页面

    /user/login.jsp

    /user/succ.jsp

    2 UserAction

    public String login()

    3 struts.xml
    4 需要用到的方法及标签

    ActionSupport方法介绍:

    l  addFieldError(String fieldName,String msg):添加字段错误信息;

    l  addActionError(String msg):添加Action错误信息;

    l  addActionMessage(String msg):添加Action信息。

    标签介绍:

    l  <s:fielderror>:获取字段错误信息;

    l  <s:actionerror>:获取Action错误信息;

    l  <s:actionmessage> :获取Action信息。


    在Struts2中,访问Action时,路径的扩展名默认为action。

    前端控制器过滤所有的请求。

    name属性的值必须与访问路径相同,但要去掉扩展名action。

    返回逻辑视图,逻辑视图只是一个字符串,它需要有对应的物理视图。

    这里定义了一个视图,其中succ是逻辑视图,与execute()方法的返回值相同。/result.jsp是物理视图,即真实的页面。

    请求处理方法名称为add

    请求处理方法名称为mod

    请求处理方法名称为del

  • 相关阅读:
    elasticsearch 中的Multi Match Query
    activiti 流程部署的各种方式
    elasticsearch 嵌套对象之嵌套类型
    elasticsearch Java High Level REST 相关操作封装
    elasticsearch 字段数据类型
    ubuntu 安装 docker
    elasticsearch 通过HTTP RESTful API 操作数据
    facenet 人脸识别(二)——创建人脸库搭建人脸识别系统
    POJ 3093 Margaritas(Kind of wine) on the River Walk (背包方案统计)
    墨卡托投影, GPS 坐标转像素, GPS 坐标转距离
  • 原文地址:https://www.cnblogs.com/xyhero/p/9348681.html
Copyright © 2011-2022 走看看