Struts 2.x

--------------------------Struts 2.x 理论介绍 --------------------------

Struts2 是在 WebWork2 基础发展而来的,和 struts1 一样, struts2 也属于 MVC 框架。尽管 Struts2 Struts1 在名字上的差别不是很大,但是两者在代码编写的风格上几乎是不一样的。既然有了 Struts1 还要推出 Struts2 的原因,主要是由于 Struts2 具有以下很明显的优点: ( 当然 Struts2 的优点远不止这些 )

(1)  在软件设计上 Struts2 没有像 Struts1 那样与 ServletAPI StrutsAPI 有着紧密的耦合, Struts2 的应用可以不依赖于 ServletAPI StrutsAPI ,这种设计属于无侵入式设计,而 Struts1 却属于侵入式设计。

(2)  Struts2 提供了拦截器,利用拦截器可以进行 AOP 编程,实现如权限拦截等功能

(3)  Struts2 提供了类型转换器,可以把特殊的请求参数转换成需要的类型,在 Struts1 中要实现该功能就必须向 Struts1 的底层实现 BeanUtils 注册类型转换器才可以

(4)  Struts2 提供支持多种表现层技术,如 JSP freeMarke Velocity

(5)  Struts2 的输入校验可以对指定方法进行校验,解决了 Struts1 的长久之痛

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

 

 

--------------------------Struts 2.x 环境配置 --------------------------

下载 struts jar 包,从 Apache 的官方网站 http://www.apache.org/ 中下载

选择 Download--Backup Sites 下的 http://www.apache.org/dist/--struts --binaries , 可以找到有关 struts 2.x 的不同版本

 

Struts 2.x jar

开发 Struts 2.x 应用需要依赖的 jar 文件在下载的解压目录的 lib 文件夹下。不同的应用需要的 jar 包是不同的。下面给出了 Struts 2.x 程序最少需要的 jar 文件

Struts2-core-2.x.x.jar:Struts2 框架的核心类库

xwork-2.x.x.jar:XWork 类库, Struts2 在其上构建

ognl-2.x.x.jar: 对象图导航语言 (Object Graph Navigation Language)Struts2 框架通过其读写对象的属性

freemarker-2.x.x.jar: Struts2 UI 标签的模板使用 FreeMarker 编写

commons-logging-1.1.x.jar ASF 出品的日志包, Struts2 框架使用这个日志包来支持 log4J JDK 的日志记录

commons-fileupload-1.2.1.jar :文件上传组建, 2.1.6 版本后必须加入此文件

1.    搭建环境

(1)    导入 jar

(2)    WEB-INF/classes 下建立配置文件: struts.xml

(3)    web.xml 文件中加入 Struts2 MVC 框架的启动配置

(4)    超链接

struts.xml文件示例

web.xml文件示例

2.    web.xml

Struts1 中, struts 框架是通过 Servlet 启动的,在 Struts2 中, struts 框架是通过 Filter 启动的。他在 web.xml 中的配置如下:

< filter >

    < filter-name > struts2 </ filter-name >

    < filter-class >

org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter

</ filter-class >

<!-- 自从 Struts 2.1.3 以后,下面的 FilterDispatcher 已经标注为过时

<filter-class>

org.apache.struts2.dispatcher.FilterDispatcher

</filter-class>

-->

</ filter >

