struts2介绍

Struts2是Apache发行的MVC开源框架。注意:它只是表现层web(MVC)框架。

Struts1也是apache开发的一套mvc的开源框架。在2005年之前非常流行。
弊端:Struts1的核心控制器就是一个Servlet。随着使用者的增多,弊端开始出现。

SRE实战 互联网时代守护先锋,助力企业售后服务体系运筹帷幄!一键直达领取阿里云限量特价优惠。

在long long ago,有一个设计超前的框架XWork,后来推出了XWork1和WebWork2。
Struts2就是apache和OpenSymphony组织合并开发出来。
里面包含了WebWork2的核心及Struts的一些特性和功能。除此之外,和Struts1没有任何关系了。

struts环境搭建

下载struts2的jar包:下载struts2 的 2.3.33版本

  • 创建web项目
  • 导入所需要的jar包(可以在example的struts2-blank.war中的lib下找)
    • struts笔记 随笔 第1张
    • Struts核心jar包
      • struts2-core-2.3.33.jar
      • xwork-core-2.3.33.jar
    • OGNL表达式
      • ognl-3.0.19.jar
    • 开源日志 log for java
      • log4j-core-2.3.jar
      • log4j-api-2.3.jar
    • 基于子类的动态代理
      • asm-3.3.jar
    • 提供其于对象的表现形式
      • asm-3.3.jar
    • 提供基于事件的表现形式
      • asm-commons-3.3.jar
    • 文件上传所需要的包
      • commons-fileupload-1.3.2.jar
      • asm-commons-3.3.jar
    • 页面 模板框架
      • freemarker-2.3.22.jar
    • 对于字节码的支持,jBoss的一个子项目
      • javassist-3.11.0.GA.jar
    • 对java.lang的扩展
      • commons-lang3-3.2.jar
  • 在src下创建struts.xml配置文件
<?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>

</struts>
  • 在web.xml中配置核心过滤器(配置的目的是用于拦截请求,由Struts的规则去处理请求,而不是用以前的servlet去处理)
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
         version="4.0">
    <filter>
        <filter-name>struts2</filter-name>
        <filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
    </filter>
    <!-- struts过滤器拦截请求的规则 -->
    <filter-mapping>
        <filter-name>struts2</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
</web-app>
  • Action配置

struts笔记 随笔 第2张

  • 写一个HelloAction的类,需要写个sayHello方法

struts笔记 随笔 第3张

  • 在WebContent中添加一个success.jsp页面

  • 部署项目,启动tomcat,访问路径测试

struts默认是处理.action的请求,或者不带action也可以,其它后缀的都不会拦截,会放行,如jsp

Struts2的执行流程

struts笔记 随笔 第4张

  • tomcat启动
    • 实例化并初始化过滤器
    • 加载struts.xml配置文件
  • 客户端发送请求
    • 请求到达过滤器
    • 截取请求的动作名称,并从struts中找
    • 找到后,实例化动作类
    • 调用对应的动作方法,方法有返回值
    • 根据返回值,找到name取值对应的结果视图
    • 返回结果视图

struts2的配置文件加载顺序

struts有很多配置文件
当应用被tomcat加载的时候,struts2的配置文件就已经被加载过了。

  • 加载顺序
配置文件名 所在位置 说明
default.properties struts2-core-2.3.15.3.jar\org\apache\struts2 不能修改
struts-default.xml struts2-core-2.3.15.3.jar 不能修改
strtuts-plugin.xml 在struts2提供的插件jar包中 不能修改
struts.xml 应用中 可以修改
struts.properties 应用中 可以修改
web.xml 应用中 可以修改,可以给过滤器配置参数

default.properties的一些默认配置:

  • struts.i18n.encoding=UTF-8:国际化
  • struts.action.extension=action:默认访问扩展后缀,可以是action,也可以没有后续
  • struts.devMode = false:是否是开发模式。开发模式:改了配置文件,不需要重启。输出更多的错误信息。开发阶段建议为true。

struts-default中默认的拦截器分组

默认的包里有一结果类型,如转发和重定向
struts笔记 随笔 第5张

默认情况下,struts会使用defaultStack的拦截器分组
struts笔记 随笔 第6张

struts-defualts中主要的内容:结果类型、拦截器分组,默认使用的接替器分组
struts笔记 随笔 第7张

