然后在网页" />

Action 1 理解Struts

系统 1656 0

在摸索中渐渐找到了属于自己的学习方式 learn ** in action 而且喜欢上了in action 系列的书

我的记性实在不是很好 但是我知道自己擅长的是归纳和总结 加上我是完美主义者 所以到现在很多问题我都从根源上理解和解决了 所以in action 的学习方法是最适合我的

Struts的核心是MVC的控制层 它将模式和视图连接起来 可以用来定义超链 表单和用户动作组件

超链可以这样

< forward name ="welcome"
path
="pages/index.jsp" />
然后在网页里
<% @tagliburi = " /tags/struts-logic " prefix = " logic " %>

< logic:redirectforward = " welcome " />

也可以

< global-forwards >
....
< forward
name ="welcome"
path
="/welcome.do" />
</ global-forwards >

< action-mappings >
< action
path ="/welcome"
type
="org.apache.struts.actions.ForwardAction"
parameter
="/pages/welcome.jsp" />
......
</ action-mappings >

通过实现的ActionForm来处理表单数据和完成验证的工作

定位和实例化ActionForm

< form-beans >
< form-bean name ="logonForm" type ="ergal.LogonForm" />
</ form-beans >

在html表单中的action 指向一个Action 用这个Action来处理数据 Struts会 自动把其看作form来处理

看例子

< struts-config >

<!-- ========================================FormBeanDefinitions -->
< form-beans >
< form-bean name ="logonForm" type ="ergal.LogonForm" />
</ form-beans >


<!-- ===================================GlobalForwardDefinitions -->
......

<!-- ===================================ActionMappingDefinitions -->
< action-mappings >
......

< action
path ="/logonSubmit"
type
="ergal.LogonAction"
name
="logonForm"
scope
="request"
validate
="true"
input
="/pages/logon.jsp" >
< forward
name ="success"
path
="/pages/welcome.jsp" />
</ action >

</ action-mappings >

</ struts-config >

html的表单交出以后 根据action属性转向一个url来处理 在这里就是LogonSubmit 它通过LogonAction来处理数据

强制把其数据作为了Form的字段数据 就像Hibernate持久化了一个POJO一样 然后通过一定的逻辑来进行验证from和想要的数据是否符合 从而实现了验证

例子

文件目录树

webtest
| |-- index.jsp
|
| |-- META-INF
| | |-- MANIFEST.MF
| |
| |-- pages
| | |-- logon.jsp
| | |-- struts-power.gif
| | |-- velocity-power.gif
| | |-- welcome.jsp
| |
| |-- WEB-INF
| | |-- struts-bean.tld
| | |-- struts-config.xml
| | |-- struts-html.tld
| | |-- struts-logic.tld
| | |-- struts-nested.tld
| | |-- struts-tiles.tld
| | |-- tiles-defs.xml
| | |-- validation.xml
| | |-- validator-rules.xml
| | |-- web.xml
| |
| | |classes
| | |
| | | |-- ergal
| | | | |-- Constants.class
| | | | |-- LogoffAction.class
| | | | |-- LogonAction.class
| | | | |-- LogonForm.class
| | | | |-- UserDirectory.class
| | | | |-- UserDirectoryException.class
| | | |
| | | |-- resources
| | | | |-- application.properties
| | | | |-- users.properties
| | |-- lib
......
| | |
| | |--src
| | | |-- build.xml
| | |
| | | |-- java
| | | |
| | | | |-- ergal
| | | | | |-- Constants.java
| | | | | |-- LogoffAction.java
| | | | | |-- LogonAction.java
| | | | | |-- LogonForm.java
| | | | | |-- UserDirectory.java
| | | | | |-- UserDirectoryException.java
| | | | |
| | | |-- resources
| | | | |-- application.properties
| | | | |-- users.properties

核心部分

index.jsp

<% @tagliburi = " /tags/struts-logic " prefix = " logic " %>

< logic:redirectforward = " welcome " />

直接转向welcome.jsp

welcome.jsp

<% ... @tagliburi = " /tags/struts-bean " prefix = " bean " %>
<% ... @tagliburi = " /tags/struts-html " prefix = " html " %>
<% ... @tagliburi = " /tags/struts-logic " prefix = " logic " %>

