Posts Tagged ‘springMvc’

Ajax Simplifications in Spring 3.0

February 17th, 2010

แปลและย่อมาจากจาก Ajax Simplifications in Spring 3.0
Spring and Ajax Overview
จุดประสงค์สำหรับ Entry นี้คือการสาธิตการทำงานแบบ Aynchronous ระหว่าง JavaScript (jQuery, Dojo) และ SpringMVC 3.0 เพื่อให้เห็นความสามารถใหม่ใน Spring3 เนื่องก่อนหน้านี้ Spring เองไม่มีฟีเจอร์ในเรื่องของ
การทำงาน Ajax Remoting ในตัวมันเองทำให้ต้องเลี่ยงไปใช้ไลบารี่เช่น DWR เข้ามาช่วยแต่ช่วงหลังๆการส่งข้อมูลแบบ RESTful-JSON เป็นที่นิยมมากขึ้นทำให้ Spring3 ได้เตรียมความพร้อมในเรืองนี้มาให้เลย โดย Spring3
สามารถทำการสร้าง response ที่เป็น JSON ได้นอกจากนี้ยังสามารถ Bind JSON Parameter กลับมาเป็น Java Object ได้ด้วยเลยซึ่งจะแสดงให้เห็นตัวอย่างในส่วนต่อไปของเนื้อหา

MVC Ajax Sample
ตัวอย่าง ที่จะใช้ใน Entry นี้นั้นสามารถ export ได้จาก https://src.springframework.org/svn/spring-samples/mvc-ajax/trunk/ โดยหลังจากได้ sourcecode มาแล้วเราสามารถลอง deploy และลองเล่นได้เลยครับโดยสามารถ pack
เป็น WAR แล้วค่อยนำไป deploy ได้เลยหรือจะใช้บริการ Embeded Jetty ก็สามารถทำได้ด้วยการเพิ่ม plugin เข้าไปใน pom.xml ดังนี้ครับ

    <build>
        <plugins>
            <plugin>
                <groupid>org.mortbay.jetty</groupid>
                <artifactid>maven-jetty-plugin</artifactid>
            </plugin>
	...
	...
	...
       </plugins>

หลังจากเพิ่ม pluging แลัวเราก็พิมพ์ mvn jetty:run ได้เลยครับ
» Read more: Ajax Simplifications in Spring 3.0

SpringMVC ใน Spring 3.0 ง่ายจริงหรือ

December 23rd, 2009

Spring MVC ใน Spring 3.0 ง่ายจริงหรือ ??

คำถามนี้ ผมไม่สามารถตอบแทนใครได้ จนกว่าคุณจะได้ลองใช้เองเท่านั้น

หลังจากที่ Spring Framework 3.0 GA ปล่อยออกมาแล้ว ก็มีบทความต่างๆ ออกมา เช่น
- Spring Framework 3.0 goes GA
- Infoq :: What’s New in Spring 3.0
- TSS :: SpringSource takes Spring 3.0 to GA

และบทความ
MVC Simplifications in Spring 3.0 โดยผมอ้างอิงมาจากบทความนี้นะครับ มาดูกันว่า SpringMVC ใน Spring 3 มันง่ายจริงไหม ???

Let’s Go !!!!!

1. ว่าด้วยเรื่องการ configuration มีอะไรที่เปลี่ยนแปลงบ้าง

1.1 mvc:annotation-driven

...
<mvc:annotation-driven  />
...

เป็น tag สำหรับทำการ register HandlerMapping และ HandlerAdapter ลงใน request ที่จะส่งไปยัง @Controller และเพิ่มความสามารถอื่นๆ ไปด้วย ถ้ามี libraries ใน classpath เช่น
- สามารถใช้งาน Type ConversionService ในการแปลงชนิดของข้อมูล
- สนับสนุนการใช้งาน @NumberFormat สำหรับการจัดรูปแบบของข้อมูลชนิด Number
- สนับสนุนการใช้งาน @DateTimeFormat สำหรับการจัดรูปแบบของข้อมูลชนิด Date, Calendar และ Joda Time
- สนับสนุนการใช้งาน @Valid สำหรับ validate input ที่เข้ามายัง @Controller ( JSR 303 )
- สนับสนุนการอ่านและเขียน XML ด้วย JAXB
- สนับสนุนการอ่านและเขียน JSON ด้วย Jackson

