首页 > 代码库 > Struts2框架基本使用

Struts2框架基本使用

 

时间:2017-1-6 16:53

 

修改struts.xml配置文件不需要重启服务器。


Struts2框架

    一、
        *   介绍Struts2
        *   关于Struts2配置(关于Action配置)
        *   关于Struts2结果类型
    二、
        *   Struts2处理请求参数
        *   Struts2的类型转换(了解)
        *   Struts2的校验
    三、
        *   Struts2的国际化
        *   Struts2的拦截器
        *   Struts2文件上传与下载
        *   Struts2中ognl与valuestack
    四、
        *   ognl与valuestack
        *   Struts2中的防止表单重复提交
        *   Struts2中的Ajax插件
    五、
        *   练习(增删改查)


——什么是Struts2 

1、Struts2是一个非常优秀的MVC框架,基于Model2设计模型,只能在JavaWeb项目中应用。

2、由传统Struts1和WebWork两个经典框架发展而来。

3、Struts2核心功能
    *   允许POJO(Plain Old Java Object)对象作为Action。
    *   Action的excute方法不再与Servlet API耦合,更容易测试。
    *   支持更多视图技术(JSP、FreeMarker、Velocity)。
    *   基于Spring AOP思想的拦截器机制,更易扩展。
    *   更强大、更易用的输入校验功能。
    *   整合Ajax支持

4、Struts2核心:WebWork
    WebWork核心是XWork,XWork提供了很多核心功能:前端拦截器(Interceptor),运行时表单属性验证,类型转换,强大的表达式语言,(OGNL - the Object Graph Navigation Language),IoC(Inversion of Control 反转控制)容器等。

——Struts2的下载和安装

1、到http://struts.apache.org/download.cgi 去下载Struts2最新版本。

2、Struts2目录结构
    *   apps:该文件包含了基于Struts2的示例应用。
    *   docs:该文件夹下包含了Struts2相关文档,包括Struts2快速入门、Struts2的文档以及API等文档。
    *   lib:该文件夹下包含了Struts2框架和核心类库,以及Struts2第三方插件类库
    *   src:该文件夹下包含了Struts框架的全部源代码。
        >   core:Struts2的源代码
        >   xwork-core:xwork的源代码

3、开发时没必要将lib目录下的jar文件全部复制到项目中。
    可以到:struts-2.3.15.1\apps\struts2-blank\WEB-INF\lib目录下找到必要jar包。

——Struts2之HelloWorld

Struts2的Web项目尽量使用JavaEE5.0版本,因为Struts2是基于配置文件进行开发的。

1、导入jar包
    struts-2.3.15.1\apps\struts2-blank\WEB-INF\lib目录下找到必要jar包即可。

2、创建index.jsp、hello.jsp页面

3、对Struts2框架进行配置
    1)web.xml文件中配置前端控制器(核心控制器),其实就是一个Filter,目的是使Struts2框架生效。
        该过滤器的init()方法加载了Struts2框架必要的配置文件。

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

    2)创建一个struts.xml配置文件,这个是Struts2框架的配置文件,目的是使Struts2的流程可以执行。
        名称:struts.xml
        位置:src文件夹下(classes文件夹下)

 

4、创建一个HelloAction类
    要求:在HelloAction类中创建一个返回值是String类型的无参方法。

    public String hello(){
        return "hello";
    }


5、在struts.xml文件中配置HelloAction

<struts>
    <package name="default" namespace="/" extends="struts-default">
        <action name="hello" class="com.wyc.action.HelloAction" method="hello">
            <result name="hello">/hello.jsp</result>
        </action>
    </package>
</struts>


6、在index.jsp中添加链接,进行测试:
    <a href="http://www.mamicode.com/${pageContext.request.contextPath }/hello" >第一次使用Struts2</a>

    在地址栏中输入:http://localhost/struts2_day01/index.jsp,访问超链接,就可以看到HelloAction类中的hello方法执行了,并且跳转到了hello.jsp页面。

7、流程分析:

技术分享

8、手写代码实现Struts2功能
    1)创建一个Filter:StrutsFilter
    2)在web.xml文件中配置StrutsFilter
    3)在StrutsFilter中拦截操作,并访问Action中的方法,跳转到hello.jsp页面。

