企业🤖AI Agent构建引擎,智能编排和调试,一键部署,支持私有化部署方案 广告
进行数据验证前,我们先解决一个一直没有影响我们编码,但可能却影响心情的小问题。 即没有引用servlet而引发的错误警告: ![https://box.kancloud.cn/2b1e3c5689812d4b0fde5e7948da1294_1148x202.png](https://box.kancloud.cn/2b1e3c5689812d4b0fde5e7948da1294_1148x202.png) 该类为tomcat为我们提供的类,修复步骤如下: bulidpath -> config buildpath -> Libraries -> add Library... -> Server Runtime -> Apache Tomcat v7.0 -> finish -> ok。 这时候, 红色的小叉叉应该没有了。 <hr /> 下面,我们正式加入验证信息。 流程图如下: ![https://box.kancloud.cn/1702cc12ea19dbdc7877c15d7e87e0c4_690x1214.png](https://box.kancloud.cn/1702cc12ea19dbdc7877c15d7e87e0c4_690x1214.png) ## 定义出错后的操作界面error jsp/teacher/error.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>验证错误</title> </head> <body> <h2>验证错误</h2> </body> </html> ``` ## 配置路由 假设我们为新增数据的保存操作进行验证,则我们配置保存操作的路由: struts.xml ``` <!-- 保存数据 --> <action name="save" class="com.mengyunzhi.javaee.action.teacher.Save"> <!-- 设置V层,相对于WebContent的绝对路径 --> <result name="success">/jsp/success.jsp</result> <result name="error">/jsp/error.jsp</result> <result name="input">/jsp/teacher/error.jsp</result> </action> ``` > 有人问为什么要使用input,而不用其它的呢。原因是因为大家都用input,所以我们也用input能够更好的和其它软件工程师交流。 ## 测试路由与V层 打开保存的类,然后注释掉原返回值,新增返回input com.mengyunzhi.javaee.action.teacher SaveAction 我们对用户名的长度进行规定,并在V层输出我们返回的错误信息。 ``` ... // 错误信息 private String error; public String getError() { return error; } public String execute() { if (this.username.length() < 4) { error = "用户名长度过短"; return input; } if (this.name.length() < 3) { error = "姓名长度过短"; return input; } ...... ``` ### V层显示 ``` <h2>验证错误</h2> <h3><s:property value="error" /></h3> ``` > V层只所以可以使用`error`这个变量,这由于在Action中,存在getError()方法. ### 测试: ![https://box.kancloud.cn/6d3afc94fe7944c8f031a27563ddd5fe_748x322.png](https://box.kancloud.cn/6d3afc94fe7944c8f031a27563ddd5fe_748x322.png) ## 增加多个验证,并一次性输出 流程图如下: ![https://box.kancloud.cn/decfc0b2137185515cdfa7caef5f312b_364x624.png](https://box.kancloud.cn/decfc0b2137185515cdfa7caef5f312b_364x624.png) ### 触发器 ``` ... public class SaveAction extends TeacherAction { ... if (username.length() < 4) { addActionError("用户名长度过短"); } if (this.name.length() < 3) { addActionError("姓名长度过短"); } ... // 存在错误,则返回input if (hasActionErrors()) { return INPUT; } else { return SUCCESS; } ... ``` > 我们间接的继承了`ActionSupport`,而`addActionError`等函数,则正是`ActionSupport`中的方法。 ### V层 ``` <h2>验证错误</h2> <ul> <s:iterator value="actionErrors" var="actionError" status="status"> <li><s:property value="#actionError" /></li> </s:iterator> </ul> ``` ### 测试 ![https://box.kancloud.cn/a567b03ea8db1982b6769d082e8a6a1d_852x346.png](https://box.kancloud.cn/a567b03ea8db1982b6769d082e8a6a1d_852x346.png) 总结:我们可以在继承ActionSupport后,很简单的实现了字段的验证,这在实际的开发中,也是必要的。 示例代码如下: ``` package com.mengyunzhi.javaee.action.teacher; import java.util.Collection; import org.hibernate.HibernateException; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.Transaction; import org.hibernate.cfg.Configuration; import org.hibernate.service.ServiceRegistry; import org.hibernate.service.ServiceRegistryBuilder; public class SaveAction extends TeacherAction { /** * 创建时间:2017.1.16 */ private static final long serialVersionUID = 1L; private String username; private String password; private String sex; private String name; private String email; public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public String getSex() { return sex; } public void setSex(String sex) { this.sex = sex; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } // 该execute方法将被自动调用, 方法的返回类型必须为String public String execute() { if (username.length() < 4) { addActionError("用户名长度过短"); } if (this.name.length() < 3) { addActionError("姓名长度过短"); } // 实例化并加载数据库配置文件 Configuration configuration = new Configuration().configure(); // 构造服务注册对象 ServiceRegistry serviceRegistry = new ServiceRegistryBuilder() .applySettings(configuration.getProperties()) .buildServiceRegistry(); // 创建会话工厂(session factory)) SessionFactory sessionFactory = configuration .buildSessionFactory(serviceRegistry); // 创建会话(这里的session也是会话的意思,我们以前接触的http中的session,处理的是用户与服务器的对话) Session session = sessionFactory.getCurrentSession(); // 开启事务(使用缓冲池进行数据库的连接) Transaction transaction = session.beginTransaction(); // 在这里,必须使用try catch finally语句。来确定会话正常关闭. // 否则,当操作数据库产生错误时,你可能需要重启mysql服务 try { // 初例化 赋值 com.mengyunzhi.javaee.entity.Teacher teacher = new com.mengyunzhi.javaee.entity.Teacher(); teacher.setName(name); teacher.setUsername(username); teacher.setEmail(email); teacher.setPassword(password); // 由于sex的类型是String对象,所以需要使用equals()来判等 if (sex.equals("0")) { teacher.setSex(false); } else { teacher.setSex(true); } session.save(teacher); // 提交事务 transaction.commit(); // 捕获异常 } catch (HibernateException e) { } finally { // 如果session处于开启状态,则关闭session if (session.isOpen()) { // 关闭会话 session.close(); } } // 存在错误,则返回input if (hasActionErrors()) { return INPUT; } else { return SUCCESS; } } } ``` > 注意:上述代码未重构,直接在C层调用实体层,是错误的做法。我们将在下一个班级管理中,对该方法进行重构. <hr /> 下面,我们共同看看Struts使用注解进行验证的方法。 我们在前面学过了,数据由用户发送的时候,直接调用了action类的setXXX方法,来进行赋值。Struts的验证也是利用了这一点,在进行赋值时,进行验证。如果正确的则正确执行,如果错误,则返回"input". 流程图如下: ![https://box.kancloud.cn/9aa4c2d12384f92a242887264c9f935d_882x1516.png](https://box.kancloud.cn/9aa4c2d12384f92a242887264c9f935d_882x1516.png) # 内置验证 首先,我们删除在execute中用于验证的代码,并直接返回SUCCESS. 然后,我们在setName()、setUsername()方法上添加注解,来实现验证. ``` ... @RequiredStringValidator( message="用户名不能为空") @StringLengthFieldValidator( minLength="4", maxLength="8", trim=true, message="用户名必须介于4-8之间") public void setUsername(String username) { this.username = username; } ... @RequiredStringValidator( message="姓名不能为空") @StringLengthFieldValidator( minLength="2", trim=true, message="姓名不能少于2位") public void setName(String name) { this.name = name; } ``` ## V层显示错误信息 验证字段产生的错误将自动存储在`fieldErrors`中,该字段同样位于`ActionSupport`中,同时为我们提供了`getFieldErrors`供我们在前台调用。 ``` <ul> <!-- 循环输出字段验证发生的错误 --> <s:iterator value="fieldErrors" var="fieldError"> <li><s:property /></li> </s:iterator> </ul> ``` ![https://box.kancloud.cn/d6b30601c55ce08e2bca1a4dc1750cf2_722x348.png](https://box.kancloud.cn/d6b30601c55ce08e2bca1a4dc1750cf2_722x348.png) 不止如此,我们还可以使用struts的内置标签来快捷的输出错误: ``` <body> <h2>验证错误</h2> <ul> <!-- 循环输出字段验证发生的错误 --> <s:iterator value="fieldErrors" var="fieldError"> <li><s:property /></li> </s:iterator> </ul> <!-- 使用struts内置标题输出字段,将自动带入出错信息 --> <s:textfield label="姓名:" name="name" /> <br /> <s:textfield label="用户名:" name="username" /> </body> ``` ![https://box.kancloud.cn/d63c34721992d581b49e4562e9c44e2c_814x476.png](https://box.kancloud.cn/d63c34721992d581b49e4562e9c44e2c_814x476.png) 好像,如果出现错误的话,应该再显示add界面,并在add界面显示错误吧。 <hr /> 没错,的确是这样,现在,让我们重构V层。 1. 修改路由 ``` <!-- 保存数据 --> <action name="save" class="com.mengyunzhi.javaee.action.teacher.Save"> <!-- 设置V层,相对于WebContent的绝对路径 --> <result name="success">/jsp/success.jsp</result> <result name="error">/jsp/error.jsp</result> <result name="input">/jsp/teacher/add.jsp</result> </action> ``` 2. 重构add.jsp ``` <form action="save" method="post"> <s:textfield label="姓名:" name="name" /> <br /> <s:textfield label="用户名:" name="username" /> <br /> 性别:<select name="sex"> <option value="0">男</option> <option value="1">女</option> </select> <br /> 邮箱:<input type="text" name="email" /><br /> 密码:<input type="password" name="password" /><br /> <button type="submit">submit</button> </form> ``` 3. 删除jsp/teacher/error.jsp ![https://box.kancloud.cn/d63c34721992d581b49e4562e9c44e2c_814x476.png](https://box.kancloud.cn/d63c34721992d581b49e4562e9c44e2c_814x476.png) 作业:验证其它3个字段;增加udpate的验证。 > 官方文档:[http://127.0.0.1:8081/docs/validation.html](http://127.0.0.1:8081/docs/validation.html), [http://127.0.0.1:8081/docs/validation-annotation.html](http://127.0.0.1:8081/docs/validation-annotation.html)