1.2 mvc:view-controller

...
<mvc:view-controller path="/" view-name="welcome" />
...

กลไกภายในของ SpringMVC นั้นจะทำการ register [ "/" คู่กับ viewname ชื่อว่า welcome ] โดยที่ ParameterizableViewController จะทำการเลือก view มา render ต่อไป โดยจากตัวอย่างนั้น เมื่อมี request “/” เข้ามาจะทำการเลือก view ชื่อว่า welcome มา render กลับไป ซึ่ง view นั้นจะมีนามสกุลเป็น jsp เก็บไว้ใน folder ที่ config ไว้ในส่วน InternalResourceViewResolver [ ซับซ้อนดีจริงๆ ]

1.3 mvc:interceptors

<mvc:interceptors>
    <bean class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor" />
</mvc:interceptors>

ทำการ register HandlerInterceptors ลงใน Controller ทุกๆ ตัว
จากตัวอย่างเป็นการเปลี่ยน Locale ของระบบ โดยส่ง parameter ชื่อว่า locale เข้ามายัง Controller

2. ว่าด้วยเรื่อง Data Binding และ Validation
มีบทความอธิบายแบบละเอียดที่นี่ Spring 3 Type Conversion and Validation

เป็นส่วนของการ binding และ validation ข้อมูลต่างๆ ที่ส่งเข้ามายัง Controller ซึ่งจะทำงานก่อนที่จะเข้าทำงานใน method ต่างๆ ของ Controller โดยสิ่งที่ทำประกอบไปด้วย
- ฺBinding ของมูลลงใน Model
- Conversion ข้อมูลก่อน binding ลงใน Model
- Validate ข้อมูลก่อน binding ลงใน Model
[ ดูๆ ไปเหมือน Conversion และ Validation phrase ใน JSF เลยนะครับ ]

ตัวอย่างของ method create ใน Controller

@RequestMapping(method=RequestMethod.POST)
public String create(@Valid Account account, BindingResult result) {
    if (result.hasErrors()) {
        return "account/createForm";
    }
    this.accounts.put(account.assignId(), account);
    return "redirect:/account/" + account.getId();
}

เมื่อมี request เข้ามายัง method create จะทำการ validate ข้อมูลที่ส่งเข้ามา กับ class Account [ จากการกำหนด @Valid ไว้ ] ถ้าเกิดข้อผิดพลาดก็จะส่งออกมายัง method นั้นๆ เลย

มาดูหน้าตาของ class Account ซึ่งเป็น model สำหรับเก็บข้อมูลว่าเป็นอย่างไร

public class Account {

	private Long id;

	@NotNull
	@Size(min=1, max=25)
	private String name;

	@NotNull
	@NumberFormat(style=Style.CURRENCY)
	private BigDecimal balance = new BigDecimal("1000");

	@NotNull
	@NumberFormat(style=Style.PERCENT)
	private BigDecimal equityAllocation = new BigDecimal(".60");