< html >
< head >
< title > Welcome! </ title >
< html:base />
</ head >

< body >
< logic:present name ="user" >
< h3 > Welcome < bean:write name ="user" property ="username" /></ h3 >
</ logic:present >

< logic:notPresent scope ="session" name ="user" >
< h3 > Welcomeworld! </ h3 >
</ logic:notPresent >

< html:errors />

< UL >
< LI >< html:link forward ="logon" > Signin </ html:link ></ LI >
< logic:present name ="user" >
< LI >< html:link forward ="logoff" > Signout </ html:link ></ LI >
</ logic:present >
</ UL >
< img src ="struts-power.gif" alt ="Poweredbystruts" >
</ body >
</ html >

这里用了taglib 里面是个逻辑引用 定义在web.xml中

这里还用了present和notPresent 用来判别制定对象是否存在来决定是否处理内容

logon.jsp

<% ... @tagliburi = " /tags/struts-html " prefix = " html " %>

< html >
< head >
< title > SigninPlease! </ title >
</ head >

< body >
< html:errors />
< html:form action ="logonSubmit" focus ="username" >
< table border ="0" width ="100%" >
< tr >
< th align ="right" > Username: </ th >
< td align ="left" >< html:text property ="username" /></ td >
</ tr >
< tr >
< th align ="right" > Password: </ th >
< td align ="left" >< html:password property ="password" /></ td >
</ tr >
< tr >
< td align ="right" >< html:submit /></ td >
< td align ="left" >< html:reset /></ td >
</ tr >
</ table >
</ html:form >
</ body >
</ html >

这里的action指向了logonSumit

现在来看struts-config.xml

<? xmlversion="1.0"encoding="ISO-8859-1" ?>

<! DOCTYPEstruts-configPUBLIC
"-//ApacheSoftwareFoundation//DTDStrutsConfiguration1.2//EN"
"http://jakarta.apache.org/struts/dtds/struts-config_1_2.dtd"
>



< struts-config >

<!-- ========================================FormBeanDefinitions -->
< form-beans >
< form-bean name ="logonForm" type ="ergal.LogonForm" />
</ form-beans >


<!-- ===================================GlobalForwardDefinitions -->
< global-forwards >
< forward
name ="logoff"
path
="/logoff.do" />
< forward
name ="logon"
path
="/logon.do" />
< forward
name ="welcome"
path
="/welcome.do" />
</ global-forwards >


<!-- ===================================ActionMappingDefinitions -->
< action-mappings >
< action
path ="/welcome"
type
="org.apache.struts.actions.ForwardAction"
parameter
="/pages/welcome.jsp" />

< action
path ="/logon"
type
="org.apache.struts.actions.ForwardAction"
parameter
="/pages/logon.jsp" />

< action
path ="/logonSubmit"
type
="ergal.LogonAction"
name
="logonForm"
scope
="request"
validate
="true"
input
="/pages/logon.jsp" >
< forward
name ="success"
path
="/pages/welcome.jsp" />
</ action >

< action
path ="/logoff"
type
="ergal.LogoffAction" >
< forward
name ="success"
path
="/pages/welcome.jsp" />
</ action >
</ action-mappings >

</ struts-config >

先是给一个ActionForm命名 并制定类 然后定义全局可用的forwards 都赋予一个逻辑地址

然后action-mapping

<action
path="/logonSubmit"
type="ergal.LogonAction"
name="logonForm"
scope="request"
validate="true"
input="/pages/logon.jsp">
<forward
name="success"
path="/pages/welcome.jsp"/>
</action>

制定了actionForm和来源地址

Form很简单 就像一个POJO

LogonForm.java

package ergal;

import javax.servlet.http. * ;
import org.apache.struts.action. * ;

public class LogonForm extends ActionForm
... {
private Stringusername;
private Stringpassword;

public void setUsername(Stringusername)
... {
this .username = username;
}

public StringgetUsername()
... {
return this .username;
}


public void setPassword(Stringpassword)
... {
this .password = password;
}

public StringgetPassword()
... {
return this .password;
}


public void reset(ActionMappingmapping,HttpServletRequestrequest)
... {
setPassword(
null );
setUsername(
null );
}


public ActionErrorsvalidate(ActionMappingmapping,HttpServletRequestrequest)
... {

ActionErrorserrors
= new ActionErrors();

if ((username == null ) || (username.length() < 1 ))
errors.add(
" username " ,
new ActionError( " error.username.required " ));

if ((password == null ) || (password.length() < 1 ))
errors.add(
" password " ,
new ActionError( " error.password.required " ));

return errors;

}

}