=============================================================================
示例代码:

struts.xml文件:

<struts>
    <action name="hello" class="com.wyc.action.HelloAction" method="hello">
        <result name="hello">/hello.jsp</result>
        <result name="hello2">/hello2.jsp</result>
    </action>
</struts>


----------------------------------------------------------------------------------------------------------------------------

StrutsFilter:

package com.wyc.web.filter;
 
import java.io.File;
import java.io.IOException;
import java.lang.reflect.Method;
 
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
 
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
 
public class StrutsFilter implements Filter {
 
    public void destroy() {
 
    }
 
    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException {
        // 1、强转
        HttpServletRequest request = (HttpServletRequest)req;
        HttpServletResponse response = (HttpServletResponse)resp;
 
        /*
         * 2.1、得到请求资源路径
         */
        // 得到请求路径
        // uri:/Struts_day01_1/hello
        String uri = request.getRequestURI();

        // 得到项目名
        // contextPath:/Struts_day01_1
        String contextPath = request.getContextPath();
 
 
        // hello
        String path = uri.substring(contextPath.length()+1); 
 
 
        /*
         * 使用path去struts.xml文件中查找某一<action name=path>
         */
        SAXReader reader = new SAXReader();
        try {
            Document doc = reader.read(new File(this.getClass().getClassLoader().getResource("struts.xml").getPath()));
 
            Element action = (Element) doc.selectSingleNode("//action[@name=‘" + path + "‘]"); // "//action[‘hello‘]"
 
            if(action != null){
                // 得到action元素的class属性和method属性
                String className = action.attributeValue("class");
                String methodName = action.attributeValue("method");
 
 
                // 通过反射得到Class对象,然后得到Method对象
                Class c = Class.forName(className);
                Method method = c.getDeclaredMethod(methodName);
 
 
                // 执行method方法,并获取返回值
                String returnValue = http://www.mamicode.com/(String) method.invoke(c.newInstance());
 
 
                // 使用返回的字符串去<action>下查找其子元素result的name属性值,获取与返回字符串相同的<result>元素
                Element e = (Element) action.selectSingleNode("//result[@name=‘" + returnValue + "‘]");
 
                if(e != null){
                    // 表示result存在,可以执行跳转
                    String skipPath = e.getText();
 
 
                    request.getRequestDispatcher(skipPath).forward(request, response);
                    return;
                }
 
            }
 
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
 
 
        // 3、放行
        chain.doFilter(req, resp);
    }
 
    public void init(FilterConfig arg0) throws ServletException {
 
    }
 
}

------------------------------------------------------------------------------------------------------------------

HelloAction.java

package com.wyc.action;
 
public class HelloAction {
    public String hello(){
        System.out.println("hello");
        return "hello";
    }
}
=======================================================================



——Struts2的流程分析与工具配置

1、运行流程:
    请求  -->  StrutsPrepareAndExecuteFilter(核心控制器、核心拦截器、前端控制器、前端拦截器)  -->  Interceptors(拦截器,实现代码功能,核心是AOP动态代理)  -->  Action的execute  -->  Result(结果页面)

    拦截器:在struts-default.xml中定义
    执行拦截器:在defaultStack中引用拦截器

    可以通过源码级别断点调试,证明拦截器执行了(学会导入源码,选中完整类名,然后ctrl + t)。

技术分享


2、手动配置struts.xml文件中提示操作
    1)复制http://struts.apache.org/dtds/struts-2.3.dtd
        到该目录中查找dtd文件:struts-2.3.15.1\src\core\src\main\resources
    2)在Windows —— Preferences —— 输入XML —— XML Catalog —— Add ——在Location中填入dtd文件路径 ——Key type选择URI —— URI中填入(名称空间):http://struts.apache.org/dtds/struts-2.3.dtd —— OK

    导入DTD时,应该和配置DTD版本一致。

3、关联Struts2的源文件
    Ctrl + Shift + t,输入类名查找对应类,然后关联源码。
    如果是com.opensymphony.xxx,就在xwork-core目录中查找。
    如果是org.apache.struts2.xxx,就在core目录中查找

