Java 开发框架 Struts 相关知识分享
ValueStack
ValueStack, 即值栈对象。
值栈对象:
是整个 struts 数据存储的核心,或者叫中转站。
用户每次访问 struts 的 action,都会java培训创建一个 Action 对象、值栈对象、ActionContext 对象; 然后把 Action 对象放入值栈中;最后再把值栈对象放入 request 中,传入 jsp 页面。
(key: struts.valueStack);开发者只需要通过 ActionContext 对象就可以访问 struts 的其他的关键对象。(ActionContext 是给开发者用的,便于学习与使用。)
Struts 标签
Struts 标签取值,就使用了 Ognl 表达式语言。
Struts2 中国际化
写资源文件
Msg.properties 默认的语言环境;找不到配置就找它
Msg_en_US.properties 美国
加载
<constant name="struts.custom.i18n.resources" value="loaderman.config.msg"></constant>
使用: 标签 name 值直接写配置文件中的 key
<s:text name="title"></s:text>
另外一点,
(推荐)加载资源文件通过常量加载
还可以在页面加载, 这样用:
<s:i18n name="loaderman.config.msg">
<s:text> 标签必须放到标签体中。
</s:i18n>
Struts 数据效验
表单数据的验证:
前台验证:主要是通过 JS 验证, 表达数据是否合法!
后台验证:通过后台 java 代码进行验证! Struts 也提供了数据效验的方式!
Struts 数据效验, 通过拦截器完成:
<interceptor name="validation" class="org.apache.struts2.interceptor.validation.AnnotationValidationInterceptor"/>
代码方式验证 Action 中所有的方法:
步骤:
1.搭建 struts 环境
login.jsp
3.UserAction.java
Struts 数据效验错误信息处理:
public synchronized void addFieldError(String fieldName, String errorMessage) {// 1. 保存错误信息的 map 集合 final Map<String, List<String>> errors = internalGetFieldErrors();// 2. Map 的 value 值 (一个 key,对应的多个值用 list 存储)List<String> thisFieldErrors = errors.get(fieldName);// 3. 如果错误信息的 map 中没有当前的 key,就直接创建集合 if (thisFieldErrors == null) {// 创建 thisFieldErrors = new ArrayList<String>();errors.put(fieldName, thisFieldErrors);}// 4. 添加错误信息 thisFieldErrors.add(errorMessage);}
action 实现:
import com.opensymphony.xwork2.ActionSupport;
/**
注意:如果要想用 struts 的数据效验功能,必须继承 ActionSupport 或实现相关接口
*/public class UserAction extends ActionSupport {
// 封装请求数据 private User user = new User();public void setUser(User user) {this.user = user;}public User getUser() {return user;}
/*// 重写数据验证的方法 public void validateRegister() {// 用户名非空 if (user.getUserName() == null || "".equals(user.getUserName())) {// 保存错误信息 super.addFieldError("userName", "用户名必须填写!");}// 密码 if (user.getPwd() == null || "".equals(user.getPwd())) {super.addFieldError("pwd", "密码必填");}}*/
@Overridepublic void validate() {// 用户名非空 if (user.getUserName() == null || "".equals(user.getUserName())) {// 保存错误信息 super.addFieldError("userName", "用户名必须填写!");}// 密码 if (user.getPwd() == null || "".equals(user.getPwd())) {super.addFieldError("pwd", "密码必填");}}
// 业务方法 public String register() {System.out.println(user);System.out.println(1);return SUCCESS;}
// 列表展示(不用数据效验)public String list() {return SUCCESS;}}
代码方式验证 Action 中指定的方法:
写验证方法命名规则:
validate + 要验证的方法名
如:public void validateRegister() { 只会验证当前 action 的 register 方法!
XML 方式验证 Action 中所有的方法:
总结代码方式验证:繁琐,设计很多重复的验证逻辑!
例如:非空验证、数值验证、email、日期等。
Struts 对于常用的验证,进行了封装,即提供了验证器, 验证指定的常用业务逻辑!
Struts 提供的所有验证器:
路径:xwork-core-2.3.4.1.jar/com.opensymphony.xwork2.validator.validators/default.xml<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE validators PUBLIC"-//Apache Struts//XWork Validator Definition 1.0//EN""http://struts.apache.org/dtds/xwork-validator-definition-1.0.dtd">
如果写 xml,从而定义验证规则:
1)XML 文件名称语法:ActionClassName-validation.xml
注意:此 xml 需要与当期要验证的 action 在同一个目录:
举例:UserAction-validation.xml
2) 写 XML
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE validators PUBLIC"-//Apache Struts//XWork Validator 1.0.3//EN""http://struts.apache.org/dtds/xwork-validator-1.0.3.dtd">
<validators>
<!-- 验证的每一个字段用 field 表示 -->
<field name="user.userName">
<!-- 指定使用的验证器 -->
<field-validator type="requiredstring">
<!-- 验证失败的错误提示信息 -->
<message>用户名不能为空!</message>
</field-validator>
</field>
<!-- 验证 pwd -->
<field name="user.pwd">
<!-- 非空 -->
<field-validator type="requiredstring">
<message>密码不能为空!</message>
</field-validator>
<!-- 长度 -->
<field-validator type="stringlength">
<param name="minLength">6</param>
<param name="maxLength">8</param>
<message>密码必须为 6-8 位~~~~</message>
</field-validator>
</field>
<!-- 验证日期 -->
<field name="user.birth">
<field-validator type="date">
<message>日期格式不对!</message>
</field-validator>
</field>
<!-- 验证 Email -->
<field name="user.email">
<field-validator type="email">
<message>邮箱格式错误!</message>
</field-validator>
</field>
</validators>
XML 方式验证 Action 中指定的方法:
与上面 xml 验证方式大致相同:验证 xml 文件内容不变;
文件命名:
语法:ActionClassName-ActionName-validation.xml
举例:UserAction-user_register-validation.xml
验证 UserAction 中的 register 方法
验证总结
代码:
重写 validate() , 验证 action 所有方法
Validate 方法名(), 验证指定“方法名”的方法
Xml:
验证所有方法:ActionClassName-validation.xml
验证指定方法:ActionClassName-actionName-validation.xml
代码验证:
比较灵活,可以满足所有的需求. 比较繁琐,要写重复的验证判断逻辑!
适合:表单字段较少的情况用!
XML 验证:
通用,但不够灵活;可以验证特定简单的业务。
适合:验证表单字段较多,可以大大简化代码!(配置文件过多)
验证错误处理
Struts 在进行数据效验的时候,验证失败,会返回 input 视图,要求我们要在 struts.xml 中配置 input 视图对应的错误页面!
配置:
Struts.xml
<!-- 注册失败跳转到注册页面,显示失败信息 -->
<global-results>
<result name="input">/register.jsp</result>
</global-results>
JSP 显示错误:
方式 1:显示所有错误
<%@taglib uri="/struts-tags" prefix="s" %>
<!-- 显示的是 struts 在运行时期产生的所有错误 -->
<s:fielderror></s:fielderror>
方式 2:显示指定的错误
<!-- 修改 struts 标签默认的样式:不让换行 -->
<style type="text/css">
ul{
display: inline;
}
ul li{
display: inline;
color: red;
}
</style>
显示指定的错误:
<s:fielderror fieldName="user.userName"></s:fielderror>
方式 3: 修改标签定义的模板
找到 fielderror 标签定义的模板文件:
Struts-core.jar\template\simple\ fielderror.ftl
把修改后的 fielderror.ftl 文件,放到 src/ template/ simple/ fielderror.ftl
这样标签显示的样式就修改了!
fielderror.ftl
<#--/*
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.*/--><#if fieldErrors??><#t/><#assign eKeys = fieldErrors.keySet()><#t/><#assign eKeysSize = eKeys.size()><#t/><#assign doneStartUlTag=false><#t/><#assign doneEndUlTag=false><#t/><#assign haveMatchedErrorField=false><#t/><#if (fieldErrorFieldNames?size > 0) ><#t/><#list fieldErrorFieldNames as fieldErrorFieldName><#t/><#list eKeys as eKey><#t/><#if (eKey = fieldErrorFieldName)><#t/><#assign haveMatchedErrorField=true><#t/><#assign eValue = fieldErrors[fieldErrorFieldName]><#t/><#if (haveMatchedErrorField && (!doneStartUlTag))><#t/><#assign doneStartUlTag=true><#t/></#if><#t/><#list eValue as eEachValue><#t/>{eEachValue}</#list><#t/></#if><#t/></#list><#t/></#list><#t/><#if (haveMatchedErrorField && (!doneEndUlTag))><#t/><#assign doneEndUlTag=true><#t/></#if><#t/><#else><#t/><#if (eKeysSize > 0)><#t/><ul<#rt/><#if parameters.cssClass??>class="{parameters.cssClass?html}"<#rt/><#else>class="errorMessage"<#rt/></#if><#if parameters.cssStyle??>style="${parameters.cssStyle?html}"<#rt/></#if>
<#list eKeys as eKey><#t/><#assign eValue = fieldErrors[eKey]><#t/><#list eValue as eEachValue><#t/><li><span><#if parameters.escape>{eEachValue!?html}<#else>{eEachValue!}</#if></span></li></#list><#t/></#list><#t/></ul></#if><#t/></#if><#t/></#if><#t/>
Struts 简单 UI 标签
用户名:<s:textfield name="user.name"></s:textfield>密码:<s:textfield name="user.pwd"></s:textfield><s:submit value="登陆"></s:submit></s:form>
注意:给 form 指定主题,form 下所有的表单元素都应用此主题!对于 struts 标签默认的主题样式:
default.xml/struts.ui.theme=xhtm
truts ognl 表达式语言几个符号
获取非根元素值 、 动态都建 map 集合
$ 配置文件取值
% 提供一个 ognl 表达式运行环境
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%><%@taglib uri="/struts-tags" prefix="s"%><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"><html><head><title>My JSP 'index.jsp' starting page</title><meta http-equiv="pragma" content="no-cache"><meta http-equiv="cache-control" content="no-cache"><meta http-equiv="expires" content="0"></head>
<body>
<br/>获取 request 域数据<br/>
<!-- property 标签是对象类型的标签,默认支持 ognl 表达式, 会从根元素去 China 名称对应的值 -->
<s:property value="China"/> <br/>
<!-- 如果直接赋值,需要用单引号 -->
<s:property value="'China'"/> <br/>
<s:property value="#request.cn"/> <br/>
<s:property value="%{#request.cn}"/> <br/> <!-- 同上 -->
<!-- 值类型的标签,value 值默认就是值类型,不支持 ognl 表达式 -->
国家:<s:textfield name="txtCountry" value="%{#request.cn}"></s:textfield>
</body>
</html>
struts 数据回显
数据回显,必须要用 struts 标签!
action:
// 进入修改页面
public String viewUpdate() {
// 模拟一个对象(先获取一个 id,再根据 id 调用 service 查询,把查到的结果保存到域)
User userInfo = new User();
userInfo.setUserName("Jack");
userInfo.setEmail("loaderman@163.com");
ActionContext ac = ActionContext.getContext();
// Map<String,Object> request = (Map<String, Object>) ac.get("request");
// request.put("userInfo", userInfo);
/************* 数据回显***************/
// 获取值栈
ValueStack vs = ac.getValueStack();
vs.pop();// 移除栈顶元素
vs.push(userInfo); // 入栈
// 进入修改页面
return "viewUpdate";
}
JSP:
<body>
<%@taglib uri="/struts-tags" prefix="s" %>
<br/>
<!-- 在页面文本框内,显示要修改记录的数据 -->
<!-- 手动通过 value 设置显示的值
<s:form action="#">
用户名:<s:textfield name="user.userName" value="%{#request.userInfo.userName}"></s:textfield> <br/>
邮箱:<s:textfield name="user.email" value="%{#request.userInfo.email}"></s:textfield> <br/>
</s:form>
-->
<!-- 数据回显技术:s:textfield 会自动查找根元素数据(Ognl 表达式语言取值) -->
<s:form action="#">
用户名: <s:textfield name="userName"></s:textfield> <br/>
邮箱: <s:textfield name="email"></s:textfield> <br/>
</s:form>
<s:debug></s:debug>
</body>
Struts 模型驱动
Struts 运行时候,会执行默认的拦截器栈,其中有一个拦截器,模型驱动拦截器:
<interceptor name="modelDriven" class="com.opensymphony.xwork2.interceptor.ModelDrivenInterceptor"/>
@Overridepublic String intercept(ActionInvocation invocation) throws Exception {Object action = invocation.getAction();
if (action instanceof ModelDriven) {ModelDriven modelDriven = (ModelDriven) action;ValueStack stack = invocation.getStack();Object model = modelDriven.getModel();if (model != null) {stack.push(model);}if (refreshModelBeforeResult) {invocation.addPreResultListener(new RefreshModelBeforeResult(modelDriven, model));}}return invocation.invoke();}
Struts 数据回显和模型驱动
prams 拦截器,可以把请求数据自动填充的 action 的属性中
举例 1:JSP<input type=text name=userName /><input type=text name=pwd />
Actionclass UserAction{// 封装请求数据 private String userName;private String pwd;//.. set 方法}
举例 2:JSP<input type=text name=user.userName /><input type=text name=user.pwd />
Actionclass UserAction{// 封装请求数据 private User user;..}
举例 3:(模型驱动)JSP<input type=text name=userName /><input type=text name=pwd />
Actionclass UserAction{// 封装请求数据 private User user;..}
步骤及原理
步骤:
1.实现 ModelDriver 接口
实现接口方法:接口方法返回的就是要封装的对象
对象一定要实例化。
package loaderman.b_form;
import java.util.Map;
import com.opensymphony.xwork2.ActionContext;import com.opensymphony.xwork2.ActionSupport;import com.opensymphony.xwork2.ModelDriven;import com.opensymphony.xwork2.util.ValueStack;
/**
数据回显
模型驱动
*/public class UserAction extends ActionSupport implements ModelDriven<User> {
// 封装请求数据 private User user = new User();public void setUser(User user) {this.user = user;}public User getUser() {return user;}
// 实现模型驱动接口方法 @Overridepublic User getModel() {return user;}
public String add() {// 测试:使用了模型驱动,是否数据正常?OkSystem.out.println(user);return "success";}
// 进入修改页面 public String viewUpdate() {// 模拟一个对象(先获取一个 id,再根据 id 调用 service 查询,把查到的结果保存到域)User userInfo = new User();userInfo.setUserName("Jack");userInfo.setEmail("yuanjie@loaderman.cn");
ActionContext ac = ActionContext.getContext();// Map<String,Object> request = (Map<String, Object>) ac.get("request");// request.put("userInfo", userInfo);
/************* 数据回显***************/// 获取值栈 ValueStack vs = ac.getValueStack();vs.pop();// 移除栈顶元素 vs.push(userInfo); // 入栈
// 进入修改页面 return "viewUpdate";}
// 业务方法 public String index() {// 保存数据到 request 域 ActionContext ac = ActionContext.getContext();Map<String,Object> request = (Map<String, Object>) ac.get("request");request.put("cn", "China");
return SUCCESS;}}
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%><%@taglib uri="/struts-tags" prefix="s"%><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"><html><head><title>My JSP 'index.jsp' starting page</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:form action="/user_add" method="post">用户名:<s:textfield name="userName"></s:textfield> <br/>密码:<s:textfield name="pwd"></s:textfield> <br/>
<s:submit value="保存用户"></s:submit></s:form></body></html>
评论