	@DateTimeFormat(style="S-")
	@Future
	private Date renewalDate = new Date(new Date().getTime() + 31536000000L);
...
...
...

จะเห็นได้ว่ามีการใช้งาน Annotation มากมาย เพื่อใช้สำหรับการ validate ข้อมุลในแต่ละ fields โดย Annotation ต่างๆ เช่น @NumberFormat, @DateTimeFormat เป็นต้น ซึ่งถูก register มาตั้งแต่ข้อ 1.1 แล้ว

ต่อมา

- ถ้าในขั้นตอนการ validate เกิดข้อผิดพลาดขึ้นมา จะทำการ render หน้า createForm ขึ้นมา
- ถ้าไม่มีข้อผิดพลาด จะทำการบันทึกข้อมูล และ redirect ไปยัง url /account/ ซึ่งจะเข้าทำงานใน method getView ใน Controller ดังนี้

@RequestMapping(value="{id}", method=RequestMethod.GET)
public String getView(@PathVariable Long id, Model model) {
	Account account = this.accounts.get(id);
	if (account == null) {
		throw new ResourceNotFoundException(id);
	}
	model.addAttribute(account);
	return "account/view";
}

- ใน method getView นี้จะรับจาก HTTP GET และมี parameter 1 ตัวชื่อว่า id ชนิดตัวเลข
- ใน method นี้มี feature หนึ่งที่น่าสนใจคือ ถ้าไม่เจอข้อมูลตาม id ที่ส่งเข้ามาแล้วจะโยน exception ออกมา

จากตัวอย่างคือ ResourceNotFoundException มีหน้าตาดังนี้

@ResponseStatus(value=HttpStatus.NOT_FOUND)
public class ResourceNotFoundException extends RuntimeException {

	private Long resourceId;

	public ResourceNotFoundException(Long resourceId) {
		this.resourceId = resourceId;
	}