4、使用ConfigBroswer插件(了解)
    提供在浏览器中查看Struts2配置加载情况。
    将解压后的struts2/lib/struts2-config-browser-plugin-2.3.7.jar复制到WEB-INF/lib目录下
    访问:localhost:8080/struts2_day01/config-browser/index.action查看struts2配置加载情况。

——Struts2配置(重点)

1、Struts2配置文件加载顺序:
    1)Struts2框架要想执行,必须先加载StrutsPrepareAndExecuteFilter
        在StrutsPrepareAndExecuteFilter类的init()方法中对Dispatcher进行了初始化操作。
        在Dispatcher类中定义的init()方法内就描述了Struts2配置文件的加载顺序:

 
            init_DefaultProperties(); // [1] —— struts2-core-2.3.15.1.jara包中的org/apache/struts2/default.properties
            init_TraditionalXmlConfigurations(); // [2] —— struts2-core-2.3.15.1.jara包中的struts-default.xml, struts-plugin.xml, struts.xml
            init_LegacyStrutsProperties(); // [3] —— 自定义struts.properties
            init_CustomConfigurationProviders(); // [5] —— 自定义配置文件
            init_FilterInitParameters() ; // [6] —— web.xml
            init_AliasStandardObjects() ; // [7] —— 加载Bean

            第一个加载的文件:default.properties文件
                作用:定义了Struts2框架中所有常量。
                位置:org/apache/struts2/default.properties

                properties文件定义键值对,定义值。
                XML文件定义关系。


            第二个加载的文件:
                struts-default.xml:
                    作用:配置了bean, interceptor, result等信息。
                    位置:struts2-core-2.3.15.1.jara包中。
                struts-plugin.xml
                    它是struts2框架中所使用的插件的配置文件。
                struts.xml
                    使用struts2框架所使用的配置文件。

            第三个加载的文件:自定义的struts.properties
                可以自定义常量,而不是用struts.properties中定义的常量。

            第四个加载的文件:web.xml

        在开发中,后加载文件中的配置会将先加载文件中的配置覆盖。

——关于Action的配置(重点)

1、struts.xml
    1)<package>:
            用于声明一个包,管理Action类。(通常情况下一个模块一个package)
            Struts2所有action都通过package管理。
            struts-default是struts-default.xml定义的一个package,其中包含大量拦截器和结果集。
            Action的访问路径 = namespace + action的name属性

        *   name
            包名,用于声明一个包名,包名不能重复。

        *   namespace
            与<action>元素的name属性合并,确定了一个唯一可以访问Action类的路径。
 
        *   extends
            表示继承的包名。

        *   abstract
            可以取值为true或false,(true)表示可以用于继承。

    2)<action>
            用于声明一个Action类。
        *   name
            表示一个Action类的名称,在同一个包内,Action的名称是唯一的。
            它与<package>元素中的namespace属性确定了一个访问Action类的路径。

        *   class
            Action类的完整包名

        *   method(请求处理方法)
            表示要访问的Action类中的方法的名称。

    3)<result>
            用于确定返回结果。

        *   name
            与Action类中的方法返回值做对比,确定跳转路径。

        *   type
            确定跳转处理方式。

2、关于Action配置其他细节
    1)默认值:
        <package namespace="默认值">
            *   namespace的默认值是"/";

        <action class="默认值" method="默认值">
            *   class的默认值:com.opensymphony.xwork2.ActionSupport
            *   method默认值:ActionSupport类中的execute()方法

        <result name="默认值">
            *   name的默认值是execute()方法的返回值return SUCCESS;,也就是"success"。

    2)关于访问Action的路径问题
        现在的Action配置是:
            <package name="default" namespace="/" extends="struts-default">
                <action name="hello" class="com.wyc.action.DefaultAction">
                    <resule>/hello.jsp</result>
                </action>
            </package>

        当输入:http://localhost/Struts2_day01_2/a/b/c/hello时,也可以访问到Action类。

        因为:Struts2中的Action被访问时,它会首先查找:
            1: namespace="/a/b/c"    action的name=hello,没有找到
            2: namespace="/a/b"       action的name=hello,没有找到
            3: namespace="/a"          action的name=hello,没有找到
            4: namespace="/"            action的name=hello,找到了

            如果最后也查找不到,会报404错误。

    3)默认的处理请求Action
        作用:处理其他Action处理不了的路径。
        <default-action-ref name="action的name属性" />
        配置这个元素后,当所有的Action无法处理访问路径时,会执行name指定的<action>元素。
        只在同包中有效。

    4)Action的默认处理类
        在Action配置时,如果不写class属性,默认是:comm.opensymphony.xwork2.ActionSupport。
        <default-class-ref class="com.wyc.action.DefaultAction"/>
        配置这个元素后,在当前包中,如果<action>元素不写class属性,那么默认处理Action请求的处理类就为class指定的类。
        只在同包中有效。

