Struts2表單驗證、Struts2的國際化-day04

2020-08-12 20:22:24

第一節 Struts2表單驗證

1.1 伺服器端Action驗證的兩種方式

第一種

  • struts2自帶表單欄位的驗證

    • 第一種重寫validate方法,如果數據不對,可以往FieldError新增欄位錯誤資訊
      • 注意:
      • 1.表單一定要用struts的標籤:s:form/s:textfield
      • 2.addFieldError裡的key,是表單的name的值(否則報錯)
      • 3.validate對於Action來說是全域性,也就是對action的所有方法都會攔截驗證
      • 4.在不需要驗證的action方法上,可以宣告一個註解@SkipValidation,忽略校驗
  • UserAction.java

package com.it.web.action;
import com.it.model.User;

import org.apache.commons.lang3.StringUtils;
import org.apache.struts2.interceptor.validation.SkipValidation;

import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.ModelDriven;

public class UserAction extends ActionSupport implements ModelDriven<User> {

	private User user = new User();
	@Override
	public User getModel() {
		return user;
	}
	
	@Override
	public void validate() {
		//判斷使用者名稱是否爲空
		//if(username == null && "".equals(username))
		if(StringUtils.isEmpty(user.getUsername())){
			addFieldError("username", "使用者名稱不能爲空");
		}
		
		//判斷密碼是否爲空
		if(StringUtils.isEmpty(user.getPassword())){
			addFieldError("password", "密碼不能爲空");
		}
	}
	
	public String register(){
	//com.opensymphony.xwork2.validator.validators.RequiredStringValidator
		System.out.println("register方法....");
		System.out.println(user);
		return NONE;
	}

	/**
	 * 返回一個列表
	 * @return
	 */
	//@SkipValidation
	public String list(){
		return "list";
	}
	
}

validate對於Action來說是全域性,也就是action的所有方法都會攔截驗證,執行list測試方法(如果不使用註解@SkipValidation),直接存取list,會報錯,無法存取到userlist.jsp頁面,因爲validate驗證方法全域性性,所有方法都會被它驗證。

  • register.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib uri="/struts-tags" prefix="s"%>
<!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>Insert title here</title>
<s:head></s:head>
</head>
<body>

<hr>
<!-- struts表單的特點
1.action不需要寫專案名,會自動加
2.會給表單裏面的內容放在table中,並加上樣式
3.struts的表單項必須要有name
 -->
Struts的Form標籤<br>
<%-- <s:fielderror></s:fielderror> --%>
<s:form action="/user/register.action">
	<!--  
	requiredLabel:代表必填專案
	requiredPosition:必填*號位置
	showPassword:回顯時,密碼還在
	-->
	<s:textfield name="username" label="使用者名稱" requiredLabel="true" requiredPosition="left"></s:textfield>
	<s:password name="password" label="密碼" showPassword="true"></s:password>
	<s:textfield name="birthday" label="生日"></s:textfield>
	<%-- <s:checkbox name="hobby" label="寫程式碼" value="寫程式碼"></s:checkbox>
	<s:checkbox name="hobby" label="泡妞" value="泡妞"></s:checkbox>
	<s:checkbox name="hobby" label="買房" value="買房"></s:checkbox> --%>
	<!-- list使用的OGNL表達式 -->
	<s:checkboxlist list="#{'寫程式碼':'寫程式碼','泡妞':'泡妞','買房':'買房'}" label="愛好" name="hobby"></s:checkboxlist>
	<s:radio list="#{'true':'已婚','false':'未婚'}" name="married" label="是否已婚"></s:radio>
	<s:submit value="註冊"></s:submit>
</s:form>
</body>
</html>
  • 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.devMode" value="true"></constant>
	
	<!-- 設定參數 -->
	<package name="p1" extends="struts-default">
		<action name="register" class="com.it.web.action.UserAction" method="register">
			<!-- input:回顯,出現錯誤後,顯示哪個介面 -->
			<result name="input">/register.jsp</result>
		</action>
		<action name="list" class="com.it.web.action.UserAction" method="list">
			<result name="list">/userlist.jsp</result>
		</action>
	</package>
	