	public Long getResourceId() {
		return resourceId;
	}
}

ถ้าเกิด ResourceNotFoundException ขึ้นมาแล้วจะส่ง HTTP Status= 404 [ Page not found ] ออกไป โดยเราสามารถกำหนด error page ตาม HTTP Status ได้อีกด้วย ซึ่งเป็นความสามารถที่น่าสนใจไม่น้อยทีเดียวครับ

เท่าที่ทดสอบใช้งานมานั้น พบว่า SpringMVC ใน Spring 3.0 นั้นพยายามที่จะลดจำนวนการของ code รวมไปถึงการ configuration ลงไป แต่ก็ได้เพิ่ม Annotation เข้ามาอย่างมากกมายเช่นกัน ซึ่งมีทั้งข้อดีและข้อเสีย ตามแต่ละคนจะมองกันไปครับ แต่ถ้ามองว่ามันช่วยให้ง่ายขึ้น ก็ถือว่ามันมีประโยชน์ แต่ถ้ามองว่ามันยุ่งยากก็กลับไปใช้แบบเดิมก็ไม่แปลกครับ …

ส่วนผมจะลองใช้งานมันต่อไปครับ แล้วจะนำมาอธิบายในบทความต่อๆ ไปครับ ….

ส่วนตัวอย่างนั้น สามารถ checkout ออกมาจาก svn repositories ของ SpringSource ได้จากคำสั่ง

svn co https://src.springframework.org/svn/spring-samples/mvc-basic/trunk/

ปล. ในตัวอย่างนี้มีการใช้งาน UrlRewrite ด้วยนะครับ จะทำให้ url ที่ได้สวยงามยิ่งขึ้นครับ และนำมาอธิบายการใช้งานต่อไปครับ

JavaRebel + Spring in Eclipse WTP plug-in

May 12th, 2009

จากที่พี่ @roofimon พูดถึงเรื่อง JavaRebel มันก็ช่างโดนใจน้อยๆของผมเหลือเกิน เพราะไอ้เรื่องนี้ก็ทิ่มแทงใจผมมาตั้งแต่วันแรกที่ทำเลยลองทำตาม blog ดูก็โอ้ว happy แต่ด้วยความที่ผมใช้ cmd maven แล้วมันไม่ถนัดมือไปหน่อยเลยว่ากันด้วยเรื่อง ide ก็เลยมานั่งนึกดู ถ้ายังนึกถึงรักเก่าที่ยังคบหาอยู่ก็ Netbeans พอมานั่งคุยกับรักปัจจุบันก็ eclipse ก็เลยมานั่งเทียบสิ่งนึงที่ javarebel ทำคือเมื่อมีการเปลี่ยนแปลง class มันจะทำการ reload ให้เรางั้นก็มานั่งลองดูเริ่มกันที่ Netbean ผมใช้ 6.5 นั่นคือผมว่ามันน่ารักสู้ eclipse ไม่ได้ในงานนี้ตรงที่มันไม่มี compile on save แต่เห็นว่า 6.7 มีนะครับแต่ก็ไม่รู้จะหล่อแค่ไหนเลยคิดว่าเรื่องที่เป็นจุดน่าจะเลือกก็คือ compile on save เลยมามองว่า eclipse ทำได้ดีกว่าเลย เอาวะ eclipse ก็ eclipse ก็มานั่งดู web ของ javarebelที่ http://www.zeroturnaround.com/javarebel/ อ้ะๆ เกิดสวรรค์น้อยๆที่เค้ามีการ ทำ eclipse plug-in ออกมาให้ด้วยแถมยังคงต่อกับ wtp plug-in ที่ eclipse เค้าคุยนักคุยหนาว่านี่หล่ะเจ๋งพอๆกะ netbeans ก็เลยเอาหล่ะเอามาลงกันก่อนเลย
ผมใช้ eclipse 3.4 codename***** และ wtp plug-in ซึ่งมันติดมาอยู่แล้วถ้าใครโหลดตัวที่เป็น web dev มาโดยการ ติดตั้ง plug-in ก็ตามฟอร์มครับ update site โลดโดย update site อยู่ที่ http://www.zeroturnaround.com/update-site/
แล้วก็ติดตั้งกันไป

หลังจากเราติดตั้งเรียบร้อยก็ว่ากันต่อที่การใช้งานหล่ะต๊กตาในการใช้งานของผมคือ Appfuse คงไม่ต้องร่ายยาวว่ามันคืออะไรนะครับ อันนี้คาดว่าน่าจะเคยลองเล่นกันแล้วแต่ถ้ายังขอให้บอกวันหลังจะเอามาเขียนเป็นอีกหนึ่ง entry ครับโดยผมก็เอา appfuse-springmvc มา adapt นิดหน่อยโดยไม่ใช้ maven ครับ ด้วยเหตุผลของเด็กน้อยโปรแกรมเมอร์จนๆ อย่างผมไม่มีเน็ตแรงๆ 5mb ไว้ใช้งานที่บ้านเลยต้อง offline กันไป

แต่ผมก็จะทำตามขั้นตอนของ คุณ @roofimon นะครับโดยขั้นตอนพี่เค้าเขียนไว้อย่างเมพแล้วเลยขอทำตามขั้นตอนหน่อยแต่เปลี่ยนวิธีก็เลยเอาของพี่มา adapt apply หน่อยๆ อิอิ

ไป download ไลบรารี่มาก่อนที่ http://www.zeroturnaround.com/javarebel/
จากนั้นเราก็ต้องบอกให้ Servlet Container ที่เราใช้ว่าเราช่วยโหลดได้นี่เข้าไปหน่อยนะจังหวะที่มัน Start-up ซึ่งในที่นี้ผมประมาณว่าทุกคนใช้ Tomcat นะครับดังนั้นสิ่งที่เราต้องทำคือไปที่ catalina.bat แล้วเพิ่มคำสั่งนี้เข้าไป(เอาไว้ประมาณ บรรทัดที่ 231)

