Struts实例的解析,一个例子就懂了好多~

    xiaoxiao2021-03-25  111

    在前面的一篇文章中,使用的是官方例子,这里对其进行一个分析学习。

    这个例子是基于Struts2的,和Struts1有区别。

    代码的整体结构如下

    先从配置文件入手,struts.xml中

    <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.3//EN" "http://struts.apache.org/dtds/struts-2.3.dtd"> <struts> <constant name="struts.enable.DynamicMethodInvocation" value="false" /> <constant name="struts.devMode" value="true" /> <package name="default" namespace="/" extends="struts-default"> <default-action-ref name="index" /> <global-results> <result name="error">/error.jsp</result> </global-results> <global-exception-mappings> <exception-mapping exception="java.lang.Exception" result="error"/> </global-exception-mappings> <action name="index"> <result type="redirectAction"> <param name="actionName">HelloWorld</param> <param name="namespace">/example</param> </result> </action> </package> <include file="example.xml"/> <!-- Add packages here --> </struts> 有include的xml文件,example.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="example" namespace="/example" extends="default"> <action name="HelloWorld" class="example.HelloWorld"> <result>/example/HelloWorld.jsp</result> </action> <action name="Login_*" method="{1}" class="example.Login"> <result name="input">/example/Login.jsp</result> <result type="redirectAction">Menu</result> </action> <action name="*" class="example.ExampleSupport"> <result>/example/{1}.jsp</result> </action> <!-- Add actions here --> </package> </struts>

    在上面可以看到通配符*,支持通配符

    <action name="Login_*" method="{1}" class="example.Login"> <result name="input">/example/Login.jsp</result> <result type="redirectAction">Menu</result> </action>

    想必:Login_execute, Login_test 等Action名称, 而method="{1}" 中的{1} 应该是 第一个通配符的值, 例如execute, test, 也就是说要执行java 类Login 中的execute,input方法。 实验一下:http://localhost:8080/Struts2Demo/example/Login_execute, 注意namespace 是/example 果然登录界面出现了:

    上面的...required是必然出现的,因为检查为false

    测试一下 http://localhost:8080/Struts2Demo/example/Login_test

    由于没有test方法,所以肯定抛异常,这个异常是自己定义的啦

    <global-results> <result name="error">/error.jsp</result> </global-results> 这里的error.jsp

    <%@ page contentType="text/html;charset=UTF-8" language="java"%> <%@ taglib prefix="s" uri="/struts-tags"%> <html> <head> <title>Simple jsp page</title> </head> <body> <h3>Exception:</h3> <s:property value="exception" /> <h3>Stack trace:</h3> <pre> <s:property value="exceptionStack" /> </pre> </body> </html> 但是,上面的一篇文章中有说ActionForm的,但是在哪里啊,没有找到。

    原来,Struts2中有进步的啦。

    在Struts1 中,是使用ActionForm 来封装从浏览器中来的数据,每个Action 都需要写一个ActionForm,, 用起来虽然比较麻烦,但是比较清晰。 在Struts2中,我们似乎并没有看到类似的概念,只看到在Action中的一些getter和setter方法,例如class Login 中的username,password

    /* * $Id: Login.java 471756 2006-11-06 15:01:43Z husted $ * * 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. */ package example; public class Login extends ExampleSupport { public String execute() throws Exception { if (isInvalid(getUsername())) return INPUT; if (isInvalid(getPassword())) return INPUT; return SUCCESS; } private boolean isInvalid(String value) { return (value == null || value.length() == 0); } private String username; public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } private String password; public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } } 在Login.jsp中,肯定有与其相对应的类似javabean的东西

    <s:form action="Login"> <s:textfield key="username"/> <--- 肯定是和class Login 中的username 绑定 <s:password key="password" /> <--- 肯定是和class Login 中的password 绑定 <s:submit/> </s:form>我们在setUsername和setPassword中,可以加入一些System.out函数,来看一下何时调用。

    在Struts2中, Form 和 Action是混到一起了,Action中可以有实例变量,并且可以被框架自动赋值(当然是通过setter方法),至于通过getter暴露出的属性值,在jsp中可以引用。 既然Action中有实例变量,那就意味着Struts2会为每一个http request 创建一个新的Action实例(Struts1不是这样的),所以你不用担心线程安全问题。

    为什么要混合ActionForm和Action?

    为每个Action开发一个ActionForm确实是一件不那么Happy的事情,需要额外的工作建立一个额外ActionForm的类, 并且这个类只能用在相关的Action上。 Struts2 则把Action和ActionForm合并为一了, 咋一看感觉比较乱,但用起来就会发现,确实是极大的减少了开发量,通过简单的getter/setter就能获取界面上的数据。 虽然在设计上看起来不够优雅和完美,但实用性十足,这就够了。 对于那些追求完美的同学, 我相信struts2 还是能支持ActionForm 的。

    如何做输入验证?

    就是简单的一个xml文件中验证的啦,在Login_validator.xml文件中,

    <!DOCTYPE validators PUBLIC "-//Apache Struts//XWork Validator 1.0.2//EN" "http://struts.apache.org/dtds/xwork-validator-1.0.2.dtd"> <validators> <field name="username"> <field-validator type="requiredstring"> <message key="requiredstring"/> </field-validator> </field> <field name="password"> <field-validator type="requiredstring"> <message key="requiredstring"/> </field-validator> </field> </validators> 1. 有两个field,肯定是验证两个的啦。

    2. 然后,field-validator的type是requiredstring,就是说需要字符串类型的啦,也不想要null

    3. 如果失败,需要message,这里的massage是key=。。。所以,一定是个键值,在resource中有定义的。

    4. 估计也是根据名字来进行统配的。<ActionName>_validator.xml,所以是和Action相配的,需要在同一个package下面。

    HelloWorld.message= Struts is up and running ... requiredstring = ${getText(fieldName)} is required. password = password username = username Missing.message = This feature is under construction. Please try again in the next interation. 上面就是有个requiredstring的键值, ${getText(fieldName)} is required其中,

    fieldName 应该就是当前要验证的filed的名称,例如"username", "password" 而getText() 应该是struts2提供的方法,估计是为了多语言处理的,如果当前的field 是"username" , 那么 getText(“username”) 在这个例子中就是“User Name”.

    错误信息怎么显示?

    验证失败,肯定要在jsp 中输入错误信息,这一点Struts2的tag library已经给我们封装好了, 当然是高度封装:

    <%@ page contentType="text/html; charset=UTF-8" %> <%@ taglib prefix="s" uri="/struts-tags" %> <html> <head> <title>Sign On</title> </head> <body> <s:form action="Login"> <s:textfield key="username"/> <s:password key="password" /> <s:submit/> </s:form> </body> </html> 如果username 或者password没有输入, struts2就会在每一个输入域的上方显示错误消息。 注意 <s:textfield key="username"/> 用的是key = xxx , 你可以试一下 name=xxxx, 就可以发现 其中的奥秘: 使用key =xxx , 最终的html中既有label ,又有input field, 使用name=xxx,只会输出 input filed ,需要自己来写label 了。

    我只能通过xml文件类配置输入验证吗

    当然不是,这个例子中就有的啦。

    重写方法validate。

    观察一下Login这个类, 它最终扩展了ActionSupport ,这个类有很多和验证相关的方法,例如addFieldError (),validate()等等,我们尝试一下在class Login中覆盖validate方法:

    public void validate(){ if(!"andy".equals(getUsername())){ addFieldError("username",getText("user.incorrect")); } if(!"pass4andy".equals(getPassword())){ addFieldError("password",getText("password.incorrect")); } } 当然要记得在package.properties 新添加两个message 

    user.incorrect=User name is not correct

    password.incorrect=Password is not correct

    当然,这里可以去查调用其它的,比如来查数据库的啦。

    后记

    部分参考 http://www.myexception.cn/program/1434295.html

    谢谢

    转载请注明原文地址: https://ju.6miu.com/read-25029.html

    最新回复(0)