< filter-mapping >

    < filter-name > struts2 </ filter-name >

    < url-pattern > /* </ url-pattern >

</ filter-mapping >

3.    struts.xml

StrutsPrepareAndExecuteFilter init() 方法中将会读取类路径下默认的配置文件 struts.xml 完成初始化操作。

注意, struts2 读取到 struts.xml 的内容后,以 javabean 形式存放在内存中,以后 struts2 对用户的每次请求处理将使用内存中的数据,而不是每次都读取 struts.xml 文件

在默认的配置文件 struts.xml 中加入如下配置:

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

<! DOCTYPE struts PUBLIC

    "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"

    "http://struts.apache.org/dtds/struts-2.0.dtd" >

 

< struts >

    < constant name = "struts.enable.DynamicMethodInvocation" value = "false" />

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

    < include file = "example.xml" />

 

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

       < action name = "helloworld" class = "cn.itcast.action.HelloWorldAction" method = "execute" >

           < result name = "success" > /WEB-INF/page/hello.jsp </ result >

       </ action >

     </ package >

 

    <!-- Add packages here -->

</ struts >

4.    struts2 框架中使用包来管理 Action ,包的作用和 java 中的类包是非常类似的,它主要用于管理一组业务功能相关的 action 。在实际应用中,我们应该把一组业务功能相关的 Action 放在同一个包下。

配置包时必须指定 name 属性,该 name 属性值可以任意取名,但必须唯一,他不对应 java 的类包,如果其他包要继承该包,必须通过该属性进行引用。包的 namespace 属性用于定义该包的命名空间,命名空间作为访问该包下的 Action 的路径的一部分,如访问上面例子的 Action ,访问路径为: /test/helloworld.action namespace 属性可以不配置,对本例而言,如果不指定该属性,默认的命名空间为 “” (空字符串)。 method = "execute" 表示交给 Action execute 方法执行

通常每个包都应该继承 struts-default 包, 因为 Struts2 很多核心的功能都是拦截器来实现。如:从请求中把请求参数封装到 action 、文件上传和数据验证等等都是通过拦截器实现的。 struts-default 定义了这些拦截器和 Result 类型。可以这么说:当包继承了 struts-default 才能使用 struts2 提供的核心功能。 struts-default 包是在 struts2-core-2.x.x.jar 文件中的 struts-default.xml 中定义。 struts-default.xml 也是 Struts2 默认配置文件。 Struts2 每次都会自动加载 struts-default.xml 文件。

包还可以通过 abstract=“true” 定义为抽象包,抽象包中不能包含 action

5.    struts.xml 配置文件的元素格式规范

The content of element type “struts-config” must match

”(result-types?,interceptors?,default-interceptor-ref?,default-action-ref?,default-class-ref?,global-results?,global-exception-mappings?,action*)”

这是在 MyEclipse 环境下这样来定义的,所以使用此 IDE 时就必须遵守这个规范

 

 

---------------------- 第一个 Struts2 应用 —HellWorld---------------------

1.    导入 jar

2.    配置 web.xml 文件

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

< web-app 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" >

   

  < filter >

    < filter-name > struts2 </ filter-name >

    < filter-class > org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter </ filter-class >

  </ filter >

 

  < filter-mapping >

    < filter-name > struts2 </ filter-name >

    < url-pattern > /* </ url-pattern >

  </ filter-mapping >

 

  < welcome-file-list >

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

  </ welcome-file-list >

</ web-app >

3.    配置 struts.xml 文件

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

<! DOCTYPE struts PUBLIC

    "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"

    "http://struts.apache.org/dtds/struts-2.0.dtd" >

 

< struts >

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

        < action name = "helloworld" class = "com.action.HelloWorldAction" >

           < result name = "success" > /WEB-INF/page/hello.jsp </ result >

       </ action >

     </ package >

 

    <!-- Add packages here -->

   

</ struts >

4.    创建 HelloWorldAction

public class HelloWorldAction {

    private String msg ;

   

    public String getMessage() {

       return msg ;

    }

 

    public String execute(){

       msg = " 我的第一个 struts2 应用 " ;

       return "success" ;

    }

}

5.    创建 index.jsp hello.jsp 页面

index.jsp

<%@ page language = "java" import = "java.util.*" pageEncoding = "ISO-8859-1" %>

< html >

  < head >

  </ head >

  < body >

    This is my JSP page. < br >

    < a href = "test/helloworld" > helloworld </ a >

  </ body >

</ html >

 

hello.jsp

<%@ page language = "java" import = "java.util.*" pageEncoding = "UTF-8" %>

< html >

  < head >

    < title > My JSP 'hello.jsp' starting page </ title >

  </ head >

  < body >

    ${message }

  </ body >

</ html >

 

开启 tomcat ,访问 http://localhost:8009/Struts%202.xTest/index.jsp 执行测试

 

struts1 中,通过 < action path = “/test/helloworld” > 节点的 path 属性指定访问该 action URL 路径。在 struts2 中,情况就不是这样了,访问 struts2 action URL 路径由两部份组成:包的命名空间 +action 的名称,例如访问本例子 HelloWorldAction URL 路径为: /test/helloworld ( 注意:完整路径为: http://localhost: 端口 / 内容路径 /test/helloworld) 。另外我们也可以加上 .action 后缀访问此 Action

 

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

        < action name = "helloworld" class = "cn.itcast.action.HelloWorldAction" method = "execute" >

    < result name = "success" > /WEB-INF/page/hello.jsp </ result >

        </ action >

  </ package >

 

 

--------------------- 解决 struts2 配置文件无提示问题 ----------------------

Struts.xml 配置文件没有提示,原因是

http://struts.apache.org/dtds/struts-2.0.dtd 文件找不到,因为这个路径属于网络路径,如果你的机器没有上网就下载不到该文件,所以配置文件中就没有提示

两个做法:

1.    机器要连接到互联网上, IDE 会自动下载并配置该文件

2.    IDE 中配置该 dtd 文件

Myeclipse 中, Window—Preferences—-MyEclipse—Files and Editors—XML

--XML Catalog—- 选择 Add 按钮添加

Location 中选择 struts-2.0.dtd 文件的路径

dtd 文件一般在 Struts 2.1.8.1/src/core/src/main/resources/ struts-2.0.dtd

Key Tpye 中选择 URI

Key 中填写 http://struts.apache.org/dtds/struts-2.0.dtd

 

回到 dtd 文件中,随便回一下车,在保存下,就可以出现提示了

 

 

--------------------------Action 名称的搜索顺序 -------------------------

1.    获得请求路径的 URI ,例如 url 是:

http://server/struts2/path1/path2/path3/test.action

2. 首先寻找 namespace /path1/path2/path3 package ,如果存在这个 package ,则在这个 package 中寻找名字为 test action ,如果不存在这个 package 则转步骤 3

3 .寻找 namespace /path1/path2 package ,如果存在这个 package ,则在这个 package 中寻找名字为 test action ,如果不存在这个 package ,则转步骤 4

4 .寻找 namespace /path1 package ,如果存在这个 package ,则在这个 package 中寻找名字为 test action ,如果仍然不存在这个 package ,就去默认的 namaspace package 下面去找名字为 test action (默认的命名空间为空字符串 "" ),如果还是找不到,页面提示找不到 action

 

 

------------------------Action 配置中的各项默认值 ------------------------

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

        < action name = "helloworld" class = "com.action.HelloWorldAction" >

           < result name = "success" > /WEB-INF/page/hello.jsp </ result >

       </ action >

       < action name = "hello" >

           < result > /WEB-INF/page/hello.jsp </ result >

       </ action >

     </ package >

hello 是一个各项属性都为默认值的 Action

1> 如果没有为 action 指定 class ,默认是 ActionSupport

2> 如果没有为 action 指定 method ,默认执行 action 中的 execute() 方法。

3> 如果没有指定 result name 属性,默认值为 success

当用户请求这个 action 的时候,首先会交给 ActionSupport 处理,然后 ActionSupport 类包含了一个默认的 execute() 方法,且其方法默认返回值为一个字符串常量 SUCCESS ,该字符串的值为 ”success”

 

 

---------------------Action result 的各种转发类型 ----------------------

1.    Struts1 中有两种转发类型

< action path = "/control/employee" />

    < forward name = "add" > index.jsp </ forward 内部请求转发方式

    < forward name = "add" redirect = "true" > index.jsp </ forward

浏览器重定向方式

</ action >

 

Struts2 中,也有对应于 Struts1 的两种方式

< action name = "helloworld" class = "cn.itcast.action.HelloWorldAction" >

< result name = "success" > /WEB-INF/page/hello.jsp </ result >

dispatcher 方式

</ action >

result 配置类似于 struts1 中的 forward ,但 struts2 中提供了多种结果类型,常用的类型有: dispatcher( 默认值 ) redirect redirectAction plainText

Dispatcher 就对应于 Struts1 的内部请求转发

Redirect 浏览器重定向不能访问到 WEB-INF 下的内容,只能由内部请求转发来方式访问

2.    Struts2 中的静态重定向

< action name = "redirect" >

    < result type = "redirect" > /employeeAdd.jsp </ result >

</ action >

type 属性用来指定接口的类型,这里是采用了重定向的方式

3.    Struts.xml 文件中配置的 action 跳转页面携带参数

中文参数和英文参数

HelloWorldAction 中定义一个 username 属性,并在 execute param 方法中赋初值

execute 用于英文参数, param 用于中文参数

public class HelloWorldAction {

    private String msg ;

    private String username ;

   

    public void setUsername(String username) {

       this . username = username;

    }

 

    public String getUsername() {

       return username ;

    }

 

    public String getMessage() {

       return msg ;

    }

 

    public String execute(){

       username = "Shiki" ;

       msg = " 我的第一个 struts2 应用 " ;

       return "success" ;

    }

    public String param(){

       //username="Shiki";

       username =URLEncoder.encode( " 传智播客 " );

       msg = " 我的第一个 struts2 应用 " ;

       return "success" ;

    }

}

配置 struts.xml 文件

< action name = "helloworld" class = "com.action.HelloWorldAction" method = "execute" >

    < result name = "success" > /WEB-INF/page/hello.jsp </ result >

</ action >

< action name = "param" class = "com.action.HelloWorldAction" method = "param" >

< result name = "success" > /employeeAdd.jsp?username=${username}

</ result >

</ action >

index.jsp 文件中测试

< a href = "test/param" > 带参链接 </ a >< br >

通过 ${username} 这个表达式就可以访问 action 中的 username 属性,但是该属性名 必须与属性的 setXXX 方法的 XXX 部分的名称相同,且首字母小写,与 struts 中的 formbean 利用反射机制获取值的方式基本一致

 

在配置文件中,都是调用同一个 action ,但是请求使用的 method 方法不同,所以这种写法很类似于 Struts1 中的 DispatchAction

4.    Struts2 中的 redirectAction( 重定向 Action)

(1) 同一个包中从一个 action 转到另一个 action

配置 struts.xml 配置文件

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

< action name = "param"

class = "com.action.HelloWorldAction" method = "param" >

       < result name = "success" >

/employeeAdd.jsp?username=${username}

</ result >

</ action >

< action name = "redirectAction" >

< result type = "redirectAction" > param </ result >

</ action >

</ package >

index.jsp 文件中测试

< a href = "test/redirectAction" > 重定向 Action </ a >< br >

 

(2) 不同包中从一个 action 转到另一个 action

上述例子是当 action 在同一个包中的情况,

那么如果是不同包中的 action 之间要进行重定向 action

如果我要重定向到其他包的 action ,这时候我们就要采用 <param> 配置项,为 redirectAction 这个类型所对应的 java 类的属性注入值,这个属性是用来注入值的,这个类型的背后实际上是对应了一个 java 类,要想查找这个类,从 Struts2 jar 包中找到,核心类文件 struts2-core-2.1.8.1.jar---struts-default.xml ,从中就能找到如下信息:

< result-type name = "redirectAction" class = "org.apache.struts2.dispatcher.ServletActionRedirectResult" />

然后为该类中的 actionName namespace 属性注入值,来指定 redirectAction 要重定向到

哪个命名空间底下的 action

配置 struts.xml 文件

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

< action name = "redirectAction" >

       < result type = "redirectAction" >

           < param name = "namespace" > /control/department </ param >

           < param name = "actionName" > xxx </ param >

       </ result >

    </ action >

</ package >

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

     < action name = "xxx" >

        < result > /WEB-INF/page/hello.jsp </ result >

     </ action >

</ package >

index.jsp 文件中测试

< a href = "test/redirectAction" > 重定向 Action </ a >< br >

5.    plainText

这种结果类型用的不是很多,它可以原样显示出视图的代码,这个功能比较适合用于在一个技术网站中,其中有一个功能是供用户浏览某些程序的源代码,可以采用 plainText 转发类型转发到一个 jsp ,然后可以将这个 jsp 的代码原样显示给用户看

有一个缺点是:这种视图不能原样读取 WEB-INF 目录下的文件,只是会去解析

配置 struts.xml 文件

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

     < action name = "xxx" >

        < result > /WEB-INF/page/hello.jsp </ result >

     </ action >

  </ package >        

在目标页面 hello.jsp 中要包含一些中文字符,用来为下个问题做铺垫

<%@ page language = "java" import = "java.util.*" pageEncoding = "UTF-8" %>

< html >

  < head >

    < title > My JSP 'hello.jsp' starting page </ title >

  </ head >

  < body >

    ${message }  这里是 hello.jsp

  </ body >

</ html >

index.jsp 文件中测试

< a href = "test/plainText" > plainText 原样显示 </ a >< br >

测试后,发现代码部分都会原样显示,但是中文字符却是乱码

struts 在读取文件的时候,是采用系统默认的 jdk 编码方式来读取以 UTF-8 编码存放的文件

所以我们要修改配置文件,必须为 plainText 类型背后对应的 java 类注入两个属性值: location charSet

< action name = "plainText" >

    < result type = "plainText" >

       < param name = "location" > /WEB-INF/page/hello.jsp </ param >

       < param name = "charSet" > UTF-8 </ param > <!-- 读取文件的编码方式 -->

             

    </ result >

</ action >

6.    全局视图

让一个包里的一个视图可以供包内其他 action 使用

配置 struts.xml 文件

在包内的最开头,先定义全局视图 ( 必须在所有的 action 之前定义,否则无效 )

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

< global-results >

       < result name = "message" > /redirect.jsp </ result >

</ global-results >

< action name = "manage" class = "com.action.HelloWorldAction" method = "add" >

</ action >

</ package >

HelloWorldAction 中创建 add 方法

public String add(){

    return "message" ; // 直接返回全局视图的名称

}

index.jsp 页面中测试

< a href = "test/manage" > 全局视图 </ a >< br >

7.    包继承

默认的全局视图只能由其所在包内的 action 来调用,那么如果想让其他包内的 action 都可以使用呢 ?

我们可以定义一个 package ,在其中定义全局视图,如果其他包中的 action 想调用全局视图,那么这些包就可以去继承这个定义全局视图的包

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

    < global-results >

       < result name = "message" > /WEB-INF/page/message.jsp </ result >

    </ global-results >

</ package >

< package name = "global" namespace = "/global" extends = "aa" >

    < action name = "manage"

class = "com.action.HelloWorldAction" method = "add" >

    </ action >

</ package >

 

result 中还可以使用 ${ 属性名 } 表达式访问 action 中的属性,表达式里的属性名对应 action 中的属性。如下:

< result type = "redirect" > view.jsp?id=${id} </ result >

 

 

------------------------- Action 的属性注入值 --------------------------

Struts2 Action 中的属性提供了依赖注入功能,在 struts2 的配置文件中,我们可以很方便地为 Action 中的属性注入值。注意:属性必须提供 setter 方法。

1.    Action 中定义一个属性,用于以后为该属性传入值

public class IocAction  extends ActionSupport{

 

    private String savepath ;

 

    public String getSavepath() {

       return savepath ;

    }

 

    public void setSavepath(String savepath) {

       this . savepath = savepath;

    }

 

    @Override

    public String execute() throws Exception {

       return SUCCESS ;

    }

}

2.    配置 struts.xml 文件

< action name = "Ioc" class = "com.action.IocAction" >

    < param name = "savepath" > /image </ param >

    <!-- <param> 配置节点给 action 中的属性注入值 -->

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

</ action >

 

3.    index.jsp 文件中测试

< a href = "test/Ioc" > Action 的属性注入值 </ a >< br >

 

 

---------------------- 指定需要 Struts 2 处理的请求后缀 ---------------------

1.    设定请求 action 的后缀名

前面我们都是默认使用 .action 后缀名或无后缀访问 Action 。其实默认后缀是可以通过常量 ”struts.action.extension“ 进行修改的,例如:我们可以配置 Struts 2 只处理以 .do 为后缀的请求路径:

修改 struts.xml 配置文件

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

<! DOCTYPE struts PUBLIC

    "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"

    "http://struts.apache.org/dtds/struts-2.0.dtd" >

< struts >

    < constant name = "struts.action.extension" value = "do" />

</ struts >

如果用户需要指定多个请求后缀,则多个后缀之间以英文逗号( , )隔开。如:

< constant name = "struts.action.extension" value = "do,go" />

 

 

-------------------------- 配置文件中常量的使用 --------------------------

1.    常量的定义

常量可以在 struts.xml struts.properties 中配置,建议在 struts.xml 中配置,两种配置方式如下:

struts.xml 文件中配置常量

<struts>

    <constant name="struts.action.extension" value="do"/>

</struts>

struts.properties 中配置常量 该文件也要与 struts.xml 文件一同放在 src 的根目录下

struts.action.extension=do

因为常量可以在下面多个配置文件中进行定义,所以我们需要了解 struts2 加载常量的搜索顺序 :

struts-default.xml

struts-plugin.xml

struts.xml

struts.properties

web.xml

如果在多个文件中配置了同一个常量,则后一个文件中配置的常量值会覆盖前面文件中配置的常量值 .

2.    常用的常量介绍

(1) 指定默认编码集 , 作用于 HttpServletRequest setCharacterEncoding 方法 freemarker velocity 的输出

当我们以 post 方式发送一些中文请求参数的时候, tomcat 默认是以 ISO-8859-1 的方式来接受中文请求参数,如果我们要想得到正确的中文数据,

我们就可以使用 request setCharacterEncoding 方法重新设定字符集

< constant name = "struts.i18n.encoding" value = "UTF-8" />

(2) 该属性指定需要 Struts 2 处理的请求后缀,该属性的默认值是 action ,即所有匹配 *.action 的请求都由 Struts2 处理。

如果用户需要指定多个请求后缀,则多个后缀之间以英文逗号( , )隔开。

< constant name = "struts.action.extension" value = "do" />

(3) 设置浏览器是否缓存静态内容 , 默认值为 true( 生产环境下使用 ), 开发阶段最好关闭

< constant name = "struts.serve.static.browserCache" value = "false" />

(4) struts 的配置文件修改后 , 系统是否自动重新加载该文件 , 默认值为 false( 生产环境下使用 ), 开发阶段最好打开 , 当值为 true 的时候,只要修改了配置文件,就不需要重新启动服务器,直接刷新就可以了

< constant name = "struts.configuration.xml.reload" value = "true" />

(5) 开发模式下使用 , 这样可以打印出更详细的错误信息 , 主要用于查错

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

(6) 默认的视图主题

< constant name = "struts.ui.theme" value = "simple" />

(7) spring 集成时,指定由 spring 负责 action 对象的创建

< constant name = "struts.objectFactory" value = "spring" />

(8) 该属性设置 Struts 2 是否支持动态方法调用,该属性的默认值是 true 。如果需要关闭动态方法调用,则可设置该属性为 false

< constant name = "struts.enable.DynamicMethodInvocation" value = "false" />

(9) 上传文件的大小限制

如果想利用 struts2 来上传一些大文件,超过了某一个固定值之后, struts2 默认是不接收的,它不会接收超过它大小限制的文件,如果要上传一些大文件,而这些文件又超过了 struts2 默认的文件大小限制,就可以通过这个常量来设置 struts2 可以接收更大的文件

struts2 上传文件的大小并不是单步文件的大小,而是上传文件的总大小 , 上传三个文件,就是三个文件加起来的总大小

< constant name = "struts.multipart.maxSize" value = "10701096" />

 

 

------------------Struts2 的处理流程与 Action 的管理方式 -------------------

 

1.    Struts2 的处理流程

StrutsPrepareAndExecuteFilter Struts 2 框架的核心控制器,它负责拦截由 <url-pattern>/*</url-pattern> 指定的所有用户请求,当用户请求到达时,该 Filter 会过滤用户的请求。默认情况下,如果用户请求的路径不带后缀或者后缀以 .action 结尾,这时请求将被转入 Struts 2 框架处理,否则 Struts 2 框架将略过该请求的处理。当请求转入 Struts 2 框架处理时会先经过一系列的拦截器,然后再到 Action 。假设发现请求路径带有后缀,但又不是 struts2 要处理的后缀,这时候就不会转入到 Struts2 的框架处理,检测到路径不匹配,不是它要处理的路径的时候, filter 就会掠过该请求的处理

2.    Struts1 action Struts2 action 在管理方式上有什么不同

Struts1 action 的管理方式是当 action 一旦被创建出来后,先放入缓存中去,以后用户的每一次请求都会从缓存中获取这个 action 来进行处理,这种设计模式属于单例设计模式,在应用的生命周期内你会存在一个 action 的实例来处理用户的请求

Struts1 不同, Struts2 对用户的每一次请求都会创建一个 Action ,所以 Struts2 中的 Action 是线程安全的。

 

 

--------------------- 为应用指定多个 xxx.xml 配置文件 ----------------------

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

一般在企业开发中,通常都会以模块来划分配置文件,一个模块就是一个配置文件,最后在项目集成的时候我们会把各个模块的配置文件通过 <include> 元素包含进来

struts.xml 中很少会配置一些某个功能的 action ,只会定义一些所有模块都会使用的公共配置并包含进来各个模块的文件包含进来

 

下面的 struts.xml 通过 <include> 元素指定多个配置文件:

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

<! DOCTYPE struts PUBLIC

    "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"

    "http://struts.apache.org/dtds/struts-2.0.dtd" >

< struts >

    < include file = "department.xml" />

< include file = "employee.xml" />

</ struts >

 

department.xml

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

<! DOCTYPE struts PUBLIC

    "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"

    "http://struts.apache.org/dtds/struts-2.0.dtd" >

< struts >

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

       < action name = "list" class = "com.action.IocAction" method = "execute" >

           < param name = "savepath" > department </ param >

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

       </ action >

    </ package >

</ struts >

 

employee.xml

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

<! DOCTYPE struts PUBLIC

    "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"

    "http://struts.apache.org/dtds/struts-2.0.dtd" >

< struts >

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

       < action name = "list" class = "com.action.IocAction" method = "execute" >

           < param name = "savepath" > employee </ param >

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

       </ action >

    </ package >

</ struts >

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

 

 

----------------Struts2 实现 Struts1-DispatchAction 功能 ----------------

struts1 中,由请求路径中所带参数指定调用哪个 action 的方法,我们可以让 action 继承 DispatchAction ,然后再配置文件中指定 parameter 元素来定义参数的名称,这个参数就可以指定要执行 action 下的哪个方法

Struts2 中如何实现 struts1 中由请求参数指定要执行的方法的这个功能呢 ?

有两种方法:

1.    动态方法调用

(1)  继续使用 IocAction ,在其中添加一个 addUI 方法

public class IocAction  extends ActionSupport{

 

    private String savepath ;

 

    public String getSavepath() {

       return savepath ;

    }

 

    public void setSavepath(String savepath) {

       this . savepath = savepath;

    }

 

    public String addUI(){

       savepath = "addUI" ;

       return SUCCESS ;

    }

   

    @Override

    public String execute() throws Exception {

       return SUCCESS ;

    }

}

(2)  修改 strust.xml 配置文件

< action name = "Ioc" class = "com.action.IocAction" >

           < param name = "savepath" > /image </ param >

           <!-- <param> 配置节点给 action 中的属性注入值 -->

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

       </ action >

(3)  index.jsp 中测试

如果 Action 中存在多个方法时,我们可以使用 !+ 方法名调用指定方法。

动态方法调用 < br >

< a href = "test/Ioc!execute" > execute 方法 </ a >< br >

< a href = "test/Ioc!addUI" > addUI 方法 </ a >

 

如果请求路径是以 .action 为后缀的,假设访问上面 action URL 路径为:

test/Ioc.action

要访问 action addUI() 方法,我们可以这样调用:

test/Ioc!addUI.action

 

Struts2.1 版本中,对于这种做法已经不建议使用了

如果不想使用动态方法调用,我们可以通过常量

struts.enable.DynamicMethodInvocation 关闭动态方法调用。

< constant name = "struts.enable.DynamicMethodInvocation" value = "false" />

如果已经禁止了动态方法调用,你在后面企图使用 !+ 方法名这种方式来调用 action 中的方法时,是不会成功的,会报 HTTP Status 400 错误

2.    使用通配符定义 action

(1)  继续使用 IocAction ,不对其做任何修改

(2)  修改 struts.xml 文件,对 action 添加通配符的使用

< action name = "Ioc_*" class = "com.action.IocAction" method = "{1}" >

    < param name = "savepath" > /image </ param >

    <!-- <param> 配置节点给 action 中的属性注入值 -->

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

</ action >

action Ioc 后面加上 * 号通配符, _ 下划线只是为了更好地区分 action 和方法,可写可不写,通配符可以匹配以 Ioc_ 开头的所有 action

那么我们在应用中希望得到 * 号所匹配的内容,例如 :list_addUI ,也就是要得到 addUI 这部分内容,我们打算得到 * 号的内容,把这个字符串作为方法的名称,我们使用 {1} 这种方式来定配置 method 元素的内容, 1 就表示第一个 * 号,而且通配符 * 可以定义多个,在整个 action 定义中在各个元素内都可以使用通配符

例如:

< action name = "Ioc_*_*_*" class = "com.action.{1}" method = "{2}" >

    < param name = "savepath" > /image </ param >

    < result name = "success" > / {3} .jsp </ result >

</ action >

上边定义的 Ioc_* 这个 action ,依然可以和

< action name = "Ioc" class = "com.action.IocAction" >

           < param name = "savepath" > /image </ param >

           <!-- <param> 配置节点给 action 中的属性注入值 -->

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

       </ action >

这个 action 同时存在于 struts.xml 文件中,因为 name 不同 两个 action 的配置相互之间不干扰

(3)  index.jsp 中测试

使用通配符定义 action < br >

< a href = "test/Ioc_execute" > execute 方法 </ a >< br >

< a href = "test/Ioc_addUI" > addUI 方法 </ a >

 

 

---------------------------- 请求参数的接收 -----------------------------

如何去接收客户端浏览器发送过来的请求参数,只有得到了用户的数据,才能去进行处理

Struts2 中不再使用 formbean 这种方式来接收请求参数,在 Action 类中定义与请求参数同名的属性, struts2 便能自动接收请求参数并赋予给同名属性。

1.    采用基本类型接收请求参数 (get 方式 )

(1)  Action 使用 IocAction ,但在其中添加 id name 属性,并添加访问器和构造器

public class IocAction  extends ActionSupport{

 

    private int id ;

    private String name ;

 

    @Override

    public String execute() throws Exception {

       return SUCCESS ;

    }

    public int getId() {

       return id ;

    }

    public void setId( int id) {

       this . id = id;

    }

    public String getName() {

       return name ;

    }

    public void setName(String name) {

       this . name = name;

    }

}

(2)  Struts.xml 配置文件

< action name = "Ioc" class = "com.action.IocAction" >

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

</ action >

(3)  修改结果跳转页面 message.jsp ,添加对 id name 属性的显示

<%@ page language = "java" import = "java.util.*" contentType = "text/html; charset=utf-8" %>

< html >

  < head >

  </ head >

  < body >

     id=${id} < br >

    name=${name} < br >

  </ body >

</ html >

(4)  index.jsp 进行测试

< a href = "test/Ioc?id=1&name=Shiki" > 接收 id name 请求参数 </ a >

2.    采用基本类型接收请求参数 (post 方式 )

修改 index.jsp 测试页面,使用表单提交的方式,将 method 方式改为 post

post 方式接收 id name 请求参数

< form action = "test/Ioc" method = "post" >

编号: < input type = "text" name = "id" >< br >

    名称: < input type = "text" name = "name" >< br >    

< input type = "submit" value = " 提交 " >< br >

</ form >

3.    采用复合类型接收请求参数

Action 中引用一个 javabean 的对象作为一个属性,用这个属性去接收请求参数,请求参数中的内容对应着对象中所包含的基本类型,那么我们在发送请求的时候这个参数该如何命名呢

form 表单的 name 属性,或者是用表达式的显示页面,都是用 action 对象名 . 属性名的方式来赋值或取值

 

 

(1)  创建一个 javabean ,用来保存 id name

public class Person {

 

    private int id ;

    private String name ;

   

    public int getId() {

       return id ;

    }

    public void setId( int id) {

       this . id = id;

    }

    public String getName() {

       return name ;

    }

    public void setName(String name) {

       this . name = name;

    }

}

(2)  Struts.xml 配置文件不做更改

< action name = "Ioc" class = "com.action.IocAction" >

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

</ action >

(3)  修改结果跳转页面 message.jsp ,添加对 person 对象的 id name 属性的显示

<%@ page language = "java" import = "java.util.*" contentType = "text/html; charset=utf-8" %>

< html >

  < head >

  </ head >

  < body >

    id=${person.id} < br >

    name=${person.name} < br >

  </ body >

</ html >

(4)  index.jsp 页面进行测试

采用复合类型接收请求参数

< form action = "test/Ioc" method = "post" >

编号: < input type = "text" name = "person.id" >< br >

名称: < input type = "text" name = "person.name" >< br >

< input type = "submit" value = " 提交 " >< br >

</ form >

 

Struts2 首先通过反射技术调用 Product 的默认构造器创建 product 对象 , 然后再通过反射技术调用 product 中与请求参数同名的属性的 setter 方法来获取请求参数值。

 

如果使用的 struts2 的版本是 2.1.6 ,这个版本中存在一个 bug ,即接收到的中文请求参数为乱码 ( post 方式提交 ) ,原因是 struts2.1.6 在获取并使用了请求参数后才调用 HttpServletRequest setCharacterEncoding() 方法进行编码设置,导致应用使用的就是乱码请求参数。这个 bug struts2.1.8 中已经被解决,如果在使用 struts2.1.6 时碰到这个问题,可以新建一个 Fileter ,把这个 Filter 放置在 Struts2 Filter 之前,然后 doFilter() 方法里添加以下代码

public void doFilter(){

    HttpServletRequest req=(HttpServletRequest) request;

    Req.setCharacterEncoding(“UTF-8”); // 根据你所使用的编码来设定

    Filterchain.doFilter(request,response);

}

 

 

--------------------------- 自定义类型转换器 ----------------------------

1.    如果我们希望在 Action 中接收一个 Date 类型的请求参数,是否能接收到呢

看看 Struts2 是否能接收到一个 Date 类型的数据

(1)  Action 中添加 birthday 属性及其 getter setter 方法,并在 execute 方法中在控制台输出 birthday 的值

private Date birthday ;

public Date getBirthday() {

    return birthday ;

}

public void setBirthday(Date birthday) {

    this . birthday = birthday;

}

@Override

public String execute() throws Exception {

    System. out .println( birthday );

    return SUCCESS ;

}

(2)  继续使用 IocAction

< action name = "Ioc" class = "com.action.IocAction" >

    < param name = "savepath" > /image </ param >

    <!-- <param> 配置节点给 action 中的属性注入值 -->

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

</ action >

(3)  success.jsp 中添加对 birthday 属性的输出

----- 接收日期类型请求参数 ----- < br >

${birthday}

(4)  index.jsp 页面中测试

< a href = "test/Ioc?birthday=2010-09-07" > Action 中接收 Date 类型的请求参数,格式为: 2010-09-07 </ a >< br >

在页面和控制台都会输出 : Tue Sep 07 00:00:00 CST 2010 ,说明可以接收到该日期类型的参数。并转化为英文的格式输出

2.    如果要求传递过去的日期格式不是 2010-09-07 ,而是 20100907 ,那么 Struts2 能否接收到这种格式的数据并转化成 Date 类型呢

index.jsp 页面中测试

< a href = "test/Ioc?birthday=20100907" > Action 中接收 Date 类型的请求参数,格式为: 20100907 </ a >< br >

在页面中会原样输出 20100907 ,但是在控制台会因为输出 birthday 变量的值而报错,因为 birthday Date 类型,但是 Struts2 默认会将传递过来的无法识别的类型作为 String 类型来处理

3.    java.util.Date 类型的属性可以接收格式为 2009-07-20 的请求参数值。但如果我们需要接收格式为 20091221 的请求参数,我们必须定义类型转换器,否则 struts2 无法自动完成类型转换。

这样,我们就需要定义类型转换器, Struts2 中为我们提供了两种类型转换器

(1)  局部类型转换器:只对某一个 Action 起作用

(2)  全局类型转换器:对整个应用起作用

4.    局部类型转换器

(1)  创建一个转换器类,需要继承 DefaultTypeConverter 类,并实现其中 convertValue 方法

public class DateTypeConverter extends DefaultTypeConverter {

    @Override

    public Object convertValue(Map<String, Object> context, Object value, Class toType) {

       /*

       Map<String, Object> context 属于 ognl 表达式

       Object value 表示传递过来的请求参数值,例如 birthday=2010-09-07

       Class toType 表示当前传递过来的请求参数要转换成的类型,也就是与 Action 中对应的那个属性的类型

       */

       SimpleDateFormat dateFormat = new SimpleDateFormat( "yyyyMMdd" );

       /*

       DateFormat 是日期 / 时间格式化子类的抽象类,它以与语言无关的方式格式化并分析日期或时间。

       日期 / 时间格式化子类(如 SimpleDateFormat )允许进行格式化(也就是日期 -> 文本)、

       分析(文本 -> 日期)和标准化。

       */

       try {

           if (toType == Date. class ){ // 当字符串向 Date 类型转换时

              String[] params = (String[]) value;

           /* 这里将请求参数的值转换为了 String 数组 , 因为 Struts2 采用 request.getParameterValues()

              方式来接收请求参数,要考虑到多种情况,例如:多选框中获取到的值就一定是一个数组 */

              return dateFormat.parse(params[0]);

              // 从给定字符串的开始分析文本,以生成一个日期。在 dateFormat 定义的类型是 yyyyMMdd

           } else if (toType == String. class ){ // Date 转换成字符串时

              Date date = (Date) value;

              return dateFormat.format(date); // 将一个 Date 格式化为日期 / 时间字符串。

           }

       } catch (ParseException e) {}

       return null ;

    }

}

