zoukankan      html  css  js  c++  java
  • Struts学习总结 学习

    ContextMap 包含值栈包含 root(list结构)和context(map结构)  值栈包含contextMap的引用.  Actioncontext是工具类 可以获取他们

    Struts2拥有优良的设计和功能,其优势具体如下:  优点

    l 项目开源,使用及拓展方便,天生优势。

    提供Exception处理机制。

    l Result方式的页面导航,通过Result标签很方便的实现重定向和页面跳转。  全局结果视图

    l 通过简单、集中的配置来调度业务类,使得配置和修改都非常容易。

    l 提供简单、统一的表达式语言来访问所有可供访问的数据。

    l 提供标准、强大的验证框架和国际化框架。

    l 提供强大的、可以有效减少页面代码的标签。

    提供良好的Ajax支持。

    l 拥有简单的插件,只需放入相应的JAR包,任何人都可以扩展Struts2框架,比如自定义拦截器、自定义结果类型、自定义标签等,为Struts2定制需要的功能,不需要什么特殊配置,并且可以发布给其他人使用。

    l 拥有智能的默认设置,不需要另外进行繁琐的设置。使用默认设置就可以完成大多数项目程序开发所需要的功能。

    上面列举的就是Struts2的一系列技术优势,只需对它们简单了解即可,在学习了后面的知识后,会慢慢对这些技术优势有更

    好的理解和体会。

     

    请简述下Struts2 的执行流程.

    首先是,启动tomcat服务器,这时候会加载web.xml,当读到filter标签时,会创建过滤器对象。struts2的核心过滤器(StrutsPrepareAndExecuteFilter)会负责加载类路径下的struts.xml配置文件。接下来,从客户端发送请求过来 先经过前端控制器(核心过滤器StrutsPrepareAndExecuteFilter),前端控制器会根据请求的名称在struts.xml中找到对应的配置,创建我们的动作类对象(每次访问时都会创建新的Action对象),然后执行指定的方法,根据方法的返回值找到Result的配置进行页面的跳转.最后响应浏览器。

     加载struts2的配置文件,他们的加载顺序及作用.

    default.properties

    struts-default.xml

    strtuts-plugin.xml

    struts.xml

    struts.properties

    web.xml

    当多个配置文件中,有相同的参数,后加载的配置文件中的值会把前面加载的配置文件的值给覆盖了。

     实现一下动作类的三种创建方式.

    第一种:无侵入式创建一个action实现一个跳转(实际开发中基本不用)

    第二种:实现Action接口的定义方式 (实际开发中用的也不多)

    第三种:继承ActionSupport (们实际开发中采用的方式)

    1. Struts2与Struts1的联系与区别是什么?为什么要用Struts2?

    答案:

    struts1与struts2都是mvc框架的经典实现模式。

    Struts2不是从Struts1升级而来,而是有WebWork改名而来,Struts 2以WebWork为核心,采用拦截器的机制来处理用户的请求

    区别:(了解几条即可)

    1.核心控制器改成了过滤器(过滤器比Servlet的级别要高,因为程序运行时是先进入过滤器再进入Servlet)

    2.struts1要求业务类必须继承Action或dispatchAction,struts2不强制这么做,只需要提供一个pojo

    3.绑定值到业务类时struts1是通过ActionForm,struts2是通过模型或属性驱动直接绑定到Action属性。

    4.struts1严重依赖于Servlet(因为太过于依赖于api的HttpServletRequest与HttpServletResponse的两个参数),

    struts2就则脱离了Servlet的API。

    5.管理Action时struts1是单例模式,struts2是每个请求产生一个实例

    6.在表达式的支持上struts2不仅有jstl,还有功能更加强大的ognl表达式

    7.struts1的类型转换是单向的(页面到ActionForm),struts2是双向的(页面到Action再到页面回显)

    8.校验,struts1没有针对具体方法的校验,struts2提供了指定某个方法进行效验,还有框架校验。

     请求(.action)---->经过StrutsPrepareAndExecuteFilter 核心控制器---->进入到Struts2的拦截器Interceptor(实现代码功能)----->通过action的名称找对应的Action类----->执行Action类的execute方法----->通过execute方法中返回的字符串,在Struts.xml中找对应的结果页面(result)【在action执行之前,执行了defaultStack拦截器栈】

    * 拦截器 在 struts-default.xml定义 【它位于sruts2-core-xxx.jar目录下】

    * 执行拦截器 是 defaultStack 中引用拦截器

     获取域对象的两种方式 例如获取request

    1.1 使用ServletActionContext

    为了直接访问Servlet APIStruts2框架提供了ServletActionContext类,在实际开发中,这也是我们采用最多的方式。该类包含了几个常用的静态方法,具体如下:

    l static HttpServletRequest getRequest():获取Web应用的HttpServletRequest对象。

    l static HttpServletResponse getResponse():获取Web应用的HttpServletResponse对象。

    l static ServletContext getServletContext():获取Web应用的ServletContext对象。

    l static PageContext getPageContext():获取Web应用的PageContext对象。

    接下来,讲解如何通过ServletActionContext访问Servlet API。使用方式如下:

    /**

     * struts2框架中有三种方式可以获取到ServletAPI对象

     * ServletAPI对象包含了:

     * request,response,HttpSession,ServletContext

     * 第一种方式:

     * 使用的是ServletActionContext对象,它里面提供了一些静态方法,可以让我们获取到ServletAPI

     * 此种方式,使我们实际开发中采用最多的方式

     * 此时我们还要记住一件事:

     * 这四个对象,有一个已经变了,和其他三个不一样,找出来,记住。

     *

     * org.apache.struts2.dispatcher.StrutsRequestWrapper@1577071 它是那个不一样的

    org.apache.catalina.connector.ResponseFacade@1973ca4

    org.apache.catalina.session.StandardSessionFacade@e4d72

    org.apache.catalina.core.ApplicationContextFacade@fe7e93

     *

     */

    public class HelloAction extends ActionSupport{

     

    private HttpServletRequest request;

    private HttpServletResponse response;

    private HttpSession session;

    private ServletContext application;

    /**

     * @return

     */

    public String sayHello(){

    request = ServletActionContext.getRequest();

    response = ServletActionContext.getResponse();

    session = request.getSession();

    application = ServletActionContext.getServletContext();

     

    System.out.println(request);

    System.out.println(response);

    System.out.println(session);

    System.out.println(application);

    return SUCCESS;

    }

    }

    1.2 通过实现接口的方式

    Struts2还提供了一系列接口,具体如下:

    l ServletRequestAware:实现该接口的Action可以直接访问Web应用的HttpServletRequest实例。

    l ServletResponseAware:实现该接口的Action可以直接访问Web应用的HttpServletResponse实例。

    l SessionAware:实现该接口的Action可以直接访问Web应用的HttpSession实例。

    l ServletContextAware:实现该接口的Action可以直接访问Web应用的ServletContext实例。

    /**

     * struts2框架中有三种方式可以获取到ServletAPI对象

     * ServletAPI对象包含了:

     * request,response,HttpSession,ServletContext

     * 第三种方式:

     * 采用实现接口的方式,来获取对象

     * 能够使用对象的原因:

     * 是因为在我们的sayHello方法执行之前,已经有一些拦截器执行了。

     *  通过struts-default.xml我们能知道默认的拦截器栈defaultStack,

     *  在我们的动作配置时,默认就会有该拦截器栈中的所有拦截器执行。先正序,再倒序。

     *  

     *  帮我们给对象赋值全靠一个名称为servletConfig的拦截器

     *  

     *  拦截器的重要性:

     *   他可以在不改变我们动作方法的代码基础上,对我们的动作方法进行增强。

     */

    public class Hello3Action extends ActionSupport

    implements ServletRequestAware,ServletResponseAware,ServletContextAware{

     

    private HttpServletRequest request;

    private HttpServletResponse response;

    private HttpSession session;

    private ServletContext application;

    /**

     * @return

     */

    public String sayHello(){

     

    session = request.getSession();

     

    System.out.println(request);

    System.out.println(response);

    System.out.println(session);

    System.out.println(application);

    return SUCCESS;

    }

     

    @Override

    public void setServletRequest(HttpServletRequest request) {

    this.request = request;

    }

    @Override

    public void setServletResponse(HttpServletResponse response) {

    this.response = response;

    }

    @Override

    public void setServletContext(ServletContext application) {

    this.application = application;

    }

     

     

    }

    1. 值栈ValueStack的原理与生命周期?  

    答案:

    1)ValueStack贯穿整个 Action 的生命周期,保存在request域中,所以ValueStack和request的生命周期一样。当Struts2接受一个请求时,会迅速创建ActionContext工具类,  

    ValueStack,action。然后把action存放进ValueStack,所以action的实例变量可以被OGNL访问。请求来的时候,action、ValueStack的生命开始,请求结束,action、ValueStack的生命结束;  

    2)action是多例的,和Servlet不一样,Servelt是单例的;  

    3)每个action的都有一个对应的值栈,值栈存放的数据类型是该action的实例,以及该action中的实例变量,Action对象默认保存在栈顶;  

    4)ValueStack本质上就是一个ArrayList;  

    5)关于ContextMap,Struts 会把下面这些映射压入 ContextMap 中:  只能用%{#取出}

    parameters  :   该 Map 中包含当前请求的请求参数  

    request     :   该 Map 中包含当前 request 对象中的所有属性  session :该 Map 中包含当前 session 对象中的所有属性  

    application :该 Map 中包含当前 application 对象中的所有属性  

    attr:该 Map 按如下顺序来检索某个属性: request, session, application           

    6)使用OGNL访问值栈的内容时,不需要#号,而访问request、session、application、attr时,需要加#号;  

    7)注意: Struts2中,OGNL表达式需要配合Struts标签才可以使用。如:<s:property value="name"/>  

    8)在struts2配置文件中引用ognl表达式 ,引用值栈的值 ,此时使用的"$",而不是#或者%;  

     OGNL表达式和EL表达式的区别

    OGNL可以访问静态属性和静态方法  

    随机数:<s:property value="@java.lang.Math@random()"/>

     

    1.1.1 OGNL表达式创建集合

    1.1.1.1 list集合

    HTML在浏览器上输出一个单选性别:

    <input type="radio" name="gender" value=""/>

    <input type="radio" name="gender" value=""/>

    <br/>

    Struts2的单选按钮标签输出一个单选

    <%--s:radio用于在浏览器上显示一个单选按钮

    list属性取值是一个OGNL表达式

    {}就表示创建了一个List集合 List list = new ArrayList();

    {'',''}

    list.add("");list.add("");

    --%>

    <s:radio name="gender" list="{'',''}" label="性别"/>

    1.1.1.2 map集合

    HTML在浏览器上输出一个单选性别:Map结构

    <input type="radio" name="gender" value="male"/>

    <input type="radio" name="gender" value="female"/>

    <br/>

    <%--#{}就表示创建了一个Map

    里面的写法

    #{'key':'value','key':'value'......}

     --%>

    <s:radio name="gender" list="#{'male':'','female':''}" label="性别"/>

     

     

    1.1 ActionContext

    1.1.1 ActionContext对象概述

    它是一个工具类,是struts2框架提供给我们的,可以让我们调用其中的方法,快速的操作ContextMap。用它操作OGNL上下文对象,比直接操作ContextMap要方便很多。

    1.1.2 ActionContext对象以及和ContextMap的关系

    ActionContext就相当于对ContextMap进行了一次再封装

    1.1.3 ActionContext何时创建

    由于ActionContext是操作的ContextMapContextMap中封了我们一次请求的所有数据,所以它的创建应该是每次请求访问Action时,即核心控制器(StrutsPrepareAndExecuteFilter)doFilter方法执行时,下图是代码截取:

    1.1.1 ValueStack对象概述

    ValueStackStruts的一个接口,字面意义为值栈,OgnlValueStack是ValueStack的实现类,客户端发起一个请求struts2架构会创建一个action实例同时创建一个OgnlValueStack值栈实例,OgnlValueStack贯穿整个 Action 的生命周期。

    它是ContextMap中的一部分,里面的结构是一个List,是我们可以快速访问数据一个容器。它的封装是由struts2框架完成的。

    通常情况下我们是从页面上获取数据。它实现了栈的特性(先进后出)。

    1.1.2 ValueStack的内部结构

    OnglValueStack 中包含了一个CompoundRoot的对象和context上下文对象,该对象继承了ArrayList,并且提供了只能操作集合第一个元素的方法,所以我们说它实现了栈的特性。同时,它里面定义了一个ContextMap的引用,也就是说,我们有值栈对象,也可以通过值栈来获取ContextMap

    1.1.1.1 如何让Action中定义的成员出现在值栈中

    Action定义一个私有属性,并且提供公有get/set方法,那么该属性就会出现在值栈的Property Name中。显示的名称是根据get/set方法后面的内容决定的,与私有成员变量名称叫什么无关。

    EL表达式原来的搜素顺序:

    page Scope——>request Scope——>sessionScope——>application Scope

    EL表达式改变后的搜索顺序:

    page Scope>request Scope>valueStack>contextMap>sessionScope>application Scope

     

     

    在不修改源码的基础上,已有的方法进行动态增强。

     

    struts2中,拦截器它就是对我们的动作方法进行增强。(其实就是把重复性的代码提取出来,然后放到拦截器中,统一管理,统一调用)

    1.1 自定义拦截器

    在程序开发过程中,如果需要开发自己的拦截器类,就需要直接或间接的实现com.opensymphony.xwork2.interceptor.Interceptor接口。其定义的代码如下:

    public interface Interceptor extends Serializable {

    void init();

    void destroy();

        String intercept(ActionInvocation invocation) throws Exception;

    }

    该接口提供了三个方法,其具体介绍如下。

    l void init():该方法在拦截器被创建后会立即被调用, 它在拦截器的生命周期内只被调用一次. 可以在该方法中对相关资源进行必要的初始化。

    l void destroy():该方法与init方法相对应,在拦截器实例被销毁之前,将调用该方法来释放和拦截器相关的资源。它在拦截器的生命周期内,也只被调用一次。

    l String intercept(ActionInvocation invocation) throws Exception该方法是拦截器的核心方法,用来添加真正执行拦截工作的代码,实现具体的拦截操作。它返回一个字符串作为逻辑视图,系统根据返回的字符串跳转到对应的视图资源。每拦截一个动作请求, 该方法就会被调用一次。该方法的ActionInvocation参数包含了被拦截的Action的引用,可以通过该参数的invoke()方法,将控制权转给下一个拦截器或者转给Actionexecute()方法

    如果需要自定义拦截器,只需要实现Interceptor接口的三个方法即可。然而在实际开发过程中,除了实现Interceptor接口可以自定义拦截器外,更常用的一种方式是继承抽象拦截器类AbstractIntercepter。该类实现了Interceptor接口,并且提供了init()方法和destroy()方法的空实现。使用时,可以直接继承该抽象类,而不用实现那些不必要的方法。拦截器类AbstractInterceptor中定义的方法如下所示:

    public abstract class AbstractInterceptor implements Interceptor {

        public void init() {}

        public void destroy() {}

        public abstract String intercept(ActionInvocation invocation)

    throws Exception;

    }

    从上述代码中可以看出,AbstractInterceptor类已经实现了Interceptor接口的所有方法,一般情况下,只需继承AbstractInterceptor类,实现interceptor()方法就可以创建自定义拦截器。

    只有当自定义的拦截器需要打开系统资源时,才需要覆盖AbstractInterceptor类的init()方法和destroy()方法。与实现Interceptor接口相比,继承AbstractInterceptor类的方法更为简单。

    当然还有更简单的,AbstractInterceptor还有一个子类,MethodFilterInterceptor,该类中提供了两个属性,可以告知拦截器对哪些方法进行拦截或者对哪些方法排除。

    1.1.1 自定义步骤

    通过在拦截器类视图上我们可以得知,我们定义拦截器可以有三种办法:

    第一种:定义一个类,实现Interceptor接口

    第二种:定义一个类,继承AbstractInterceptor

    第三种:定义一个类,继承MethodFilterInterceptor

    看完两个类之后,我们有了结论。即:选择第三种方式,比第二种多了一个功能,就是告知拦截器哪些方法我们需要拦截,哪些方法我们不需要拦截。(注意:不要想着很傻的问题,在需要拦截和不需要拦截的属性中提供同一个方法

    1.1.1 配置拦截器

    <!-- 一个公共包 -->

    <package name="myDefault" extends="struts-default" abstract="true">

    <!-- 声明拦截器 -->

    <interceptors>

    <interceptor name="checkLogin" 

    class="com.itheima.web.interceptors.CheckLoginInterceptor"/>

    <!-- 定义一个拦截器栈 -->

    <interceptor-stack name="myDefaultStack">

    <interceptor-ref name="checkLogin">

    <!-- 由于我们使用了继承MethodFilterInterceptor

    此时我们可以告知拦截器,排除掉登录方法 -->

    <param name="excludeMethods">login</param>

    </interceptor-ref>

    <interceptor-ref name="defaultStack"></interceptor-ref>

    </interceptor-stack>

    </interceptors>

     

    <!-- 修改默认拦截器栈,设置我们自定义的拦截器栈

    这样的话我们写的所有动作都有了检查登录功能。并且排除了登录方法-->

    <default-interceptor-ref name="myDefaultStack"/>

     

    <!-- 全局结果视图 -->

    <global-results>

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

    </global-results>

    </package>

     

     

     

     

     

     

     

    1.1.1 @InterceptorRef

    出现的位置:

    它可以出现在动作类上或者Action注解中。

    作用:

    用于配置要引用的拦截器或者拦截器栈

    属性:

    value用于指定拦截器或者拦截器栈

    示例:

    出现在动作方法上:

    /**

     * 查询所有客户

     * @return

     */

    @Action(value="findAllCustomer",results={

    @Result(name="findAllCustomer",location="/jsp/customer/list.jsp")

    },interceptorRefs={

    @InterceptorRef("myDefaultStack")

    })

    public String findAllCustomer(){

    customers = customerService.findAllCustomer();

    return "findAllCustomer";

    }

     

    出现在动作类上:

    @InterceptorRef("myDefaultStack")

    public class CustomerAction extends ActionSupport implements ModelDriven<Customer> {

    private Customer customer = new Customer();

     

    @Override

    public Customer getModel() {

    return customer;

    }

    }

     

    OgnlValueStack贯穿整个 Action 的生命周期。

    它是ContextMap中的一部分,里面的结构是一个List,是我们可以快速访问数据一个容器。它的封装是由struts2框架完成的。

    通常情况下我们是从页面上获取数据。

    1. 请阐述一下ValueStack的内部结构

    在 OnglValueStack 中包含了一个CompoundRoot的对象,该对象继承了ArrayList,并且提供了只能操作集合第一个元素的方法,所以我们说它实现了栈的特性。同时,它里面定义了一个ContextMap的引用,也就是说,我们有值栈对象,也可以通过值栈来获取ContextMap。

    1. 继承AbstractInterceptor继承MethodFilterInterceptor的区别

    答:MethodFilterInterceptor多了一个功能,就是告知拦截器哪些方法我们需要拦截,哪些方法我们不需要拦截。推荐使用。

     

     

     

    1. 【简答题】拦截器和过滤器的区别

    答:

    拦截器:

    拦截器是struts2框架自己的,只有使用了struts2框架的工程才能用。

    拦截器它是只有进入struts2核心内部之后,才会起作用,如果访问的是jsp, html,css,image或者js是不会进行拦截的。

    过滤器:

    过滤器是servlet规范中的一部分,任何java web工程都可以使用。

    过滤器在url-pattern中配置了/*之后,可以对所有要访问的资源拦截。

    1、①拦截器是基于java的反射机制的,而过滤器是基于函数回调

    2、②过滤器依赖与servlet容器,而拦截器不依赖与servlet容器

    3、③拦截器只能对action请求起作用,而过滤器则可以对几乎所有的请求起作用

    4、④拦截器可以访问action上下文、值栈里的对象,而过滤器不能

    5、⑤在action的生命周期中,拦截器可以多次被调用,而过滤器只能在容器初始化时被调用一次

    拦  拦截器 :是在面向切面编程的就是在你的service或者一个方法,前调用一个方法,或者在方法后调用一个方法比如动态代理就是拦截器的简单实现,在你调用方法前打印出字符串(或者做其它业务逻辑的操作),也可以在你调用方法后打印出字符串,甚至在你抛出异常的时候做业务逻辑的操作。

    配置拦截器 并不拦截login方法

    <package name="myDefault" extends="struts-default">
    <!-- 声明拦截器 -->
    <interceptors>
    <interceptor name="checkLogin"
    class="cn.itcast.action.CheckUserInterceptor"/>
    <!-- 定义一个拦截器栈 -->
    <interceptor-stack name="myDefaultStack">
    <interceptor-ref name="checkLogin">
    <!-- 由于我们使用了继承MethodFilterInterceptor, 此时我们可以告知拦截器,排除掉登录方法 -->
    <param name="excludeMethods">login</param>
    </interceptor-ref>
    <interceptor-ref name="defaultStack"></interceptor-ref>
    </interceptor-stack>
    </interceptors>

    <!-- 修改默认拦截器栈,设置我们自定义的拦截器栈, 这样的话我们写的所有动作都有了检查登录功能。并且排除了登录方法 -->
    <default-interceptor-ref name="myDefaultStack" />

     

     

    1. 举例Struts2中通过拦截器实现了哪些功能?

    答案:

    参数绑定、参数校验、类型转换等

    1. struts2有哪些优点?

    答案:

    1)在软件设计上Struts2的应用可以不依赖于Servlet API和struts API。 Struts2的这种设计属于无侵入式设计;  

    2)拦截器,实现如参数拦截注入等功能;  

    3)类型转换器,可以把特殊的请求参数转换成需要的类型;  

    4)多种表现层技术,如:JSP、freeMarker、Velocity等;  

    5)Struts2的输入校验可以对指定某个方法进行校验;  

    6)提供了全局范围、包范围和Action范围的国际化资源文件管理实现

     支持全局结果视图

    支持Ognl  

  • 相关阅读:
    hdu1003 Max Sum【最大连续子序列之和】
    HDU 2639 骨头收集者 II【01背包 】+【第K优决策】
    poj2184 Cow Exhibition【01背包】+【负数处理】+(求两个变量的和最大)
    HDU 2955_Robberies 小偷抢银行【01背包】
    UVa 562
    HDU 1159 Common Subsequence 【最长公共子序列】模板题
    hdu 5748 Bellovin【最长上升子序列】
    POJ 3903 Stock Exchange 【最长上升子序列】模板题
    UVA 624 CD[【01背包】(输出路径)
    hdu 2546 饭卡【01背包】
  • 原文地址:https://www.cnblogs.com/shan1393/p/9178986.html
Copyright © 2011-2022 走看看