struts2框架的知识点,虽然分了几个小节,感觉内容还是挺多的,但是你仅仅是入门了而已,想要进一步地提升自己,你得有一颗持之以恒的学习的心,最后的内容我都将在这篇博客中讲到,所以篇幅可能会有点长,希望大家能够耐心阅读。

首先介绍一下struts2的配置。

还记得我们创建的test.jsp文件吗?直接看到这篇博客的同学们也不用去翻阅我之前的博客,因为我在之前的博客中只是简单地介绍了使用,而并没有深入,我并没有讲解每一步的作用,和为什么要这样写。所以,直接从该篇博客开始阅读学习也是可以的,我将从最基础的配置开始重新进行讲解,并讲述每一步的作用、原因。

那么test.jsp文件里的代码很简单,就是一个超链接。

<%@ page language="java" pageEncoding="utf-8" contentType="text/html; charset=utf-8"%>
<%@ taglib uri="/struts-tags" prefix="s"%>
<html>
<head>
<title>My JSP 'index.jsp' starting page</title>
</head>
<body>
入门的路径:<br>
<a href="${pageContext.request.contextPath}/primer/helloWorldAction.action">helloWorld</a><br>
</body>
</html>

那就介绍一下访问helloWorld应用的路径的设置。

在struts2中,访问struts2中action的URL路径由两部份组成:

包的命名空间+action的名称