3、关于Struts2中的常量配置
    在default.properties文件中声明了Struts2中的常量。

    可以在哪些文件中配置常量?
        *   struts.xml(应用最多)
            >   <constant name="常量名称" value="http://www.mamicode.com/常量值"></constant>
        *   struts.properties(基本不用)
        *   web.xml(了解)
            >   在<filter>元素下通过<init-param>初始化参数进行配置。
            >   在web.xml文件中配置的常量会覆盖struts.xml文件中的配置。

    1)常用常量:
        *   struts.action.extension=action,,
            这个常量用于指定Struts2框架默认拦截的后缀名,例如:
                localhost/Struts2_day01/hello.action(可以访问)
                localhost/Struts2_day01/hello(可以访问)
                localhost/Struts2_day01/hello.abc(不可以访问)
            在struts.xml文件中设置:
                <constant name="struts.action.extension" value="http://www.mamicode.com/abc,,"></constant>
            运行结果如下:
                localhost/Struts2_day01/hello.action(不可以访问)
                localhost/Struts2_day01/hello(可以访问)
                localhost/Struts2_day01/hello.abc(可以访问)

        *   struts.i18n.encoding=UTF-8
            相当于request.setCharacterEncoding("UTF-8");,可以解决POST请求的乱码问题。

        *   struts.serve.static.browserCache=false
            false表示不缓存,true表示浏览器会缓存静态内容,产品环境设置true,开发环境设置false。

        *    struts.devMode=true
            DevelopModel,开发模式,相当于热部署。
            修改struts.xml文件后不需要重启服务器。
            提供详细报错页面,而不是只显示404等错误信息。

        *   struts.configuration.xml.reload=true
            当struts的配置文件修改后,系统是否自动重新加载该文件,默认值为false(生产环境下使用),开发阶段最好打开 



4、struts.xml文件的分离
    因为多个模块的package太多会影响阅读,为了方便阅读,所以可以让一个模块保存一个配置文件,将多个package分离,使用时引入配置文件即可。
    引入方式:
        <include file="文件路径" />

——Action类的创建方式

1、有三种创建方式:
    1)创建一个POJO类(直接创建一个class)
        POJO类表示没实现任何接口,没继承任何父类,除了Object类。
        优点:无耦合。
        缺点:所有工作都要自己实现,代码量大。

        底层通过反射来实现:
            Struts2框架读取struts.xml获得完整Action类名 —— object = Class.forName(完整类名).newInstance() —— Method m = obj.getMethod("execute"); —— m.invoke(obj); 通过反射执行execute()方法。

    2)实现Action接口
        为了让用户开发的Action更加规范,Struts2提供了一个Action接口。
        创建一个类,实现Action接口:com.opensymphony.xwork2.Action
        优点:耦合低,提供了五种逻辑视图(字符串常量),定义了一个行为方法(execute())。
        缺点:所有工作都要自己实现,但是已经得到标准规范。

        五种逻辑视图:(Action处理数据后进行页面跳转)
            public static final String SUCCESS = "success";    // 数据处理成功(成功页面)
            public static final String NONE = "none";    // 页面不跳转,与return null 效果相同
            public static final String ERROR = "error";    // 数据处理发送错误(错误页面)
            public static final String INPUT = "input";    // 用户输入数据有误,通常用于校验表单数据
            public static final String LOGIN = "login";    // 主要权限认证(登录页面)

        示例代码:
            public class HelloAction implements Action {
                public String execute(){
                    System.out.println("hello");
                    return "success";
                }
            }

    3)继承ActionSupport(推荐)
        com.opensymphony.xwork2.ActionSupport类实现了Action接口。
        优点:功能比较完善,ActionSupport支持校验(实现Validateable接口)、错误信息设置、支持国际化(实现LocaleProvider接口)
        缺点:耦合度高。

        示例代码:
            public class HelloAction2 extends ActionSupport {
                @Override
                public String execute(){
                    System.out.println("hello");
                    // return "success";
                    return NONE; // 相当于return null;
                }
            }

