day25_day27_Struts2_学习回顾


day25_01_学习回顾

 1、Struts2框架在三层架构中哪部分进行的再优化?     答:

        表现层、MVC模式。 2、Struts1和Struts2的一个显著区别是什么?     答:

        Struts1的核心控制器是一个servlet。         Struts2的核心控制器是一个过滤器。 3、Struts2的编写步骤?     答:

        1、拷贝必要jar包到classpath中(即拷贝jar包到WebRoot/WEB-INF/lib中),原则是:用哪个拷贝哪个。         2、at the top of classpath(在最顶层的构建路径),建立一个默认名称为struts.xml的配置文件。在struts.xml文件中进行配置。         3、在web.xml中配置控制器。         4、建立动作类和动作方法。         5、建立一个访问视图的.jsp文件和结果视图页面。 4、Struts2的执行过程?     答:

        tomcat启动,加载应用的web.xml --> tomcat实例化并初始化过滤器 --> 加载struts.xml配置文件 -->         客户浏览器发送请求:hello.action --> 请求到达过滤器 --> 截取请求的动作名称hello,并从struts.xml中查找 -->         找到后,实例化HelloAction动作类,每次都会创建新的实例 --> 调用对应的sayHello()动作方法,方法有返回值 --> 根据返回值找对应的结果视图 --> 找到结果jsp页面 --> 响应浏览器,展示结果 5、Struts2的配置文件加载时机和加载顺序?     答:

        Struts2的配置文件的加载时机:当应用被tomcat加载的时候,struts2的配置文件就已经被加载过了。         Struts2的配置文件的加载顺序:default.properties --> struts-default.xml --> struts-plugin.xml --> struts.xml --> struts.properties --> web.xml                                                                 存的是常量  拦截器、结果视图、默认的动作类  插件   我们自己写的  一般不用它   我们自己写的         加载文件的顺序必须是web.xml文件先加载的,读到了里面配置了一个Struts的核心控制器--过滤器,         然后该过滤器的init方法才去执行,它在执行的时候会初始化一些常量、拦截器、结果视图、默认的动作类、插件、配置的属性,给对应的属性赋值。 6、常量中struts.devMode是什么意思,如何配置?     答:

        是否是开发模式。开发模式:改了配置文件,不需要重启。输出更多的错误信息。开发阶段建议为true。         <constant name="struts.devMode" value="true"><constant/> 7、struts.xml配置文件中package的四个属性分别什么意思?     答:

        name属性:指定包的名称         extends属性:指定当前包的父包。         abstract属性:把包声明为一个抽象包。抽象包就是用来被继承的。只有没有<action>元素的包,才能被定义为抽象包。         namespace属性:名称空间。当指定了名称空间之后,访问路径就变成了:访问路径 = 名称空间 + 动作名称 8、访问带有名称空间的动作时,是如何查找的?例如: /user/abc/action1.action     答:

        先找名称空间 /user/abc 找不到,就找 /user ,找不到,就找 / ,找不到,就报错         有 /user/abc ,再在当前包找动作名称,找不到,就找默认的名称空间中的动作名称,找不到,就报错,其余以此类推         找到了,就执行。 9、action元素的三个属性什么意思?     答:

        name属性:动作的名称。         class属性:指定动作类,即动作类全名。         method属性:指定要执行的动作方法,即动作类中的方法名称。 10、result元素的两个属性分别指的是什么?     答:

        name属性:结果视图名称。         type属性:结果视图类型。 11、4个常用结果类型分别是什么?     答:

        dispatcher:请求转发 ,是默认值(本动作下)         redirect:请求重定向(本动作下)         chain:请求转发到另一个动作         redirectAction:请求重定向到另一个动作 12、访问ServletAPI的两种方式?     答:

        第一种方式:使用的是ServletActionContext的对象(此种方式简单明了,推荐此种方式)         第二种方式:使用的是 依赖注入 的形式,把我们想要的对象注入进来,是由一个 ServletConfigInterceptor的拦截器 为我们做的。需要实现3个接口,实现其中的方法。


day25_02_学习回顾