该类型转换器可以实现双向转换,由请求参数的值转换为属性的值,利用 Struts2 标签进行数据回显需要将请求参数转换为 String 类型的值

(2)  将上面的类型转换器注册为局部类型转换器

Action 类所在的包下放置 ActionClassName-conversion.properties 文件, ActionClassName Action 的类名,后面的 -conversion.properties 是固定写法,对于本例而言,文件的名称应为 IocAction-conversion.properties ,在 properties 文件中的内容为:

birthday= com.TypeConverter.DateTypeConverter

Key 是对 Action 类中的哪个属性进行类型转换

Value 表示使用的是哪个类型转换器类 ( 带包名 )

(3)  index.jsp 页面中测试

< a href = "test/Ioc?birthday=20100907" > 局部类型转换器 </ a >< br >

也可以正常的输出结果了: Tue Sep 07 00:00:00 CST 2010

5.    全局类型转换器

如果对所有的 Date 属性都要进行 20100907 这种格式的转换,那么我们就要使用全局类型转换器

继续使用上面定义的 DateTypeConverter 类型转换器类, 将其注册为全局类型转换器:

WEB-INF/classes 下放置 xwork-conversion.properties 文件 (src 根目录下 ) ,在 properties 文件中的内容为:

待转换的类型 = 类型转换器的全类名

