在摸索中渐渐找到了属于自己的学习方式 learn ** in action 而且喜欢上了in action 系列的书
我的记性实在不是很好 但是我知道自己擅长的是归纳和总结 加上我是完美主义者 所以到现在很多问题我都从根源上理解和解决了 所以in action 的学习方法是最适合我的
Struts的核心是MVC的控制层 它将模式和视图连接起来 可以用来定义超链 表单和用户动作组件
超链可以这样
path ="pages/index.jsp" />
< logic:redirectforward = " welcome " />
也可以
....
< 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-bean name ="logonForm" type ="ergal.LogonForm" />
</ form-beans >
在html表单中的action 指向一个Action 用这个Action来处理数据 Struts会 自动把其看作form来处理
看例子
<!-- ========================================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
< logic:redirectforward = " welcome " />
直接转向welcome.jsp
welcome.jsp
<% @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
< 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
<! 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
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
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
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
public class Properties
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文件中读取 键值 并和传值进行比较