1、如何封装静态请求参数?     答:

        在 struts.xml 配置文件中,通过参数注入的方式,给动作类的参数注入值。相当于调用的是该参数的 setter 方法 。         是由默认的 拦截器栈 中的一个 拦截器staticParams 来完成参数注入的。         示例: <param name="username">张三</param> 2、动作类和模型分开的动态封装请求参数,set和get方法是怎么调用的?     答:

        getXxx         setXxx         getXxx         或者         getXxx         getXxx 3、使用模型驱动,动态封装请求参数的要求是什么?     答:

        要想使用模型驱动,前提:必须使动作类和数据模型分开写。             1、动作类需要实现一个ModelDriver的接口,注意:该接口需要写泛型。             2、实现接口中的抽象方法getmodel()。             3、在使用模型驱动的时候,数据模型必须由我们自己来实例化。 4、实际开发中类型转换的两种情况是什么?     答:

        实际开发中用户通过浏览器输入的数据都是字符串String或者字符串数组String[]。         写数据:(增、删、改)是String或String[]转换为其他类型。         读数据:(查)是其他类型转换为String。 5、Struts2中提供的常用类型转换分几类?     答:

        3类:         1、基本数据类型 自动转换         2、日期类型:默认按照 本地日期格式 转换成(yyyy-MM--dd)         3、字符串数组:默认用 逗号+空格 ,连接成一个字符串 6、自定义类型转换器是如何注册的?(两种情况)     答:

        1、局部类型转换器,按照 属性 来注册的。             在属性所属的javabean包下新建:                 javabean名称-conversion.properties 文件                 要转换的属性名称=类型装换器的全类名                 示例:birthday=com.itheima.web.converter.MyTypeConverter         2、全局类型转换器,按照 要转换的数据类型 来注册的。             在顶层目录下新建:                 xwork-conversion.properties 文件                 要转换的数据类型=类型转换器的全类名                 示例:java.util.Date=com.itheima.converter.MyTypeConverter 7、如何解决编程式验证使得动作类中的全部动作方法都验证?     答:

        1、使用 @SkipValidation 注解。         2、重新定义验证方法的名称,格式为:validate+动作名称,动作名称的首字母要大写哦! 8、声明式验证的分别可以基于什么?     答:

        1、基于字段的声明式验证:验证谁 --> 怎么验证 --> 验证结果         2、基于验证器的声明式验证:怎么验证 --> 验证谁 --> 验证结果 9、命名声明式验证xml文件名的两种方式,有什么不同?     答:

        通过编写 验证规则 的 xml文件 。需要验证时,编写xml文件,不要验证时,就不编写。         1、针对动作类中的 所有动作方法 进行验证:             在动作类所在的包中,建立一个 ActionClassName-validation.xml 的文件             示例:UserAction-validation.xml         2、针对动作类中的 某个动作方法 进行验证:             在动作类所在的包中建立一个 xml文件 ,名称为 ActionClassName-ActionName-validation.xml 注意:是动作名称,不是动作方法名称             示例:UserAction-register-validation.xml


day26_学习回顾

1、国际化的消息资源文件如何命名?     答:

        主要文件名_语言代码_国家代码.properties         主要文件名.properties(默认资源包) 2、Struts2中全局范围的资源包、包范围的资源包和动作类范围的资源包,哪个加载优先级高?页面上如何读取指定的消息资源包?     答:

        全局范围的资源包:message_en_US.properties         包范围的资源包:package_zh_CN.properties         动作范围的资源包:Demo1Action_zh_CN.properties         动作类范围的资源包的优先级最高。         页面上使用标签 <s:text name="xxx" /> 读取指定的消息资源包。 3、Struts2中拦截器的执行时机?     答:

        执行动作方法之前,正序执行拦截器。         执行结果视图之后,到序执行拦截器。 4、自定义拦截器的步骤是什么?     答:

        a、编写一个普通类,继承AbstractInterceptor类 或者 实现Interceptor接口 。重写其抽象的intercept方法。         b、在struts.xml中配置拦截器,注意拦截器必须先声明、再使用。

5、多个拦截器如何确定执行顺序?     答:

        单个拦截器的执行顺序:拦截器 --> 动作方法 --> 结果视图 --> 拦截器 --> 浏览器响应页面         当有多个拦截器的时候,是由使用顺序决定执行顺序,与声明顺序无关。 6、自定义拦截器除了继承AbstractInterceptor还可以继承哪个?另一个有什么好处?     答:

        还可以 继承MethodFilterInterceptor 并且 重写doIntercept方法。         好处:在struts的配置文件中,通过参数注入的方式,配置需要拦截哪些方法,和需要放过哪些方法。 7、文件上传是哪个拦截器为我们做的?如何限定上传文件的大小和类型?     答:

        是fileupload拦截器。         限定上传文件的大小:             1、在struts.xml中改变default.properties文件中的常量。常量是:maxSize             2、给Struts2默认的拦截器栈中的fileUpload拦截器注入参数。(此法行不通) 8、struts2中文件下载是由哪个结果类型完成的?需要我们提供什么参数?     答:

        Stream结果类型完成的。         我们需要给Stream结果类型注入的参数是:             1、contextType:文件的MIME类型             2、contextDisposition:文件的下载方式             3、inputName:字节输入流 9、OGNL是什么?使用它能否访问普通方法?能否直接访问静态方法?     答:

        OGNL:对象图导航语言。         能访问。         不能直接访问,需要开启允许静态方法访问的开关。开关名为:allowStaticMethodAccess 10、ActionContext和ValueStack什么时候创建?是否是线程安全的?     答:

        每次动作访问时,就会创建。多例,是线程安全的。         因为每次把数据绑定到了线程局部变量(ThreadLocal)上。 11、ContextMap中的结构是什么样的?     答:

        Context Map是OGNL的上下文,里面有两大部分组成:ActionContext + ValueStack         是一个Map集合中封装多个Map结合。