对于本例而言, xwork-conversion.properties 文件中的内容为:

java.util.Date= com.TypeConverter.DateTypeConverter

对于应用中的所有 Date 类型的数据都可以使用 DateTypeConverter 类型转换器类进行注册

 

 

--------------- 访问或添加 request/session/application 属性 ---------------

Action 中并没有使用到 Servlet API ,我们在其方法中无法得到 Session 对象, Request 对象和 ServletContext 对象

Struts2 为了避免用户直接访问 ServletAPI ,对这几个范围作了封装,可以通过 ActionContext 对象向这三个范围中访问或添加属性

1.    ActionContext

(1)  创建 ScopeAction ,向三个范围中添加属性

public class ScopeAction extends ActionSupport{

    @Override

    public String execute() throws Exception {

      

       ActionContext ctx = ActionContext.getContext ();

       ctx.getApplication().put( "app" , " 应用范围 " ); // ServletContext 里放入 app

       ctx.getSession().put( "ses" , "session 范围 " ); // session 里放入 ses

       ctx.put( "req" , "request 范围 " ); // request 里放入 req

       return "scope" ;

    }

}

(2)  struts.xml 文件中配置 ScopeAction

< action name = "scope" class = "com.action.ScopeAction" >

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

</ action >

(3)  ScopeAction 的跳转页面为 scope.jsp ,创建该页面,并在其中输出三个范围中属性的内容

