SpringWeb
เรื่องต่อจาก Service คือการทำ Web Layer ครับแต่เนื่องจากในโลกของ Java นั้นเรามีตัวเลือกมากมายสำหรับ Layer นี้และด้วยความที่มันมีเยอะก็ทำให้เกิดปัญหาเพราะไม่รู้จะเลือกอะไรดี มันดีไปหมดน่าใช้ไปหมด
จนบางครั้งเกิดอาการรักพี่เสียดายน้องไม่กล้าเลือก แต่สำหรับงานนี้ขอใช้ SpringMVC ครับเนื่องจากสามารถ integrate เข้ากับ technology อื่นๆของ spring ได้ง่ายที่สุดและผมถนัดที่สุดด้วยครับ
โดยในที่นี้ผมจะสร้างแค่เพจเดียวนะครับเพื่อให้เห็นภาพเร็วที่สุดว่าระหว่าง controller กับ service ต่างๆมี relation กันอย่างไรบ้าง โดยที่หน้าที่จะทำคือหน้า User List
ก่อนอื่นเรามีอะไรต้องทำเยอะพอสมควรเพื่อให้โปรเจคของเรากระโดดจาก Service ไปที่ Web
เรื่องแรกคือเรื่อง pom.xml ครับเพื่อเพิ่มความสามารถของ jetty และไลบรารี่ต่างๆที่จะต้องใช้ดังนี้
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>2.5.6</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.4</version>
</dependency>
<dependency>
<groupId>jstl</groupId>
<artifactId>jstl</artifactId>
<version>1.1.2</version>
</dependency>
<dependency>
<groupId>taglibs</groupId>
<artifactId>standard</artifactId>
<version>1.1.2</version>
</dependency>
ถัดมาเราต้องเพิ่ม maven plugin เพื่อทำให้เราสามารถสั่ง mvn jetty:run หรือ mvn jetty:run-war ได้จากโปรเจคของเราเลย
<plugin>
<groupId>org.mortbay.jetty</groupId>
<artifactId>maven-jetty-plugin</artifactId>
</plugin>
เรื่องต่อไปคือพวก Descriptor File ที่เราต้องเพิ่มเข้าไปในโปรเจค เรามาค่อยๆทำกัน
ก่อนอื่นคือสร้าง Folder ใหม่ที่ {project}/main/src/main/webapp ให้สร้าง WEB-INF และเพิ่มไฟล์ web.xml เข้าไปที่มีรายละเอียดตามนี้ครับ
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd" >
<servlet>
<servlet-name>springapp</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>springapp</servlet-name>
<url-pattern>*.lmth</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>
index.jsp
</welcome-file>
</welcome-file-list>
</web-app>
รายละเอียดขออธิบายคร่าวๆครับ คือ application ของเราจะรอฟัง request จากด้านนอกว่าจะมี request ที่มีการลงท้ายด้วย *.lmth หรือไม่เช่น http://xxx.xxx/xxx.lmht โดยถ้ามีปุ๊ประบบจะทำการส่ง request นั้น
ไปให้ springapp ที่เป็น DispatcherServlet จากนั้นตัว Dispatcher จะทำการหาเหยื่อที่ต้องมาทำงานจริงจากไฟล์ springapp-servlet.xml ต่อแล้วมันอยู่ไหน ไม่เจอ เพราะยังไม่ได้สร้าง สร้างสิ หน้าตาเป็นแบบนี้ครับ
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
<!-- the application context definition for the springapp DispatcherServlet -->
<bean name="/usrList.lmth" class="com.spring66.tutorial.web.controller.UsrListController">
</bean>
</beans>
รายละเอียดไม่มีอะไรแปลกตาเพราะเราจะมอง controller เป็น bean หนึ่งตัวเท่านั้นเองเพียงแต่ชื่อของมัน ณ ตอนนี้จะดูไม่หล่อหน่อยเพราะมันจะเป็นคล้ายๆ url เพื่อใช้ระบุว่ามันเป็นคนรับ request ที่ลงท้ายด้วย
*/usrList.lmth ครับและจะทำหน้าที่รับ request ต่อมาจาก Dispatcher
งานนี้ขอขี้โกงไม่สร้าง Test นะครับขี้เกียจเดี๋ยวค่อย test เหอๆๆๆๆ รายละเอียดของ controller นั้นเป็นไปตามนี้
package com.spring66.tutorial.web.controller;
import com.spring66.tutorial.model.Users;
import com.spring66.tutorial.model.UsersExpression;
import com.spring66.tutorial.service.UserService;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.AbstractController;
/**
*
* @author TwinP
*/
public class UsrListController extends AbstractController {
@Override
protected ModelAndView handleRequestInternal(HttpServletRequest arg0, HttpServletResponse arg1) throws Exception {
String now = (new Date()).toString();
logger.info("Returning hello view with " + now);
return new ModelAndView("usrList.jsp", "now", now);
}
}
controller ตัวนี้ไม่มีอะไรซับซ้อนเลยครับ สร้างเวลาปัจจุบันก่อนแล้วส่งต่อไปให้หน้า view ครับดังนั้นเพื่อไม่ให้เป็นการเสียเวลาเราจะสร้าง view ก่อนชื่อ usrList.jsp เอาไว้ที่ WEB-INF/ โดยมีรายละเอียดดังนี้
<%@page contentType="text/html" 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=windows-1252">
<title>JSP Page</title>
</head>
<body>
<h1>Hello World!</h1>
</body>
</html>
เพื่อไม่ให้เป็นการเสียกำลังใจเราจะลองเรียกกันก่อนว่าไอ้ที่เราทำไปออกหมหน้าตาจะเป็นอย่างไรนั้นเราสามารถทำได้โดยการเรียก
mvn jetty:run
และเปิดเบราเซอร์แล้วเรียก http://localhost:8080 ได้เลยครับ

ตรง lmth นี่ มันย่อมาจากอะไรอ่ะครับ?
ไม่มีอะไรครับ ตอนแรกจะ map เป็น *.html แต่ดูไม่หล่อเลยเอาเป็น *.lmth ดังนั้นจะเห็นได้ว่าเราสามารถ map เป็น *.อะไรก็ได้เพื่อ หลอกชาวบ้านไม่ให้รู้ว่าเวบเราเขียนด้วยอะไรครับ
ผมเคยลอง แต่ยังไม่เคยเอามาใช้เลยครับ ….
ขอบคุณสำหรับ บทความ ครับ
ถ้าเป็นไปได้ อยากให้มี validation client side + server side ด้วยจะดีมากเลยครับ ยังไงจะรอ อ่านน่ะครับ
ตี้
ของผมมัน error แฮะ
HTTP ERROR 404
Problem accessing /imim-app/WEB-INF/. Reason:
NOT_FOUND
Jetty มันว่างี้อะครับ เป็นกันมั้ยครับ