day27_学习回顾

1、ActionContext是什么结构?里面都有哪些数据?

 答:

        OGNL上下文 = 值栈(ValueStack)+ 大的contextMap(包含本身和小的contextMap)

                                              List集合      +    Map集合

        大的contextMap = ActionContext,是大Map中有小Map。  大Map中里面有三大域对象:request、session、application,attr 和 parameters。这些大Map的值都是小Map。

        ActionContext的核心结构是维护了一个Map<String, Object>类型的context变量。数据的存储和读取都是通过context对象来实现的。

2、ActionContext是如何保证数据线程安全的?

    答:

        ActionContext的获取是通过它的静态方法getContext()得到。

        Struts2会根据每一次的http请求来创建对应的ActionContext,它是与当前线程绑定的线程局部变量(ThreadLocal)。         每一次请求,就是一个线程,对应着一个request;

        每一次请求,会创建一个Action,每一个action对应一个ActionContext,每一次请求也对应着一个ValueStack。         request ---> ActionContext --> Action --> ValueStack  它们都对应着一次请求(或一个线程)。

        ActionContext把当前线程作为key,当前线程存的,只能当前线程访问,其他线程访问不到。

3、ValueStack是什么结构?

    答:

        List集合。

4、默认栈顶元素是什么?

  答:

        如果我们在动作类中没有往 值栈(根) 中放入数据的话,那么我们的动作类对象默认是在值栈的栈顶

5、ValueStack的setValue方法和set方法分别什么意思?

答:

        setValue(String expr, Object value)         参数说明:             String expr:它是一个OGNL表达式             Object value:我们要操作的数据         把数据存到哪里去?             看expr(OGNL表达式)是否使用了#

 如果使用了#,把数据存在ContextMap中,大Map中 如果没使用#,把数据存在ValueStack中,值栈中

        例如:

            vs.setValue("#name", "张三"); // 把数据存放到ContextMap中。 key=name valeu=张三             vs.setValue("name", "李四"); // 把ValueStack中第一个name属性的值替换成李四。如果整个ValueStack中都没有一个name属性的对应的setName方法,会报错。

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

        set(String key, Object o);         参数说明:             String key:Map的key             Object o:Map的value         如果栈顶是一个Map元素,即List集合中放的是Map集合,直接把key作为Map的key,把Object作为Map的value存入,即直接把数据存入Map。存入的是栈顶。         如果栈顶不是一个Map元素,那就创建一个Map对象,把key作为Map的key,把Object作为Map的value,并压入栈顶

6、Struts2中,EL表达式是如何查找数据的?

    答:

        jsp中,EL表达式的查找顺序:pageScope  --> requestScope --> sessionScope --> applicationScope

        Struts2对EL表达式查找顺序的改变:pageScope --> requestScope --> valueStack(根中) --> 剩余的contextMap(小Map) --> sessionScope --> applicationScope

7、iterator标签中var属性有什么作用?

    答:

         var:取值就是一个字符串             如果写了该属性:Struts2框架就会把var的值作为key,把当前遍历的元素作为value,存到ActionContext这个大Map中。             如果不写该属性:Struts2框架就会把当前遍历的元素压入值栈ValueStack的栈顶

8、#,$,%分别都有什么作用?

    答:

3.1、#    a、取contextMap中键key对应的值value时使用,例如:<s:property value="#name"/>    b、OGNL中创建Map对象时使用,例如:<s:radio list="#{'male':'男', 'female':'女'}"/> 3.2、$    a、在JSP中使用EL表达式时使用,例如:${name}    b、在xml配置文件中,编写OGNL表达式时使用,例如:在文件下载时,文件名编码:struts.xml --> ${@java.net.URLEncoder.encode(filename)} 3.3、%    在struts2中,有些标签的value属性取值就是一个OGNL表达式,例如:<s:property value="OGNL Expression"/>    还有一部分标签,value属性的取值就是普通字符串,例如:<s:textfield value="username"/>,    如果想把一个普通的字符串强制看成是OGNL表达式,就需要使用 %{} 把字符串套起来。例如:<s:textfield value="%{username}"/>。    当然在 <s:property value="%{OGNL Expression}"/> 也可以使用,但一般不会这么用,因为你两次告诉我你是OGNL表达式,不是有病吗!