ActionForm有个基本效验方法

ActionErrors validate ( ActionMapping mapping, javax.servlet.ServletRequestrequest)

可以重写这个方法 定制 主要用来检验域是否都输入了数据

验证Action

LogonAction.java

package ergal;

import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpServletResponse;
import org.apache.struts.action.Action;
import org.apache.struts.action.ActionError;
import org.apache.struts.action.ActionErrors;
import org.apache.struts.action.ActionMessage;
import org.apache.struts.action.ActionMessages;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;
import org.apache.struts.action.ActionServlet;


public final class LogonAction extends Action
... {
public boolean isUserLogon(Stringusername,Stringpassword) throws UserDirectoryException
... {
return UserDirectory.getInstance().isValidPassword(username,password);
}


public ActionForwardexecute(ActionMappingmapping,ActionFormform,
HttpServletRequestrequest,
HttpServletResponseresponse)
throws IOException,ServletException
... {
Stringusername
= ((LogonForm)form).getUsername();
Stringpassword
= ((LogonForm)form).getPassword();

boolean validated = false ;
try
... {
validated
= isUserLogon(username,password);
}

catch (UserDirectoryExceptione)
... {
ActionMessageserrors
= new ActionMessages();
errors.add(ActionErrors.GLOBAL_ERROR,
new ActionError( " error.logon.invalid " ));
saveErrors(request,errors);
return mapping.getInputForward();
}


if ( ! validated)
... {
ActionMessageserrors
= new ActionMessages();
errors.add(ActionErrors.GLOBAL_ERROR,
new ActionError( " error.logon.invalid " ));
saveErrors(request,errors);
return mapping.getInputForward();
}


HttpSessionsession
= request.getSession();
session.setAttribute(Constants.USER_KEY,form);



StringBuffermessage
= new StringBuffer( " LogonAction:User' " );
message.append(username);
message.append(
" 'loggedoninsession " );
message.append(session.getId());
servlet.log(message.toString());


return (mapping.findForward(Constants.SUCCESS));

}

}

这里引用了另一个定制的一个验证数据的UserDirectory

UserDirectory.java

package ergal;

import java.io. * ;
import java.util. * ;

public class UserDirectory
... {
private static final StringUserDirectoryFile = " resources/users.properties " ;
private static final StringUserDirectoryHeader = " ${user}=${password} " ;

private static UserDirectoryuserDirectory = null ;

private static Propertiesp;

private UserDirectory() throws UserDirectoryException
... {

java.io.InputStreami
= null ;
p
= null ;
i
= this .getClass().getClassLoader().getResourceAsStream(UserDirectoryFile);


if ( null == i)
... {
throw new UserDirectoryException();
}


else
... {

try
... {
p
= new Properties();
p.load(i);
i.close();
}

catch (java.io.IOExceptione)
... {
p
= null ;
System.out.println(e.getMessage());
throw new UserDirectoryException();
}

finally
... {
i
= null ;
}

}

}


public static UserDirectorygetInstance() throws UserDirectoryException
... {

if ( null == userDirectory)
... {

userDirectory
= new UserDirectory();

}


return userDirectory;

}


public StringfixId(StringuserId)
... {
return userId.toUpperCase();
}


public boolean isValidPassword(StringuserId,Stringpassword)
... {

if ( null == password) return false ;

String_userId
= fixId(userId);

if ( ! isUserExist(_userId)) return false ;

return (password.equals(getPassword(_userId)));

}


public boolean isUserExist(StringuserId)
... {

if ( null == userId) return false ;


return ! ( null == p.getProperty(userId));

}




public StringgetPassword(StringuserId)
... {
return p.getProperty(userId);
}




public EnumerationgetUserIds()
... {
return p.propertyNames();
}




public void setUser(StringuserId,Stringpassword) throws UserDirectoryException
... {

// nonulls
if (( null == userId) || ( null == password))
... {
throw new UserDirectoryException();
}



try
... {

p.put(fixId(userId),password);
p.store(
new FileOutputStream(UserDirectoryFile),
UserDirectoryHeader);

}


catch (IOExceptione)
... {

throw new UserDirectoryException();

}

}


}

