Struts2配置与JSP表达式语言详解
1. Struts2拦截器与配置元素
在Struts2中,拦截器是一个重要的概念,它可以在Action执行前后执行一些操作。以下是一个基本的拦截器栈
basicStack
的定义:
<interceptor-stack name="basicStack">
<interceptor-ref name="exception"/>
<interceptor-ref name="servlet-config"/>
<interceptor-ref name="prepare"/>
<interceptor-ref name="checkbox"/>
<interceptor-ref name="params"/>
<interceptor-ref name="conversionError"/>
</interceptor-stack>
要使用这些拦截器,只需引用该拦截器栈:
<action name="..." class="...">
<interceptor-ref name="basicStack"/>
<result name="input">/jsp/Product.jsp</result>
<result>/jsp/ProductDetails.jsp</result>
</action>
1.1 interceptors元素
interceptors
元素必须直接出现在
package
元素下,用于为该包注册拦截器。例如:
<package name="main" extends="struts-default">
<interceptors>
<interceptor name="validation" class="..."/>
<interceptor name="logger" class="..."/>
</interceptors>
</package>
1.2 package元素
为了实现模块化,Struts的Action被分组到包中,包可以看作是模块。
struts.xml
文件可以有一个或多个
package
元素。
package
元素的属性如下表所示:
| Attribute | Description |
| — | — |
| name* | 包名,在整个
struts.xml
文件中必须唯一。 |
| extends | 该包继承的父包。 |
| namespace | 该包的命名空间。 |
| abstract | 指示该包是否为抽象包。 |
一个
package
元素必须指定
name
属性,其值在整个
struts.xml
文件中必须唯一。它还可以指定
namespace
属性,如果
namespace
不存在,则默认值为
/
。如果
namespace
属性有非默认值,则必须将命名空间添加到调用包中Action的URI中。例如,调用默认命名空间包中Action的URI为:
/context/actionName.action
调用非默认命名空间包中Action的URI为:
/context/namespace/actionName.action
一个
package
元素几乎总是继承
struts-default.xml
中定义的
struts-default
包。
struts-default.xml
是Struts核心JAR中包含的默认配置文件,定义了标准的拦截器和结果类型。继承
struts-default
的包可以使用这些拦截器和结果类型,而无需重新注册。
1.3 param元素
param
元素可以嵌套在其他元素(如
action
、
result-type
和
interceptor
)中,用于向包含它的对象传递值。
param
元素有一个
name
属性,用于指定参数的名称。格式如下:
<param name="property">value</param>
在
action
元素中使用
param
可以设置Action的属性。例如:
<action name="customer" class="...">
<param name="siteId">california01</param>
</action>
以下
param
元素设置了
validation
拦截器引用的
excludeMethod
:
<interceptor-ref name="validation">
<param name="excludeMethods">input,back,cancel</param>
</interceptor-ref>
1.4 result元素
result
元素可以出现在
action
元素或
global-results
元素下,用于指定Action的结果。
result
元素对应于Action方法的返回值。由于Action方法在不同情况下可能返回不同的值,因此一个
action
元素可能有多个
result
元素,每个元素对应于Action方法的一个可能返回值。
result
元素的属性如下表所示:
| Attribute | Description |
| — | — |
| name | 结果名称,与Action方法的返回值相关联。 |
| type | 与该结果关联的已注册结果类型。 |
例如,以下
action
元素包含两个
result
元素:
<action name="Product_save" class="app.Product" method="save">
<result name="success" type="dispatcher">
/jsp/Confirm.jsp
</result>
<result name="input" type="dispatcher">
/jsp/Product.jsp
</result>
</action>
1.5 result-type元素
result-type
元素为包注册一个结果类型,必须直接出现在
result-types
元素下。
result-type
元素的属性如下表所示:
| Attribute | Description |
| — | — |
| name | 引用该结果类型的名称。 |
| class | 该结果类型的Java类。 |
| default | 指定该结果类型是否为包的默认结果类型。 |
例如,以下两个
result-type
元素在
struts-default
包中注册了
Dispatcher
和
FreeMarket
结果类型:
<result-type name="dispatcher" default="true"
class="org.apache.struts2.dispatcher.ServletDispatcherResult"/>
<result-type name="freemarker" class="org.apache.struts2.views.
freemarker.FreemarkerResult"/>
1.6 result-types元素
result-types
元素用于分组
result-type
元素,必须直接出现在
package
元素下。例如:
<result-types>
<result-type name="chain" class="..."/>
<result-type name="dispatcher" class="..." default="true"/>
<result-type name="freemarker" class="..."/>
</result-types>
2. struts-default.xml文件
struts-default.xml
文件是Struts核心JAR中包含的默认配置文件,定义了标准的拦截器和结果类型。以下是
struts-default.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="struts-default">
<result-types>
<result-type name="chain"
class="com.opensymphony.xwork2.ActionChainResult"/>
<result-type name="dispatcher"
class="org.apache.struts2.dispatcher.ServletDispatcherResult"
default="true"/>
<result-type name="freemarker"
class="org.apache.struts2.views.freemarker.FreemarkerResult"/>
<!-- 其他结果类型 -->
</result-types>
<interceptors>
<interceptor name="alias"
class="com.opensymphony.xwork2.interceptor.AliasInterceptor"/>
<interceptor name="autowiring"
class="com.opensymphony.xwork2.spring.interceptor.ActionAutowiringInterceptor"/>
<!-- 其他拦截器 -->
<!-- Basic stack -->
<interceptor-stack name="basicStack">
<interceptor-ref name="exception"/>
<interceptor-ref name="servlet-config"/>
<interceptor-ref name="prepare"/>
<interceptor-ref name="checkbox"/>
<interceptor-ref name="params"/>
<interceptor-ref name="conversionError"/>
</interceptor-stack>
<!-- 其他拦截器栈 -->
</interceptors>
<default-interceptor-ref name="defaultStack"/>
</package>
</struts>
在这个文件中,定义了多种结果类型和拦截器,还定义了多个拦截器栈,如
basicStack
、
validationWorkflowStack
等。
3. struts.properties文件
可以在
WEB-INF/classes
目录下创建
struts.properties
文件,以覆盖
default.properties
文件中定义的配置设置。以下是一些常见的
struts.properties
配置项及其说明:
| 配置项 | 说明 | 默认值 |
| — | — | — |
| struts.i18n.encoding | Struts默认编码 | UTF - 8 |
| struts.objectFactory | 默认对象工厂,值必须是
com.opensymphony.xwork2.ObjectFactory
的子类,支持简写符号,如
spring
代表
SpringObjectFactory
| |
| struts.objectFactory.spring.autoWire | 使用
SpringObjectFactory
时的自动装配逻辑,有效值为
name
(默认)、
type
、
auto
和
constructor
| name |
| struts.objectFactory.spring.useClassCache | 指示Struts - Spring集成模块是否应缓存
Class
实例 | true |
| struts.objectTypeDeterminer | 指定对象类型确定器,值必须是
com.opensymphony.xwork2.util.ObjectTypeDeterminer
的实现,支持简写符号,如
tiger
或
notiger
| |
| struts.multipart.parser | 指定处理文件上传中
multipart/form-data
请求的解析器 | Jakarta |
| struts.multipart.saveDir | 文件上传的默认保存目录,默认值是
javax.servlet.context.tempdir
指示的目录 | |
| struts.multipart.maxSize | 上传文件的最大大小 | 2097152 |
| struts.custom.properties | 必须加载的自定义属性文件列表 | |
| struts.mapper.class | 处理请求URL与Action映射的Action映射器 | org.apache.struts2.dispatcher.mapper.DefaultActionMapper |
| struts.action.extension | 以逗号分隔的Action扩展名列表 | action |
| struts.serve.static | 指示Struts是否应从其JAR内部提供静态内容,值为
false
表示静态内容必须在
<contextPath>/struts
可用 | true |
| struts.serve.static.browserCache | 指示过滤器调度器是否应为将被Web浏览器缓存的静态内容写入头部,值为
true
适用于开发模式,如果
struts.serve.static
为
false
,则忽略此键 | true |
| struts.enable.DynamicMethodInvocation | 指示是否启用动态方法调用,默认值为
true
,但出于安全原因,其值应为
false
| true |
| struts.enable.SlashesInActionNames | 指示Action名称中是否允许使用斜杠 | false |
| struts.tag.altSyntax | 指示是否允许使用需要
%{ ... }
的替代表达式计算语法 | true |
| struts.devMode | 指示是否应启用开发模式,值为
true
时,Struts将在每次请求时重新加载应用程序的
struts.xml
文件、验证文件和资源束 | false |
| struts.ui.theme | 默认主题 | xhtml |
| struts.ui.templateDir | 模板的默认位置 | template |
| struts.ui.templateSuffix | 默认模板类型,除了
ftl
(FreeMarker),还有
vm
(Velocity)和
jsp
(JSP) | ftl |
| struts.configuration.xml.reload | 指示如果
struts.xml
文件已更改,是否应重新加载 | false |
| struts.velocity.configfile | 默认的Velocity配置文件 | velocity.properties |
| struts.velocity.contexts | 要链接到
StrutsVelocityContext
的
VelocityContext
类名的逗号分隔列表 | |
| struts.velocity.toolboxlocation | Velocity工具盒的位置 | |
| struts.url.http.port | 构建URL时使用的HTTP端口号 | 80 |
| struts.url.https.port | 构建URL时使用的HTTPS端口号 | 443 |
| struts.custom.i18n.resources | 加载自定义默认资源束 | |
| struts.dispatcher.parametersWorkaround | 指示是否应启用处理
HttpServletRequest.getParameterMap()
的应用程序的解决方法 | false |
| struts.freemarker.manager.classname | 要使用的FreeMarker管理器类,必须是
org.apache.struts2.views.freemarker.FreemarkerManager
的子类 | |
| struts.xslt.nocache | 指定
XSLTResult
类是否应使用样式表缓存 | false |
| struts.configuration.files | 应自动加载的配置文件列表 | struts-default.xml,struts-plugin.xml,struts.xml |
| struts.mapper.alwaysSelectFullNamespace | 指示Struts是否应选择最后一个斜杠之前的所有内容作为命名空间 | false |
4. JSP表达式语言(EL)
OGNL是与Struts自定义标签一起使用的表达式语言,但在某些情况下,JSP表达式语言(EL)可以提供帮助。
4.1 EL语法
EL表达式以
${
开头,以
}
结尾,构造如下:
${expression}
例如,要编写表达式
x + y
,可以使用以下构造:
${x + y}
也可以连接两个表达式,表达式序列将从左到右进行计算,转换为字符串并连接。如果
a + b
等于8,
c + d
等于10,则以下两个表达式将产生
810
:
${a + b}${c + d}
${a + b}some${c + d}
将产生
8some10
。
如果EL表达式用于自定义标签的属性值中,表达式将被计算,结果字符串将转换为属性的预期类型:
<my:tag someAttribute="${expression}"/>
如果要发送字面量
${
,需要转义第一个字符:
\${
。
4.2 保留字
以下单词是保留字,不能用作标识符:
| | | | | |
| — | — | — | — | — |
| and | eq | gt | true | instanceof |
| or | ne | le | false | empty |
| not | It | ge | null | div |
| mod | | | | |
4.3 [ ]和.运算符
EL表达式的返回类型可以是任何类型。如果EL表达式的结果是一个有属性的对象,可以使用
[]
或
.
运算符来访问该属性。
[]
和
.
运算符功能相似,
[]
是更通用的形式,而
.
提供了一个便捷的快捷方式。
要访问作用域对象的属性,可以使用以下形式之一:
${object["propertyName"]}
${object.propertyName}
但是,如果
propertyName
不是有效的Java变量名,则只能使用第一种形式(使用
[]
运算符)。例如,以下两个EL表达式可用于访问隐式对象
header
中的HTTP头
host
:
${header["host"]}
${header.host}
通过以上内容,我们详细了解了Struts2的配置元素、
struts.properties
文件的配置以及JSP表达式语言的使用,这些知识对于开发基于Struts2的Web应用程序非常重要。
Struts2配置与JSP表达式语言详解
5. EL在实际应用中的优势
JSP表达式语言(EL)在实际开发中有诸多优势,除了前面提到的简洁语法外,还能方便地处理一些复杂的操作。
例如,在获取请求参数、会话属性等方面,EL提供了简单直接的方式。假设我们有一个请求参数
username
,可以使用
${param.username}
来获取它的值。如果要获取会话中的用户信息,假设会话中存储的用户对象键名为
user
,可以使用
${sessionScope.user}
来访问。
以下是一个简单的JSP页面示例,展示了EL在获取请求参数和会话属性方面的应用:
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>EL应用示例</title>
</head>
<body>
<h1>欢迎,${param.username}</h1>
<p>您的用户ID是:${sessionScope.user.id}</p>
</body>
</html>
在这个示例中,
${param.username}
获取了请求中的
username
参数值,
${sessionScope.user.id}
获取了会话中用户对象的
id
属性值。
6. EL与Struts2标签的结合使用
虽然OGNL是与Struts自定义标签一起使用的主要表达式语言,但在某些情况下,EL可以与Struts2标签结合使用,以提供更灵活的功能。
例如,在Struts2的表单标签中,可以使用EL来动态设置表单元素的属性。以下是一个使用EL设置表单输入框
value
属性的示例:
<s:form action="submitForm">
<s:textfield name="username" value="${sessionScope.user.username}" label="用户名"/>
<s:submit value="提交"/>
</s:form>
在这个示例中,
value="${sessionScope.user.username}"
使用EL从会话中获取用户的用户名,并将其设置为输入框的初始值。
7. 总结与最佳实践
通过对Struts2配置元素、
struts.properties
文件配置以及JSP表达式语言的学习,我们可以总结出以下最佳实践:
7.1 Struts2配置方面
-
合理使用拦截器栈
:根据不同的业务需求,选择合适的拦截器栈。例如,对于简单的业务逻辑,可以使用
basicStack;对于需要验证和工作流处理的业务,可以使用validationWorkflowStack。 - 遵循命名规范 :在定义包名、Action名、拦截器名等时,遵循统一的命名规范,提高代码的可读性和可维护性。
-
谨慎使用动态方法调用
:由于动态方法调用存在安全风险,建议将
struts.enable.DynamicMethodInvocation设置为false。
7.2 JSP表达式语言方面
- 充分利用EL的简洁性 :在JSP页面中,尽量使用EL来替代复杂的Java代码,提高代码的简洁性和可读性。
- 注意保留字的使用 :避免使用保留字作为标识符,以免出现语法错误。
- 结合Struts2标签使用 :在Struts2的标签中合理使用EL,实现动态属性设置和数据展示。
8. 流程图示例
下面是一个简单的Struts2请求处理流程图,展示了请求从客户端到服务器,经过拦截器处理,最终到达Action并返回结果的过程:
graph LR
classDef startend fill:#F5EBFF,stroke:#BE8FED,stroke-width:2px;
classDef process fill:#E5F6FF,stroke:#73A6FF,stroke-width:2px;
classDef decision fill:#FFF6CC,stroke:#FFBC52,stroke-width:2px;
A([客户端请求]):::startend --> B(Struts2过滤器):::process
B --> C{是否匹配Action}:::decision
C -->|是| D(执行拦截器栈):::process
C -->|否| E(返回404错误):::process
D --> F(执行Action方法):::process
F --> G{Action返回结果}:::decision
G -->|success| H(执行结果类型处理):::process
G -->|input| I(返回输入页面):::process
H --> J([返回响应给客户端]):::startend
I --> J
这个流程图清晰地展示了Struts2请求处理的主要步骤,帮助我们更好地理解Struts2的工作原理。
通过以上内容,我们全面深入地了解了Struts2的配置和JSP表达式语言的使用,掌握这些知识将有助于我们开发出高效、安全、易维护的Web应用程序。在实际开发中,我们应根据具体需求灵活运用这些技术,不断优化代码,提高开发效率。
超级会员免费看
143

被折叠的 条评论
为什么被折叠?



