写点什么

Java 开发框架 Struts 相关知识分享

  • 2021 年 12 月 07 日
  • 本文字数:6887 字

    阅读完需:约 23 分钟

​ValueStack


ValueStack, 即值栈对象。


值栈对象:


是整个 struts 数据存储的核心,或者叫中转站。


用户每次访问 struts 的 action,都会java培训创建一个 Action 对象、值栈对象、ActionContext 对象; 然后把 Action 对象放入值栈中;最后再把值栈对象放入 request 中,传入 jsp 页面。


(key: struts.valueStack);开发者只需要通过 ActionContext 对象就可以访问 struts 的其他的关键对象。(ActionContext 是给开发者用的,便于学习与使用。)


Struts 标签


Struts 标签取值,就使用了 Ognl 表达式语言。


Struts2 中国际化


  1. 写资源文件


Msg.properties 默认的语言环境;找不到配置就找它


Msg_en_US.properties 美国


  1. 加载


<constant name="struts.custom.i18n.resources" value="loaderman.config.msg"></constant>


  1. 使用: 标签 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 环境


  1. 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 接口


  1. 实现接口方法:接口方法返回的就是要封装的对象

  2. 对象一定要实例化。


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>


用户头像

关注尚硅谷,轻松学IT 2021.11.23 加入

还未添加个人简介

评论

发布
暂无评论
Java开发框架Struts相关知识分享