9、使用url标签中添加param标签是什么意思?

    答:

        s:url 就是创建一个地址             value:输出的就是value的值,注意:value的取值此时不在是一个OGNL表达式,而是普通字符串。             action:输出的是action的请求地址。和${pageContext.request.contextPath}/action1.action是一样的。                     但是,它可以随着配置文件中的扩展名改变而改变。而EL表达式的写法是硬编码,不会自动改变。             var:会把action的值存到contextMap中。         s:a 的效果同 s:url

        例如:

        <%--把name作为key,把value作为值,绑定到请求链接地址后面。相当于get方式拼接请求参数 ,如果value的值是中文,会自动进行URL编码                 注意:此时的value的取值是一个OGNL表达式。         --%>         <s:param name="name" value="'text'"></s:param>

10、模型驱动是如何帮我们动态封装请求参数的?

    答:

        0、数据模型和动作类分开,动作类中有数据模型的引用。

        1、在ModelDriven接口的实现类中,获取当前动作类的引用。

        2、判断该动作类是否实现了ModelDriven接口。

        3、是,就把该引用的类型强转为ModelDriven类型。

        4、如果我们在动作类中没有往 值栈(根) 中放入数据的话,那么我们的动作类对象默认是在值栈的栈顶

        5、获取值栈的引用。

        6、获取动作类中定义的数据模型对象的引用。

        7、该引用不为空,就把该对象压入栈顶。(1-7步骤是拦截器modeDriven在起作用。)

        8、再调用params拦截器的set方法把对象封装好数据(即进行赋值)。动态参数封装。

11、在struts2中,如何防止表单重复提交?

     答:

        1、使用重定向

        2、表单上使用<s:token/>生成令牌,再配合token拦截器,在struts.xml中进行相关的配置

        3、表单上使用<s:token/>生成令牌,再配合tokenSession拦截器,在struts.xml中进行相关的配置(该拦截器只会处理第一次请求,当重复提交请求时,不会再处理。


本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏IT杂记

Git 对象存储结构分析

Git 对象有:blob (数据块), tree (目录树), commit (提交), tag (标签)。

57140
来自专栏塔奇克马敲代码

在使用Qt5.8完成程序动态语言切换时遇到的问题

25140
来自专栏H2Cloud

C++中消息自动派发之二 About IDL解析器

  前一篇blog中讲了如何在C++中实现消息的自动派发,而关键点在于如何实现通过IDL文件自动生成msg_dispatcher模板类。有几个网友提醒我idl解...

41890
来自专栏ShaoYL

堆和栈的区别

298100
来自专栏小樱的经验随笔

【批处理学习笔记】第二十三课:用户变量和变量引用

用户变量     编写批处理程序时,用户根据需要自己定义的变量称之为用户变量。用户变量类似于C语言里面的变量,仅仅在定义该变量的程序中有效。     用户变量由...

29340
来自专栏武培轩的专栏

Keep面经汇总

原理:泛型的实现是靠类型擦除技术,类型擦除是在编译期完成的,在编译期,编译器会将泛型的类型参数都擦除成它的限定类型,如果没有则擦除为object类型之后在获取的...

14230
来自专栏码字搬砖

scrapy之ip池

备注: process_request(request, spider) 当每个request通过下载中间件时,该方法被调用。 process_re...

38320
来自专栏宋凯伦的技术小栈

【Node.js】一个愚蠢的Try Catch过错

  前段时间学习《深入浅出Nodejs》时,在第四章 - 异步编程中作者朴灵曾提到,异步编程的难点之一是异常处理,书中描述"尝试对异步方法进行try/catch...

22480
来自专栏架构之路

Struts2 中的值栈的理解

通过对struts2的一段时间的接触,将自己对OGNL的核心值栈说说,值栈:简单的说,就是存放action的堆栈,当我们提交一个请求道服务器端 action时,...

27830
来自专栏码代码的陈同学

Procedure Call and Stack

最近查资料时,偶然在youtobe看到了华盛顿大学自然科学与工程一位老师 关于 Procedure & Stacks 的课程,深入讲解了基于Stack的过程调用...

642290

扫码关注云+社区

领取腾讯云代金券