<%@ page language = "java" import = "java.util.*" contentType = "text/html; charset=gbk" %>

< html >

  < head >

  </ head >

  < body >

  -----Application 范围 ----- < br >

   ${applicationScope.app} < br >

  

   -----Session 范围 ----- < br >

   ${sessionScope.ses} < br >

  

   -----Request 范围 ----- < br >

   ${requestScope.req} < br >

  </ body >

</ html >

(4)  index.jsp 页面中测试

< a href = "test/scope" > 使用 ActionContext 对象向三个范围中访问或添加属性 </ a >< br >

(5)  可以在 request 属性中保存一个数组,然后在页面中使用 JSTL 表达式来输出该数组的内

Execute 方法中添加

ctx.put( "names" , Arrays.asList ( " 张三 " , " 李四 " , " 王五 " ));

scope 页面中输出

       ----- 输出 request 范围中保存的数组内容 -----

        < c:forEach items = "${names} " var = "name" >

          ${name} < br >

        </ c:forEach >               

2.    通过 ServletActionContext 类直接获取

(1)  ScopeAction 中添加一个 rsa 方法

public String rsa() throws Exception{

    HttpServletRequest request = ServletActionContext.getRequest ();

    ServletContext servletContext = ServletActionContext.getServletContext ();

    request.setAttribute( "req" , " 请求范围属性 " );

    request.getSession().setAttribute( "ses" , " 会话范围属性 " );

    servletContext.setAttribute( "app" , " 应用范围属性 " );

    //HttpServletResponse response = ServletActionContext.getResponse();

       return "message" ;

}

(2)  index.jsp 页面中测试

< a href = "test/scope!rsa" > 使用 ActionContext 对象向三个范围中访问或添加属性 </ a >< br >

3.    实现指定接口,由 struts 框架运行时注入

public class HelloWorldAction implements ServletRequestAware, ServletResponseAware, ServletContextAware{

    private HttpServletRequest request ;

    private ServletContext servletContext ;

    private HttpServletResponse response;

    public void setServletRequest(HttpServletRequest req) {

       this . request =req;

    }

    public void setServletResponse(HttpServletResponse res) {

       this .response=res;

    }

    public void setServletContext(ServletContext ser) {

       this . servletContext =ser;

    }

}

4.    总结

(1)  如果仅仅是向这三个范围中放入属性,就是用 ActionContext

(2) 有些情况下满足不了要求,必须要通过得到原始的 ServletAPI 对象就只能通过 ServletActionContext 来获取

假设现在要得到站点目录下某一个文件的绝对路径,这时候就需要使用 ServletActionContext 来得到 servletContent 对象,通过其 getRealPath() 方法来得到文件的绝对路径

 

 

------------------------------ 单文件上传 ------------------------------

1.    文件上传需要加入 commons-fileupload-1.2.1.jar commons-io-1.3.2.jar

2.    创建 FileUpLoadAction ,在 struts.xml 文件中配置该 Action

< action name = "singlefile" class = "com.action.SingleFileUploadAction" >

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

</ action >

3.    创建 fileUpload.jsp 文件

配置 formbean ,把 form 表单的 enctype 属性设置为: ”multipart/form-data”

< form enctype = "multipart/form-data" action = "test/singlefile" method = "post" >

文件上传   < input  type = "file" name = "image" >

< input type = "submit" value = " 上传 " >

</ form >

4.    Action 类中添加以下属性,属性红色部分对应于表单中文件类型里边 name 属性的名称,添加其 添加 setter/getter 方法,在默认的 execute 方法中编写文件上传的执行过程

private File image ;// 得到上传的文件

  private String image ContentType;// 得到文件的类型

  private String image FileName;// 得到文件的名称

也就是这些属性的开头部分与 < input  type = "file" name = "image" > image 相同,这样 Struts2 就可以在 Action 中通过这几个文件来保存上传的文件本身,及其类型和名称了

 

FileUpLoadAction.java

public class FileUpLoadAction extends ActionSupport{

 

    private File image ; // 得到上传的文件

    private String imageContentType ; // 得到文件的类型

    private String imageFileName ; // 得到文件的名称

 

    public File getImage() {

       return image ;

    }

   

    public void setImage(File image) {

       this . image = image;

    }

 

    public String getImageContentType() {

       return imageContentType ;

    }

 

    public void setImageContentType(String imageContentType) {

       this . imageContentType = imageContentType;

    }

 

    public String getImageFileName() {

       return imageFileName ;

    }

 

    public void setImageFileName(String imageFileName) {

       this . imageFileName = imageFileName;

    }

   

    public String singleFileUpload() throws IOException{

      

       String realpath=ServletActionContext.getServletContext ().getRealPath( "/images" );

       // 获取站点下 images 目录的真实路径

       System. out .println( " 保存路径 : " +realpath);

       System. out .println( " 文件类型 : " +getImageContentType());

       if ( image != null ){

           File savefile= new File( new File(realpath), imageFileName );

           if (!savefile.getParentFile().exists())

              savefile.getParentFile().mkdirs();

           FileUtils.copyFile ( image ,savefile);

           // 第一个参数为源文件,第二个参数为要拷贝的目标文件,我们希望把目标文件放在站点的 image 目录下

           ActionContext.getContext ().put( "message" , " 上传成功 " );

       }

       return SUCCESS ;

    }

}

5.    创建 uploadSuccess.jsp 文件,用来显示 request 中存放的 message 属性的信息

<%@ page language = "java" import = "java.util.*" contentType = "text/html; charset=utf-8" %>

< html >

  < head >

    < title > My JSP 'uploadSuccess.jsp' starting page </ title >

  </ head >

  < body >

    ${message}

  </ body >

</ html >

6.    index.jsp 中测试

< a href = "singleFileUpload.jsp" > 单文件上传 </ a >

7.    更改上传文件的大小限制

如果我们想上传一个大文件,例如 34M 多的文件,那么就会报一个异常

org.apache.commons.fileupload.FileUploadBase$SizeLimitExceededException : the request was rejected because its size (36112782) exceeds the configured maximum (2097152)

说明已经超过了上传文件的大小限制,且提示上传文件的最大值为 2097152 字节,也就是 2M

所以在 struts.xml 配置文件中定义一个常量,重新定义上传文件的大小

< constant name = "struts.multipart.maxSize" value = "36700160" />

 

 

------------------------------ 多文件上传 ------------------------------

1.    修改 Action 中几个属性的类型,都修改为数组或 List 类型,且在默认的 execute 方法中还要对文件数组进行遍历操作,所以我们重新创建一个 Action

public class MultiFileUploadAction extends ActionSupport{

 

    private File[] image ; // 得到上传的文件

    private String[] imageContentType ; // 得到文件的类型

    private String[] imageFileName ; // 得到文件的名称

   

    public File[] getImage() {

       return image ;

    }

 

    public void setImage(File[] image) {

       this . image = image;

    }

   

    public String[] getImageContentType() {

       return imageContentType ;

    }

 

    public void setImageContentType(String[] imageContentType) {

       this . imageContentType = imageContentType;

    }

 

    public String[] getImageFileName() {

       return imageFileName ;

    }

 

    public void setImageFileName(String[] imageFileName) {

       this . imageFileName = imageFileName;

    }

 