——关于Action的访问

如果没有指定method属性,则默认执行execute()方法。

1、通过设置method的属性值,来确定访问action类中的哪一个方法。

    <package name="book" namespace="/" extends="struts-default">
        <action name="book_add" class="com.wyc.action.BookAction" method="add"></action>
        <action name="book_update" class="com.wyc.action.BookAction" method="update"></action>
        <action name="book_delete" class="com.wyc.action.BookAction" method="delete"></action>
        <action name="book_search" class="com.wyc.action.BookAction" method="search"></action>
    </package>

    当访问book_add时,会调用BookAction类中的add方法,以此类推。

2、使用通配符来简化配置
    1)在struts.xml文件中配置:
        <action name="*_*" class="com.wyc.action.{1}Action" method="{2}"></action>

    2)在JSP页面中创建两个页面:book.jsp、product.jsp
        book.jsp:
            <body>
                <a href="http://www.mamicode.com/${pageContext.request.contextPath }/Book_add">book add</a>
                <a href="http://www.mamicode.com/${pageContext.request.contextPath }/Book_update">book update</a>
                <a href="http://www.mamicode.com/${pageContext.request.contextPath }/Book_delete">book delete</a>
                <a href="http://www.mamicode.com/${pageContext.request.contextPath }/Book_search">book search</a>
            </body>

        product.jsp:
            <body>
                <a href="http://www.mamicode.com/${pageContext.request.contextPath }/Product_add">product add</a>
                <a href="http://www.mamicode.com/${pageContext.request.contextPath }/Product_update">product update</a>
                <a href="http://www.mamicode.com/${pageContext.request.contextPath }/Product_delete">product delete</a>
                <a href="http://www.mamicode.com/${pageContext.request.contextPath }/Product_search">product search</a>
            </body>

        当访问book add时,这时的路径是:Book_add,那么对于struts.xml文件中第一个“*”就是Book,第二个“*”就是add。
        对于{1}Action就相当于BookAction,对于method="{2}",就相当于method="add"

    3)、使用通配符配置时注意事项:
       *   必须定义一个统一的命名规范
       *   不建议使用过多的通配符,影响阅读性

3、动态方法调用(了解)
    在struts.xml文件中配置:
        <action name="book" class="com.wyc.action.BookAction"></action>
    访问:http://localhost/Struts2_day01_2/book!add
    就可以访问到BookAction类中的add方法了。

    book!add就是动态方法调用,叹号后面写的就是方法名。

    注意:
        Struts2框架支持动态方法调用,可以在default.properties中设置动态方法调用为true
        struts.enable.DynamicMethodInvocation = true

——在Struts2框架中获取Servlet API

对于Struts2框架,不建议直接使用Servlet API。

在Struts2中获取Servlet API有三种方式:
    1、通过ActionContext获取
        *   获取一个ActionContext对象
            >   ActionContext context = ActionContext();
        *   获取Servlet API
            >   通过ActionContext获取到的不是真正的Servlet API,而是一个Map集合,集合中存放的就是对象(用键值对)存放的数据。
    2、通过注入方式获取
    3、通过ServletActionContext获取

----------------------------------------------------------------------------------------------------------------------------

1、Action访问Servlet
    在Action中用解耦和方式使用ActionContext对象间接访问Servlet API。
    在Struts2中Action API已经与Servlet API解耦和了(没有依赖关系)。
    Servlet API常见操作:
        *   获取表单提交请求参数
        *   向request, session, application三个作用域存取数据

    开发中应优先使用ActionContext,这样可以避免耦合。

