zoukankan      html  css  js  c++  java
  • Struts2第一天

    Struts2第一天

    整体课程安排:3天知识点+2天练习

    第一天:入门(action和result结果集)--一般的请求+响应

    第二天:请求数据处理相关(参数接收、类型转换、合法性校验、国际化)

    第三天:拦截器、响应数据处理相关(值栈、OGNL、struts2标签)

    第四天、第五天练习。(文件的上传下载+CRUD综合练习)

    课程内容:

    1. Struts2概述(struts2框架、前世今生、开发包下载、开发包结构)
    2. 快速入门HelloWorld(入门理论、示例、运行流程分析)
    3. Struts2运行原理(运行原理图、相关概念简介-核心控制器、拦截器、Action、结果集、核心配置文件、DTD约束提示配置)
    4. Struts常用配置(核心配置文件种类和加载顺序、Action相关映射配置详解、Action默认处理类和默认Action、常量配置、配置文件分离)
    5. Action的访问相关(Action的三种书写格式、Action的方法执行三种方式)
    6. Action使用Servlet相关API(直接调用、间接调用)
    7. result结果集的使用(局部结果集和全局结果集、结果集的类型type)

    课程目标:

    1. 学会使用基本的请求和响应
    2. 学会action的最主要的编写方式(ActionSupport)
    3. 学会如何调用action中的指定方法(通配符)
    4. 获取servelt API(静态方法调用)
    5. 掌握结果集的使用
    1. 概述

      1. Struts2是什么

    Struts2是一个非常优秀的、免费开源的MVC框架(Model2设计模型),用于创建Web应用。

    • 框架

    框架是可以重复使用的一些或一整套代码,通常与具体业务无关,也可以认为是软件的半成品。

    框架的好处:规范开发流程。

    • MVC

    全名是Model View Controller,是模型(model)-视图(view)-控制器(controller)的缩写,是一种软件设计模式,或软件设计思想。

    1. 视图-view:负责数据的显示。 
    2. 模型-model:负责数据的处理。 
    3. 控制器-controller:负责调度不同的逻辑代码(model)并显示到视图(view)。 
      MVC
      的设计思想在很多中语言中都有实现,例如java.net

     

    JSP规范提出了两种用JSP技术建立应用程序的开发模式,分别称作JSP Model 1 和JSP Model 2:

    • Model1: JSP (控制、显示)+ JavaBean (数据处理)

      缺点:页面代码太多,加载速度慢,调试麻烦。

     

    • Model2 : Servlet (控制)+ JSP(显示) + JavaBean(数据处理)--符合MVC思想架构模式。

      适合大型项目

     

    Java web企业应用开发根据又根据Model2(也可以说是根据MVC思想)制定了三层结构体系(来自于JavaEE规范)

    • 表现层(页面数据显示、页面跳转调度)jsp/servlet
    • 业务层(业务处理和功能逻辑、事务控制)service
    • 持久层(数据存取和封装、和数据库打交道)dao

     

    Struts2就是一个表现层框架,可以用来简化表现层代码开发的。

     

    Struts2核心功能:了解

    允许POJO对象作为action

    Action中的servlet API不再与方法耦合

    支持更多视图技术(jsp、freemarker、velocity)

    基于Spring AOP思想的拦截器机制

     

    1. struts2 由来

    百度百科:

     

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

    历史由来:

    Java兴起 98(最早进行java开发分方向 j2se j2ee j2me

    J2EE 企业级应用软件开发

    2000 年左右出现struts1 (几乎所有开发人员都在用

    随着互联网的发展struts1 设计慢慢开始存有缺陷和不足

    Webwork框架的出现

    该框架的设计思想比struts1 先进的多,例如:引入拦截器机制、 ognl 表达式语言

     

    struts2是在 struts 1和WebWork的技术基础上进行了合并的全新的Struts 2框架,Struts 2以WebWork为核心,但开发流程类似于struts1。

     

    Struts2的漏洞事件:

    1. 软件开发包

    官网地址:http://struts.apache.org/

    官方网站提供了两大系列版本1.x和2.x,分别成为Struts1和Struts2。

    最新版本分别为:1.3.10 和2.5.2。

    本课程学习Struts2。

     

    开发包下载:

    官方最新版本:struts-2.5.2-all.zip

     

    本次课程使用的版本是:2.3.15.3

     

     

    1. struts2 开发包结构

    使用框架需要导入jar包(也就是人家写好的一些代码)

    解压之后,源码和jar包都在里面了。

    src文件夹下的是源码

     

    在lib文件夹中有很多的struts需要用到的包,包括和spring的整合包,json的插件包等等

    总共126个jar,实际上在我们开发的时候用不到这么多。

     

    docs中的文档几乎看不懂,要快速入门我们可以看一下apps中的一些案例:

    解压之后的struts2-blank中就是一些简单的应用,结构如下 ;

    打开其中的web.xml:里面就配置了struts2需要用到的过滤器

     

    struts.xml :struts2的灵魂文件

     

    有了web.xml和struts.xml的配置文件,还需要jar包,jar包在lib文件夹中。

     

    总结13个jar包的用途:

    1. Struts2快速入门

      1. 理论

    Struts2和Servlet开发对比

    Servlet:

    缺点:一个功能对应一个请求,一个请求对应一个serlvet,每一个servlet中都可能有重复的代码。

     

    Struts:

     

    Struts2的基本运行流程图:

    Web.xml作用:配置前端控制器

    Struts.xml作用:配置请求分发

     

    【小结】

    所有的重复代码都交给前端控制器去调用完成和调度,开发者只需要在Aciton中编写业务处理相关代码即可。

    1. 入门

     

    1. 创建工程

    选择jdk版本,不要选yes,否则就使用了jdk1.5的版本,对后面使用注解支持不好,要用jdk1.5以上的。

    当然也可以改成jdk1.7的。

     

    1. 导入jar包

    Jar包地址: Struts_2.3.15.3struts-2.3.15.3appsstruts2-blankWEB-INFlib下的13个jar包

     

    1. 配置web.xml

    Ctrl+shift+T :然后输入StrutsPrepareAndExecuteFilter后可以联想出该文件,然后复制它的绝对路径即可

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

    <web-app id="WebApp_9" version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee"

        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

        xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">

     

        <display-name>struts</display-name>

        <!-- 配置sturts前端控制器 -->

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

        <welcome-file-list>

            <welcome-file>index.html</welcome-file>

            <welcome-file>index.htm</welcome-file>

            <welcome-file>index.jsp</welcome-file>

            <welcome-file>default.html</welcome-file>

            <welcome-file>default.htm</welcome-file>

            <welcome-file>default.jsp</welcome-file>

        </welcome-file-list>

    </web-app>

     

    1. 编写请求页面

    创建页面:

    hello.jsp :

    success.jsp :

    1. 编写action

    创建包和action :

    编写一个处理具体业务的action,必须实现Action接口

    具体内容如下:

    public class HelloAction implements Action{

        //exectue为实现Action接口后默认执行的方法,String是返回的结果集视图名称

        //通过这个结果集视图名称到struts.xml中可以找到对应跳转的结果集视图

        @Override

        public String execute() throws Exception {

            System.out.println("hello world!");

            //响应页面跳转:

            //返回的结果集视图名称:名字随便取(必须在struts.xml中能找到相同名称的配置)

            return "success";

        }

    }

     

     

    1. 配置struts.xml

    1、可以重上述案例的struts.xml中复制过来

    2、Struts.xml中的约束路径:在struts2-core核心jar包下的struts-2.3.dtd中

    配置完成后如果还是不能联想出struts相关的标签名称,那是因为没有配置相应的dtd约束文件

    注意:如果电脑可以上网,就会自动给你下载dtd约束文件。

    如果不能上网就需要手动配置dtd约束文件,手动配置如下:

    复制:http://struts.apache.org/dtds/struts-2.3.dtd,打开window属性

    Laction的文件路径为:之前解压文件struts-2.3.15.3srccoresrcmain esources下的struts-2.3.dtd

    点击确定后,关闭struts.xml并且重新打开,此时用alt+/就可以联想出相关标签.

     

     

     

     

    在工厂的src目录下创建一个struts.xml文件,然后将上述约束复制到struts.xml中

    Struts内容如下:

    <?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" extends="struts-default" namespace="/">

        <!—配置action和访问的类之间的对应关系 -->

        <!-- name:请求的虚拟路径名称 class:指向的具体路径 -->

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

            <!-- name:action中通过String值来找到这个标签,并返回相应的结果集视图 -->

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

            </action>

        </package>

     

    </struts>

     

     

     

     

    1. 测试

    发布到tomcat :

    启动tomcat :

    测试访问:

    1、控制台打印:

    2、显示视图

     

     

    关联源代码:

    选择开发包:

     

    1. 执行流程分析

    客户端发送请求,请求路径经过前端控制器,前端控制器读取struts.xml中的配置来分发到HelloAction中,执行默认方法后返回结果集视图名称,在struts.xml中找到相应的结果集视图并显示。

    由此可见:struts.xml是这个过程中的核心,通过这个struts.xml才能找到具体的action以及响应结果集视图。

     

     

    实际上在前端控制器走第三步分发action请求之前,还调用了一组拦截器,由于咱们并没有关于拦截器的业务因此什么都没有感觉到。

    1. Struts运行原理分析

     

    StrutsPrepareAndExecuteFilter (准备 和 执行):它是Struts2的核心控制器,它采用前端控制器模式,对用户的请求进行控制处理。相当于我们的学校的前台。

    Interceptor拦截器,Struts2可复用的代码功能都是基于(通过)它来实现的。struts2有很多内置拦截器,用来实现不同的功能。我们看看有哪些默认的拦截器:

    参考 struts-core.jar 提供 的struts-default.xml 配置文件

        默认情况下, 访问每个Action ,默认拦截器defaultStack会从上往下依次执行

    通过断点调试发现:其中包含的这些拦截器都会依次执行(按照从上倒下的顺序),即可依次实现不同的功能。 而这些功能都是通用的、经常用到的(重复的),都由拦截器来实现。

    随便找一个找到具体的类进行断点调试即可

     

     

    Action是执行具体的业务逻辑代码的,它在拦截器之后执行。(演示。。。)

    【查看类型代码】shift+ctrl+t

    通过断点调试看到,前端控制器在分发action之前就调用了拦截器。

     

    1. ConfigBrowser插件(了解)

     

    ConfigBrowser可以用来查看struts2的各类配置。

     

    知识点:如何使用struts2的插件。

    Strut22的插件的安装,只需要将插件复制到工程的lib中即可

    导入插件包 ,启动项目 ,访问:

    http://IP地址:端口/项目名称/config-browser/index.action

    通过路径,查看struts2 Action 配置加载情况

     

    1. 常用配置

      1. 核心配置文件的分类及读取顺序

    关键词:核心配置文件的种类和加载顺序,前端控制器会依次加载依次配置文件。

    Struts2的核心配置文件有两大类共6种方式,按照加载顺序分别说明如下:

    第一类:框架内置的配置文件:

    • Struts2框架内置的常量配置文件:default.properties,位于struts-core.jar包的org.apache.struts2包下。作用:定义了一些常量(键值对)。一些功能开关。
    • Struts2框架内置的核心配置文件:struts-default.xml,位于struts-core.jar包下。作用:定义了Bean元素、结果集类型、拦截器等。注意默认包:

    struts.xml中extends :

    实际就是继承了struts-default

     

    在struts2的框架体系中,struts.xml中的package主要是用来实现一些配置的复用,在使用时编写子包来继承struts-default,如此就可以复用struts-default中的一些功能。

     

    • Struts2框架插件配置文件:struts-plugin.xml,位于每个插件包的根目录。作用:用于扩展插件的一些配置。

       

      随便复制一个struts的插件包到工程中,里面就有struts-plugin.xml。

    每一个插件包中的struts-plugin.xml配置都不一样

     

     

    第二大类:用户自定义的配置文件:

    • 用户自定义核心文件配置struts.xml位于用户工程的src下。作用:用于用户开发的相关配置,如配置package、action等。

      一般都会继承struts-default,即继承struts-default.xml中的配置,否则就无法使用结果集以及拦截器的配置。

    • 用户自定义常量配置文件:struts.properties,一般位于用户工程的src下。只能用于配置一些常量(覆盖内置的default.properties中的常量配置

      一般也不太用,可以在struts.xml中直接配置常量

       

    • web.xml中配置struts2常量(了解)

     

    【注意】

    1. 配置文件加载的顺序问题:后加载的配置文件的配置内容,可以覆盖先加载的配置文件的配置内容。因此,自定义的可以覆盖默认的配置。
    2. 开发人员主要采用struts.xml(可配置action映射、常量等) 或者 struts.properties (只能配置常量)

     

     

    注意:以上第一类的3个配置文件都是不能做修改的,全部配置文件的读取顺序为:1、default.properties---2、 struts-default.xml---3、 struts-plugin.xml---4、struts.xml---5、struts.properties---6、web.xml中的常量配置

     

    当然,常量的配置一般不在struts.properties和web.xml中来配置,在struts.xml中配置即可

     

    1. 核心配置文件struts.xml

    关键字:package、action、result、constant(常量的配置)

    1. <package>

      package标签:用来管理Action和result, 实现包内配置复用 (通过包继承实现 )

       

    • name属性:包的名称,在struts容器中必须具有唯一性
    • extends属性:继承父package(中的功能),通常都继承struts-default(默认包内定义大量结果集类型和拦截器)
    • namespace属性:名称空间用来标识一个路径,来区分不同action的访问路径

     

     

     

    【示例】

    演示不同的包中相同的action通过不同的名称空间来访问。

     

    步骤一:创建新的包和action

    创建包:

    action:

    //编写action需要实现action接口

    public class HelloAction implements Action{

        //默认执行的方法

        @Override

        public String execute() throws Exception {

            System.out.println("hello world ......config!");

            return "success";

        }

        

    }

     

    步骤二:修改struts.xml

    亲:如果HelloAction是复制粘帖的话,记得把class中的绝对路径换成新的HelloAction。

    创建一个新的package:

    <struts>

        <!-- 配置常量 -->

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

        <!-- package name:包名随便取但是需要保证唯一性 extends:用来继承核心包 -->

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

     

            <!-- action:具体请求的分发 name:请求名称 class:具体要执行的类的路径 -->

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

                <!-- 配置结果集响应 name:结果集视图名称 /a_hello/result.jsp:需要响应的结果集视图 -->

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

            </action>

        </package>

     

     

            

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

            <action name="hello1" class="cn.itcast.struts.b_config.HelloAction">

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

            </action>

        </package>

         </struts>

     

    注意:在同一个package下,action的name属性也不能重复,必须是唯一的。

     

    步骤三:测试

    访问测试:http://127.0.0.1:8080/struts2_day01/config/hello.action

     

     

    Action的访问路径= IP地址:端口+namespace包名称空间 + action的name属性

    1. <action>

      action标签:用来管理具体的Action,实现请求和响应相关。

       

    • name属性:action的名字,用于配置请求
    • class属性:action对应的类,该类编写了action具体业务逻辑代码。
    1. <result>

      result标签:结果集视图,用于配置响应,标签内的值是响应的地址

       

    • name属性:结果集(结果集视图)的名字,action会根据该名字跳转到对应的地址。

     

     

     

     

    1. 配置项的默认值

      1. package-namespace默认值

    步骤一:再次创建一个新的package

    不写namespace:即为默认值

        <!-- 默认值 -->

        <package name="default2" extends="struts-default" >

            <!-- 配合默认action -->

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

            <!-- 配置默认action的具体映射 -->

            <action name="errorAction" class="cn.itcast.struts.b_config.HelloAction">

                <!-- 配置结果集 -->

                <result >/errorPage/errorPage.jsp</result>

            </action>

          

            <action name="hello2" >

                <result >/a_hello/result.jsp</result>

            </action>

        </package>

     

    步骤二:测试访问

    访问无误

    注意:不设置namespace的话,期默认值是namespace="",而不是很多人以为的namespace="/"

    由于期访问路径一样是http://127.0.0.1:8080/struts2_day01/hello.action,所以会造成很多人的误解。

     

    步骤四:分析

    默认值到底是namespace=""还是namespace="/",从配置第二个package就可以看出来:

    如果第二个package配置namespace=""的话就会产生冲突以至于报错,而如果配置成namespace="/"的话就不报错了,由此可见namesapce的默认值应该是namespace=""。

     

    1. result-name默认值

    步骤一:修改Struts.xml

    不写namespace:即为默认值

        <!-- 默认值 -->

        <package name="default2" extends="struts-default">

            <!-- 配合默认action -->

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

            <!-- 配置默认action的具体映射 -->

            <action name="errorAction" class="cn.itcast.struts.b_config.HelloAction">

                <!-- 配置结果集 -->

                <result >/errorPage/errorPage.jsp</result>

            </action>

        

            <action name="hello2" >

                <result >/a_hello/result.jsp</result>

            </action>

        </package>

     

    步骤二:测试

    测试访问hello,执行结果无误

     

    步骤三:分析

    如果result标签中的name值不配置的话,其默认值是success,但是如果使用默认值的话需要在action中返回结果集名称为SUCCESS

     

    1. action-class默认值

    步骤一:修改struts.xml

    设置默认的action-class(即不在action标签中配置class属性)

        <!-- 默认值 -->

        <package name="default2" extends="struts-default" >

            <!-- 配合默认action -->

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

            <!-- 配置默认action的具体映射 -->

            <action name="errorAction" class="cn.itcast.struts.b_config.HelloAction">

                <!-- 配置结果集 -->

                <result >/errorPage/errorPage.jsp</result>

            </action>

          

            <action name="hello2" >

                <result >/a_hello/result.jsp</result>

            </action>

        </package>

     

     

    步骤二:测试请求

    请求成功,但是后台不打印任何数据

     

    步骤三:分析

    如果不指定action标签中的class,那么会默认执行com.opensymphony.xwork2. ActionSupport,并执行其中的execute方法。

     

    由于是使用的默认class—ActionSupport,因此后台没有执行任何逻辑,直接返回了SUCCESS结果集视图名称,跳转到指定页面。

     

     

    1. 默认action

    通常我们的请求路径如果找不到相应的action就会报错如下:

    我们可以配置一个默认的action,一旦找不到相应的action就会执行默认action。

     

    【示例】

    步骤一:修改struts.xml

    配置默认action:

    <!-- 配置默认值 -->

        <package name="default2" extends="struts-default" >

        <!-- 配置默认action -->

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

        

        <action name="errorAction" class="cn.itcast.struts.b_config.HelloAction">

            <result>/errorPage/errorPage.jsp</result>

        </action>    

          

            <!-- action:具体请求的分发 name:请求名称 class:具体要执行的类的路径 -->

            <action name="hello1" >

                <!-- 配置结果集响应 name:结果集视图名称 /result.jsp:需要响应的结果集视图 -->

                <result >/a_hello/result.jsp</result>

            </action>

     

        </package>

     

    步骤二:创建响应页面

    测试访问一个不存在的action:跳转到指定的错误页面-errorPage.jsp

    errorpage.jsp需要配置加载所需图片:

    <div align="center"><img src="./images/404-xsy.jpg"/></div>

    页面内容:

    <body>

    <div align="center"><img alt="图片" src="b_config/404-xsy.jpg"></div>

    </body>

     

    步骤三:测试

     

    【面试知识】

    区分Action默认处理类(class)和默认执行的Action

    • Action默认处理类:是配置了action,但没有指定action的class,会自动调用执行默认的action类,该action在struts2的struts-default.xml文件中有配置内置默认的,也可以自定义一个进行覆盖(一般很少这样做)。

    • 默认执行的action:是用户访问的路径中找不到这个action,那么struts2会去寻找被访问的包中是否有配置一个默认执行的action,如果有配置,则执行默认配置的action,如果没有配置,则显示action找不到的错误信息哦

     

     

     

    【扩展了解】

    访问action的时候,struts有个内部规律(了解)

    如果你访问的路径中,没有定义action,会自动向上层路径寻找。

    http://127.0.0.1:8080/struts2_day01/aa/bb/cc/hello.action

    先在aa/bb/cc/找helloAction

    找到就ok,找不到,继续:

    aa/bb/中找hello.action

    ……..

    一直找到hello.action

     

    其实最终会找到根目录下的hello.action:http://127.0.0.1:8080/struts2_day01/aa/bb/cc/hello.action

     

     

    访问测试:

    缺点:代码可读性不好,不建议这样做。

     

    1. <constant>常量配置

    default.properties定义了struts2框架的大量常量,开发者可以通过改变这些常量来满足应用的需求。

    要修改这些常量,可以通过自定义核心配置来覆盖默认的值(后加载的配置文件常量,可以对先加载配置文件进行覆盖),有如下三种方式(开启开发者模式):

    • 配置src/struts.xml

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

    • 配置src/struts.properties

    struts.devModel = true

    • 配置web.xml

     

     

    【常用常量分析】

    • struts.i18n.encoding=UTF-8

        相当于 request.setCharacterEncoding("utf-8"); 解决post 请求乱码问题。

        因此,在Struts2开发时,无需关注post 乱码问题。

     

    • struts.devMode=true

    开发模式下使用,这样可以打印出更详细、友好的错误信息

    当设置开发者模式devMode =true 会激活xml配置文件自动重新加载功能。

    • struts.configuration.xml.reload=true :修改struts.xml 配置后,无需重启服务器;
    • struts.i18n.reload = true,国际化文件修改之后也不需要重启服务器。会自动加载生效。

     

    • struts.action.extension=action,,

        Action请求映射路径 默认扩展名

    问题: http://localhost:8080/struts2_day1/hello 也可以访问 HelloAction

        如果请求路径 必须以.action结尾

     

    • struts.ui.theme=xhtml

        设置页面标签显示样式

     

    • struts.enable.DynamicMethodInvocation=true

        访问Action 支持 动态方法调用

     

    • struts.multipart.maxSize=2097152

        上传文件的大小限制

     

    小结:

    如果需要更改某个常量的值,在default.properties中找到变量,将名字复制到struts.xml中进行覆盖它的值。

    1. 配置文件的分离

     

    【开发场景】

    在大部分应用里,随着应用规模的增加,系统中Action的数量也会大量增加,导致struts.xml配置文件变得非常臃肿。为了避免struts.xml文件过于庞大、臃肿,提高struts.xml文件的可读性,我们可以将一个struts.xml配置文件分解成多个配置文件,然后在struts.xml文件中包含其他配置文件。下面的struts.xml通过<include>元素指定多个配置文件:

     

    <struts>

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

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

    </struts>

     

    通过这种方式,我们就可以将Struts 2的Action按模块添加在多个配置文件中。

    Struts.xml引用其他配置文件

    如下:

     

    1. Action的编写和方法访问

      1. Action编写的三种方式

    Struts2支持三种书写Action的方式

     

    1. 自定义类实现Action

    步骤一:新建包和action

    新建一个包:cn.itcast.struts.c_action

    Action : 

    public class Demo1Action implements Action{

     

        @Override

        public String execute() throws Exception {

            System.out.println("action的第一中编写方式:实现action接口");

            return NONE;

        }

     

    }

     

    步骤二:配置Struts.xml :

    不配置结果集视图

    <!-- action的第一种编写方式:实现action接口 -->        

            <action name="demo1" class="cn.itcast.struts.c_action.Demo1Action"/>

     

    步骤三:测试

    执行结果没有响应,原因是返回了NONE的结果集名称

    后台打印:

     

    【内置的视图名称】

    Action 接口提供一组 常用的内置的逻辑视图名称:

    • SUCCESS 成功视图
    • NONE 没有结果视图,用户自己生成响应数据
    • ERROR 错误视图
    • INPUT 输入视图 (数据输入非法,要求用户重新输入)
    • LOGIN 登陆视图 (如果用户未登陆,使用登陆视图)
    1. 自定义类继承ActionSupport(重点)

    步骤一:编写Action

    public class Demo2Action extends ActionSupport{

        @Override

        public String execute() throws Exception {

            System.out.println("action的第二中编写方式:实现ActionSupport");

            return NONE;

        }

    }

     

    步骤二:配置Struts.xml

    <!-- action的第二中编写方式:实现ActionSupport -->

            <action name="demo2" class="cn.itcast.struts.c_action.Demo2Action"/>

     

    步骤三:测试

     

     

     

    这个编写方式是我们最常用的,ActionSupport实现了更多的接口,更加有利于扩展。

     

    1. 自定义POJO(了解)

    POJO(Plain Old Java Object简单的Java对象),实际就是普通的JavaBean。

    struts2使用反射的机制来进行调用执行。

    【注意】关于execute方法的编写要求,必须满足:

    • public修饰符
    • String返回值
    • 无参数方法

     

    步骤一:编写Action

    需要手动编写execute方法---固定为 public Stirng execute(){}(还没有讲到方法编写,这是暂时的写法)

    public class Demo3Action {

        public String execute(){

            System.out.println("action的第三种编写方式:自定义pojo作为action");

            return "none";

        }

    }

     

     

    步骤二:配置Struts.xml 

    <!-- action的第三种编写方式:自定义pojo作为action -->

            <action name="demo3" class="cn.itcast.struts.c_action.Demo3Action"/>

     

    步骤三:测试

    后台打印:

     

    其实,pojo的方式,底层使用反射机制,自动调用execute方法

     

    【小结】

    一般情况下都使用继承ActionSupport类的方法

    其他两种,大家了解就行了。

     

    1. Action的方法编写(重点)

    问题:是不是默认只能执行execute这个方法?是不是只能写一个方法呢?

    否。

    Action访问指定方法的方式:

    1. execute
    2. 可以通过method属性来指定需要执行的方法
    3. 通过通配符来指定需要执行的方法(重点)
    4. 通过动态方法调用来执行需要执行的方法

     

    一个action类中可以编写N个方法。

    但Action类中的可执行的方法必须满足(名字可以任意):

    • public修饰符
    • String返回值
    • 方法无参数

     

    1. 通过设置method属性来调用action中的方法

    通过action标签中的method属性来指定所要执行的方法

    【示例】

    步骤一:创建新的包名和Action 

    新建一个包:cn.itcast.struts.d_method

    Action :

    public class UserAction extends ActionSupport{

        @Override

        public String execute() throws Exception {

            System.out.println("默认方法执行!");

            return super.execute();

        }

        

        public String login(){

            System.out.println("登录成功");

            return NONE;

        }

        

        public String register(){

            System.out.println("注册成功");

            return NONE;

            

        }

    }

     

    步骤二:创建响应页面

    Login.jsp:

    <body>

    <h1>用户登录成功!</h1>

    </body>

    Register.jsp

    <body>

    <h1>用户注册成功!</h1>

    </body>

    Success.jsp:

    <body>

        <h1>success!</h1>

    </body>

     

     

    步骤三:配置Struts.xml

    <!-- action访问指定方法 -->

            <!-- 方法login方法 -->

            <action name="user_login" class="cn.itcast.struts.d_method.UserAction" method="login">

                <result name="login">/d_method/login.jsp</result>

            </action>

            <!-- 访问register -->

            <action name="user_register" class="cn.itcast.struts.d_method.UserAction" method="register">

                <result name="register">/d_method/register.jsp</result>

            </action>

     

    步骤四:测试

    执行请求:由于有两个方法,因此需要执行两次请求。

    执行注册请求:

     

    步骤五:分析

     

    注意:如果访问路径名称以及返回结果集视图使用通配符以及{1}的话,需要保证,请求路径的名称能在action标签中找到,如果使用{1}来访问指定方法和响应结果集的话,要保证方法名称和响应的结果集视图名称一致,而且必须保证结果集视图页面的名称也要一致

     

     

    问题:如果要写的业务方法非常多,那是不是每一个方法都要写一个action,感觉非常繁琐。

    有没有更好的方法解决?

    1. 使用通配符进行方法调用

    单纯使用method属性来配置action的方法,如要调用不同的方法,需要配置不同的action。配置较多。

    解决方案就是使用通配符,可实现仅通过一个method属性,就可以配置一个action中的N方法的访问。

    1. 单个通配符的使用

    步骤一:Action 

    使用之前的例子即可

     

    步骤二:配置Struts.xml

     

    步骤三:测试

    执行请求

    后台打印:

     

     

    步骤四:分析

     

    1. 两个通配符的使用

    【示例】

    步骤一:Action 

    使用之前的例子即可

     

    步骤二:配置Struts.xml 

     

    步骤三:测试

    执行请求

    后台打印:

     

    一般两个*就差不多是极限了,三个的话就没法看了,可读性非常差。

     

    1. 动态方法调用(了解)

    【示例】

    步骤一:需要开启常量中的动态方法调用

     

    步骤二:Action 

    使用之前的例子即可

     

    步骤三:配置Struts.xml 

    需要开启动态方法调用:

    配置action :

     

    步骤四:测试

    执行请求

    后台打印:

     

    步骤五:分析

     

    1. 方法总结

    【小结】

    action方法调用:

    1. 默认的execute方法调用。
    2. method属性指定调用方法。虽可以任意调用任何的方法,但一个方法需要配置一个action。
    3. method属性+通配符。可以使用一个配置,调用N方法和结果集。(重点--推荐)
    4. 动态方法调用,可以不配置method属性也能随意调用aciton中的任意方法。但必须开启动态方法调用,而且不能通过一个result标签随意配置N个结果集。
      1. Action访问Servlet相关API

    struts2默认情况下将servlet api都隐藏起来了,为了简化开发。但很多时候,我们还需要调用servlet api,比如,向session中放入一个登录用户。

    分析通过3种方式操作servlet的api。

    • 解耦方式(了解)
    • 接口注入方式(了解)
    • 静态方法(重点)

     

    1. 解耦合方式调用(间接调用)-了解

    解耦相对于耦合,这里举例:

    编写自己的Servlet的时候的调用方法doGet(HttpServletRequest, HttpServletReponse) ,需要直接在代码中依赖servletContext的 request和 response,这就是耦合。

        Struts2设计思想就是与Servlet API 解耦合,编写Action 代码中可以不再直接依赖Servlet的任何API,简化开发,也便于测试(方法简单无参)。

        那如果我们想调用这些API呢?比如向session中放入登录用户、向request中放入一个值给页面响应用。

        struts2为我们提供了一个API,可间接调用servlet api,这个api叫做:ActionContext 类 (Action 上下文 )。(可以理解该类就是一个工具类)

        【回顾了解】上下文: 与容器相关,获取容器相关对象、信息 ---- 类似于一个工具类 (如servletcontext,可以拿到一些关于web应用服务范围的一些对象信息,pageContext可以拿到关于jsp页面的一些对象信息)。

        该API提供大量间接操作Servlet API (request、 response、 session、application) 方法:

     

    提示:间接操作是指面向map的操作,而不是直接操作相关对象。通过操作map就相当于操作相关对象。

     

    【示例】

    步骤一:创建一个新的包和类

    //解耦方式调用servlet API

    public class IndirectAction extends ActionSupport{

        @Override

        public String execute() throws Exception {

            Map<String, Object> map = ActionContext.getContext().getParameters();

            String[] str = (String[]) map.get("name");

            System.out.println(str[1]);

            Map requestMap = (Map) ActionContext.getContext().get("request");

            requestMap.put("name", str[1]);

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

            sessionMap.put("name", "session_name");

            return SUCCESS;

        }

    }

     

     

    步骤二:配置struts.xml

    <!-- 解耦方式调用servlet API -->

            <action name="indirect" class="cn.itcast.struts.e_servlet.IndirectAction">

                <result>/e_servlet/success.jsp</result>

            </action>

     

     

    步骤三:配置响应页面

    结果页面success.jsp:

     

    步骤四:测试

    请求url

     

    1. 接口注入方式操作Servlet API(了解)

    获取Context需要实现ServletContextAware

    获取Request需要实现ServletRequestAware

    获取Response需要实现ServletResponseAware

    【示例】

    步骤一:编写Action 

    public class InjectAction extends ActionSupport implements ServletRequestAware,

            ServletContextAware {

     

        private HttpServletRequest request;

        private ServletContext context;

     

        @Override

        public String execute() throws Exception {

            String name = request.getParameter("name");

            request.setAttribute("name", name);

     

            request.getSession().setAttribute("name", "郭芙蓉");

     

            return super.execute();

        }

     

        @Override

        public void setServletRequest(HttpServletRequest request) {

            this.request = request;

        }

     

        @Override

        public void setServletContext(ServletContext context) {

            this.context = context;

     

        }

    }

     

    步骤二:Struts.xml 

    需要创建一个新的结果集视图injectDemo.jsp

    <!-- 接口注入方式调用servlet API -->

            <action name="inject" class="cn.itcast.struts.e_servlet.InjectAction">

                <result>/e_servlet/success.jsp</result>

            </action>

     

     

    步骤三:测试

    执行请求

     

    1. 通过ServletActionContext 类的静态方法直接获取Servlet API (推荐

     

    步骤一:编写Action 

    public class DirectAction extends ActionSupport{

        @Override

        public String execute() throws Exception {

            

            String name = ServletActionContext.getRequest().getParameter("name");

            ServletActionContext.getRequest().setAttribute("name", name);

            

            ServletActionContext.getRequest().getSession().setAttribute("name", "苏菲玛索");

            

            return super.execute();

        }

     

    }

     

    步骤二:配置Struts.xml 

    配置响应结果集:

    <!-- 静态方法直接调用 -->

            <action name="direct" class="cn.itcast.struts.e_servlet.DirectAction">

                <result>/e_servlet/success.jsp</result>

            </action>

     

     

    步骤三:测试

    执行请求

     

     

    【扩展问题】

    ServletActionContext 获取 request方法 是 static的, 有没有线程问题 ?

        会不会出现,获取错request对象的情况 ---- 不会的 (底层:ThreadLocal

        存储着每个线程的变量副本,每个线程只能取自己的value。

     

    1. result结果集的使用

    该节分为两个知识点:

    1. 局部结果集和全局结果集。
    2. 结果集类型。

     

    1. 局部结果集和全局结果集

      1. 局部结果集

    在<action> 标签内部配置的<result>元素。

    作用范围:只对当前Action有效

    【举例】

    步骤一:创建包和类

    创建工程:

    ProductAction :

    public class ProductAction extends ActionSupport {

        @Override

        public String execute() throws Exception {

            System.out.println("默认执行的方法!");

            

            return super.execute();

        }

        

        public String save (){

            System.out.println("保存商品成功!");

            return "save";

        }

    }

     

    步骤二:配置Struts.xml 

    <!-- 结果集的使用:局部结果集 -->

            <action name="product_save" class="cn.itcast.struts.f_result.ProductAction" method="save">

                <result name="save">/f_result/save.jsp</result>

            </action>

     

     

    步骤三:创建响应页面

     

    save.jsp:

     

    步骤四:测试

    执行请求:报错,找不到product这个类

    原因是:之前的双通配符的配置的作用使我们发送的请求走错地方了,要先把这个配置给注释掉。

     

    再次测试:

    注意:如果有用到两个或者两个以上的通配符,此时要注意在这个通配符所在的action标签的下方有没有用到其他通配符的action,如果有,就可能发生不可预知的错误。

     

     

    问题:如果有几个action中的响应结果集都是指向同一个jsp页面—index.jsp,是不是每一个action都要配置一下?

    答 :可以使用全局结果集

     

     

    1. 全局结果集

    在包的标签中的<global-results>中配置

    作用范围:对package内所有Action生效

     

    一般是用来对几个不同的action响应相同的结果集视图使用的

     

    【举例】 ProductAction和UserAction都有方法需要响应同一个结果集视图

    步骤一:给两个不同的action配置相同的结果集视图

    UserAction:使用之间的action即可

    public class UserAction extends ActionSupport{

        @Override

        public String execute() throws Exception {

            System.out.println("默认方法执行!");

            return super.execute();

        }

        

        public String login(){

            System.out.println("登录成功");

            return "login";

        }

        

        public String register(){

            System.out.println("注册成功");

            return "register";

            

        }

    }

    ProductAction :

    public class ProductAction extends ActionSupport {

        @Override

        public String execute() throws Exception {

            System.out.println("默认执行的方法!");

            

            return super.execute();

        }

        

        public String save (){

            System.out.println("保存商品成功!");

            return "save";

        }

    }

     

     

    步骤二:配置Struts.xml 

    配置全局结果集并把局部结果集注释掉:

     

    提示:该标签有配置顺序,将鼠标悬停在<package >标签上是可见如下提示

     

    注意:局部结果集会覆盖全局结果集

     

    步骤三:创建结果集视图

    success.jsp :

     

    步骤四:测试

     

    访问无误

     

    补充

    注意:package中的任何标签配置都是有顺序的。

     

    1. 结果集类型

    作用:控制响应的方式转发、重定向)

    配置<result> 元素时, name是逻辑视图名称, type是结果集类型。

    Struts2提供的常用结果集类型都定义在struts-default.xml 中:

    内置的结果集类型:最常用的就是红框中的几个结果集类型

    1. 转发-dispatcher

    dispatcher(默认值):请求转发。(最常用)

    作用:服务器内部是同一次请求,可采用request传递数据,URL不变。

     

    【举例】

    步骤一:action

    修改ProductAction中的save方法:添加数据

     

    public class ProductAction extends ActionSupport{

        @Override

        public String execute() throws Exception {

            System.out.println("执行默认方法!");

            return SUCCESS;

        }

        

        public String save(){

            System.out.println("保存商品成功!");

            ServletActionContext.getRequest().setAttribute("name","iphone 7 plus");

            return "save";

        }

    }

     

     

    步骤二:配置struts.xml

     

    步骤三:修改save.jsp页面,显示数据:

     

    步骤四:测试

    执行请求

     

    1. 重定向-redirect

    步骤一:配置struts.xml

     

    全局的结果集配置:

     

    还是利用上述的save方法做举例,修改strust.xml中的结果集类型即可。

    <!-- 结果集的使用:局部结果集 -->

            <action name="product_*" class="cn.itcast.struts.f_result.ProductAction"

                method="{1}">

                <!-- 结果集类型的默认值:转发 -->

                <!-- <result name="save" type="dispatcher">/f_result/save.jsp</result> -->

                <!-- 结果集类型的重定向 -->

                

                <!-- <result type="redirect">/f_result/success.jsp</result> -->

            </action>

     

    步骤二:测试

    执行请求

     

    1. 重定向到Action- redirectAction

     

     

    之前的转发和重定向都是指向页面,但有的时候我们需要执行action,例如:当做完新增商品之后,需要重新查询商品列表,这个时候就需要指向action了

    【举例】

    商品保存后重定向到查询action

     

    步骤一:action

    ProductAction中的save方法保持不变,新增一个findAll方法:

    public class ProductAction extends ActionSupport{

        @Override

        public String execute() throws Exception {

            System.out.println("执行默认方法!");

            return SUCCESS;

        }

        

        public String save(){

            System.out.println("保存商品成功!");

            ServletActionContext.getRequest().setAttribute("name","iphone 7 plus");

            return "save";

        }

        

        public String findAll(){

            System.out.println("查询所有商品成功!");

            return "findAll";

        }

    }

     

     

    步骤二:Struts.xml :修改save结果集视图

     

    步骤三:测试

    执行请求:发送新增商品的请求,执行完新增商品后重定向到product_findAll这个action,最后转发到index.jsp页面显示hello world

     

    步骤四:分析

     

    【result标签复杂写法】(了解)

    其他写法:使用<param>标签传递参数的写法

    注意param中的name属性值可以参考结果集相应的类:

     

     

     

     

    1. 课程内容整理

      1. 示例的编写步骤

    创建一个案例需要的步骤:

    1. 创建项目
    2. 导包
    3. 在web.xml中配置前端控制器
    4. 创建包
    5. 创建提交数据的页面
    6. 配置struts.xml
    7. 测试
      1. 常用配置的注意事项

    总格6个配置文件,分成两大类:

    1. 框架内置的配置文件:不能修改

      default.properties :常量配置

      struts-default.xml :配置了struts需要的bean、各类结果集以及拦截器(默认执行的拦截器栈-defaultStack

      struts-plugin.xml :struts的插件包需要的配置文件

    2. 用户自定义的配置文件:

      struts.xml:前端控制器会读取该配置文件中的标签来判断应该分发给哪个action,并且执行哪个action中的方法,最后响应哪一个结果集视图。

      struts.properties:只是用来配置常量的(了解)

      web.xml :配置常量(了解)

      潜规则:后面配置的常量会覆盖前面配置的常量

       

      加载顺序:1)default.properties  2)struts-default.xml  3)struts-plugin.xml 4)struts.xml 5)struts.properties 6)web.xml配置常量

    3、默认的Action :配置错误请求需要默认执行的action,一般用来配置友好提示。

    1. Action的编写方式

    1. 实现Action接口(掌握)
    2. 继承ActionSupport(重点,必须掌握)
    3. 自定义pojo作为action(了解)
      1. Action访问的方法

    4. execute方法:访问action默认执行
    5. method属性:访问指定方法
    6. 通配符的使用:可以通过*表示占位{1}表示第一颗的占位。(重点掌握)

      注意事项:如果有两个通配符,先注意下方是不是有其他的通配符的使用,以免造成访问路径的错误。

    7. 动态方法调用:不需要配置method属性,通过!后面的单词来调用指定的方法,需要配置常量-开启动态方法调用。

     

    1. Action访问servlet API

    1. 解耦方式调用servlet API 
    2. 接口注入方式调用servlet API :实现接口方法,并且通过setter方法进行对象的传递。
    3. 静态方法调用:推荐使用

     

    1. Result结果集的使用

    1. 分为全局和局部结果集
    2. 结果集类型的使用:dispatcher 、redirect、redirectAction、stream

     

    1. 重点和小结

     

    课后作业练习

    需求:开发一个登录的小业务。

    业务详情:

    用户输入的用户名密码错误,跳回登录页面,让用户重新登录。

    用户输入的用户名密码正确,重定向到主页,显示成功字样。--SUCCESS

    技术选型:Struts2(Web层)

     

     

  • 相关阅读:
    BOT、BT、PPP形式介绍(3)
    BOT、BT、PPP形式介绍(2)
    BOT、BT、PPP形式介绍(1)
    Linux系统下C++开发工具-远程终端软件使用
    Linux开发工具的使用
    libjingle开发人员指南
    优雅处理段错误
    捕捉段错误信号信号处理程序
    段错误bug的调试
    docker核心概念(镜像、容器、仓库)及基本操作
  • 原文地址:https://www.cnblogs.com/beyondcj/p/6270933.html
Copyright © 2011-2022 走看看