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

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

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

l 提供Exception处理机制。

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

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

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 API,Struts2框架提供了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是操作的ContextMap,而ContextMap中封了我们一次请求的所有数据,所以它的创建应该是每次请求访问Action时,即核心控制器(StrutsPrepareAndExecuteFilter)的doFilter方法执行时,下图是代码截取:

1.1.1 ValueStack对象概述

ValueStack是Struts的一个接口,字面意义为值栈,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()方法,将控制权转给下一个拦截器或者转给Action的execute()方法

如果需要自定义拦截器,只需要实现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  

Struts学习总结 学习的更多相关文章

  1. IT人的自我导向型学习:学习的4个层次

    谈起软件开发一定会想到用什么技术.采用什么框架,然而在盛行的敏捷之下,人的问题逐渐凸显出来.不少企业请人来培训敏捷开发技术,却发现并不能真正运用起来,其中一个主要原因就是大家还没有很好的学习能力.没有 ...

  2. IT人的自我导向型学习:学习的3个维度

    看到大家对我的文章赞了不少,看来大家还比较喜欢看.园子里的一些朋友和我说:”终于又看到你要在园子里发原创文章了.几年前就受益匪浅,经过几年的成长分享来的东西肯定也是精品.“ 感谢大家对我的信任,如果你 ...

  3. Deep Learning(深度学习)学习笔记整理系列之(五)

    Deep Learning(深度学习)学习笔记整理系列 zouxy09@qq.com http://blog.csdn.net/zouxy09 作者:Zouxy version 1.0 2013-04 ...

  4. Deep Learning(深度学习)学习笔记整理系列之(八)

    Deep Learning(深度学习)学习笔记整理系列 zouxy09@qq.com http://blog.csdn.net/zouxy09 作者:Zouxy version 1.0 2013-04 ...

  5. Deep Learning(深度学习)学习笔记整理系列之(七)

    Deep Learning(深度学习)学习笔记整理系列 zouxy09@qq.com http://blog.csdn.net/zouxy09 作者:Zouxy version 1.0 2013-04 ...

  6. Deep Learning(深度学习)学习笔记整理系列之(六)

    Deep Learning(深度学习)学习笔记整理系列 zouxy09@qq.com http://blog.csdn.net/zouxy09 作者:Zouxy version 1.0 2013-04 ...

  7. Deep Learning(深度学习)学习笔记整理系列之(四)

    Deep Learning(深度学习)学习笔记整理系列 zouxy09@qq.com http://blog.csdn.net/zouxy09 作者:Zouxy version 1.0 2013-04 ...

  8. Deep Learning(深度学习)学习笔记整理系列之(三)

    Deep Learning(深度学习)学习笔记整理系列 zouxy09@qq.com http://blog.csdn.net/zouxy09 作者:Zouxy version 1.0 2013-04 ...

  9. Deep Learning(深度学习)学习笔记整理系列之(二)

    Deep Learning(深度学习)学习笔记整理系列 zouxy09@qq.com http://blog.csdn.net/zouxy09 作者:Zouxy version 1.0 2013-04 ...

  10. Deep Learning(深度学习)学习笔记整理系列之(一)

    Deep Learning(深度学习)学习笔记整理系列 zouxy09@qq.com http://blog.csdn.net/zouxy09 作者:Zouxy version 1.0  2013-0 ...

随机推荐

  1. 斯坦福机器学习视频笔记 Week1 线性回归和梯度下降 Linear Regression and Gradient Descent

    最近开始学习Coursera上的斯坦福机器学习视频,我是刚刚接触机器学习,对此比较感兴趣:准备将我的学习笔记写下来, 作为我每天学习的签到吧,也希望和各位朋友交流学习. 这一系列的博客,我会不定期的更 ...

  2. 《python基础教程(第二版)》学习笔记 函数(第6章)

    <python基础教程(第二版)>学习笔记 函数(第6章) 创建函数:def function_name(params):  block  return values 记录函数:def f ...

  3. Linux 查看CPU信息

    Linux查看CPU信息的命令 more /proc/cpuinfo 结果 processor : 0 vendor_id : GenuineIntel cpu family : 6 model : ...

  4. ubuntu下搭建Scrapy框架简单办法

    1. 先执行以下命令 sudo apt-get install python-lxml sudo apt-get install libxslt1-dev sudo apt-get install p ...

  5. jQuery JS 入门记录

    1.类型转换 .toString() 转字符串 . parseInt() parseFloat() 强制转换 数字型(Number) 1.声明 var i = 1; var i = new Numbe ...

  6. npm-install once

    Once 是我最习惯的模块,它展示了几乎所有的我书写的通过issac Schlueter创建的应用. 原理很简单,Once使用各类一个函数且返回了一个函数,你可以调用这个函数,但是只能调用一次.如果你 ...

  7. 关于C++多态的理解

    多态,即多种形态.对于具有继承关系的一类对象,子类表现出了父类的某些特性,但是表现的不一样,这就是多态的现实体现.例如动物可以发声,但是狗是旺旺,狗是动物的一种,但是表现了不同的叫的特点,这就是多态. ...

  8. PyQt5布局管理(1)

    Qt布局管理按简单分可分为绝对位置布局和布局管理器布局 一.绝对位置布局: 组件不放在布局管理器中,通过函数setGeometry(x,y,width,height)来设定组件相对其父窗口的位置.其中 ...

  9. 【二叉树的递归】06填充每个节点中的下一个正确的指针【Populating Next Right Pointers in Each Node】

    ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 给定一个二叉树 struct Tr ...

  10. HDOJ1059(多重背包)

    1.解法一:多重背包 #include<iostream> #include<cstdio> using namespace std; #define MAX(a,b) (a& ...