ActionContext方法:
    *   Map  getParameters()
        获取所有请求参数的Map集合。
        Map底层是一个HashMap。

    *   void  put(String key, Object value)
        对request域存放数据。

    *   Map  getApplication()
        获取ServletContext数据Map,对应用访问存取数据。

    *   Map  getSession()
        获取session数据Map,对Session范围存取数据。

/*
 * 通过ActionContext获取Servlet API
 */
public class ServletDemo1Action extends ActionSupport {
 
    @Override
    public String execute() throws Exception {
        /*
         * 1、获取ActionContext对象
         */
        ActionContext context = ActionContext.getContext();
 
        /*
         * 2、获取Servlet API
         */
 
        // 获取application中数据
        Map<String, Object> applicationMap = context.getApplication();
        System.out.println("application: " + applicationMap.get("aname"));
 
        // 获取session中数据
        Map<String, Object> sessionMap = context.getSession();
        System.out.println("session: " + sessionMap.get("sname"));
 
        return NONE;
    }
}

----------------------------------------------------------------------------------------------------------------------------

2、使用接口注入的方式操作Servlet API(耦合)
    这种方式能够真正获取到Web对象。

    步骤:
        1)要求Action类必须实现指定接口:
            ServletContextAware接口:注入ServletContext对象
            ServletRequestAware接口:注入request对象
            ServletResponseAware接口:注入response对象
        2)重写接口中指定的方法:
            public void setServletRequest(HttpServletRequest request)
        3)声明一个web对象,使用接口中的方法对声明的web对象赋值
            private HttpServletRequest request;
            public void setServletRequest(HttpServletRequest request){
                this.request = request;
            }

    示例代码:

        /*
         * 通过注入方式获取Servlet API
         */
        public class ServletDemo2Action extends ActionSupport implements ServletRequestAware {
            private HttpServletRequest request;
 
            public String execute() {
 
                System.out.println(request.getParameter("username"));
 
                return null;
            }
 
            /*
             * 实现接口方法
             */
            public void setServletRequest(HttpServletRequest request) {
                this.request = request;
            }
        }


    分析其实现方法:
        通过Struts2的interceptor实现的。
        struts-default.xml:
            <interceptor name="servletConfig" class="org.apache.struts2.interceptor.ServletConfigInterceptor"/>
        源码:
            org.apache.struts2.interceptor.ServletConfigInterceptor拦截器中的intercept()方法:
                public String intercept(ActionInvocation invocation) throws Exception {
                    final Object action = invocation.getAction();
                    final ActionContext context = invocation.getInvocationContext();
 
                    if (action instanceof ServletRequestAware) {    // 判断Action类是否实现了ServletRequestAware接口
                        HttpServletRequest request = (HttpServletRequest) context.get(HTTP_REQUEST);    // 得到request对象
                        // 因为action是Object类型,所以需要强转 
                        ((ServletRequestAware) action).setServletRequest(request);    // 将request对象通过Action中重写的方法注入,
                    }
                    ....... 
                    return invocation.invoke();
                }

----------------------------------------------------------------------------------------------------------------------------

3、通过ServletActionContext获取Servlet API
    在ServletActionContext中方法都是静态的。
    该类的父类是ActionContext,其内部代码也是通过ActionContext获取到的。

    方法概要:
        static PageContext  getPageContext()
            获取PageContext对象。

        static HttpServletRequest  getRequest()
            获取request对象。

        static HttpServletResponse  getResponse()
            获取response对象。

        static ServletContext  getServletContext()
            获取ServletContext对象。

        没有getSession()方法,但是可以通过getPageContext().getSession()获得。
        有了pageContext,其它八个对象都可以得到。

    示例代码:

        /*
         * 通过ServletActionContext获取Servlet API
         */
        public class ServletDemo3Action extends ActionSupport {
            public String execute() {
 
                HttpServletRequest request = ServletActionContext.getRequest();
 
                System.out.println(request.getParameter("username"));
 
                return null;
            }
        }

——Result结果类型

在:struts-default.xml文件中定义。

