Struts 2 – Validation

การ Validate หรือการตรวจสอบค่า Input มีสองวิธีคือ Client side validation หรือที่เรียกติดปากว่าตรวจสอบจากหน้าบ้าน เช่นค่านี้ห้ามว่าง ต้องเป็นตัวเลขเท่านั้น ต้องเป็นจำนวนเต็มห้ามติดลบ กับ Server side validation คือการตรวจสอบในเชิง Business Logic เช่นมีอีเมล์นี้ในระบบหรือยัง หรือเป็นผู้ใช้ที่เข้าสู่ระบบแล้วมีสถานะเป็น Inactive ห้ามเข้าใช้งาน เป็นต้น

ตัว Struts 2 ได้เตรียม validation framework ไว้ทั้ง Client side และ Server side พร้อมให้ใช้งานเช่นกัน

Client side validation


  1. สร้าง xml ชื่อ RegisterAction-validation.xml แล้ววางไว้ที่ตำแหน่งเดียวกันกับคลาส RegisterAction
    RegisterAction-validation 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="email">
            <field-validator type="requiredstring">
                <message>Email is required!</message>
            </field-validator>
        </field>
        <field name="password">
            <field-validator type="requiredstring">
                <message>Password is required!</message>
            </field-validator>
        </field>
    </validators>
    

    เป็นการบอก Struts ให้ทำการ validate ค่าตัวแปรทั้งสองค่านี้ว่าห้ามว่าง หากว่างให้ทำการแสดงข้อความตามที่กำหนด

  2. ที่หน้า input.jsp ในส่วนของ tag form ให้เพิ่มคำสั่ง validate="true" เพื่อสั่งให้ struts ทำการ validate form นี้แบบ Client side
  3. ทำการ Start Server แล้วเปิดหน้า home และคลิกลิงก์ไปหน้า Register
    เมื่อทำการกดปุ่ม Submit ก็จะปรากฏข้อความ Error ตามที่กำหนดไว้ใน validator.xml
    struts2 client validation

สิ่งที่เกิดขึ้น หากทำการ view source ดูจะพบว่า มี javascript ที่ถูก generate ขึ้นมาเพื่อทำการ validate form ให้เรา ที่เป็นเช่นนี้เพราะคำสั่ง validate="true" ใน form tag นั่นเอง

Server side validation


หากท่านเป็นผู้มีประสบการณ์ในการพัฒนาเว็บซักระยะหนึ่งจะรู้ว่า เราไม่ควรไว้ใจการ validate form ด้วย javascript เนื่องจากอาจจะโดนผู้ไม่ประสงค์ดีทำการ disable javascript ไว้ ทำให้สามารถข้ามการ validate ได้ เราจึงต้องทำการ validate ค่าของ form ให้เป็นแบบ Server side ด้วย

  1. ที่คลาส RegisterAction ให้ทำการเพิ่ม method input ดังนี้
    @Override
    public void validate() {
    	if (StringUtils.isEmpty(email)){
    		addFieldError("email", "Email is required");
    	}
    	if(StringUtils.isEmpty(password)){
    		addFieldError("password", "Password is required");
    	}
    
    	//Simulate: validate exist email
    	if(!hasErrors()){
    		if(email.trim().equalsIgnoreCase("admin@localhost")){
    			addActionError("Already register email: " + email);
    		}
    	}
    }
    

    เนื่องจากผมต้องต้องการ validate ค่า input ห้ามว่างซะก่อนจึงไป validate ว่ามีอีเมล์นี้อยู่ในระบบหรือยัง โดยใช้คำสั่ง hasErrors แล้วผมทำการกำหนดค่า email ไว้ว่าหากเป็น admin@localhost ให้ทำการแสดง error ว่ามีในระบบแล้ว เพื่อให้โค้ดดูง่าย ผมจึงไม่ทำการเชื่อมต่อกับฐานข้อมูลจริงๆ

  2. แก้ไขหน้า jsp โดยเพิ่มคำสั่งนี้ก่อน form tag

    <s:if test="hasActionErrors()">
       <div class="errors">
          <s:actionerror/>
       </div>
    </s:if>
    

    เนื่องจากเป็นข้อความ error ที่ส่งมาจาก Action เก็บไว้ใน actionError จึงต้องใช้ tag นี้ในการแสดงข้อความ error นั้นออกมา โดยทำการตรวจสอบว่ามีข้อความ error ก่อนจะแสดงผลด้วย

  3. Start Server แล้วเปิดเข้ามาหน้า Register แล้วกรอกค่าที่กำหนดไว้เพื่อให้เข้ากรณีมีอีเมล์นี้ในระบบอยู่แล้ว ก็จะพบข้อความดังภาพ
    struts2 validate server side
  4. กรอกค่าอีเมล์อื่นๆ ก็จะสามารถผ่าน register ได้
    struts2 pass server side validate

ของแถมส่งท้าย


เนื่องจากข้อความ error ที่แสดงนั้นไม่เด่นพอ เราจึงต้องใช้ css เข้ามาช่วย ทาง Struts ก็ได้เตรียม css สำเร็จรูปมาให้ใช้เหมือนกัน โดยเพิ่ม tag
<s:head />

ไปไว้ในหน้า input ก่อน tag
เมื่อรันหน้า register ก็จะพบข้อความ error ที่สวยงามมากขึ้น

struts2 css form validation message

Code


input.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>Home</title>
    <s:head />
</head>
<body>
<s:if test="hasActionErrors()">
    <div class="errors">
        <s:actionerror/>
    </div>
</s:if>
<s:form action="_register" validate="true">
    <s:textfield name="email" label="E-mail"/>
    <s:password name="password" label="Password"/>
    <s:submit value="Submit"/>
</s:form>
</body>
</html>

RegisterAction.java

package com.magicalcyber.hellostruts2.action.register;

import com.opensymphony.xwork2.ActionSupport;
import org.apache.commons.lang3.StringUtils;

/**
 * Created by magicalcyber on 1/14/2015.
 */
public class RegisterAction extends ActionSupport {
    private String email;
    private String password;

    @Override
    public String execute() throws Exception {
        return SUCCESS;
    }

    @Override
    public String input() throws Exception {
        return INPUT;
    }

    @Override
    public void validate() {
        if (StringUtils.isEmpty(email)){
            addFieldError("email", "Email is required");
        }
        if(StringUtils.isEmpty(password)){
            addFieldError("password", "Password is required");
        }

        //Simulate: validate exist email
        if(!hasErrors()){
            if(email.trim().equalsIgnoreCase("admin@localhost")){
                addActionError("Already register email: " + email);
            }
        }
    }

    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;
    }
}

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s