    public String execute() throws IOException{

      

       String realpath=ServletActionContext.getServletContext ().getRealPath( "/images" );

       // 获取站点下 images 目录的真实路径

       System. out .println( " 保存路径 : " +realpath);

       System. out .println( " 文件类型 : " +getImageContentType());

       if ( image != null ){

           File savedir= new File(realpath);

           if (!savedir.getParentFile().exists())

              savedir.getParentFile().mkdirs();

           for ( int i=0;i< image . length ;i++){

              File savefile= new File(savedir, imageFileName [i]);

              FileUtils.copyFile ( image [i],savefile);

              // 第一个参数为源文件,第二个参数为要拷贝的目标文件,我们希望把目标文件放在站点的 image 目录下

           }

           ActionContext.getContext ().put( "message" , " 上传成功 " );

       }

       return SUCCESS ;

    }

}

2.    struts.xml 文件中配置该 Action

< action name = "multifile" class = "com.action.MultiFileUploadAction" >

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

</ action >

3.    创建 multiFileUpload.jsp 文件

<%@ page language = "java" import = "java.util.*" contentType = "text/html; charset=utf-8" %>

< html >

  < head >

  </ head >

  < body >

< form enctype = "multipart/form-data" action = " test/multifile" method = "post" >

        文件上传 < br >  

        文件 < input  type = "file" name = "image" >< br >

        文件 < input  type = "file" name = "image" >< br >

        文件 < input  type = "file" name = "image" >< br >

        文件 < input  type = "file" name = "image" >< br >

        < input type = "submit" value = " 上传 " >

    </ form >

  </ body >

</ html >

4.    index.jsp 页面中测试

< a href = "multiFileUpload.jsp" > 多文件上传 </ a >

 

 

------------------------------ 自定义拦截器 -----------------------------

我们通过一个小例子来讲述自定义拦截器的过程:

用一个 session 来保存用户登录或退出的状态,如果用户登录后可以访问 action 中的所有方法,如果没有登录,就不允许访问 action 中的所有方法,并提示 你没有权限执行该操作

1.    创建 interceptorAction

public class interceptorAction {

 

    private String message ;

 

    public String getMessage() {

       return message ;

    }

    public void setMessage(String message) {

       this . message = message;

    }

    public String addUI(){

       return "message" ;

    }

    public String execute(){

       return "message" ;

    }

}

2.    创建 login.jsp quit.jsp ,使用 session 来记录用户的登录和退出的状态

login.jsp

<%@ page language = "java" import = "java.util.*" pageEncoding = "ISO-8859-1" %>

< html >

  < head >

  </ head >

  < body >

    <% request.getSession().setAttribute( "user" , "Shiki" ); %>

    用户已经登录

  </ body >

</ html >

 

quit.jsp

<%@ page language = "java" import = "java.util.*" pageEncoding = "ISO-8859-1" %>

< html >

  < head >

  </ head >

  < body >

    <% request.getSession().removeAttribute( "user" ); %>

    用户已经退出

  </ body >

</ html >

3.    创建一个拦截器类 PermissionInterceptor ,用于拦截方法,

(1) 要自定义拦截器需要实现 com.opensymphony.xwork2.interceptor.Interceptor 接口

public class PermissionInterceptor implements Interceptor {

 

    public void destroy() {

    }

 

    public void init() {

    }

    /* 当拦截到 action 的时候,就执行该方法,功能类似于 Spring AOP 中的环绕通知

      * 在环绕通知中我们可以自己决定被拦截的方法何时执行

      * 在该方法中, invocation.invoke() 用于执行被拦截的方法

      */

    public String intercept(ActionInvocation invocation) throws Exception {

 

       Object user=

ActionContext.getContext ().getSession().get( "user" );

       if (user!= null ){

           return invocation.invoke(); //user 不为空,执行被拦截的方法

       }

       ActionContext.getContext ().put( "message" , " 您没有权限执行该操作 " );

       return "message" ;

    }

}

当用户登录成功,启动 invocation.invoke() 执行被拦截的方法

如果登录不成功,向 request 中设置一个 message ,用于保存错误提示信息,然后

return "message" 表示跳转到一个视图页面,提示用户登录失败,该视图需要定义为一个全局视图,供所有 action 使用

4.    配置 struts.xml 文件

(1) 在配置文件中注册拦截器

< interceptors >

    < interceptor name = "permission" class = "com.Interceptor.PermissionInterceptor" ></ interceptor >

</ interceptors >

(2) 定义全局视图

< global-results >

    < result name = "message" > /WEB-INF/page/message.jsp </ result >

</ global-results >

(3) struts.xml 文件中配置 action

< action name = "list_*" class = "com.action.interceptorAction" method = "{1}" >

</ action >

(4) 配置文件中的顺序为:拦截器,全局视图, Action ,一定要按照 xml 文件所规定的定义顺序配置

(5) action 来定义拦截器,在 action 中添加拦截器属性

< action name = "list_*" class = "com.action.interceptorAction" method = "{1}" >

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

</ action >

但是 struts2 有一个特点,如果你为某个 action 使用了自定义的拦截器,那么 struts2 的核心拦截器就会失效,这种做法会让 action 失去 struts2 的很多核心功能,因为 struts2 的很多核心功能很多都是通过拦截器来实现的,所以你为 action 定义了这个拦截器之后, struts-default 包中的默认拦截器就会失效

其中, struts-default 包中默认的拦截器包括:

< interceptor-stack name = "defaultStack" >

                < interceptor-ref name = "exception" />

                < interceptor-ref name = "alias" />

                < interceptor-ref name = "servletConfig" />

                 < interceptor-ref name = "i18n" />

                < interceptor-ref name = "prepare" />

                < interceptor-ref name = "chain" />

                < interceptor-ref name = "debugging" />

                < interceptor-ref name = "scopedModelDriven" />

                 < interceptor-ref name = "modelDriven" />

                < interceptor-ref name = "fileUpload" />

                < interceptor-ref name = "checkbox" />

                < interceptor-ref name = "multiselect" />

                < interceptor-ref name = "staticParams" />

                < interceptor-ref name = "actionMappingParams" />

                < interceptor-ref name = "params" >

                  < param name = "excludeParams" > dojo/..*,^struts/..*

</ param >

                </ interceptor-ref >

                < interceptor-ref name = "conversionError" />

                < interceptor-ref name = "validation" >

                    < param name = "excludeMethods" > input,back,cancel,browse

</ param >

                </ interceptor-ref >

                < interceptor-ref name = "workflow" >

                     < param name = "excludeMethods" > input,back,cancel,browse

</ param >

                </ interceptor-ref >

            </ interceptor-stack >

当然,上述情况不是我们希望看到的,我们希望既能保留 struts 的核心功能,也能够应用上自定义拦截器的功能,那么该怎么做呢 ?

(6) 定义一个拦截器栈,在步骤 (3) 注册的拦截器中添加拦截器栈,这个拦截器栈由 1 个或多个拦截器组成,是一堆拦截器的集合,当它执行时就会执行所包含的所有的拦截器

< interceptors >

< interceptor name = "permission" class = "com.Interceptor.PermissionInterceptor" />

        < interceptor-stack name = "permissionStack" >

             < interceptor-ref name = "defaultStack" />

<!-- 引入系统默认的拦截器栈 -->

            < interceptor-ref name = " permission " />

<!-- 引入自定义的拦截器 -->

        <!--

        把系统的拦截器栈放入最前面,定义的拦截器放在最后边,因为在前面的先执行,

        要让 struts2 的核心功能先执行,帮我们得到请求参数,上传文件等一系列的信息

        -->       

<!--

        在这个栈里边呢,我们就可以定义我们所使用的这些拦截器,其中有一个拦截器,是由系统提供的拦截器栈

        这个系统提供的拦截器栈中包含了实现 struts2 很多核心功能的拦截器

        -->

        </ interceptor-stack >

</ interceptors >

(7) action 中重新添加拦截器属性

< action name = "list_*"

class = "com.action.interceptorAction" method = "{1}" >

    < result name = "success" > /WEB-INF/page/hello.jsp </ result >

    < interceptor-ref name = "permissionStack" />

    <!-- 然后将定义的拦截器栈赋给它,这样我们的拦截器栈既能保留 struts 的核心功能,也能够应用上自定义拦截器的功能了 -->

</ action >

(8) 如果希望包下的所有 action 都使用自定义的拦截器,可以通过

<default-interceptor-ref name=“permissionStack”/> 把拦截器定义为默认拦截器。注意:每个包只能指定一个默认拦截器。另外,一旦我们为该包中的某个 action 显式指定了某个拦截器,则默认拦截器不会起作用。

定义默认拦截器的方式

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

该拦截器必须放在 action 和全局视图之前,因为 struts.xml 配置文件中的元素定义有一套默认的位置规范,必须遵守该规范,否则位置错误的元素会报错

如果我们单独为某个 action 定义了一个拦截器,又希望保留默认拦截器的作用,这时候可以先定义默认拦截器,再在 action 中定义自定义的拦截器后引入进默认的拦截器,例如:

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

< action name = "list_*"

class = "com.action.interceptorAction" method = "{1}" >

    < result name = "success" > /WEB-INF/page/hello.jsp </ result >

    < interceptor-ref name = "permissionStack" />

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

</ action >

5.    index.jsp 文件中测试

< a href = "/login.jsp" > 登录 </ a >< br >

< a href = "test/list_execute" > 执行操作 </ a >< br >

< a href = "/quit.jsp" > 退出 </ a >< br >

如果用户登录后,就会在 session 中保存一个名为 user 的信息,退出时销毁

通过该 session 的状态来判断是否具有执行操作的权限

 

 

-------------- 采用手工编写方式对 Action 中所有方法进行输入校验 ---------------

struts2 中,可以实现对 action 的所有方法进行校验或者对 action 的指定方法进行校验。

对于输入校验 struts2 提供了两种实现方法 :

采用手工编写代码实现。

基于 XML 配置方式实现。

 

我们先使用手工编写代码方式来校验输入的内容