修改struts的访问后缀

  1. 在struts.xml的配置文件中添加:<constant name="struts.action.extension" value="do"></constant>
  2. 在src下创建struts.properties,添加struts.action.extension=htm,这个会覆盖struts.xml的配置
  3. 在web.xml中配置:struts笔记 随笔 第8张

配置struts的开发模式

在struts.xml中添加:
struts笔记 随笔 第9张

struts配置文件的主要元素

package元素

在struts2的配置文件中引入了面向对象思想,使用了分包管理。易于管理动作类。便于模块化开发动作类。

属性:

  • name
    • 包的名称。必须写。且必须唯一。
  • extends
    • 一般情况下需要继承struts-default包,但不是必须的。
    • 不过如果不继承的话,将无法使用struts2提供的核心功能。
    • struts-default.xml中定义着struts-default这个包。
    • 而struts-default.xml是在我们的struts.xml加载之前加载。
  • abstract
    • 把包声明为抽象包,抽象包就是用来被继承的。
    • 只要是没有 元素的包,就可以声明为抽象包。
  • namespace
    • 名称空间。【访问路径=名称空间+动作名称】

namespace的默认取值是一个"",
注意:默认值不是/,写自定义的namespace时需要加/
struts笔记 随笔 第10张

访问路径为http://localhost:8080/day01_struts2_demo03/user/hello.action

注意:需要在访问action前添加红色命令空间

如果访问http://localhost:8080/day01_struts2_demo03/a/b/user/hello.action 是访问不了

但是如果是访问http://localhost:8080/day01_struts2_demo03/user/a/b/hello.action 是可以访问的

namespace的查找规则:
struts笔记 随笔 第11张

action元素

action元素解释

配置动作,处理请求路径

属性:

  • name:动作名称
  • class:动作类全名
  • method:动作类中的方法名称。默认是public String execute()

方法的要求:

  1. public的
  2. 返回值必须是String
  3. 没有参数

动作类的写法:

  1. 直接在写个Action类,不需要继承任何类,然后在struts.xml中配置

struts笔记 随笔 第12张

struts笔记 随笔 第13张

访问路径: http://localhost:8080/day01_struts2_demo05/user/login
  1. 写个Action类实现Action接口,然后实现excute方法

struts笔记 随笔 第14张

struts笔记 随笔 第15张

如果没有配置Method,默认执行Action的excute方法

访问路径:http://localhost:8080/day01_struts2_demo05/user/login2

Action接口中,有一些静态常量,如下图:

struts笔记 随笔 第16张

常量变量名 对应的值 说明
SUCCESS success 动作方法执行一切OK
ERROR error 动作方法执行时遇到了异常
INPUT input 回显
LOGIN login 一般转向登陆页面
NONE none 不转向任何的视图
  1. 写个Action类继承ActionSuport类【推荐使用这种方式】

ActionSupport是实现Action接口的类

struts笔记 随笔 第17张

struts笔记 随笔 第18张

访问路径:http://localhost:8080/day01_struts2_demo05/user/login3

默认的动作类:

在struts-default.xml中定义了默认动作类和方法
就是com.opensymphony.xwork2.ActionSupport 这个类

struts笔记 随笔 第19张

案例:

struts.xml:可以在Action中不配置 class 和method,会由默认的动作类来处理,ActionSupport的excute方法返回的就是success

struts笔记 随笔 第20张

访问路径: http://localhost:8080/day01_struts2_demo05/user/defaultAction

修改默认的动作类

struts笔记 随笔 第21张

action的通配符写法

struts笔记 随笔 第22张

多个通配符的写法:

struts笔记 随笔 第23张

struts笔记 随笔 第24张

优先级:绝对匹配优先。使用通配符的按照在配置文件中的先后顺序进行匹配的。

动态方法调用

struts笔记 随笔 第25张

访问路径:
http://localhost:8080/day01_struts2_demo06/student!addStudent.action
http://localhost:8080/day01_struts2_demo06/student!deleteStudent.action

result元素

result元素功能

作用:为动作指定结果视图

属性:

  • name:逻辑视图的名称,对应着动作方法的返回值。默认是success
  • type:结果类型,值得就是用什么方式跳转到定义的页面。默认是dispatcher转发

retult中type的取值:

struts笔记 随笔 第26张

  • type的默认取值时dispatcher
  • type属性的取值在struts-default.xml中定义着

struts笔记 随笔 第27张

redirect重定向:

struts笔记 随笔 第28张

chain 转发到同一个名称空间的动作

struts笔记 随笔 第29张

redirectAction 重定向到同一名称空间的动作

struts笔记 随笔 第30张

chain 转发到不同一个名称空间的动作

struts笔记 随笔 第31张

redirectAction重定向到不同一个名称空间的动作

struts笔记 随笔 第32张

result元素中param子元素

  • 在转发或者重定向到不同包下的动作时,都用到了result元素的子元素param。
  • param元素的作用:依赖注入(Dependence Injection)思想
  • 我们通过struts-default.xml中的resultTypes元素中配置可以看出,每个结果类型视图其实都是靠一个类来实现的。
  • 而param元素就是将配置的参数,注入到该类中。
  • 调用的是对应类的setter方法进行注入的。

自定义结果类型

  • 其实结果类型就是一个类,这些类都实现com.opensymphony.xwork2.Result接口。
  • 或者继承自该接口的实现类org.apache.struts2.dispatcher.StrutsResultSupport。
  • 这些类都有一个doExecute方法,用于执行结果视图。【查看源码各种结果类型的类结构】
  • struts的内部实现就是Servlet

自己写一个结果视图:

  1. 写一个类继承StrutsResultSupport或者实现`lt接口
  2. 重写doExecute方法struts笔记 随笔 第33张
  3. 配置struts.xml文件struts笔记 随笔 第34张
  4. 查看结果

优化自定义结果类型:

  1. 给结果类添加width和height的属性和get/set访求struts笔记 随笔 第35张
  2. 修改struts.xml文件,通过param注入struts笔记 随笔 第36张

全局视图和局部视图

第一步:写一个包,名为myDefault,里面写全局的配置
第二点:其它包继承myDefault包,如图

struts笔记 随笔 第37张

动作类中访问Servlet的api

  • 获取servlet api:
    • 第一种:通过ServletActionContext获取 【推荐使用】
    • 第二种:通过注入方式:先让Action实现两个接口ServletRequestAware,ServletResponseAware

struts笔记 随笔 第38张

第二种注入方式原理是因为struts有个拦截器
来实现的

查看ServletConfigIntercepto的源码

struts笔记 随笔 第39张

多个struts配置文件

多个struts配置文件的用途是为了模块开发和减少开发中的冲突

struts笔记 随笔 第40张

Action接收请求参数的方式

通过以前的Servlet来获取

struts笔记 随笔 第41张

struts笔记 随笔 第42张

struts笔记 随笔 第43张

通过Action的属性的set方法注入

struts会通过表单字段的名称,调用set方法,比如username字段会调用setUsername

struts笔记 随笔 第44张

通过Action的属性的set模型的形式注入

User.java模型:提供属性的get/set方法

struts笔记 随笔 第45张

UserAction.java
把参数封装到一个User模型中,然后Action提供模型的get/set方法

struts笔记 随笔 第46张

struts笔记 随笔 第47张

补充:讲解下面set/get方法打印顺序的原因
先获取user对象,如果没有,创建一User对象注入进去

通Action模型驱动封装参数

struts笔记 随笔 第48张

struts笔记 随笔 第49张

参数注入的原理

参数会自动注入是因为有两个拦截器在工作
查看struts-default.xml源码可以看到下面两个拦截器

修改包下的拦截器:

struts笔记 随笔 第50张

struts笔记 随笔 第51张

静态参数注入【少用】

struts可以通过action中静态注入参数,然后在Action提交属性注入
这种是静态流入,参数写死

struts笔记 随笔 第52张

用户注册案例

表现层web

第一步:在mysql中添加一个struts2_day3数据库,把db.sql的表创建下(数据库需要utf-8编码的,才可以存储中文)

第二步:将资料中db文件夹的jar导入到项目工程中(这里的数据源使用DBCP:DataBase Connection Pool 是apache公司实现的一个开源的数据源。)

第三步:将资料中db文件夹的dbcpconfig.properties导入src项目下

第四步:将DBCPUtil.java写好的导入在项目中

第五步:写webcontent中写个注册页面

struts笔记 随笔 第53张

第六步:写个UserAction,使用模型驱动来接收参数

struts笔记 随笔 第54张

struts笔记 随笔 第55张

第七步:配置struts.xml

struts笔记 随笔 第56张

持久层dao和service层

struts笔记 随笔 第57张

struts笔记 随笔 第58张

UserAction 的register方法修改

struts自定义参数类型转换

前面的多个爱好请求参数,struts框架会自动进行字符串的拼接,如拼接成【泡妞, 写代码, 买房子】,是以逗号+空格类型来拼接的

struts笔记 随笔 第59张

struts也会把字符串转换成Date类型

但是如果提交的是错误的日期,就会报错

struts有很多类型转换器

struts笔记 随笔 第60张

struts的字符串类型转换是由一个类com.opensymphony.xwork2.conversion.impl.StringConverter类来完成的

日期类型转换是由com.opensymphony.xwork2.conversion.impl.DateConverter来完成

源码分析得出,如果要自己写一个类型转换

  • 可以实现DefaultTypeConverter抽象类
  • 我们一般也可以用它的子类StrutsTypeConverter来实现

自定义日期类型转换步骤:

  1. 写一个类继承StrutsTypeConverter,并实现抽象方法
  2. 实现两个抽象方法的逻辑struts笔记 随笔 第61张
  3. 配置局部类型转换器,在模型pojo的包下配置【模型名字-conversion.properties】的一个文件,内容如下struts笔记 随笔 第62张
  4. 测试自定义日期是否生效
  5. 配置全部类型转换器
    • 在类的根路径配置一个xwork-conversion.properties文件
    • key为数据类型(全类名)
    • value为类型转换器的全类名
    • struts笔记 随笔 第63张

struts2的错误回显

前提:将前面用户注册案例的时间转化时,抛出运行时异常

struts笔记 随笔 第64张

注册时,将日期写错格式,会得到下面的一个结果,result input表示需要一个回显页面,也就是发生异常时的显示页面

struts笔记 随笔 第65张

在struts.xmp中配置回显页面

struts笔记 随笔 第66张

在register.jsp中添加struts的标签

struts笔记 随笔 第67张

回显效果

struts笔记 随笔 第68张

struts的form表单标签

struts的from标签提供了和原始html表单几乎一至的属性

属性:

  • action:请求地址。直接写动作名称,不用写contextPath
  • method: 请求方式,默认是post请求,可以不用写
  • enctype:静音编码的MIME类型

案例:将前面的用户注册案例改成struts的表单标签来显示

struts笔记 随笔 第69张

strtus的错误处理和中文显示

struts标签如果有字段错误,会回显信息

设置回显信息为红色

添加个s:head标签即可

struts笔记 随笔 第70张

效果:

struts笔记 随笔 第71张

设置回显信息中文化

  • 在模型的包中,添加一个模型+properties,配置key value
  • key格式为下面的invalid.fieldvalue.字段名
  • struts笔记 随笔 第72张
  • 效果:struts笔记 随笔 第73张

struts的表单数据验证方式

服务端Action验证

有两种方法:

struts笔记 随笔 第74张

效果:

struts笔记 随笔 第75张

xml声明式验证

全局声明方式

在action包中声明UserAction-validation.xml文件
这种方式配置是全局配置,所有action的方法都会拦截验证
如果其它方法不想验证,可配置@SkipValidation注解
dtd约束可以在xwork-core的jar包中找

struts笔记 随笔 第76张

struts默认有很多种验证器类型,声明在default.xml中(注意default.xml的位置)

struts笔记 随笔 第77张

演示密码不能大于6的配置

struts笔记 随笔 第78张

局部声明方式

在action包中声明UserAction-register-validation.xml文件
声明方式 【Action类名-方法名-validation.xml】

xml内容与上面的一样

验证器案例综合

Add.Jsp页面

struts笔记 随笔 第79张

student模型

public class Student {
    private String username;//不能为空,去空字符串
    private int age;//18~100
    private String email;//正确邮箱格式
    private String password;//3~8
    private String repassword;//与密码一至
    private int score;//必须是自然数
    private String url;//必须是一个路径
    private String gender;//性别,只有男和女

Action

struts笔记 随笔 第80张

Struts.xml

struts笔记 随笔 第81张

StudentAction-add-validation.xml

<validators>
    <!--
     1.  private String username;//不能为空,去空字符串
         requiredstring 比 required 好一点,会自动去除空格
     -->
    <validator type="requiredstring">
        <param name="fieldName">username</param>
        <message>用户名不能为空</message>
    </validator>
    
    
    <!--2.private int age;//18~100 
      1.表单的类型,会根据模型的属性类型去校验
     -->
     <validator type="int">
        <param name="fieldName">age</param>
        <param name="min">18</param>
        <param name="max">100</param>
        <message>年龄必须在18~100</message>
     </validator>
    
    
    <!-- 3.private String email;//正确邮箱格式-->
    <validator type="requiredstring">
        <param name="fieldName">email</param>
        <message>邮箱不能为空</message>
    </validator>
     <validator type="email">
        <param name="fieldName">email</param>
        <message>邮箱格式不正确</message>
     </validator>
         
     
     <!--4. private String password;//3~8 -->
     <validator type="requiredstring">
        <param name="fieldName">password</param>
        <message>密码不能为空</message>
    </validator>
    <validator type="stringlength">
        <param name="fieldName">password</param>
        <param name="minLength">3</param>
        <param name="maxLength">8</param>
        <message>密码长度为3~8</message>
    </validator>
    
    <!-- 5.private String repassword;//与密码一至 -->
    <validator type="expression">
        <param name="expression">
            <![CDATA[ password == repassword]]>
        </param>
        <message>密码不一至</message>
    </validator>
    
    <!-- 6.private int score;//必须是自然数
        regex :正则
     -->
    <!-- <validator type="regex">
        <param name="fieldName">score</param>
        <param name="regexExpression">\d+</param>
        <message>分数必须要数字</message>
    </validator> -->
    
    
    <!--    private String url;//必须是一个路径 http:// -->
    <validator type="url">
        <param name="fieldName">url</param>
        <message>URL格式不合法,以 http://开头</message>
    </validator>
    
    <!--    private String gender;//性别必填,只有男和女 -->
    <validator type="required">
        <param name="fieldName">gender</param>
        <message>性别必选</message>
    </validator>
</validators>

struts2的国际化

什么是国际化

软件的国际化:软件开发时,要使它能同时应对世界不同地区和国家的访问,并针对不同地区和国家的访问,提供相应的、符合来访者阅读习惯的页面或数据

国际化使用场景

苹果英文网:https://www.apple.com/

苹果中文网:https://www.apple.com/cn

苹果香港网:https://www.apple.com/hk

苹果日本网https://www.apple.com/jp/

固定文本的国际化

例如:消息提示,错误提示和菜单,导航栏等等固定文本

使用步骤

创建一个消息资源包

一个资源包由多个文件组成,这些文件名都有命名规范:主要文件名_语言代码_国家代码.properties。

语言代码和国家代码:有iso规定的

当文件只有主要文件名.properties时,表明它是默认资源包。浏览器会根据不同的语言环境找对应语言环境的资源包

当没有时,找默认的。

每个资源包的内容都由相同的key和对应语言环境的value组成。

比如:

message_zh_CN.properties
message_zh_HK.properties
message_en_US.properties

struts笔记 随笔 第82张

读取资源包中的内容

Java提供ResourceBundle类可以读取资源包的国际化配置文件

struts笔记 随笔 第83张

JSP中使用国际化

struts笔记 随笔 第84张

使用jstl标签来国际化

JSP标准标签库(JSTL)是一个JSP标签集合,它封装了JSP应用的通用核心功能。

JSTL支持通用的、结构化的任务,比如迭代,条件判断,XML文档操作,国际化标签,SQL标签。

除了这些,它还提供了一个框架来使用集成JSTL的自定义标签。

首先需要在项目中导入两个jar包

struts笔记 随笔 第85张

jsp中:struts笔记 随笔 第86张

struts2提供的国际化

前面的国际化与struts无关

第一步:配置资源包

配置全局的资源包

在struts.xml中配置

struts笔记 随笔 第87张

struts笔记 随笔 第88张

配置包范围的资源包

资源包名称命名规范:package_语言代码_国家代码.properties(固定的)。以此种命名方式的资源包能被该包及其子包中的动作类访问。

优先级:高于全局消息资源包

struts笔记 随笔 第89张

局部消息资源包

资源包名称命名规范:动作类名称_语言代码_国家代码.properties。以此种命名方式的资源包,只为动作类服务。

优先级最高(就近原则)。

struts笔记 随笔 第90张

注:Struts2中资源包的搜索顺序

struts笔记 随笔 第91张

第二步:读取资源包内容

jsp读取资源包内容

使用struts的标签s:text获取国际化内容

struts笔记 随笔 第92张

Action读取资源包内容

使用ActionSupport的getText方法,可以读取到资源包的内容

也就是说这个Action一定要继承ActionSupport

这种在实际开发中几乎不用

struts笔记 随笔 第93张

自由指定读取资源包

在jsp页面可以使用s:i18n标签指向读取的国际资源包文件

struts笔记 随笔 第94张

Strust2的拦截器

拦截器的重要性

Struts2中的很多功能都是由拦截器完成的。比如:servletConfig,staticParam,params,modelDriven等等。

Struts默认的拦截器配置在struts-default.xml文件中

拦截器是AOP编程思想的一种应用形式。

拦截器的执行时机

struts笔记 随笔 第95张

拦截器的部分类结构

struts笔记 随笔 第96张

简单拦截器入门

单个拦截器

第一步

创建个拦截器,继承Abastract方法,实现intercept方法

struts笔记 随笔 第97张

第二步

在struts.xml中配置拦截器,拦截器需要配置后才可使用

struts笔记 随笔 第98张

struts笔记 随笔 第99张

Demo1.jsp 的内容随便写

多个拦截器

invocation.invoke方法返回的就是视图

struts笔记 随笔 第100张

拦截器的应用场景【登录】

首先准备四个login.jsp,main.jsp, studentList.jsp, teacherList.jsp 页面

当登录成功后,跳转到main.jsp,main.jsp的内容可以跳转到学生和老师列表

UserAction

struts笔记 随笔 第101张

登录验证拦截器

struts笔记 随笔 第102张

拦截器配置

struts笔记 随笔 第103张

如果没有登录,直接访问http://localhost:8080/day03_struts2_demo04/teacherList.action会回到登录页面

案例中的问题

问题:由于我们写了自己的拦截器,默认的拦截器不起作用了。

举个简单的例子,就是不可以接收请求参数

解决办法

a、把默认拦截器加到配置

struts笔记 随笔 第104张

b、抽取一个拦截器的分组

struts笔记 随笔 第105张

c、修改默认的拦截器

上面的配置坏处是每一个Action都配置拦截器,我们修改默认的拦截器配置,就可以简便我们的代码

struts笔记 随笔 第106张

d、过滤不需要登录验证的方法

修改的默认的拦截器后,所有的Action方法都会被拦截,而登录方法是不需要拦截的

解决需要通过AbstractInterceptor类的子类入手,通过查看发现,该类还有一个子类是抽象的,可以通过MthodFilter过滤方法,如图:

struts笔记 随笔 第107张

解决步骤:

修改拦截器的继承结构

struts笔记 随笔 第108张

修改struts.xml文件,注册过滤方法

struts笔记 随笔 第109张

上面遗留的问题:我们在声明时配置了哪些方法需要拦截,哪些方法不需要拦截。但是在没有写动作类和动作方法之前,不确定方法名叫什么。

解决办法:我们需要在使用拦截器的时候给它注入参数。

struts笔记 随笔 第110张

Struts2的文件上传

Struts也提供了内置标签用于文件上传 ,我们称为文件选择域

与html的标签是一样用的

文件上传的必要前提条件

表单必须是post方法

enctype类型必须为multipart/form-data

简单文件上传

第一步:jsp和action的代码

struts笔记 随笔 第111张

Action接收到的File对象是一个临时文件,后面需要保存到另外一个路径去

struts笔记 随笔 第112张

第二步:struts.xml的配置

struts笔记 随笔 第113张

文件上传的配置

第一:配置文件上传的大小

默认情况下,struts的文件上传只允许在2M内

如果上传一个大于2M的文件,系统会报错,而且必要一个input回显结果

修改struts.xml文件

struts笔记 随笔 第114张

修改jsp文件

struts笔记 随笔 第115张

文件上传失败结果

struts笔记 随笔 第116张

修改文件上传大小限制

思路在struts.xml中改变default.properties文件中的常量。

struts笔记 随笔 第117张

第二:限制文件上传的类型

思路:通过拦截器设置文件上传的扩展名或者MIME类型

struts笔记 随笔 第118张

扩展名的错误提示

struts笔记 随笔 第119张

MIME的错误提示

struts笔记 随笔 第120张

struts笔记 随笔 第121张

struts笔记 随笔 第122张

第三:文件上传错误的中文提示

默认的错误提示信息是在
struts2-core.jar\org.apache.struts2\struts-message.properties中

struts笔记 随笔 第123张

解决办法:用国际化消息资源包,把对应的key取值改为中文即可。

常用的key值

struts笔记 随笔 第124张

步骤:

第一步:在src目录创建一个fileuploadmessage.properties文件

struts笔记 随笔 第125张

第二步:在struts.xml配置国际化

struts笔记 随笔 第126张

多文件上传

多文件上传,在Action代码中,只需要把接收的文件字段设置为数组即可

struts笔记 随笔 第127张

struts笔记 随笔 第128张

文件下载

其实就是一种结果类型(Stream)

struts笔记 随笔 第129张

struts笔记 随笔 第130张

测试下载路径

http://localhost:8080/day03_struts2_demo05/download

动态设置下载的文件名

struts笔记 随笔 第131张

struts笔记 随笔 第132张

struts的OGNL

OGNL简介

OGNL是Object Graphic Navigation Language(对象图导航语言)的缩写,

它是一个单独的开源项目。 Struts2框架使用OGNL作为默认的表达式语言。

OGNL是struts2整合的一个开源项目,所以在struts2中,要想使用OGNL表达式,必须使用Struts2标签库

OGNL相当 于EL表示式,从作用域取数据

OGNL的简单使用

s:property类型于JSP的表达式,把value的值直接输出到页面

jsp表达式:【 】

value的值就是一个OGNL表达式,它不是一个字符串

如果想把value的值当字符串输出,加单引号即可

struts笔记 随笔 第133张

OGNL的功能

访问对象方法

比如字符串的length方法

访问静态属性

访问静态方法

默认OGNL是禁止静态方法访问的,在default.properties中有个struts.ognl.allowStaticMethodAccess=false,
如想使用,需要在struts.xml文件中配置允许访问静态方法

struts笔记 随笔 第134张

封装list数据

struts笔记 随笔 第135张

struts笔记 随笔 第136张

封装Map数据

struts笔记 随笔 第137张

struts笔记 随笔 第138张

struts.xml中写OGNL

前面的文件下载就是一个OGNL表达式

struts笔记 随笔 第139张

修改

struts笔记 随笔 第140张

struts笔记 随笔 第141张

struts笔记 随笔 第142张

contextMap

动作类的生命周期

明确:

动作类是多例的,每次动作访问,动作类都会实例化。所以是线程安全的。

与Struts1的区别是,struts1的动作类是单例的。

请求数据的存放

问题:

每次请求时,都会产生一些请求数据,这些数据存放到哪里去了?   

明确:

在每次动作执行前,核心控制器StrutsPrepareAndExecuteFilter都会创建一个ActionContext和ValueStack对象。且每次动作访问都会创建。            
这两个对象存储了整个动作访问期间用到的数据。
并且把数据绑定到了线程局部变量(ThreadLocal)上了。所以是线程安全的。

struts笔记 随笔 第143张

struts笔记 随笔 第144张

contextMap 存储数据

Struts2的官方文档对contextMap的说明

struts笔记 随笔 第145张

struts笔记 随笔 第146张

注意:     
                    
    除了value stack之外,全是map,而contextMap也是一个map。
    其实就是Map中又封装的Map。(很像dbutils中KeyedHandler封装数据的结构,只是封装数据的结构)
    使用s:debug查看contextMap的数据

struts笔记 随笔 第147张

struts笔记 随笔 第148张

测试存储数据

struts笔记 随笔 第149张

struts笔记 随笔 第150张

struts笔记 随笔 第151张

contextMap中的数据操作

存数据

struts笔记 随笔 第152张

利用ActionContext存数据

struts笔记 随笔 第153张

利用ValueStack存数据

掌握三种获取ValueStack的方法

struts笔记 随笔 第154张

struts笔记 随笔 第155张

取数据

用Struts2的标签(OGNL表达式)在JSP上(用的最多)

使用s:property取数据

取contextMap中的数据,需使用#

struts笔记 随笔 第156张

取contextMap里面ValueStack中对象的属性:直接写属性名

struts笔记 随笔 第157张

如果遇有对象属性重名,可以通过OGNL表达式,选择查找的起始位置

struts笔记 随笔 第158张

struts笔记 随笔 第159张

struts笔记 随笔 第160张

特殊说明:当s:property不给定value属性时,默认取栈顶对象。

struts笔记 随笔 第161张

struts笔记 随笔 第162张

struts笔记 随笔 第163张

valueStack的其它方法

setValue方法

struts笔记 随笔 第164张

struts笔记 随笔 第165张

struts笔记 随笔 第166张

set方法

掌握压栈的顺序问题

struts笔记 随笔 第167张

struts笔记 随笔 第168张

struts笔记 随笔 第169张

findValue方法

在jsp页面上的调用的都是findValue方法

struts笔记 随笔 第170张

Struts中对EL取值顺序的改变

默认情况下EL查找顺序

表达式取值必须是servlet四大作用域 由小到大排列为

pageContext【page】   >   request >   session >   servletContext【application】

案例

struts笔记 随笔 第171张

struts笔记 随笔 第172张

在Struts中EL表达式的查找顺序的改变

OGNL表达式:

page –> request  -> valueStack(根中)-> contextMap  ->  session  ->  application

案例

struts笔记 随笔 第173张

struts笔记 随笔 第174张

源码分析

struts笔记 随笔 第175张

内容补充【了解】

struts笔记 随笔 第176张

Struts标签与OGNL的配合使用

iterator标签

struts笔记 随笔 第177张

struts笔记 随笔 第178张

效果:

struts笔记 随笔 第179张

OGNL投影(了解)

使用过滤条件投影

struts笔记 随笔 第180张

使用指定属性投影

struts笔记 随笔 第181张

回顾Struts2中#,$,%符号的使用(重要)

#

a、取contextMap中key时使用,例如

b、OGNL中创建Map对象时使用,例如:

$

a、在JSP中使用EL表达式时使用,例如${name}

b、在xml配置文件中,编写OGNL表达式时使用,例如文件下载时,文件名编码。

struts.xml——>${@java.net.URLEncoder.encode(filename)}

%

在struts2中,有些标签的value属性取值就是一个OGNL表达式,例如

还有一部分标签,value属性的取值就是普通字 符串,例如 ,
如果想把一个普通的字符串强制看成时OGNL,就需要使用%{}把字符串套起来。

例如 。

当然在 也可以使用,但不会这么用。

struts笔记 随笔 第182张

Struts的其它标签

s:set标签

value:存入map中的值,是一个OGNL表达式

var:存在map中的key

scope:存储的范围application session request page和action

不写scope,默认是action,它是在contextMap中和request中各存一份

struts笔记 随笔 第183张

s:action标签

struts笔记 随笔 第184张

struts笔记 随笔 第185张

s:if标签,s:elseif标签 s:else标签

相当于jstl中的c:choose c:wher c:otherwise

struts笔记 随笔 第186张

s:url和s:a标签

问题:参数是有一个和中文码未解决

struts笔记 随笔 第187张

表单小案例

目标

掌握checkboxlist的使用
掌握模型驱动的原理
掌握struts主题的设置

效果:

struts笔记 随笔 第188张

代码:

struts笔记 随笔 第189张

struts笔记 随笔 第190张

struts笔记 随笔 第191张

模型驱动原理

struts的ModelDrivenInterceptor 这个拦截器来完成的了模型驱动的工作 
这个可以从struts-defualt.xml找到这个拦截器
ModelDrivenInterceptor.java源码分析

struts笔记 随笔 第192张

内部娄模型数据压栈了

struts笔记 随笔 第193张

struts2中默认主题

默认主题的名称是XHTML,都是在struts的默认属性文件中定义着:default.properties

struts笔记 随笔 第194张

更改默认的主题方式

第一:在标签内加theme属性

struts笔记 随笔 第195张

第二:配置全局的theme

struts笔记 随笔 第196张

防止表单重复提交(拦截器)【面试题】

表单重复提交原理图

struts笔记 随笔 第197张

1、Servelt的表单重复提交的一种解决方案

session存验证码

比如在登录时,可以通过验证码存在session中来解决【画图】

struts笔记 随笔 第198张

struts笔记 随笔 第199张

struts笔记 随笔 第200张

2、Struts的表单重复提交解决方案

a、使用重定向

struts笔记 随笔 第201张

b、使用<s:token/>生成令牌配合token拦截器

struts笔记 随笔 第202张

struts笔记 随笔 第203张

此种解决方式不太符合逻辑,它是产生了错误之后再告知用户,应该一直停留在当前界面

c、使用 生成令牌配合tokensession拦截器

struts笔记 随笔 第204张

扫码关注我们
微信号:SRE实战
拒绝背锅 运筹帷幄