Struts2入门

Struts2简介

  Struts2是在WebWork2基础上发展而来的。Struts2和Struts1一样,也都是属于MVC框架。不过有一点大家需要注意的是:虽然Struts2和Struts1在名字上差别不大,但Struts2应用的代码编写风格与Struts1几乎可以说是不一样的。那么既然有了Struts1,为何还要推出Struts2呢?主要是因为Struts2有以下优点:

  1. 在软件设计上,Struts2没有像Struts1那样跟Servlet API和Struts API有着紧密的耦合,Struts2的应用可以不依赖于Servlet API和Struts API。 Struts2的这种设计属于无侵入式设计,而Struts1却属于侵入式设计。
  2. Struts2 提供了拦截器,利用拦截器可以进行 AOP 编程,实现如权限拦截等功能。
  3. Struts2 提供了类型转换器,可以将特殊的请求参数转换成需要的类型。在Struts1中,如果我们要实现同样的功能,就必须向Struts1的底层实现BeanUtil注册类型转换器才行。
  4. Struts2提供支持多种表现层技术,如:JSP、freeMarker、Velocity等。
  5. Struts2 的输入验证可以对指定方法进行验证,解决了Struts1长久之痛
  6. 提供了全局范围、包范围和 Action 范围的国际化资源文件管理实现。

1、搭建Struts2开发环境

搭建Struts2环境时,我们一般需要以下几个步骤:

  • 找到开发Struts2应用需要使用到的jar文件
  • 编写Struts2的配置文件
  • 在web.xml文件中加入Struts2 MVC框架启动配置
1.1、下载Struts2的相关jar包

在开发 Struts2 框架之前先要下载相关的 jar 包,Struts 的官方网站截图如图 3-1 所示:
image.png

单击 Download 按钮开始下载,本人所下载的是struts-2.3.24-
all.zip,目前最新版为2.5.14.1。下载的 ZIP 文件内容有Struts2 的示例,源代码及帮助文档。

1.2、Struts2 的 最基本Jar 包

可以从 Struts2 框架解压目录下的 apps 中的 struts2-blank.war中获取。
image.png

将 struts2-blank.war 扩展名修改为 zip 后,解压。在其 WEB-INF\lib 中所有 Jar 即为 Struts2运行的基本 Jar 包。从使用的两小日志 Jar 包可以看出,Struts2 使用的是 Log4j2 日志技术。


Struts2 的 基本Jar 包
1.3、Struts2 的配置文件

Struts2 的默认配置文件为 struts.xml,该文件需存放在 WEB-INF/classes 下。即,在myEclipse 中应放在 src 目录下。Struts2 配置文件的头部可以从 struts2-core-2.3.24.jar 下的 struts-2.3.dtd 中找到。
Struts2 的配置文件的dtd文件
Struts2 的配置文件的头部

1.4、配置 Struts2 的启动项

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

<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xmlns="http://java.sun.com/xml/ns/javaee" 
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
    http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5">
  <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>
</web-app>

若忘记了配置细节,可从 struts2-blank.war 解压目录中 WEB-INF 下的 web.xml 中复制。
Struts2的web.xml
1.5、 搭建成功的测试

将该项目部署到服务器后,启动服务器,在控制台没有报错,则说明 Struts2 应用平台搭建成功。

2、Struts2工作流程

2.1、 开发流程

(1)编写页面
(2)定义 Action 类
(3)注册 Action
(4)编写结果页面

2.2、开发流程分析

  从客户端发送请求过来,先经过前端控制器(核心过滤器,StrutsPrepareAndExecuteFilter),过滤器中执行一组拦截器(一组拦截器,就会完成部分功能代码),到底哪些拦截器执行了呢?在Struts2中定义了很多拦截器,在其默认栈中的拦截器会得到执行,这个我们可以通过断点调试的方式测试,拦截器执行完成以后,就会执行目标Action,在Action中返回一个结果视图,根据result的配置进行页面的跳转。用图来表示即为:
Struts2执行流程
2.3、Struts2的配置文件的加载顺序

  每次从客户端发送请求到服务器都要先经过Struts2的核心过滤器StrutsPrepareAndExecuteFilter,这个过滤器有两个功能:预处理和执行。在预处理中主要就是来加载配置文件的。对应的是过滤器中的init方法,而执行是用来执行一组拦截器完成部分功能的,对应的是过滤器的doFilter方法。所以我们如果要去了解Struts2的配置文件的加载顺序,那么我们需要查询过滤器的init方法。在web.xml配置文件中,按Ctrl+鼠标左键点击StrutsPrepareAndExecuteFilter进入源代码如下:
image.png

在init方法中,调用了init的initDispatcher的方法来加载配置文件,进入到该代码中:
image.png
我们会发现这个方法又调用了dispatcher的init方法,进入init方法内部:
image.png
这一系列的代码就是用来加载Struts2的配置文件的。

init_DefaultProperties(); // [1]

加载org/apache/struts2/default.properties,该文件配置的是Struts2的所有的常量。

init_TraditionalXmlConfigurations(); // [2]

加载struts-default.xml、struts-plugin.xml、struts.xml。

init_LegacyStrutsProperties(); // [3]

加载用户自定义的struts.properties。

init_CustomConfigurationProviders(); // [5]

加载用户配置的提供对象。

init_FilterInitParameters() ; // [6]

加载web.xml。

init_AliasStandardObjects() ; // [7]

加载标准对象。
根据上面的代码我们可以得出配置文件的加载顺序,如下:

  1. default.properties
  2. struts-default.xml
  3. struts-plugin.xml
  4. struts.xml,配置Action以及常量。
  5. struts.properties,配置常量。
  6. web.xml,配置核心过滤器以及常量。

  前三个配置文件我们不用关心,是Struts2内部的配置文件,我们无法修改,能修改的文件就是struts.xml、struts.properties、 web.xml配置文件。这几个配置文件的加载是有一定顺序的。这三个配置文件都可以修改Struts2的常量的值,要记住的是,后加载配置文件中常量的值会将先加载的配置文件中常量的值给覆盖掉。

3、第一个Struts2应用程序

完成功能:
  用户登录后在页面显示“Struts2 欢迎你【xxx】,年龄为xx岁!”,将用户名显示出来。
实现步骤:
  在搭建好 Struts2 环境后,完成下面步骤:
Step1:新建页面 index.jsp

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

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <title>第一个Struts2应用程序</title>
  </head>
  
  <body>
    <form action="${pageContext.request.contextPath }/test/login.action" method="post">
        用户名:<input type="text" name="name"><br>
        年&emsp;龄:<input type="text" name="age"><br>
        <input type="submit" value="登录">
    </form>
  </body>
</html>

Step2:创建 Action 类

package com.zenghai.actions;

import com.opensymphony.xwork2.ActionSupport;

public class LoginAction extends ActionSupport {
  private static final long serialVersionUID = 1L;
  private String name;
  private int age;
  public String getName() {
      return name;
  }
  public void setName(String name) {
      this.name = name;
  }
  public int getAge() {
      return age;
  }
  public void setAge(int age) {
      this.age = age;
  }
  @Override
  public String execute() throws Exception {
      System.out.println("name = " + name);
      System.out.println("age = " + age);
      return SUCCESS;
  }
}

  对于Servlet来说,每次访问Servlet的时候,都会执行Servlet里面的service()方法。而对于Action来说,每次访问Action的时候,默认执行Action里面名称为execute的方法。注意:创建方法的要求是方法不能有参数。
  Action类编写好了以后,Struts2框架如何识别它就是一个Action呢?那么我们需要修改struts.xml文件对Action类进行配置。
Step3:修改 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>
    <constant name="struts.devMode" value="true" />
    <package name="login" namespace="/test" extends="struts-default">
        <action name="login" class="com.zenghai.actions.LoginAction">
            <result name="success">/welcome.jsp</result>
        </action> 
    </package>
</struts>

  配置代码<constant name="struts.devMode" value="true" />的作用是使 Struts 2 框架运行在开发模式,在此种模式下对异常的报错信息显示的比较完整,便于排错。但在项目部署时要删除。
  配置 代 码 <package name="login" namespace="/test" extends="struts-default">的 作 用 是 定 义 一 个package 包。在Struts2框架中使用包来管理Action,包的作用和java中的类包是非常类似的,它主要用于管理一组业务功能相关的Action。在实际应用中,我们应该把一组业务功能相关的Action放在同一个包下。配置包时必须指定name属性,该name属性值可以任意取名,但在整个项目中必须唯一,它不对应java类,如果其他包要继承该包,必须通过该name属性进行引用。
  包的namespace属性用于定义该包的命名空间。命名空间作为访问该包下Action的路径的一部分,该属性可以不配置,对本例而言,如果不指定该属性,默认的命名空间为“”(空字符)。命名空间对于Struts2来说有减少重复代码的作用。例如下面的URL