通过重写 validate() 方法实现, validate() 方法会校验 action 中所有与 execute 方法签名相同的方法。当某个数据校验失败时,我们应该调用 addFieldError() 方法往系统的 fieldErrors 添加校验失败信息(为了使用 addFieldError() 方法, action 可以继承 ActionSupport ),如果系统的 fieldErrors 包含失败信息, struts2 会将请求转发到名为 input result 。在 input 视图中可以通过 <s:fielderror/> 显示失败信息。

validate() 使用例子:

public void validate () {

if(this.mobile==null||"".equals(this.mobile.trim())){ 

this.addFieldError("username", " 手机号不能为空 ");

}

else{ 

if(!Pattern.compile("^1[358]//d{9}").matcher(this.mobile.trim()).matches()){

       this.addFieldError(“mobile", " 手机号的格式不正确 ");

}

}

}

验证失败后,请求转发至 input 视图:

<result name="input">/WEB-INF/page/addUser.jsp</result>

addUser.jsp 页面中使用 <s:fielderror/> 显示失败信息。

 

1.    创建 validate.jsp 页面,对用户名和手机号进行简单的校验

<%@ page language = "java" pageEncoding = "UTF-8" %>

<%@ taglib uri = "/struts-tags" prefix = "s" %>

<! DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" >

< html >

  < head >

    < title > 输入校验 </ title >

    < meta http-equiv = "pragma" content = "no-cache" >

    < meta http-equiv = "cache-control" content = "no-cache" >

    < meta http-equiv = "expires" content = "0" >

  </ head >

 

  < body >

   < s:fielderror />

   < form action = "${pageContext.request.contextPath} /test/manage_update " method = "post" >

        用户名 : < input type = "text" name = "username" /> 不能为空 < br />

         手机号 : < input type = "text" name = "mobile" /> 不能为空 , 并且要符合手机号的格式 1,3/5/8, 后面是 9 个数字 < br />

        < input type = "submit" value = " " /></ form >

  </ body >

</ html >

 

2.    创建 PersonAction

public class PersonAction extends ActionSupport{

 

    private String username ;

    private String mobile ;

    public String getUsername() {

       return username ;

    }

    public void setUsername(String username) {

       this . username = username;

    }

    public String getMobile() {

       return mobile ;

    }

    public void setMobile(String mobile) {

       this . mobile = mobile;

    }

   

    public String update(){

       ActionContext.getContext ().put( "message" , " 更新成功 " );

       return "message" ;

    }

   

    public String save(){

       ActionContext.getContext ().put( "message" , " 保存成功 " );

       return "message" ;

    }

   

    @Override

    public void validate() { // 会对 action 中的所有方法校验

       if ( this . username == null || "" .equals( this . username .trim())){

           this .addFieldError( "username" , " 用户名不能为空 " );

       }

       if ( this . mobile == null || "" .equals( this . mobile .trim())){

           this .addFieldError( "mobile" , " 手机号不能为空 " );

       } else {

           if (!Pattern.compile ( "^1[358]//d{9}$" ).matcher( this . mobile ).matches()){

              this .addFieldError( "mobile" , " 手机号格式不正确 " );

           }

       }

    }

}

3.    struts.xml 文件中配置该 Action

< action name = "manage_*" class = "com.action.PersonAction" method = "{1}" >

    < result name = "input" > /validate.jsp </ result >

    < result name = "message" > /WEB-INF/page/message.jsp </ result >

</ action >

4.    index.jsp 页面中测试

< td > 输入校验 < br >

    < a href = "validate.jsp" > 采用手工编写方式对 Action 中所有方法进行输入校验 </ a >< br >

 

 

----------------------- Action 指定方法进行校验 -------------------------

在实际业务中,有些时候我们只是要对 Action 中的某个方法进行校验。这种时候 validate 方法就满足不了我们的需求,它是对所有方法进行校验,而不是指定的方法。

 

通过 validateXxx() 方法实现, validateXxx() 只会校验 action 中方法名为 Xxx 的方法。其中 Xxx 的第一个字母要大写。当某个数据校验失败时,我们应该调用 addFieldError() 方法往系统的 fieldErrors 添加校验失败信息(为了使用 addFieldError() 方法, action 可以继承 ActionSupport ),如果系统的 fieldErrors 包含失败信息, struts2 会将请求转发到名为 input result 。在 input 视图中可以通过 <s:fielderror/> 显示失败信息。

validateXxx() 方法使用例子:

public String add () throws Exception{  return "success";}  

public void validateAdd (){

          if(username==null && "".equals(username.trim()))  this.addFieldError("username", " 用户名不能为空 ");

}

验证失败后,请求转发至 input 视图:

<result name="input">/WEB-INF/page/addUser.jsp</result>

addUser.jsp 页面中使用 <s:fielderror/> 显示失败信息。

 

1.    validate 方法的方法名更改为 validateUpdate ,实现对 update 的方法进行输入校验

2.    index.jsp 页面中测试

< a href = "validate.jsp" > Action 指定方法进行校验 </ a >< br >

 

 

---------------------------- 输入校验的流程 -----------------------------

1. 类型转换器对请求参数执行类型转换,并把转换后的值赋给 action 中的属性。

2. 如果在执行类型转换的过程中出现异常,系统会将异常信息保存到 ActionContext conversionError 拦截器将异常信息添加到 fieldErrors 里。不管类型转换是否出现异常,都会进入第 3 步。

3. 系统通过反射技术先调用 action 中的 validateXxx() 方法, Xxx 为方法名。

4. 再调用 action 中的 validate() 方法。

5. 经过上面 4 步,如果系统中的 fieldErrors 存在错误信息(即存放错误信息的集合的 size 大于 0) ,系统自动将请求转发至名称为 input 的视图。如果系统中的 fieldErrors 没有任何错误信息,系统将执行 action 中的处理方法。

 

 

-------------- 基于 XML 配置方式实现对 action 的所有方法进行校验 ---------------

使用基于 XML 配置方式实现输入校验时, Action 也需要继承 ActionSupport ,并且提供校验文件,校验文件和 action 类放在同一个包下,文件的取名格式为: ActionClassName-validation.xml ,其中 ActionClassName action 的简单类名, -validation 为固定写法。如果 Action 类为 cn.itcast.UserAction ,那么该文件的取名应为: UserAction-validation.xml 。下面是校验文件的模版:

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

<! DOCTYPE validators PUBLIC "-//OpenSymphony Group//XWork Validator 1.0.3//EN" "http://www.opensymphony.com/xwork/xwork-validator-1.0.3.dtd" >

< validators >

    < field name = "username" >

        < field-validator type = "requiredstring" >

            < param name = "trim" > true </ param >

            < message > 用户名不能为空 ! </ message >

        </ field-validator >

    </ field >

</ validators >

<field> 指定 action 中要校验的属性, <field-validator> 指定校验器,上面指定的校验器 requiredstring 是由系统提供的,系统提供了能满足大部分验证需求的校验器,这些校验器的定义可以在 xwork-2.x.jar 中的 com.opensymphony.xwork2.validator.

validators 下的 default.xml 中找到。

<message> 为校验失败后的提示信息 , 如果需要国际化,可以为 message 指定 key 属性, key 的值为资源文件中的 key

在这个校验文件中,对 action 中字符串类型的 username 属性进行验证,首先要求调用 trim() 方法去掉空格,然后判断用户名是否为空。

 

1.    PersonAction 中的手工校验方式代码注释掉,在 PersonAction 的包下创建 PersonAction-validation.xml 校验文件。

 

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

<! DOCTYPE validators PUBLIC "-//OpenSymphony Group//XWork Validator 1.0.3//EN" "http://www.opensymphony.com/xwork/xwork-validator-1.0.3.dtd" >

< validators >

    < field name = "username" >

        < field-validator type = "requiredstring" >

            < param name = "trim" > true </ param >

            < message > 用户名不能为空 ! </ message >

        </ field-validator >

    </ field >

    < field name = "mobile" >

        < field-validator type = "requiredstring" >

            < param name = "trim" > true </ param >

            < message > 手机号不能为空 ! </ message >

        </ field-validator >

        < field-validator type = "regex" >

            < param name = "expression" ><![CDATA[ ^1[358]/d{9}$ ]]></ param >

            < message > 手机号格式不正确 ! </ message >

       </ field-validator >

    </ field >

</ validators >

2.    index.jsp 页面中测试

< a href = "validate.jsp" > 基于 XML 配置方式实现对 action 的所有方法进行校验 </ a >< br >

 

在编写 ActionClassName-validation.xml 校验文件时 , 如果提示不了帮助信息 , 可以按下面方式解决:

windwos->preferences->myeclipse->files and editors->xml->xmlcatalog

“add”, 在出现的窗口中的 location 中选 “File system”, 然后在 xwork-2.1.2 解压目录的 src/java 目录中选择 xwork-validator-1.0.3.dtd, 回到设置窗口的时候不要急着关闭窗口 , 应把窗口中的 Key Type 改为 URI Key 改为 http://www.opensymphony.com

/xwork/xwork-validator-1.0.3.dtd

 

 

--------------------------Struts 2.x 环境配置 -------------------------

 

-----------------------struts2 提供的校验器列表 -------------------------

系统提供的校验器如下:

1.    required ( 必填校验器 , 要求 field 的值不能为 null)

2.    requiredstring ( 必填字符串校验器 , 要求 field 的值不能为 null, 并且长度大于 0, 默认情况下会对字符串去前后空格 )

3.    stringlength( 字符串长度校验器 , 要求 field 的值必须在指定的范围内 , 否则校验失败 ,minLength 参数指定最小长度 ,maxLength 参数指定最大长度 ,trim 参数指定校验 field 之前是否去除字符串前后的空格 )

4 regex( 正则表达式校验器 , 检查被校验的 field 是否匹配一个正则表达式 .expression 参数指定正则表达式 ,caseSensitive 参数指定进行正则表达式匹配时 , 是否区分大小写 , 默认值为 true)

5. int( 整数校验器 , 要求 field 的整数值必须在指定范围内 ,min 指定最小值 ,max 指定最大值 )

6 double( 双精度浮点数校验器 , 要求 field 的双精度浮点数必须在指定范围内 ,min 指定最小值 ,max 指定最大值 )

7. fieldexpression( 字段 OGNL 表达式校验器 , 要求 field 满足一个 ognl 表达式 ,expression 参数指定 ognl 表达式 , 该逻辑表达式基于 ValueStack 进行求值 , 返回 true 时校验通过 , 否则不通过 )

8. email( 邮件地址校验器 , 要求如果 field 的值非空 , 则必须是合法的邮件地址 )

9. url( 网址校验器 , 要求如果 field 的值非空 , 则必须是合法的 url 地址 )

10. date( 日期校验器 , 要求 field 的日期值必须在指定范围内 ,min 指定最小值 ,max 指定最大值 )

11. conversion( 转换校验器 , 指定在类型转换失败时 , 提示的错误信息 )

12. visitor( 用于校验 action 中的复合属性 , 它指定一个校验文件用于校验复合属性中的属性 )

13. expression(OGNL 表达式校验器 ,expression 参数指定 ognl 表达式 , 该逻辑表达式基于 ValueStack 进行求值 , 返回 true 时校验通过 , 否则不通过 , 该校验器不可用在字段校验器风格的配置中 )

 

校验器的使用例子

required  必填校验器

< field-validator type = "required" >

       < message > 性别不能为空 ! </ message >

</ field-validator >

requiredstring  必填字符串校验器

< field-validator type = "requiredstring" >

       < param name = "trim" > true </ param >

       < message > 用户名不能为空 ! </ message >

</ field-validator >

stringlength :字符串长度校验器

< field-validator type = "stringlength" >

    < param name = "maxLength" > 10 </ param >

    < param name = "minLength" > 2 </ param >

    < param name = "trim" > true </ param >

    < message ><![CDATA[ 产品名称应在 2-10 个字符之间 ]]></ message >

</ field-validator >

email :邮件地址校验器

< field-validator type = "email" >

    < message > 电子邮件地址无效 </ message >

</ field-validator >

regex :正则表达式校验器

< field-validator type = "regex" >

     < param name = "expression" ><![CDATA[ ^1[358]/d{9}$ ]]></ param >

     < message > 手机号格式不正确 ! </ message >

</ field-validator >

int :整数校验器

< field-validator type = "int" >

    < param name = "min" > 1 </ param >

    < param name = "max" > 150 </ param >

    < message > 年龄必须在 1-150 之间 </ message >

</ field-validator >

字段 OGNL 表达式校验器

< field name = "imagefile" >

    < field-validator type = "fieldexpression" >

       < param name = "expression" ><![CDATA[ imagefile.length() <= 0 ]]></ param >

       < message > 文件不能为空 </ message >

    </ field-validator >

</ field >

 

 

--------------------------Struts 2.x 环境配置 -------------------------

 

--------------------------Struts 2.x 环境配置 -------------------------

 

--------------------------Struts 2.x 环境配置 -------------------------

 

----------------Struts2+Spring2.5+Hbernate3.3 整合开发 ----------------

下面给出整合开发时 Struts 2 Hibernate Spring 需要的 JAR

Struts 安装包下的

struts2-core-2.x.x.jar :Struts 2 框架的核心类库

xwork-2.x.x.jar :XWork 类库, Struts 2 在其上构建

ognl-2.6.x.jar : 对象图导航语言( Object Graph Navigation Language ), struts2 框架通过其读写对象的属性

freemarker-2.3.x.jar :Struts 2 UI 标签的模板使用 FreeMarker 编写

commons-fileupload-1.2.x.jar 文件上传组件, 2.1.6 版本后需要加入此文件

struts2-spring-plugin-2.x.x.jar :用于 struts2 集成 Spring 的插件

hibernate 核心安装包下的 ( 下载路径: http://www.hibernate.org/ ,点击“ Hibernate Core” 右边的“ Downloads”):

hibernate3.jar

lib/bytecode/cglib/hibernate-cglib-repack-2.1_3.jar

lib/required/*.jar

hibernate 注解安装包下的 ( 下载路径: www.hibernate.org ,点击“ Hibernate Annotations” 右边的“ Downloads”):

hibernate-annotations.jar

lib/ejb3-persistence.jar hibernate-commons-annotations.jar

Hibernate 针对 JPA 的实现包 ( 通过导入 JPA 的实现包,可以实现 Hibernate 对枚举类型的映射,下载路径: www.hibernate.org ,点击“ Hibernate Entitymanager” 右边的“ Downloads”):

hibernate-entitymanager.jar

lib/test/log4j.jar slf4j-log4j12.jar

Spring 安装包下的

dist/spring.jar

lib/c3p0/c3p0-0.9.1.2.jar   lib/aspectj/aspectjweaver.jar aspectjrt.jar    lib/cglib/cglib-nodep-2.1_3.jar

lib/j2ee/common-annotations.jar     lib/log4j/log4j-1.2.15.jar      lib/jakarta-commons/commons-logging.jar

整合时,建议先整合 Spring Hibernate ,然后在集成 Struts2

1.    src 源文件夹下创建 Spring 配置文件 beans.xml

添加需要使用的命名空间

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

< beans

    xmlns = "http://www.springframework.org/schema/beans"

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

    xmlns:context = "http://www.springframework.org/schema/context"

    xmlns:aop = "http://www.springframework.org/schema/aop"

    xmlns:tx = "http://www.springframework.org/schema/tx"

    xsi:schemaLocation = "http://www.springframework.org/schema/beans

    http://www.springframework.org/schema/beans/spring-beans-2.0.xsd

    http://www.springframework.org/schema/context

    http://www.springframework.org/schema/context/spring-context-2.5.xsd

    http://www.springframework.org/schema/aop

    http://www.springframework.org/schema/aop/spring-aop-2.5.xsd

http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd

" >

    < aop:aspectj-autoproxy proxy-target-class = "true" />

    < context:component-scan base-package = "com.bean.service.impl" />

</ beans >

Spring 中我们要把一个 bean 交给 spring 管理,可以使用 bean 配置节点,还有扫描 + 注解的方式

为了加快开发效率,我们采用扫描 + 注解的方式

添加启动扫描功能的配置项

< context:component-scan base-package = " 添加被扫描的包 " />

2.    Spring 中集成 Hibernate

配置 c3p0 数据源

< bean id = "dataSource" class = "com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method = "close" >

    < property name = "driverClass" value = "org.gjt.mm.mysql.Driver" />

    < property name = "jdbcUrl" value = "jdbc:mysql://localhost:3306/ssh2?useUnicode=true&amp;characterEncoding=UTF-8" />

    < property name = "user" value = "root" />

    < property name = "password" value = "root" />

    <!-- 初始化时获取的连接数,取值应在 minPoolSize maxPoolSize 之间。 Default: 3 -->

    < property name = "initialPoolSize" value = "1" />

    <!-- 连接池中保留的最小连接数。 -->

    < property name = "minPoolSize" value = "1" />  

    <!-- 连接池中保留的最大连接数。 Default: 15 -->

    < property name = "maxPoolSize" value = "300" />

    <!-- 最大空闲时间 ,60 秒内未使用则连接被丢弃。若为 0 则永不丢弃。 Default: 0 -->

    < property name = "maxIdleTime" value = "60" />

    <!-- 当连接池中的连接耗尽的时候 c3p0 一次同时获取的连接数。 Default: 3 -->

    < property name = "acquireIncrement" value = "5" />

    <!-- 60 秒检查所有连接池中的空闲连接。 Default: 0 -->

    < property name = "idleConnectionTestPeriod" value = "60" />

创建 sessionFactory

< bean id = "sessionFactory" class = "org.springframework.orm.hibernate3.LocalSessionFactoryBean" >

    < property name = "dataSource" ref = "dataSource" />

    < property name = "mappingResources" >

        < list >

            < value > cn/itcast/bean/Person.hbm.xml </ value >

        </ list >

        </ property >

        < property name = "hibernateProperties" >

        < value >

                hibernate.dialect=org.hibernate.dialect.MySQL5Dialect

               hibernate.hbm2ddl.auto=update

               hibernate.show_sql=false

               hibernate.format_sql=false

        </ value >

    </ property >

</ bean >

配置事务管理器,使用 Spring 的最大的一个原因是要因为要使用 Spring 的事务管理服务

< bean id = "txManager"

class = "org.springframework.orm.hibernate3.HibernateTransactionManager" >

< property name = "sessionFactory" ref = "sessionFactory" />

</ bean >

添加注解方式事务管理的配置项

< tx:annotation-driven transaction-manager = "txManager" />

3.    业务的实现,员工列表的添加

创建员工的 javabean

public class Employee {

    private String username ;

    private String password ;

    private Gender gender = Gender. MAN ;

   

    public Employee(){}

   

    public Employee(String username, String password) {

       this . username = username;

       this . password = password;

    }

    public String getUsername() {

       return username ;

    }

    public void setUsername(String username) {

       this . username = username;

    }

    public String getPassword() {

       return password ;

    }

    public void setPassword(String password) {

       this . password = password;

    }

    public Gender getGender() {

       return gender ;

    }

    public void setGender(Gender gender) {

       this . gender = gender;

    }

}

因为要介绍枚举类型在 Hibernate 如何映射,所以我们使用一个枚举类型的值 gender ,并创建该枚举类型值的类 Gender

/**

  * 性别

  */

public enum Gender {

    MAN ,

    WOMEN ;

}

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值