 set JAVA_OPTS=-noverify -javaagent:{PATH_TO_JAVAREBEL}javarebel.jar %JAVA_OPTS% 

เมื่อเราใช้ ide + plug-in เราก็ใช้วิธีการ

ไปที่ Window » Preferences » JavaRebel แล้วก็จะเจอความงามซ่นอยู่ครับโดยเราก็เลือก JavaRebel jar location ครับเพื่อให้ ตัว wtp ของเรารู้จัก JavaRebel แล้วก็ไป

run >> run config… ก็จะเจอหน้าตาสวยงามดังนี้ครับ

ตามที่วงเลยครับเท่านี้ก็ลองมา test start server กันดูก็จะเห็นแบบนี้ใน console

ถ้าที่ comsole มีข้อความนี้แสดงขึ้นมาแสดงว่าเรามาถูกทาง

#############################################################

ZeroTurnaround JavaRebel 2.0 (200903241906)

(c) Copyright Webmedia, Ltd, 2007-2009. All rights reserved.

เปิดการใช้งานให้กับตัว servlet container ของเราผมใช้ tomcat 6 นะครับโดยไปเปิด server editor ขึ้นมาแล้วเตะสองทีเร็วๆจากนั้นจะพบกับหน้าจอ tomcat config แบบนี้ครับ

พอดีไปโขมยเค้ามาเด่วผมมาแก้รูปให้นะครับพอดีมัน upload ขึ้น server ไม่ได้

น่านยังมีกันเราลืมโดยบอกว่าให้เช็คให้ดีนะให้เราไปปิด auto publish ซะตอนแรกผมก็ไปปิดครับเชื่อคนง่ายพอมาเขียนโอ้ว happy อย่างยิ่งแต่เราลืมมองไปว่าแก้ class มันไม่มีปัญหาครับแต่ถ้าเราแก้ jsp มันไม่ publis ไปให้เราอ่ะงงเลยเลยทำตามนี้ไปก่อนแล้วกันครับเด่วจะ เล่าให้ฟังหลังๆ

mvn archetype:create -DgroupId=com.mycompany.app -DartifactId=my-webapp -DarchetypeArtifactId=maven-archetype-webapp

เราก็จะได้เวบโปรเจคโง่ๆมาหนึ่งอันหนึ่งชื่อ my-webapp จากนั้นเราต้องเพิ่มความสามารถของ JavaRebel เข้าไปให้ maven ด้วยโดยให้เราเปิด pom.xml ขึ้นมาแล้วเพิ่ม plugin เข้าไปดังนี้

ที่บรรทัดประมาณที่ 11

<pluginRepositories>
<pluginRepository>
<id>zt-repo</id>
<name>Zero turnaround repo</name>
<url>http://repos.zeroturnaround.com/maven2</url>
</pluginRepository>
</pluginRepositories>

อีกส่วนที่ประมาณบรรทัดที่ 139 ในส่วนของ plugins

<plugin>
<groupId>org.zeroturnaround</groupId>
<artifactId>javarebel-maven-plugin</artifactId>
<executions>
<execution>
<id>generate-rebel-xml</id>
<phase>process-resources</phase>
<goals>
<goal>generate</goal>
</goals>
</execution>
</executions>
</plugin>

เมื่อเรียบร้อยแล้วให้สั่ง mvn javarebel:generate คำสั่งนี้จะไปสร้างไฟล์ชื่อ rebel.xml ที่ WEB-INF/classes ครับโดยไฟล์นี้จะทำหน้าที่กำหนด target ที่เก็บ class ไฟล์และ resources ต่างที่เราต้องการให้ทำ auto-reload เมื่อเกิดการเปลี่ยนแปลง

ขั้นตอนนี้ผมข้ามเรียบครับเพราะผมสร้างproject มาเอง dynamic web project manage มือใช้ ant ครับส่วน maven ที่อาไว้ gen file rebel.xml ก็ไม่ต้องครับเด่วเราใช้เวทมนต์ตามประสา วิสาดดดด

โดยไปคลิกขวาที่โปรเจ็คแล้วจะเห็นเมนูให้เรา generate rebe.xml ครับ แล้วให้ไปเลือกที่ที่เราไว้นั่นคือ output folder นั่นเอง
เท่ากับว่าตอนนี้เราก็มาถึง

<?xml version="1.0" encoding="UTF-8"?>
<application xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://www.zeroturnaround.com" xsi:schemaLocation="http://www.zeroturnaround.com/alderaan/rebel-2_0.xsd">
<classpath>
<dir name="D:/workspace-seanet/TMS/build/classes">
</dir>
</classpath>
</application>

ละ พอ เหนื่อยครับทดลอง run โลดครับเมื่อรันจะเห็นว่าจะมี log ท่อนนึงบอกเราว่า

=============================== [JavaRebel Spring Framework Plugin DISABLED] ===============================
Plugins are contributed by third party and can cause compatibility problems.
If you have any troubles set -Drebel.spring_plugin=false to disable it.
------------------------------------------------------------------------------------------
Description: Supports adding new beans and adding new bean dependencies using
annotations or XML. Singletons will be reconfigured after the change. It also
supports adding or changing Spring MVC controllers or handlers.
=============================== [/JavaRebel Spring Framework Plugin DISABLED] ] ==============================