</struts>

  • userlist.jsp:測試方法,隨便寫一句話
  • 效果
    在这里插入图片描述

第二種

  • 第二種:寫一個方法,格式:validate+方法名(第一個字母大寫【如:validateRegister】

  • 注意:只針對方法有效,它是一個區域性欄位校驗

  • UserAction.java中修改部分程式碼,去掉此方法的@Override,否則報錯,因爲validateRegister不是ActionSupport中的方法

public void validateRegister() {
		//判斷使用者名稱是否爲空
		//if(username == null && "".equals(username))
		if(StringUtils.isEmpty(user.getUsername())){
			addFieldError("username", "使用者名稱不能爲空");
		}
		
		//判斷密碼是否爲空
		if(StringUtils.isEmpty(user.getPassword())){
			addFieldError("password", "密碼不能爲空");
		}
	}

validateRegister只針對方法有效,它是一個區域性欄位校驗,此時不使用註解@SkipValidation,直接存取list,也能存取得到
在这里插入图片描述

1.2 xml宣告式驗證

全域性式宣告方式

  • 在action包中宣告UserAction-validation.xml檔案
  • 這種方式設定是全域性設定,所有action的方法都會攔截驗證
  • 如果其它方法不想驗證,可設定@SkipValidation註解
  • dtd約束可以在xwork-core的jar包中找

xml方式設定的檔名字首要與Action類名一致

在这里插入图片描述

  • UserAction-validation.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE validators PUBLIC
  		"-//Apache Struts//XWork Validator 1.0.3//EN"
  		"http://struts.apache.org/dtds/xwork-validator-1.0.3.dtd">
  		<!--dtd在xwork-core-2.3.33.jar中可以找到-->
<validators>
	<!-- 第一種校驗欄位方式 :field-->
	<field name="username">
		<field-validator type="requiredstring">
			<param name="fieldName">username</param>
			<message>使用者名稱不能爲空-xml</message>
		</field-validator>
	</field>
	
	<!-- 第二種校驗欄位方式 :validator更簡便-->
	<validator type="requiredstring">
		<param name="fieldName">password</param>
		<message>密碼不能爲空-xml</message>
	</validator>
</validators>
  • 效果
    在这里插入图片描述

全域性宣告方式,所有action的方法都會攔截驗證,此時存取list無法存取到
在这里插入图片描述

區域性宣告方式

  • 在action包中宣告UserAction-register-validation.xml檔案
    宣告方式 【Action類名-方法名-validation.xml】
  • xml內容與上面的一樣
    在这里插入图片描述

此時再存取list,可以存取到
因爲此時UserAction-register-validation.xml只驗證它的register方法
在这里插入图片描述

其它

  • struts預設有很多種驗證器型別,宣告在default.xml中
  • 注意default.xml的位置

validators裡有很多struts的預設驗證設定
default.xml的位置:如下圖
在这里插入图片描述

例如:密碼不能大於6位的設定

<validator type="stringlength">
	<param name="fieldName">password</param>
	<param name="maxLength">6</param>
	<message>密碼不能大於6位</message>
</validator>

在这里插入图片描述

1.3 驗證器綜合案例

add.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib uri="/struts-tags" prefix="s"%>
<!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>Insert title here</title>
<s:head></s:head>
</head>
<body>

<hr>
<s:debug></s:debug><%--debug模式,能看到更多的錯誤資訊--%>
新增學生
<s:actionerror/><%--拿到actionError裡的 密碼不一致 資訊--%>
<s:form action="/stu/add.action">
	<s:textfield name="username" label="使用者名稱"/>
	<s:textfield name="age" label="年齡"/>
	<s:textfield name="email" label="郵箱"/>
	<%-- <s:password name="password" label="密碼"/> --%>
	<s:textfield name="password" label="密碼"/>
	<s:textfield name="repassword" label="確認密碼"/>
	<s:textfield name="score" label="成績"/>
	<s:textfield name="url" label="個人主頁"/>
	<s:radio list="{'',''}" name="gender" label="性別"></s:radio>
	<s:submit value="提交"/>	
</s:form>
</body>
</html>

Student.java

package com.it.model;

public class Student {
	private String username;//不能爲空,去空字串
	private int age;//18~100
	private String email;//正確郵箱格式
	private String password;//3~8
	private String repassword;//與密碼一至
	private int score;//必須是自然數
	private String url;//必須是一個路徑 http://
	private String gender;//性別,只有男和女
	public String getUsername() {
		return username;
	}
	public void setUsername(String username) {
		this.username = username;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	public String getEmail() {
		return email;
	}
	public void setEmail(String email) {
		this.email = email;
	}
	public String getPassword() {
		return password;
	}
	public void setPassword(String password) {
		this.password = password;
	}
	public String getRepassword() {
		return repassword;
	}
	public void setRepassword(String repassword) {
		this.repassword = repassword;
	}
	public int getScore() {
		return score;
	}
	public void setScore(int score) {
		this.score = score;
	}
	public String getUrl() {
		return url;
	}
	public void setUrl(String url) {
		this.url = url;
	}
	public String getGender() {
		return gender;
	}
	public void setGender(String gender) {
		this.gender = gender;
	}
	@Override
	public String toString() {
		return "Student [username=" + username + ", age=" + age + ", email=" + email + ", password=" + password
				+ ", repassword=" + repassword + ", score=" + score + ", url=" + url + ", gender=" + gender + "]";
	}
		
}

StudentAction.java

package com.it.web.action;


import com.it.model.Student;
import com.it.model.User;
import com.it.service.IUserService;
import com.it.service.impl.UserServiceImpl;

import org.apache.commons.lang3.StringUtils;
import org.apache.struts2.interceptor.validation.SkipValidation;

import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.ModelDriven;

public class StudentAction extends ActionSupport implements ModelDriven<Student> {
	
	private Student stu = new Student();
	@Override
	public Student getModel() {
		// TODO Auto-generated method stub
		return stu;
	}
	 
	public String add(){
		//com.opensymphony.xwork2.validator.validators.RequiredFieldValidator
		//com.opensymphony.xwork2.validator.validators.RequiredStringValidator
		//com.opensymphony.xwork2.validator.validators.IntRangeFieldValidator
		//com.opensymphony.xwork2.validator.validators.StringLengthFieldValidator
		//com.opensymphony.xwork2.validator.validators.ExpressionValidator
		//com.opensymphony.xwork2.validator.validators.RegexFieldValidator
		System.out.println(stu);
		return NONE;
	}
}

struts.xml

<package name="p2" extends="struts-default" namespace="/stu">
		<action name="add" class="com.it.web.action.StudentAction" method="add">
			<result name="input">/add.jsp</result>
		</action>
</package>

StudentAction-add-validation.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE validators PUBLIC
  		"-//Apache Struts//XWork Validator 1.0.3//EN"
  		"http://struts.apache.org/dtds/xwork-validator-1.0.3.dtd">
<validators>
	<!--
	 1.  private String username;//不能爲空,去空字串
		 requiredstring 比 required 好一點,會自動去除空格
	 -->
	<validator type="requiredstring">
		<param name="fieldName">username</param>
		<message>使用者名稱不能爲空</message>
	</validator>
	
	
	<!--2.private int age;//18~100 
	  1.表單的型別,會根據模型的屬性型別去校驗
	 -->
	 <validator type="int">
	 	<param name="fieldName">age</param>
	 	<param name="min">18</param>
	 	<param name="max">100</param>
	 	<message>年齡必須在18~100</message>
	 </validator>
	
	
	<!-- 3.private String email;//正確郵箱格式-->
	<validator type="requiredstring">
		<param name="fieldName">email</param>
		<message>郵箱不能爲空</message>
	</validator>
	 <validator type="email">
	 	<param name="fieldName">email</param>
	 	<message>郵箱格式不正確【如:[email protected]</message>
	 </validator>
		 
	 
	 <!--4. private String password;//3~8 -->
	 <validator type="requiredstring">
		<param name="fieldName">password</param>
		<message>密碼不能爲空</message>
	</validator>
	<validator type="stringlength">
		<param name="fieldName">password</param>
		<param name="minLength">3</param>
		<param name="maxLength">8</param>
		<message>密碼長度爲3~8</message>
	</validator>
	
	<!-- 5.private String repassword;//與密碼一至 -->
	<validator type="expression">
		<param name="expression">
			<![CDATA[ password == repassword]]>
		</param>
		<message>密碼不一致</message>
	</validator>
	
	<!-- 6.private int score;//必須是自然數
		regex :正則
	 -->
	<validator type="regex">
		<param name="fieldName">score</param>
		<param name="regexExpression">\d+</param>
		<message>分數必須爲數位</message>
	</validator>
	
	
	<!-- 	private String url;//必須是一個路徑 http:// -->
	<validator type="url">
		<param name="fieldName">url</param>
		<message>URL格式不合法,以 http://開頭</message>
	</validator>
	
	<!-- 	private String gender;//性別必填,只有男和女 -->
	<validator type="required">
		<param name="fieldName">gender</param>
		<message>性別必選</message>
	</validator>
</validators>

效果:

在这里插入图片描述

第二節 Struts2的國際化

2.1 什麼是國際化

  • 軟體的國際化:軟件開發時要使它能同時應對世界不同地區和國家的存取,並針對不同地區和國家的存取,提供相應的、符合來訪者閱讀習慣的頁面或數據

2.2 國際化使用的場景

2.3 固定文字的國際化

  • 例如:訊息提示,錯誤提示和選單,導航欄等等固定文字。

第一步:建立一個訊息資源包

  1. 一個資源包由多個檔案組成,這些檔名都有命名規範:主要檔名_語言程式碼_國家程式碼.properties
  2. 語言程式碼和國家程式碼:由iso規定的。
  3. 當檔案只有主要檔名.properties時,表明它是預設資源包。瀏覽器會根據不同的語言環境找對應語言環境的資源包。
  4. 當沒有時,找預設的。
  5. 每個資源包的內容都由相同的key和對應語言環境的value組成。
  6. 例如:
    • message_zh_CN.properties(zh代表語言程式碼中文,CN國家程式碼中國)
    • message_zh_HK.properties(zh中文,HK香港)
    • message_en_US.properties(en英文,US美國)
      在这里插入图片描述

第二步:讀取資源包中的內容

  • Java提供ResourceBundle類可以讀取資源包的國際化組態檔
  • I18NTest.java
package com.it.test;

import java.util.Locale;
import java.util.ResourceBundle;

import org.junit.Test;

public class I18NTest {

	@Test
	public void test1(){
		//讀取國際化資源數據
		//使用ResourceBundle讀取數據
		//baseName=包名+檔名
		//預設讀取是中文
		//ResourceBundle rb = ResourceBundle.getBundle("resources.message");
		
		//指定讀取某個國家國際化數據
		//ResourceBundle rb = ResourceBundle.getBundle("resources.message", Locale.US);
		ResourceBundle rb = ResourceBundle.getBundle("resources.message", Locale.CHINA);
		
		System.out.println(rb.getString("login.username"));
		System.out.println(rb.getString("login.password"));
		System.out.println(rb.getString("login.submit"));
	}
}

  • 測試效果
    在这里插入图片描述

第三步:JSP中使用國際化

  • 本質還是java實現
  • login.jsp
<%@page import="java.util.ResourceBundle"%>
<%@page import="java.util.Locale"%>
<%@ 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>Insert title here</title>
</head>
<body>

<hr>
<%
	Locale local = Locale.getDefault();//獲取到一個預設的國家語言
	ResourceBundle rb = ResourceBundle.getBundle("resources.message", local);<%-- <%=local.US %> --%>
%>
<%=local %><%-- <%=local.US %> --%>
<form action="${pageContext.request.contextPath}/login.action">
	<%=rb.getString("login.username")%><input type="text" name="username"><br>
	<%=rb.getString("login.password")%><input type="password" name="password"><br>
	<input type="submit" value="<%=rb.getString("login.submit")%>">
</form>
</body>
</html>
  • zh_CN預設中文格式
    在这里插入图片描述
  • en_US
    在这里插入图片描述

第四步:使用jstl標籤來國際化

  • JSP標準標籤庫(JSTL)是一個JSP標籤集合,它封裝了JSP應用的通用核心功能。
  • JSTL支援通用的、結構化的任務,比如迭代,條件判斷,XML文件操作,國際化標籤,SQL標籤。
  • 除了這些,它還提供了一個框架來使用整合JSTL的自定義標籤。
  1. 首先需要在專案中匯入兩個jar包
    在这里插入图片描述
  2. Jsp中程式碼截圖如下
    在这里插入图片描述

2.4 Struts提供的國際化

  • 前面的國際化與struts無關

第一步:設定資源包

  1. 設定全域性的資源包
  • 在struts.xml中設定
	<!-- 開發模式 -->
	<constant name="struts.devMode" value="true"></constant>
	
	<!-- 設定全域性的國際化 -->
	<constant name="struts.custom.i18n.resources" value="resources.message"/>
	
  • 程式碼同上
    在这里插入图片描述
    在这里插入图片描述

  • login2.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib uri="/struts-tags" prefix="s"%>
<!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>Insert title here</title>
</head>
<body>

<hr>
<form action="${pageContext.request.contextPath}/login.action">
		<s:text name="login.username"/> <input type="text" name="username"><br>
		<s:text name="login.password"/><input type="password" name="password"><br>
		<input type="submit" value="<s:text name="login.submit"/>">
</form>
</body>
</html>
  • 效果:
    在这里插入图片描述
  • 在IE瀏覽器設定語言偏好設定後重新整理瀏覽器
    在这里插入图片描述
  1. 設定包範圍的資源包
  • 資源包名稱命名規範:package_語言程式碼_國家程式碼.properties(固定的)。以此種命名方式的資源包能被該包及其子包中的動作類存取。

  • 優先順序:高於全域性訊息資源包
    在这里插入图片描述
    在这里插入图片描述

  • 寫一個UserAction.java

package com.it.web.action;

import com.opensymphony.xwork2.ActionSupport;

public class UserAction extends ActionSupport{

	public String login(){
		//com.opensymphony.xwork2.interceptor.ModelDrivenInterceptor
		//讀取資源包數據-讀取資源順序【區域性-包級別-全域性】
		System.out.println(getText("login.username"));
		System.out.println(getText("login.password"));
		System.out.println(getText("login.submit"));
		return NONE;
	}
}
  • 在struts.xml中設定
	<!-- 開發模式 -->
	<constant name="struts.devMode" value="true"></constant>
	
	<!-- 設定全域性的國際化 -->
	<constant name="struts.custom.i18n.resources" value="resources.message"/>
	
	<package name="p1" extends="struts-default">
		<action name="login" class="com.it.web.action.UserAction" method="login">	
		</action>
	</package>
  • 存取路徑:http://localhost:8080/day04_struts2_demo3/login
  • 效果:
    在这里插入图片描述
  1. 區域性訊息資源包
  • 資源包名稱命名規範:動作類名稱_語言程式碼_國家程式碼.properties。以此種命名方式的資源包,只爲動作類服務。
  • 優先順序最高(就近原則)
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
  1. Struts2中資源包的搜尋順序:
    在这里插入图片描述

第二步:讀取資源包內容

  1. jsp讀取資源包內容
  • 使用struts的標籤s:text獲取國際化內容,上面的jsp程式碼中已使用
    在这里插入图片描述
  1. Action讀取資源包內容
  • 使用ActionSupport的getText方法,可以讀取到資源包的內容
  • 也就是說這個Action一定要繼承ActionSupport
  • 這種在實際開發中幾乎不用
    在这里插入图片描述
  1. 自由指定讀取資源包
  • 在jsp頁面可以使用s:i18n標籤指向讀取的國際資源包檔案
    在这里插入图片描述
  • 修改後的login2.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib uri="/struts-tags" prefix="s"%>
<!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>Insert title here</title>
</head>
<body>
<hr>
<form action="${pageContext.request.contextPath}/login.action">
	<s:i18n name="com.it.web.package">
		<s:text name="login.username"/> <input type="text" name="username"><br>
		<s:text name="login.password"/><input type="password" name="password"><br>
		<input type="submit" value="<s:text name="login.submit"/>">
	</s:i18n>
</form>
</body>
</html>
  • 效果:指定存取包範圍內資源檔案
    在这里插入图片描述