1、理解处理结果
    *   Action处理完用户请求后,会返回一个普通字符串。
    *   整个普通字符串就是一个逻辑视图名。
    *   Struts2根据逻辑视图名,决定运行哪个结果。
    *   Struts2处理结果使用<result>元素进行配置。
        >   局部结果:将<result>作为<action>的子元素进行配置
        >   全局结果:将<result>作为<global-result>的子元素进行配置
    *   配置<result>元素通常需要指定两个属性
        >   name:该属性指定配置逻辑视图名
        >   type:该属性指定结果类型(跳转方式、处理方式)

2、<result>标签属性:
    *   name属性:
        与action中的method的返回值匹配,获取跳转路径,进行跳转。

    *   type属性:
        作用是定义跳转方式。
        对于type属性的取值范围有以下几种:(可以在struts-default.xml文件中查看)
        >   chain:请求转发,一般情况下用于从一个Action跳转到另一个Action。
        >   dispatcher:请求转发,是默认值,一般用于从Action跳转到jsp页面。
        >   freemarker:模板技术,将页面与数据分离,通过freemarker将数据和页面整合到一起。
        >   httpheader
        >   plainText
        >   redirect:重定向,一般用于从Action重定向到页面。
        >   redirectAction:重定向,一般用于从Action重定向到另一个Action。
            redirectAction有两个参数:
                actionname:指定目标Action的名称,它是默认属性。
                namespace:用来指定目标Action的名称空间,默认为"/"。 
        >   stream:代表从服务器端返回一个流,一般用于下载。
        >   velocity:模板引擎
        >   xslt

    <package name="struts-default" abstract="true">
        <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>
    </package>

    必须掌握:
        chain、dispatcher、redirect、redirectAction、stream
        两个转发、两个重定向、一个流。 
    了解:freemarker、velocity

3、局部结果页面与全局结果页面
    当多个action中都是用了相同的result,这时可以把result定义为全局结果页面。
<struts>
    <package name="default" namespace="/" extends="struts-default">
 
        <!-- 全局结果,当前package中的Action都可以使用 -->
        <global-results>
            <result>/demo2_success.jsp</result>
            <!-- 当存在多个result时,以后面的result为准 -->
            <result>/demo1_success.jsp</result>
        </global-results>

        <action name="demo1" class="com.wyc.action.ServletDemo1Action">
            <!-- 局部结果,仅限当前Action使用 -->
            <result>/demo1_success.jsp</result>
        </action>
        <action name="demo2" class="com.wyc.action.ServletDemo2Action">
            <!-- 如果当前action下没有result,那么就会到全局中查找 -->
        </action>
        <action name="demo3" class="com.wyc.action.ServletDemo3Action"></action>
    </package>
</struts>

——练习:登录操作

1、需求:
    用户通过表单进行登录,登陆失败将页面转发到login.jsp,并显示错误信息。
    登录成功后将用户存储到Session中,重定向到success.jsp页面,并展示用户信息。

2、所需页面
    login.jsp
        >   提供登录表单
        >   登录失败时显示错误信息
    success.jsp
        >   登录成功后通过session获取用户信息并显示到页面
 
3、所需类
    LoginAction
        >   获取Servlet API,获取表单信息
        >   校验用户信息
            >   登录成功,重定向到success.jsp
            >   登录失败,转发到login.jsp
    User类
        实体类
        >   private String username;
        >   private String password;

——总结

    1、Struts2环境搭建
        *   导入jar包:
            >   struts2/apps/strut_blank.war文件
        *   web.xml如何配置:
            >   配置StrutsPrepareAndExecuteFilter
        *   struts.xml如何配置:
            >   在src目录下(classes)
    2、Struts2运行流程
        *   如何通过反射执行action
    3、配置文件加载顺序
        *   每个配置文件的用途是什么
        1)default.properties
        2)struts-default.xml  struts-plugin.xml  struts.xml
        3)struts.properties
        4)web.xml 
    4、<package><action><result>元素的配置
        *   package:用于管理action
            >   name:包名,唯一
            >   namespace:与action的name属性确定访问action的路径。
            >   extends:继承的包名,一般继承struts-default
        *   action:声明一个action
            >   name:action名称,在同一个包下不能重名
            >   class:action完整类名,默认是ActionSupport
            >   method:action类中的方法名,要求无参,返回值为String,默认值为execute
        *   result:结果视图
            >   name:与action的method方法的返回值进行匹配确定跳转路径
            >   type:跳转方式
                在struts-default.xml文件中定义:
                    chain, dispatcher, redirect, redirectAction, stream
    5、Action的三种创建方式
        *   POJO
        *   实现Action接口
        *   继承ActionSupport类
    6、指定method的调用方法
        *   指定method属性
        *   通配符
        *   动态方法调用
    7、Action访问Servlet API
        *   ActionContext
        *   访问指定接口(注入)
        *   ServletActionContext
    8、结果类型
        *   <result>标签的type属性取值。
    9、自定义常量
        *   在struts.xml文件中定义
            >   <constant name="" value="" />
        *   在struts.properties文件中定义
        *   在web.xml文件中定义 
            >   <init-param></initparam>
 