โห งอแง เลยครับไม่ตรงตัณหาของผมอย่างยิ่งเพราะผมจะเอามาใช้กับ spring แล้วขึ้นมายังงี้มันยอมไมได้เลยอ่าน log เล่นๆ เอ้อเค้าก็บอกวิธีมานี่หว่า If you have any troubles set -Drebel.spring_plugin=false to disable it.
เอาเลยผมไปจัดการไปที่ run>>condig… แล้วก็ไปเพิ่มที่นี่เลยครับ

เท่านี้หล่ะแล้วลองใหม่ก็จะเห็ฯlogหน้าตาพอจะสวยงามประมาณนี้

=============================== [JavaRebel Spring Framework Plugin ===============================
Plugins are contributed by third party and can cause compatibility problems.
If you have any troubles set -Drebel.spring_plugin=false to disable it.
------------------------------------------------------------------------------------------
Description: Supports adding new beans and adding new bean dependencies using
annotations or XML. Singletons will be reconfigured after the change. It also
supports adding or changing Spring MVC controllers or handlers.
=============================== [/JavaRebel Spring Framework Plugin ] ==============================

เท่านี้ก็หรูแล้ว

ทีนี้ลองแก้ file .java ดูแล้วไป refresh ดูครับไม่ต้องไปคลิก run ใหม่นะครับไม่ตรงจุดประสงค์อย่างยิ่งเพราะอย่างที่รู้มันก็จะไป restart server หรือไม่ก็ deploy ทับซึ่งมันไม่เหมาะกับเครื่องโปรแกรมเมอร์จนๆแรมน้อยๆอย่างผมครับแต่ก็นะพอไปดู log เฮ้ยมัน publih ไปให้เรา

ก็นั่นหล่ะครับเพราะว่าเรายังไมได้ตั้งให้มัน ปิดการ auto publish แต่ปัญหาอยู่ตรงนี้ครับพอเราไปตั้งให้มัน never auto publish มันก็จะไม่ยอม publish jsp ให้เราแต่ ตัว class แน่นอนอยู๋แล้วว่า javarebel agent รับผิดชอบเราก็เลยต้องโกง wtp กันหน่อยโดยยังตั้ง auto publish
อยู่แล้วไปเลือกเป็น module ให้มันปิดการ publish ซะเท่านี้เลย

พิมซะเมื่อยครับลองรันแล้วเทสกันดูหลาย case นะครับโดยรวมมันรวดเร็วอำนวยความสะดวกให้เราชาว spring66 มากมายผมซื้อแน่ๆ เขียนไปเขียนมาอ่านไปอ่านมายังงงอยู่ครับเอาเป็นว่าใครลองแล้วติด comment ถามกันมาแล้วกันครับ

ปล. ขอโทษด้วยครับ คุณ @roofimon นัดไว้ว่าจะขึ้นเที่ยงคืนแต่มาเอาเที่ยงวันครับ

SpringMVC ภาคแถม JSON View

February 26th, 2009

ภาคสี่ เราผ่านการ POST ข้อมูลไปจัดเก็บแล้วครับในตอนที่แล้ว ตอนนี้เป็นตอนแถมในภาคของ SpringMVC นั่นคือถ้ามผมต้องการส่ง Response กลับไปให้ Browser เป็นรูปแบบอื่น
เช่น JSON จะทำยังไงเพราะถ้าผมทะลึ่งอยากใช้ ExtJS หรือ Dojo ที่สามารถทำงานกับข้อมูลที่ถูกแปลงเป็น JSON ได้ดีเราจะทำอย่างไรครับ
โชคดีที่มีคนอยากได้แบบนี้แล้วเหมือนกันโดยโปรเจคนี้ชื่อ SpingJSON-View ครับเนื่องจาก SpringMVC เราสามารถปล่อย View ออกมาได้สามล้านแบบครับ XML, PDF … JSON
ดังนั้นอย่ารอช้าครับเริ่มด้วยการเพิ่มไลบรารี่เข้าไปใน pom.xml ก่อนครับตามสูตร

        <dependency>
            <groupId>net.sf.spring-json</groupId>
            <artifactId>spring-json</artifactId>
            <version>1.1</version>
        </dependency>

ต่อไปเราต้องบอกให้ SpringMVC รู้ว่าเรามี View แบบใหม่แล้วนะชื่อ jsonView เพื่อให้มันสามารถจัดการรับมือได้อย่างถูกต้องโดยสิ่งที่เราจะต้องทำคือการเพิ่มไฟล์ชื่อ views.xml เข้าไปที่
WEB-INF ให้มีรายละเอียดตามนี้ครับ

<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.0.xsd">
    <bean name="jsonView" class="org.springframework.web.servlet.view.json.JsonView"/>
</beans>

จากนั้นสิ่งที่เราต้องทำคือเพิ่ม mapping เข้าไปใน web.xml เพื่อแยกว่า response ที่เราต้องการเป็น JSON นั้นเราจะแยกไฟล์ออกไปไม่ให้ปะปนกับของเดิมครับ โดยผมจะสร้างไฟล์ชื่อ
springjson66-servlet.xml ขึ้นมาเพื่อใช้เก็บ Controller ทุกตัวที่ทำงานเกี่ยวกับ JSON ไว้ในนี้ หลังจากสร้างไฟล์เรียบร้อยก็จัดการไปเพิ่มข้อมูลเข้าไปใน web.xml ดังนี้ครับ

    <servlet>
        <servlet-name>springjson66</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <load-on-startup>2</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>springjson66</servlet-name>
        <url-pattern>*.json</url-pattern>
    </servlet-mapping>

โดยที่ request อะไรก็ตามที่ลงท้ายด้วย *.json จะถูกส่งต่อไปให้ springjson66 จัดการต่อครับจากนั้นให้เราไปสร้าง Controller หนึ่งตัวครับที่มีหน้าที่ดึงข้อมูลออกมาจากตารางที่เราต้องการ
และทำการเปลี่ยนผลที่ได้ออกมาเป็น JSON ดังนี้ครับ

/**
 *
 * @author TwinP
 */
public class SimpleJsonGetController implements Controller {

    private AppUserService appUserService;

    @Override
    public ModelAndView handleRequest(HttpServletRequest arg0, HttpServletResponse arg1) throws Exception {
        Map model = new HashMap();
        model.put("model", this.appUserService.getUsers(null));
        return new ModelAndView("jsonView", model);
    }

    /**
     * @return the appUserService
     */
    public AppUserService getAppUserService() {
        return appUserService;
    }

    /**
     * @param appUserService the appUserService to set
     */
    public void setAppUserService(AppUserService appUserService) {
        this.appUserService = appUserService;
    }
}

จะเห็นได้ว่าไม่มีอะไรแต่กต่างจากเดิมมากนักสิ่งที่ต่างคือจังหวะที่เราคืนค่าออกมาจากเมธอด handleRequest นั้นเราเพียบแต่ระบุเพิ่มเติมว่าเราต้องการให้แปลงเป็น JSON นะแต่ Controller นี้จะใช้
งานไม่ได้ถ้าเราไม่ไป register มันไว้ตามระเบียบของ Spring โดยที่เราจะไปใส่ข้อมูลไว้ที่ springjson66-servlet.xml ครับ

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN"
		  "http://www.springframework.org/dtd/spring-beans-2.0.dtd">

<beans>
    <bean name="simpleJsonGetController"
          class="com.spring66.tutorial.web.controller.SimpleJsonGetController">
        <property name="appUserService" ref="appUserService"/>
    </bean>

    <bean name="urlMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
        <property name="mappings">
            <props>
                <prop key="/hello.json">simpleJsonGetController</prop>
            </props>
        </property>
    </bean>
    <bean  name="viewResolver" class="org.springframework.web.servlet.view.XmlViewResolver" />
</beans>

เป็นอันเรียบร้อยครับต่อไปสุดท้ายคือเราต้องไปสร้าง View ที่สามารถรับ response เป็น JSON แล้วเอาไป process ต่อได้ในทันควันนั่นคือ ExtJS ครับโดยที่ผมจะไม่ลงรายละเอียดนะครับเขียนเลยละกัน

<html>
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
    <title>Paging Grid Example</title>

    <link rel="stylesheet" type="text/css" href="scripts/ext/resources/css/ext-all.css" />

    <!-- GC -->
    <!-- LIBS -->
    <script type="text/javascript" src="scripts/ext/adapter/ext/ext-base.js"></script>
    <!-- ENDLIBS -->

    <script type="text/javascript" src="scripts/ext/ext-all.js"></script>
    <link rel="stylesheet" type="text/css" href="css/examples.css" />

    <script type="text/javascript" src="scripts/usrJSONService.js"></script>
    </head>
    <body>

        <!?- grid will render to this element -?>
        <div id="db-grid"></div>

    </body>
</html>

จากไฟล์นี้ผมไปเรียก JS พิเศษหนึ่งไฟล์ชื่อ usrJSONService.js ครับโดยไฟล์นี้จะทำหน้าที่ไปเรียก controller ของเราและเอาผลมา process ใส่ grid แบบบ้านๆของ ExtJS ครับ

Ext.onReady(function(){
    // create the data store
    var store = new Ext.data.JsonStore({
        url: 'hello.json',
        root: 'model',
        fields: [
        {
            name: 'usrFirstLogin'//, mapping: 'usrFirstLogin', type: 'date', dateFormat: 'timestamp'
        },

        {
            name: 'usrId'
        },

        {
             name: 'regDate'//, mapping: 'usrFirstLogin', type: 'date', dateFormat: 'timestamp'
        },
        {
            name: 'usrPwd'
        },
        {
            name: 'logDate'//, mapping: 'usrFirstLogin', type: 'date', dateFormat: 'timestamp'
        },
        {
            name: 'usrName'
        }
        ]
    });
    //store.loadData(myData);
    store.load();

    // create the Grid
    var grid = new Ext.grid.GridPanel({
        store: store,
        columns: [
        {
            id:'usrFirstLogin',
            header: "usrFirstLogin",
            width: 160,
            sortable: true,
            dataIndex: 'usrFirstLogin'
        },

        {
            header: "usrId",
            width: 75,
            sortable: true,
            renderer: 'usMoney',
            dataIndex: 'usrId'
        },

        {
            header: "regDate",
            width: 75,
            sortable: true,
            dataIndex: 'regDate'
        },

        {
            header: "% logDate",
            width: 75,
            sortable: true,
            dataIndex: 'logDate'
        }
        ],
        stripeRows: true,
        autoExpandColumn: 'usrFirstLogin',
        height:350,
        width:600,
        title:'Array Grid'
    });

    grid.render('db-grid');
});

เรียบร้อยครับเราก็ได้ View สุดสวยกันแล้วครับภาคต่อไปเราจะลองมา POST ผ่าน ExtJS กันนะครับ