刷新驗證
struts2的驗證功能主要是使用ActionSupport類,實現了了以下接口:Action(提供execute()方法), Validateable(驗證), ValidationAware(返回出錯方法), TextProvider(讀取屬性文件), LocaleProvider(讀取國際化資源), Serializable。對於Struts驗證功能有兩種方式手工編寫代碼和基於XML配置方式實現,本文先研究手工編寫方式。
一、手工編寫代碼實現對action中所有與execute()簽名相同方法輸入校驗
1、對Action繼承ActionSupport並覆寫方法validate(),校驗其用戶名稱不能爲空,代碼如下:
package com.struts.service;
import com.opensymphony.xwork2.Action;
import com.opensymphony.xwork2.ActionSupport;
import com.struts.controller.Login;
@SuppressWarnings("serial")
public class LoginService extends ActionSupport{
private Login login;
public Login getLogin() {
return login;
}
public void setLogin(Login login) {
this.login = login;
}
/**
* 對前臺傳遞的數值進行校驗
*/
@Override
public void validate(){
if(this.login.getUsername() == null ||"".equals(login.getUsername())){
this.addFieldError("login.username", "用戶名不能爲空!");
}
}
public String execute(){
if(login!=null){
System.out.println(login.getUsername());
System.out.println(login.getPassword());
System.out.println(login.getBirthday());
}
return Action.SUCCESS;
}
}
2、創建jsp頁面:
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@taglib prefix="s" uri="/struts-tags" %>
<!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>
<!-- 使用debug標籤可以調試 -->
<s:debug></s:debug><br/>
<!-- 使用struts的標籤 可以封裝到實體bean中 -->
<form action="login.action" method="post">
<s:textfield name="login.username" label="用戶名"></s:textfield><br/>
<s:password name="login.password" label="密碼"></s:password><br/>
<s:textfield name="login.birthday" label="出生日期"></s:textfield><br/>
<s:submit value="登錄"/>
</form>
</body>
</html>
3、當點擊”登錄“時,如果沒有進行刷新驗證,則需要在struts配置文件中配置名爲input的result標籤,配置文件如下:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration2.3//EN" "http://struts.apache.org/dtds/struts-2.3.dtd">
<struts>
<!-- 開發者模式 -->
<constant name="struts.devMode" value="true"/>
<!-- 登錄所實現的包 -->
<package name="login" namespace="/" extends="struts-default">
<interceptors>
<!--自定義攔截器 -->
<interceptor name="myInterceptor" class="com.struts.interceptor.MyInterceptor"/>
<interceptor-stack name="myInterceptorStack">
<interceptor-ref name="myInterceptor"/>
<interceptor-ref name="defaultStack"/>
</interceptor-stack>
</interceptors>
<!-- 配置默認的攔截器棧,這樣包下的action都會經過此攔截器,不需要每個action都配置-->
<default-interceptor-ref name="myInterceptorStack"/>
<action name="login" class="com.struts.service.LoginService">
<result name="success">/ok.jsp</result>
<result name="input">/login.jsp</result>
<!-- <interceptor-ref name="myInterceptor"/>自定義的攔截器,沒有下面配置的defaultStack則前臺頁面的屬性不會自動封裝導致傳遞值內容爲空
<interceptor-ref name="defaultStack"/>默認的攔截器棧 -->
</action>
</package>
</struts>
4、當按照上述配置完成後,如果沒有輸入用戶名,則在頁面上提示顯示如下:
常量的使用
1、使用struts常量:<constant name="struts.ui.theme" value="simple"/>,避免struts2標籤的冗餘。但是會造成<s:textfield/>中的label顯示出來,因此,修改jsp頁面顯示如下:
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@taglib prefix="s" uri="/struts-tags" %>
<!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>
<!-- 使用debug標籤可以調試 -->
<s:debug></s:debug><br/>
<form action="login.action" method="post">
用戶名:<s:textfield name="login.username"></s:textfield><br/>
密碼:<s:password name="login.password"></s:password><br/>
出生日期:<s:textfield name="login.birthday"></s:textfield><br/>
<s:submit value="登錄"/>
</form>
</body>
</html>
2、使用常量後,用戶名爲空後頁面上不再提示錯誤信息,但是根據debug信息,可以發現錯誤信息
因此,我們可以使用EL表達式來獲取錯誤信息。此外在頁面上還要解開對EL表達式的限制:<%@page isELIgnored="false" %>
EL表達式爲:${errors.login.username[0]},但是發現使用EL表達式後頁面上並沒有出現錯誤信息,但是在Debug中發現存在值。有以下兩種解決辦法:
①在LoginService的類中調用addFieldError時傳入的key值中不能帶”.“,譬如說this.addFieldError("username", "用戶名不能爲空!");則在頁面上使用${errors.username[0]}來進行提示。
②使用<s:fielderror fieldName="login.username"/>標籤,但是發現樣式亂掉了,使用firefox的fiebug顯示,發現在使用此標籤時,struts2默認增加了ul等標籤。簡單的一種方法是爲此增加樣式:
<style type="text/css">
ul.errorMessage {color: #FF3300;}
ul.errorMessage {list-style-type: none;display: inline;margin: 0px;padding: 3px;}
ul.errorMessage li {list-style-type: none;display: inline;}
</style>
另外,對於<s:fielderror>標籤中的theme的應用不太熟悉,如果有了解的朋友則指教一番,在此先謝謝了。
二、手工編寫代碼實現對action中指定方法輸入校驗
對action中指定方法輸入校驗:通過validateXxxx()方法進行實現。validateXxxx()方法只會校驗方法名爲Xxxxx的方法,
1、在LoginService中添加login方法和validateLogin方法:
package com.struts.service;
import com.opensymphony.xwork2.Action;
import com.opensymphony.xwork2.ActionSupport;
import com.struts.controller.Login;
@SuppressWarnings("serial")
public class LoginService extends ActionSupport{
private Login login;
public Login getLogin() {
return login;
}
public void setLogin(Login login) {
this.login = login;
}
/**
* 對前臺傳遞的數值進行校驗
*/
@Override
public void validate(){
if(this.login.getUsername() == null ||"".equals(login.getUsername())){
this.addFieldError("username", "用戶名不能爲空!");
}
}
//對指定方法進行校驗
public void validateLogin(){
if(this.login.getUsername() == null ||"".equals(login.getUsername())){
this.addFieldError("username", "特定方法校驗:用戶名不能爲空!");
}
}
public String execute(){
if(login!=null){
System.out.println(login.getUsername());
System.out.println(login.getPassword());
System.out.println(login.getBirthday());
}
return Action.SUCCESS;
}
public String login(){
return Action.SUCCESS;
}
}
2、編寫配置文件,當登錄時調用login()方法,配置文件如下:<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration2.3//EN" "http://struts.apache.org/dtds/struts-2.3.dtd">
<struts>
<!-- 開發者模式 -->
<constant name="struts.devMode" value="true"/>
<!-- 主題模式爲simple,避免使用struts標籤造成標籤冗餘 -->
<constant name="struts.ui.theme" value="simple"/>
<!-- 登錄所實現的包 -->
<package name="login" namespace="/" extends="struts-default">
<interceptors>
<!--自定義攔截器 -->
<interceptor name="myInterceptor" class="com.struts.interceptor.MyInterceptor"/>
<interceptor-stack name="myInterceptorStack">
<interceptor-ref name="myInterceptor"/>
<interceptor-ref name="defaultStack"/>
</interceptor-stack>
</interceptors>
<!-- 配置默認的攔截器棧,這樣包下的action都會經過此攔截器,不需要每個action都配置-->
<default-interceptor-ref name="myInterceptorStack"/>
<action name="login" class="com.struts.service.LoginService" method="login">
<result name="success">/ok.jsp</result>
<result name="input">/login.jsp</result>
<!-- <interceptor-ref name="myInterceptor"/>自定義的攔截器,沒有下面配置的defaultStack則前臺頁面的屬性不會自動封裝導致傳遞值內容爲空
<interceptor-ref name="defaultStack"/>默認的攔截器棧 -->
</action>
</package>
</struts>
如上配置後,頁面正確出現錯誤信息。輸入校驗流程
在上述兩種輸入校驗中,我們發現,在對特定方法校驗時,validate()方法不起作用了。其實,validate()方法也起作用了,在debug中發現,errors中有兩個值:
因此,我們可以看到輸入校驗的流程爲:
首先,類型轉換器進行類型轉換,並將轉換後的值給action中的屬性賦值,如果在執行轉換過程中出現異常,則會將異常信息添加到fieldErrors中,接下來,通過反射技術調用action中 validateXxxx()方法,如果有錯誤則存放到fieldErrors中,然後調用validate()方法,出現錯誤則存放在fieldErrors中。最後,如果fieldErrors中出現錯誤,則系統自動轉發請求至input的視圖中。