这里用了class的getClassLoder()方法 和ClassLoader的getResourceAsStream()方法

ClassLoader getClassLoader ()
返回该类的类加载器。
InputStream getResourceAsStream ( String name)
返回读取指定资源的输入流。

最后返回的是一个InpuStream

java.util
类 Properties

    
      java.lang.Object
    
    继承者 
    
      java.util.Dictionary
    
    <K,V>
      
    继承者 
    
      java.util.Hashtable
    
    <
    
      Object
    
    ,
    
      Object
    
    >
          
    继承者 
    
      java.util.Properties
    
  
所有已实现的接口:
Serializable , Cloneable , Map < Object , Object >
直接已知子类:
Provider

      public class 
      
        Properties
      
    
extends Hashtable < Object , Object >
  

Properties 类表示了一个持久的属性集。 Properties 可保存在流中或从流中加载。属性列表中每个键及其对应值都是一个字符串。

一个属性列表可包含另一个属性列表作为它的“默认值”;如果未能在原有的属性列表中搜索到属性键,则搜索第二个属性列表。

因为 Properties 继承于 Hashtable ,所以可对 Properties 对象应用 put putAll 方法。但强烈反对使用这两个方法,因为它们允许调用方插入其键或值不是 Strings 的项。相反,应该使用 setProperty 方法。如果在“有危险”的 Properties 对象(即包含非 String 的键或值)上调用 store save 方法,则该调用将失败。

load store 方法按下面所指定的、简单的面向行的格式加载和存储属性。此格式使用 ISO 8859-1 字符编码。可以使用 Unicode 转义符 来编写此编码中无法直接表示的字符;转义序列中只允许单个 'u' 字符。可使用 native2ascii 工具对属性文件和其他字符编码进行相互转换。

loadFromXML(InputStream) storeToXML(OutputStream, String, String) 方法按简单的 XML 格式加载和存储属性。默认使用 UTF-8 字符编码,但如果需要,可以指定某种特定的编码。XML 属性文档具有以下 DOCTYPE 声明:

     <!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
 
  

注意,导入或导出属性时 访问系统 URI (http://java.sun.com/dtd/properties.dtd);该系统 URI 仅作为一个惟一标识 DTD 的字符串:

        <?xml version="1.0" encoding="UTF-8"?>

    <!-- DTD for properties -->

    <!ELEMENT properties ( comment?, entry* ) >

    <!ATTLIST properties version CDATA #FIXED "1.0">

    <!ELEMENT comment (#PCDATA) >

    <!ELEMENT entry (#PCDATA) >

    <!ATTLIST entry key CDATA #REQUIRED>
 重要的方法
  
  
String getProperty ( String key)
用指定的键在此属性列表中搜索属性。
String getProperty ( String key, String defaultValue)
用指定的键在属性列表中搜索属性。
  
void load ( InputStream inStream)
从输入流中读取属性列表(键和元素对)。
  
void store ( OutputStream out, String comments)
以适合使用 load 方法加载到 Properties 表中的格式,将此 Properties 表中的属性列表(键和元素对)写入输出流。

Enumeration <?> propertyNames ()
返回属性列表中所有键的枚举,如果在主属性列表中未找到同名的键,则包括默认属性列表中不同的键。

这里用到了load方法从InputStream中加载流 然后用getProperty()方法

该类展示了如何从property文件中读取 键值 并和传值进行比较

Action 1 理解Struts


更多文章、技术交流、商务合作、联系博主

微信扫码或搜索:z360901061

微信扫一扫加我为好友

QQ号联系: 360901061

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描下面二维码支持博主2元、5元、10元、20元等您想捐的金额吧,狠狠点击下面给点支持吧,站长非常感激您!手机微信长按不能支付解决办法:请将微信支付二维码保存到相册,切换到微信,然后点击微信右上角扫一扫功能,选择支付二维码完成支付。

【本文对您有帮助就好】

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描上面二维码支持博主2元、5元、10元、自定义金额等您想捐的金额吧,站长会非常 感谢您的哦!!!

发表我的评论
最新评论 总共0条评论