http://localhost:8080/login/one.action
http://localhost:8080/login/two.action
http://localhost:8080/login/three.action

Struts1的配置代码有可能是这样的:

<action path= "/login/one" forward= "one.jsp" >
<action path= "/login/two" forward= "two.jsp" >
<action path= "/login/three" forward= "three.jsp" >

这样就会有很多重复的代码,而是使用Struts2的命名空间属性就可减少重复的代码,Struts2的配置代码:

<package name="login" namespace="/login" extends="struts-default">
  <action name="one" class= .... >
    <result name="success">one.jsp</result> 
  </action>
  <action name= "two" class= .... >
    <result name="success">two.jsp</result> 
  </action>
  <action name="two" class= .... >
    <result name="success">three.jsp</result> 
  </action>
</package>

  通常每个包都应该继承struts-default包, struts-default包是由Struts2内置的,它定义了Struts2内部的众多拦截器和Result类型。Struts2很多核心的功能都是通过这些内置的拦截器实现的。如:从请求中把请求参数封装到action、文件上传和数据验证等等都是通过拦截器实现的。当包继承了struts-default包才能使用Struts2提供的这些功能。 struts-default包是在struts2-core-2.x.x.jar文件中的struts-default.xml中定义的。struts-default.xml也是Struts2默认配置文件。 Struts2每次都会自动加载struts-default.xml文件。
  action的配置: Action映射是框架中的基本“工作单元”。Action映射就是将一个请求的URL映射到一个Action类中,当一个请求匹配某个Action名称时,框架就使用这个映射来确定如何处理请求。在struts.xml文件中,通过 <action> 元素对请求的Action和Action类进行配置。 <action> 元素中共有4个属性,这4个属性的说明如表所示:

属性 说明
name 必填属性,标识Action,指定了Action所处理的请求的URL
class 可选属性,指定Action对应Action类
method 可选属性,指定请求Action时调用的方法
converter 可选属性,指定类型转换器的类

  其中name属性和namespace属性共同决定了访问路径,class对应的是Action类的全路径。Method指定了执行Action的那个方法,默认是execute方法。
注意:在一个package标签里面可以写多个action标签,并且action标签的name属性值不能一样。如:

<package name="demo1" extends="struts-default" namespace="/">
  <action name= "user" class= "com.zenghai.action.UserAction">
    <result name= "ok" >/user.jsp</result>
  </action>
  <action name="person" class="com.zenghai.action.PersonAction">
    <result name="success">/person.jsp</result>
  </action>
</package>

  result的配置: Action类的方法是有返回值的,配置返回值之后,可跳转到不同的页面中。result标签里面的name属性值即是Action类里面的方法的返回值。如:

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

返回值为"success"时,跳转到/welcome.jsp页面。在一个action标签里面可写多个result标签,但要注意result标签的name属性值不能相同。
Step4:创建 welcome.jsp 页面

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <title>第一个Struts2应用程序</title>
  </head>
  <body>
    Struts2 欢迎你【${name }】,年龄为${age }岁!
  </body>
</html>

第一个Struts应用程序完成,启动服务器,访问index.jsp页面,输入信息提交后,显示的页面如下则成功:


image.png
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,012评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,628评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,653评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,485评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,574评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,590评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,596评论 3 414
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,340评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,794评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,102评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,276评论 1 344
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,940评论 5 339
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,583评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,201评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,441评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,173评论 2 366
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,136评论 2 352

推荐阅读更多精彩内容

  • 本文包括: 1、Struts 2 概述2、Struts 2 快速入门3、Struts 2 的执行流程4、配置 st...
    廖少少阅读 2,956评论 3 13
  • 前言 这是Strtus的开山篇,主要是引入struts框架...为什么要引入struts,引入struts的好处是...
    Java3y阅读 912评论 1 16
  • 概述 什么是Struts2的框架Struts2是Struts1的下一代产品,是在 struts1和WebWork的...
    inke阅读 2,253评论 0 50
  • 人和人之间要有缘分才能相遇、爱上。人和书之间,也是。 以前遇到过几种版本的《小王子》,译者都不同,却怎么也读不进去...
    勒尤阅读 1,276评论 2 5
  • 当scan_enable=0,数据流如下图 insert scan测试两部分:1.sequential parte...
    罐头说阅读 508评论 0 0