——Struts2核心知识点及问题

1、struts2在web.xml配置的Filter叫什么?
2、struts2的Action有几种书写方式?
3、能否在struts2的Action定义多个业务方法?如何做到不同的请求访问Action的不同方法?
4、自定义struts2类型转换器实现实现哪个接口,如何配置局部转换器和全局转换器?
5、struts2的国际化信息文件有哪几类?
6、xml进行struts2请求参数校验时,指定方法的校验文件和所有方法校验文件命名规则是什么?
7、struts2的Action中如何使用ServletAPI?
8、简单描述struts2的值栈对象的内部存储结构
9、addFieldError、addActionError和addActionMessage 有何区别?
10、struts2中有哪些常用结果类型?你用过哪些?
11、你是否在struts2开发中 自定义过拦截器,实现什么功能?
12、struts2 UI主题有哪些?你用过哪些? 底层实现是什么?
13、struts2 和 struts1 有何区别?
14、struts2 中如何使用 Ajax ?
15、struts2 的拦截器使用了哪种设计模式 ?
 
——关于Struts2中约定访问规则

从struts2.1开始,struts2 引入了Convention插件来支持零配置
使用约定无需struts.xml或者Annotation配置
需要 struts2-convention-plugin-2.3.7.jar 、asm-*.jar(三个)
插件会自动搜索action、actions、struts、struts2包下所有Java类
所有实现了com.opensymphony.xwork2.Action的Java类
所有类名以Action结尾的Java类
下面类名都符合Convention插件
cn.itcast.struts2.HelloAction
cn.itcast.actions.books.BookSearchAction
cn.itcast.struts.user.UserAction
cn.itcast.estore.action.test.LoginAction
 
 
struts2-convention-plugin-2.3.7.jar 中struts-plugin.xml重要常量
<constant name="struts.convention.package.locators" value="http://www.mamicode.com/action,actions,struts,struts2"/>  默认扫描包
<constant name="struts.convention.exclude.packages" value="http://www.mamicode.com/org.apache.struts.*,org.apache.struts2.*,org.springframework.web.struts.*,org.springframework.web.struts2.*,org.hibernate.*"/> 不扫描
<constant name="struts.convention.action.suffix" value="http://www.mamicode.com/Action"/> 默认扫描以Action结尾的类
<constant name="struts.convention.result.path" value="http://www.mamicode.com/WEB-INF/content/"/> 结果result页面存放位置
<constant name="struts.convention.classes.reload" value="http://www.mamicode.com/false" /> Action类文件重新自动加载
 
如果Action类名包含Action后缀,将Action后缀去掉
将Action类名的驼峰写法,转成中划线写法
例如:
cn.itcast.struts2.HelloAction 映射到 /hello.action
cn.itcast.actions.books.BookSearchAction  映射到 /books/book-search.action
cn.itcast.struts.user.UserAction 映射到 /user/user.action
cn.itcast.estore.action.test.LoginAction 映射到 /test/login.action
 
默认情况下,Convention总会到Web应用的WEB-INF/content路径下定位结果资源
<constant name="struts.convention.result.path" value="http://www.mamicode.com/WEB-INF/content/"/>
约定: actionName + resultCode + suffix 
例如:
访问cn.itcast.struts.user.UserAction返回success
Convention优先使用 WEB-INF/content/user/user-success.jsp
如果user-success.jsp不存在,会使用user-success.html
如果user-success.html不存在,会使用user.jsp

Struts2框架基本使用