例如: 访问本例子HelloWorldAction的URL路径为: /primer/helloWorldAction.action (注意:完整路径为:http://localhost:端口/内容路径/primer/helloWorldAction.action)。另外我们也可以加上.action后缀访问此Action。

 <package name="primer" namespace=“/primer“   extends="struts-default">
<action name="helloWorldAction" class="cn.itcast.primer.HelloWorldAction">
<result name="success" type="dispatcher">/success.jsp</result>
</action>
</package>

路径中的action名称必须和你在package标签下配置的action标签的name属性一致。

接下来我们在test.jsp文件中加入如下代码。

       测试Action名称的搜索顺序:<br>
<a href="${pageContext.request.contextPath}/primer/primer/primer/helloWorldAction.action">helloWorld</a><br>
<a href="${pageContext.request.contextPath}/primer/primer/helloWorldAction.action">helloWorld</a><br>
<a href="${pageContext.request.contextPath}/primer/helloWorldAction.action">helloWorld</a><br> 没有为action指定class<br>
<a href="${pageContext.request.contextPath}/primer/actionNoClass.action">helloWorld</a><br> 测试struts2 输出没有命名空间helloworld:<br>
<a href="${pageContext.request.contextPath}/primer/userAction.action">helloWorld</a><br>

如果我们去点击这三个请求链接会发生什么呢?

你们试着点击一下就会发现,这三个请求链接都能被正确地处理运行。那我们就想,为什么没有配置却能够正确运行呢?这是因为在struts2中,当你点击请求链接时,它会对Action进行一个搜索。以第一个链接为例, <a href="${pageContext.request.contextPath}/primer/primer/primer/helloWorldAction.action">helloWorld</a>,当你点击链接时,会去搜索/primer/primer/primer/helloWorldAction.action,当查询不到时,会搜索/primer/primer/helloWorldAction.action,查询不到时,会搜索/primer/helloWorldAction.action,以此类推,直到Action被找到。所以如果我这么写, <a href="${pageContext.request.contextPath}/primer/primer/aaa/helloWorldAction.action">helloWorld</a>,程序就会报错。

那如果没有为action标签配置class属性,程序会有问题吗?

在package标签中添加一个action标签。

<action name="actionNoClass">
<result name="success">/primer/success.jsp</result>
</action>

此时我们运行并点击,会发现程序仍然正确运行了,那问题来了,我连class都没配置,它是如何运行得到结果success,并跳转页面的呢?

我们查阅struts-default.xml文件,看到最后几行的配置

 <default-class-ref class="com.opensymphony.xwork2.ActionSupport" />

你明白了吗?在没有为action指定class的时候,struts2框架默认会执行该Action。而我们查阅ActionSupport类的源码时,找到了一个方法。

public static final String SUCCESS = "success";

public String execute() throws Exception {
return SUCCESS;
}

这个方法再熟悉不过了吧,所以为什么没有配置class属性也能正常运行,相信你已经明白了。

如果请求的路径查找不到action的情况下,程序运行会抛出异常 ,可以通过配置当找不到action的情况下,会执行默认的action

<package name="primer"  namespace="/"  extends="struts-default">
<!--指定默认的action引用,如果该包下没有对应action配置,则启用该配置-->
<default-action-ref name="helloWorldAction"></default-action-ref> <action name="helloWorldAction" class="cn.itcast.primer.HelloWorldAction">
<result name="success" type="dispatcher">/success.jsp</result>
</action>
<action name="actionNoClass">
<result>/success.jsp</result>
</action>
</package>

接下来我们来了解一下ActionSupport类,它是我们没有指定class执行的默认Action。

它远比Action接口强大,所以我们在编写Action类时可以改为继承ActionSupport类。

相信很多同学在开始的时候对这个.action的后缀表示无法理解,为什么写.action?我们来了解一下。

StrutsPrepareAndExecuteFilter是Struts 2框架的核心控制器,它负责拦截由/*指定的所有用户请求,当用户请求到达时,该Filter会过滤用户的请求。默认情况下,如果用户请求的路径不带后缀或者后缀以.action结尾,这时请求将被转入Struts 2框架处理,否则Struts 2框架将略过该请求的处理。

根据配置文件:struts2-core-2.1.8.1.jar包下的 org.apache.struts2/default.properties文件定义的常量决定

struts.action.extension=action,,

默认处理的后缀是可以通过常量”struts.action.extension“进行修改的,如下面配置Struts 2只处理以.do为后缀的请求路径:

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

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

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

我们还有第二种方式来修改后缀。

在struts.properties中配置常量, (struts.properties文件放置在src下)

struts.action.extension=do.go

既然有两种方式,那么如果我两种方式都实现了,它会启用哪个配置呢?我就不卖关子了,如果你两种方式都实现了,struts2框架会启用struts.properties的配置。那这是为什么呢?我可以给你解释一下。

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

1 struts-default.xml

2 struts-plugin.xml

3 struts.xml

4 struts.properties(自己创建)

5 web.xml

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

通俗点说,越后执行的文件优先级越高。

虽然实现方式有两种,但是不建议大家使用第二种自己创建配置文件的方式。

然后是常用的常量介绍。

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



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

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



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



配置当国际化文件修改时,重新加载该国际化资源文件,默认值是false(不重新加载),true为重新加载



当struts的配置文件修改后,系统是否自动重新加载该文件,默认值是false(不重新加载),true为重新加载



开发模式下使用,这样可以打印出更详细的错误信息,默认值为false(生产环境下使用),开发阶段最好打开



默认的视图主题



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



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

为 false



上传文件的大小限制

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

接下来是第二个部分,struts2的结果类型。

我们新建文件夹resulttype,然后创建form.jsp文件

<%@ page language="java" pageEncoding="utf-8" contentType="text/html; charset=utf-8"%>
<%@ taglib uri="/struts-tags" prefix="s"%>
<html>
<head>
<title>My JSP 'index.jsp' starting page</title>
</head>
<body>
<form action="${pageContext.request.contextPath}/resulttype/resulttypeAction.action"
name="form1" method="post">
<input type="submit" value="提交">
</form>
</body>
</html>

然后我们创建出对应的Action,这次我们不实现Action接口了,而是继承ActionSupport类。

public class ResultTypeAction extends ActionSupport {
@Override
public String execute() throws Exception {
System.out.println("ResultTypeAction ..."); HttpServletRequest request = ServletActionContext.getRequest();
request.setAttribute("username", "username_request"); return "success";
}
}

对其进行配置,在struts.xml文件中添加

<package name="resulttype" namespace="/resulttype" extends="struts-default">
<action name="resulttypeAction" class="cn.itcast.action.ResultTypeAction">
<result name="success">/resulttype/success.jsp</result>
</action>
</package>

转向的success.jsp页面如下

<%@ page language="java" pageEncoding="utf-8" contentType="text/html; charset=utf-8"%>
<%@ taglib uri="/struts-tags" prefix="s"%>
<html>
<head>
<title>My JSP 'index.jsp' starting page</title>
</head>
<body>
resulttype : ${requestScope.username}
</body>
</html>

点击提交按钮,页面成功显示保存在request范围的数据,这说明了什么?说明我的转向方式一定是转发,如果是重定向的话数据就取不到了。其实,在result标签里有一个type属性,它可以用来设置转向方式,只不过它默认是"dispatcher"。

这是第一种设置转向的方式,我们也有第二种。

<result name="success" type="dispatcher">
<param name="location">/resulttype/success.jsp</param>
</result>

这样配置result标签也能实现转向。这个location指的是要转发到的页面。这种方式的实现原理在struts-default.xml文件中也能被找到,我就不带大家看了,感兴趣的同学可以自己研究一下。了解了转发,那重定向如何实现?这太简单了,将type值改为"redirect"即可。

注意了,重定向中,转向到jsp才能这样写,而如果想转向到action,你需要这样配置:

<result name="success" type="redirectAction">
<param name="actionName">helloWorldAction</param>
<param name="namespace">/primer</param>
</result>

最后一个部分就是struts2通配符与动态方法的调用。

在说这个之前先来拓展一个知识点。

我们先新建一个test.jsp文件。

<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<a href="${pageContext.request.contextPath }/bookAction.action">提交</a>
</body>
</html>

里面只有一个超链接,然后配置struts.xml文件,相信配置已经难不倒各位了,那我就对action作如下配置。

<action name="bookAction" class="cn.itcast.action.BookAction">
<result name="success">/success.jsp</result>
<result name="add">/bookaction.jsp</result>
</action>

然后创建BookAction.java文件。

public class BookAction extends ActionSupport{
@Override
public String execute() throws Exception {
System.out.println("BookAction ...");
return "success";
} public String add(){
System.out.println("add ...");
return "add";
}
}

我们运行项目,然后点击提交,页面会转向success.jsp文件,那么我如果想点击页面从而跳转到我们配置的bookaction.jsp文件呢?其实很简单,在action标签中有一个method属性,只需将它的值设置为方法名即可。那这个自定义的方法是不是可以随便编写呢?当然是不行的。它必须由public关键字修饰,必须有返回值,该方法不能传参,总结来说,就是除了方法名和execute方法一样,其它的都必须和它一样。到这里有人就会说了,你这句话有问题,execute方法抛出了异常,而自定义的方法却没有抛出,我解释一下,这是因为我们写的测试代码过于简单,以至于没有异常可供处理,所以你可以不抛异常,但是当代码很复杂的时候,程序或多或少都会有异常,这时候就必须抛出异常了。

这部分就先这样,回到我们的重点,通配符。

我们在test.jsp文件中添加三个超链接。

    通配符映射示例(1):<br>
<a href="${pageContext.request.contextPath}/a_add.action"> 通配符映射示例(1)</a><br>
<a href="${pageContext.request.contextPath}/b_add.action"> 通配符映射示例(1)</a><br>
<a href="${pageContext.request.contextPath}/c_add.action"> 通配符映射示例(1)</a><br>
<br>
<br>
<br>

然后配置struts.xml。

<action name="a_add" class="cn.itcast.action.BookAction" method="add">
<result name="success">/success.jsp</result>
<result name="add">/bookaction.jsp</result>
</action>
<action name="b_add" class="cn.itcast.action.BookAction" method="add">
<result name="success">/success.jsp</result>
<result name="add">/bookaction.jsp</result>
</action>
<action name="c_add" class="cn.itcast.action.BookAction" method="add">
<result name="success">/success.jsp</result>
<result name="add">/bookaction.jsp</result>
</action>

运行程序,程序正常运行,但是这样的配置显然很麻烦,有没有什么简单一点的写法呢?这时候通配符就派上用场了,我们把之前的配置都删掉,然后编写如下配置。

<action name="*_add" class="cn.itcast.action.BookAction" method="add">
<result name="success">/success.jsp</result>
<result name="add">/bookaction.jsp</result>
</action>

运行项目是没有问题的。这个*号就是通配符,有些语言基础的同学应该都了解,我就不多说了。

下面给出struts2通配符的知识点。

一个 Web 应用可能有成百上千个 action 声明. 可以利用 struts 提供的通配符映射机制把多个彼此相似的映射关系简化为一个映射关系

通配符映射规则

若找到多个匹配, 没有通配符的那个将胜出

若指定的动作不存在, Struts 将会尝试把这个 URI 与任何一个包含着通配符 * 的动作名及进行匹配

若 Struts 找到的带有通配符的匹配不止一个, 最后一个匹配将胜出

被通配符匹配到的 URI 字符串的子串可以用 {1}, {2} 来引用. {1} 匹配第一个子串, {2} 匹配第二个子串…{0} 匹配整个 URI

  • 可以匹配零个或多个字符, 但不包括 / 字符. 如果想把 / 字符包括在内, 需要使用 **. 如果需要对某个字符进行转义, 需要使用 \。

最后就是动态方法调用了。

动态方法调用: 通过 url 动态调用 Action 中的方法

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

默认情况下, Struts 的动态方法调用处于激活状态, 若想禁用该功能, 则可以在 struts.xml 文件中添加如下 constant 元素:



以上面的项目为例,我可以不再action中配置method,而在超链接的url地址中作如下修改:

<a href="${pageContext.request.contextPath }/bookAction!add.action">提交</a>

这样我也能在点击提交按钮后调用配置action中的add方法。这就是动态方法调用。

到这里,struts2框架的学习就结束了,当然,struts2框架的知识远不止如此,感兴趣的同学可以继续深入学习,我这里就先告一段落了。

SSH开发模式——Struts2(第三小节)的更多相关文章

  1. SSH开发模式——Struts2(第一小节)

    在制定了学习计划的学习过程中,我感觉学习还是很有效率的.很短的时间内,我便学习完了JavaWeb的连接池.DbUtils框架及其一些工具类的使用. 学无止境,学习这些知识还远远不够,所以,在接下来的时 ...

  2. SSH开发模式——Struts2(第二小节)

    上一小节已经学会了如何去搭建Struts2的开发环境,该篇博客我们继续深入Struts2,了解Struts2框架的拦截器. 首先对我们在web.xml文件配置的过滤器进行一个源码的分析. 在Strut ...

  3. SSH开发模式——Struts2进阶

    在之前我有写过关于struts2框架的博客,好像是写了三篇,但是之前写的内容仅仅是struts2的一些基础知识而已,struts2还有很多有趣的内容等待着我们去发掘.我准备再写几篇关于struts2的 ...

  4. SSH框架之Struts2第三篇

    1.3相关知识点 : 1.3.1 OGNL的表达式 : 1.3.1.1 什么是OGNL OGNL是Object-Graph Navigation Language的编写,它是一种功能强大的表达式语言, ...

  5. MVC开发模式的数据运行流程

    对于java中经典的开发模式MVC,有一些感触!现说一下Java中数据的运行流程,由于我技术有限,有错的话欢迎提出,不喜勿喷! 我们知道在MVC开发模式,包括三部分视图层V(view).控制层C(Co ...

  6. 吴裕雄--天生自然JAVA SPRING框架开发学习笔记:SSH框架(Struts2+Spring+Hibernate)搭建整合详细步骤

    在实际项目的开发中,为了充分利用各个框架的优点,通常都会把 Spring 与其他框架整合在一起使用. 整合就是将不同的框架放在一个项目中,共同使用它们的技术,发挥它们的优点,并形成互补.一般而言,在进 ...

  7. 《ASP.NET MVC4 WEB编程》学习笔记------Entity Framework的Database First、Model First和Code Only三种开发模式

    作者:张博出处:http://yilin.cnblogs.com Entity Framework支持Database First.Model First和Code Only三种开发模式,各模式的开发 ...

  8. 前端工程化(三)---Vue的开发模式

    从0开始,构建前后端分离应用 导航 前端工程化(一)---工程基础目录搭建 前端工程化(二)---webpack配置 前端工程化(三)---Vue的开发模式 前端工程化(四)---helloWord ...

  9. APP的三种开发模式

    转载于http://pleasureswx123.github.io/2014/09/15/APP%E7%9A%84%E4%B8%89%E7%A7%8D%E5%BC%80%E5%8F%91%E6%A8 ...

随机推荐

  1. eval 与 exec, compile区别

    exec 不是表达式: python 2. x, 中的一个语句和 python 3. x. 中的一个函数它编译并立即计算一个字符串中包含的语句或者语句集. 例如: exec('print(5)') # ...

  2. JNDI总结(一)

    一.数据源的由来 在Java开发中,使用JDBC操作数据库的四个步骤如下:   ①加载数据库驱动程序(Class.forName("数据库驱动类");)   ②连接数据库(Conn ...

  3. HTML5-新增语义化结构标签

    总结目录结构: 1.简洁的DOCTYPE声明 2.新的布局结构标签 header,article,section,aside,footer 3.新的其它常用标签: nav,hgroup,figure, ...

  4. spring的jdbcTemplate的使用

    转载:http://1358440610-qq-com.iteye.com/blog/1826816 一.首先配置JdbcTemplate: 要使用Jdbctemplate 对象来完成jdbc 操作. ...

  5. 面试必问之ArrayList

    ArrayList概述 (1)ArrayList 是一种变长的集合类,基于定长数组实现. (2)ArrayList 允许空值和重复元素,当往 ArrayList 中添加的元素数量大于其底层数组容量时, ...

  6. codeforces 339 D.Xenia and Bit Operations(线段树)

    这个题目属于线段树的点更新区间查询,而且查的是整个区间,其实不用写query()函数,只需要输出根节点保存的值就可以了. 题意: 输入n,m表示有2^n个数和m个更新,每次更新只把p位置的值改成b,然 ...

  7. 补充Java面试记录

    补充Java面试记录 背景:这两天面试遇到的部分问题都分散在了前面两篇文摘中,这里再做一些其他的记录,以备不时之需! 一.谈谈你对SpringBoot的理解? SpringBoot简介:SpringB ...

  8. vue在窗口大小改变时强制刷新组件的方法

    mounted () { window.onresize = () => { return (() => { this.$forceUpdate(); })() } }

  9. 不等"金九银十",金风八月,我早已拿下字节跳动的offer

    字节跳动,我是在网上投的简历,之前也投过一次,简历都没通过删选,后来让师姐帮我改了一下简历,重新投另一个部门,获得了面试机会.7月23日,中午HR打电话过来预约了下午4点半面试,说会在线写代码,让我准 ...

  10. 第三章 Linux基本命令操作

    第三章  Linux基本命令操作 ¨  本节所讲内容: ¨  3.1  Linux终端介绍 Shell提示符 Bash Shell基本语法 ¨  3.2  基本命令的使用:ls.pwd.cd.hist ...