1. การเริ่มต้นใช้งานพื้นฐาน SpringMVC สร้างโปรแกรม HelloWorld
1. ก่อนนำเข้าแพ็คเกจ JAR ที่ SpringMVC ต้องการ
2. เพิ่มการกำหนดค่าเกี่ยวกับ SpringMVC ในไฟล์การกำหนดค่า web.xml
<!-กำหนดค่าการตั้งค่าของ SpringMvcDispatcherservlet และกำหนดค่าการแมป-> <servlet> <servlet-name> springmvc </servlet-name> <servlet-lass> org.springframework.web.servlet.dispatcherservlet <param-value> classpath: springmvc-servlet.xml </param-value> </init-param> <!-<load-on-startup> 1 </load-on-startup>-> </servlet>
3. เพิ่มไฟล์การกำหนดค่า SpringMvc-servlet.xml ภายใต้ SRC
<? xml version = "1.0" การเข้ารหัส = "utf-8"?> <beans xmlns = "http://www.springframework.org/schema/beans" xmlns: xsi = "http://ww.w3.org/2001/xml xmlns: context = "http://www.springframework.org/schema/context" xmlns: mvc = "http://www.springframework.org/schema/MVC http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/Context http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.1.xsd ทรัพยากรคงที่-> <MVC: Default-Servlet-Handler/> <!-ถ้าคุณใช้คำอธิบายประกอบคุณต้องกำหนดค่าการตั้งค่าต่อไปนี้-> <MVC: คำอธิบายประกอบที่ขับเคลื่อนด้วย/> <!-กำหนดค่า InternalResourceViewResolver-> <bean id = "InternalResourceViewResolver" /> <!-คำต่อท้าย-> <property name = "suffix" value = ". jsp" /> </ebean> </ebeans>
4. สร้างโฟลเดอร์ชื่อ JSP ในโฟลเดอร์ Web-Inf เพื่อจัดเก็บมุมมอง JSP สร้าง hello.jsp และเพิ่ม "Hello World" ให้กับร่างกายของคุณ
5. สร้างแพ็คเกจและคอนโทรลเลอร์ดังแสดงด้านล่าง
6. เขียนรหัสคอนโทรลเลอร์
@controller @requestmapping ("/mvc") คลาสสาธารณะ mvccontroller {@requestmapping ("/hello") สตริงสาธารณะสวัสดี () {return "hello"; -7. เริ่มเซิร์ฟเวอร์และพิมพ์ http: // localhost: 8080/ชื่อโครงการ/mvc/hello
1.Dispatcherservlet
DispatchERServlet เป็นตัวควบคุมล่วงหน้าที่กำหนดค่าไว้ในไฟล์ web.xml การสกัดกั้นคำขอจับคู่ กฎการจับคู่ servlet จะต้องถูกกำหนดด้วยตัวเอง คำขอที่สกัดกั้นจะถูกแจกจ่ายไปยังตัวควบคุมเป้าหมายตามกฎที่เกี่ยวข้องสำหรับการประมวลผล นี่เป็นขั้นตอนแรกในการกำหนดค่าสปริง MVC
2. InternalresourceViewResolver
ดูชื่อตัวแก้ไข
3. คำอธิบายประกอบข้างต้น
@Controller รับผิดชอบในการลงทะเบียนถั่วในบริบทฤดูใบไม้ผลิ
@RequestMapping คำอธิบายประกอบระบุว่าคำขอ URL ใดที่สามารถประมวลผลได้สำหรับคอนโทรลเลอร์
@Controller
รับผิดชอบในการลงทะเบียนถั่วในบริบทฤดูใบไม้ผลิ
@requestmapping
คำอธิบายประกอบระบุว่าคำขอ URL ใดที่สามารถประมวลผลได้สำหรับคอนโทรลเลอร์
@requestbody
คำอธิบายประกอบนี้ใช้ในการอ่านส่วนหนึ่งของข้อมูลร่างกายของคำขอคำขอใช้ httpmessageConverter ที่กำหนดค่าโดยระบบสำหรับการแยกวิเคราะห์จากนั้นผูกข้อมูลที่เกี่ยวข้องกับวัตถุที่จะส่งคืนจากนั้นผูกข้อมูลวัตถุที่ส่งคืนโดย httpmessageConverter กับพารามิเตอร์ของวิธีการในคอนโทรลเลอร์
@ResponseBody
คำอธิบายประกอบนี้ใช้ในการเขียนวัตถุที่ส่งคืนโดยวิธีคอนโทรลเลอร์ไปยังพื้นที่ข้อมูลร่างกายของวัตถุตอบสนองหลังจากแปลงเป็น httpmessageconverter ที่เหมาะสมเป็นรูปแบบที่ระบุ
@modelattribute
ใช้ @ModelAttribute Annotation บนคำนิยามวิธี: Spring MVC ก่อนที่จะเรียกวิธีการประมวลผลเป้าหมายวิธีการที่คำอธิบายประกอบ @ModelAttribute ในระดับวิธีจะถูกเรียกทีละหนึ่ง
ใช้ @ModelAttribute Annotation ก่อนที่จะป้อนพารามิเตอร์เมธอด: คุณสามารถรับวัตถุจากวัตถุโดยนัยให้ผูกพารามิเตอร์การร้องขอไปยังวัตถุจากนั้นส่งผ่านวิธีลงในวัตถุพารามิเตอร์เพื่อเพิ่มวิธีการลงในโมเดล
@requestparam
ใช้ @requestparam เพื่อส่งพารามิเตอร์คำขอไปยังวิธีการร้องขอ
@PathVariable
ผูก URL placeholder กับพารามิเตอร์รายการ
@ExceptionHandler
คำอธิบายประกอบในวิธีการวิธีการจะถูกดำเนินการเมื่อมีข้อยกเว้นเกิดขึ้น
@ControllerAdvice
ทำให้คอนโทรลเลอร์เป็นคลาสการจัดการข้อยกเว้นทั่วโลก วิธีการที่มีคำอธิบายประกอบด้วยวิธี @ExceptionHandler ในชั้นเรียนสามารถจัดการกับข้อยกเว้นทั้งหมดที่เกิดขึ้นในคอนโทรลเลอร์
// จับคู่โดยอัตโนมัติ @RequestMapping ("/person") สตริงสาธารณะ toperson (ชื่อสตริงอายุสองเท่า) {system.out.println (ชื่อ+""+อายุ); กลับ "สวัสดี"; -1. เขียนคลาสเอนทิตีบุคคล
Package Test.springMvc.Model; บุคคลระดับสาธารณะ {สตริงสาธารณะ getName () {ชื่อคืน; } โมฆะสาธารณะ setName (ชื่อสตริง) {this.name = name; } public int getage () {return Age; } การตั้งค่าโมฆะสาธารณะ (อายุ int) {this.age = อายุ; } ชื่อสตริงส่วนตัว; อายุ int ส่วนตัว; -2. วิธีการเขียนในคอนโทรลเลอร์
// มวยโดยอัตโนมัติ @requestmapping ("/person1") สตริงสาธารณะ toperson (บุคคล p) {system.out.println (p.getName ()+""+p.getage ()); กลับ "สวัสดี"; - // พารามิเตอร์ถูกแปลงใน initbinder @requestmapping ("/วันที่") วันที่สตริงสาธารณะ (วันที่วันที่) {system.out.println (วันที่); กลับ "สวัสดี"; } // ในช่วงเวลาของการเริ่มต้นให้แปลงประเภท "สตริง" เพื่อพิมพ์ "วันที่" @InitBinder เป็นโมฆะสาธารณะ initbinder (ServletRequestDatabinder Binder) {Binder.RegisterCustomEditor (วันที่. - // ส่งพารามิเตอร์ไปยัง front-end @RequestMapping ("/show") public String showperson (แผนที่ <String, Object> MAP) {Person P = คนใหม่ (); map.put ("p", p); p.setage (20); P.SetName ("Jayjay"); กลับ "แสดง"; -แผนกต้อนรับจะได้รับ "p" ในโดเมนคำขอ
// ส่งพารามิเตอร์ไปยัง front-end โดยใช้ ajax @requestmapping ("/getPerson") โมฆะสาธารณะ getPerson (ชื่อสตริง, PrintWriter PW) {pw.write ("สวัสดี"+ชื่อ); } @RequestMapping ("/ชื่อ") สตริงสาธารณะ Sayshello () {return "ชื่อ"; -แผนกต้อนรับเรียกด้วยรหัส jQuery ต่อไปนี้
$ (function () {$ ("#btn") คลิก (ฟังก์ชัน () {$ .post ("mvc/getPerson", {ชื่อ: $ ("#name"). val ()}, ฟังก์ชัน (ข้อมูล) {แจ้งเตือน (ข้อมูล);});});}); // เปลี่ยนเส้นทาง @requestmapping ("/redirect") การเปลี่ยนเส้นทางสตริงสาธารณะ () {return "เปลี่ยนเส้นทาง: สวัสดี"; -1. ต้องนำเข้าแพ็คเกจสองขวด
2. เพิ่มในไฟล์การกำหนดค่า SpringMVC
<!-อัปโหลดการตั้งค่า-> <bean id = "MultipartResolver"> <property name = "MaxUploadSize" value = "102400000"
3. รหัสวิธี
@RequestMapping (value = "/upload", method = requestMethod.post) การอัปโหลดสตริงสาธารณะ (httpservletRequest req) โยนข้อยกเว้น {MultiparthttpservletRequest MREQ = (MultipArthttpServletRequest) req; ไฟล์ multipartFile = mreq.getFile ("ไฟล์"); string filename = file.getoriginalfilename (); SimpledateFormat SDF = ใหม่ SimpleDateFormat ("yyyymmddhhmmss"); fileOutputStream fos = new fileOutputStream (req.getSession (). getServletContext (). getRealPath ("/")+"อัปโหลด/"+sdf.format (วันที่ใหม่ ())+filename.substring fos.write (file.getBytes ()); fos.flush (); fos.close (); กลับ "สวัสดี"; -4. รูปแบบแผนกต้อนรับ
<form action = "mvc/upload" method = "post" enctype = "multipart/form-data"> <input type = "file" name = "file"> <br> <input type = "ส่ง" value = "ส่ง"> </form>
@controller @requestmapping ("/test") คลาสสาธารณะ mvccontroller1 {@requestmapping (value = "/param") สตริงสาธารณะ testrequestparam (@requestparam (value = "id") จำนวนเต็ม @requestparam (value = "name") ชื่อสตริง) กลับ "/สวัสดี"; -1.RestController
@controller@requestmapping ("/rest") คลาสสาธารณะ restcontroller {@requestmapping (value = "/user/{id}", method = requestMethod.get) สตริงสาธารณะรับ (@PathVariable ("id") จำนวนเต็ม) กลับ "/สวัสดี"; } @RequestMapping (value = "/user/{id}", method = requestMethod.post) โพสต์สตริงสาธารณะ (@PathVariable ("id") จำนวนเต็ม) {system.out.println ("โพสต์"+id); กลับ "/สวัสดี"; } @requestMapping (value = "/user/{id}", method = requestMethod.put) สตริงสาธารณะใส่ (@PathVariable ("id") จำนวนเต็ม) {system.out.println ("ใส่"+id); กลับ "/สวัสดี"; } @RequestMapping (value = "/user/{id}", method = requestMethod.delete) การลบสตริงสาธารณะ (@PathVariable ("ID") ID จำนวนเต็ม) {System.out.println ("ลบ"+id); กลับ "/สวัสดี"; -2. ฟอร์มฟอร์มส่งคำขอวางและลบ
กำหนดค่าใน web.xml
<!-กำหนดค่า hiddidhttpmethodfilter, แปลงวิธีการโพสต์เพื่อวางหรือลบ-> <filter> <filter-name> hervedhttpmethodfilter </filter-name> <filter-class> org.springframework.web.filter <Tilter-Name> HIDVERHTTPMETHODFILTER </filter-Name> <URL-PATTERN>/*</url-pattern> </filter-mapping>
ในเบื้องหน้าคุณสามารถใช้รหัสต่อไปนี้เพื่อสร้างคำขอ
<form action = "rest/user/1" method = "post"> <input type = "hidden" name = "_ method" value = "Put"> <input type = "submit" value = "ใส่"> </form> <form action = "ผู้ใช้/1" method = "post"> value = "get"> </form> <form action = "ret/user/1" method = "post"> <input type = "hidden" name = "_ method" value = "delete"> <input type = "subment" value = "delete"> </form>
1. นำเข้าแพ็คเกจ JAR ต่อไปนี้
2. รหัสวิธี
@controller @requestmapping ("/json") คลาสสาธารณะ JsonController {@ResponseBody @RequestMapping ("/ผู้ใช้") ผู้ใช้สาธารณะรับ () {ผู้ใช้ u = ผู้ใช้ใหม่ (); u.setid (1); U.SetName ("Jayjay"); U.SetBirth (วันที่ใหม่ ()); กลับคุณ; -1. จัดการข้อยกเว้นในท้องถิ่น (ในคอนโทรลเลอร์)
@ExceptionHandler Public ModelandView ExceptionHandler (Exception Ex) {ModelAndView MV = NEW MODELANDVIEW ("ข้อผิดพลาด"); mv.addobject ("ข้อยกเว้น", ex); System.out.println ("ใน testexceptionhandler"); กลับ MV; } @RequestMapping ("/ข้อผิดพลาด") ข้อผิดพลาดสตริงสาธารณะ () {int i = 5/0; กลับ "สวัสดี"; -2. จัดการข้อยกเว้นทั่วโลก (ตัวควบคุมทั้งหมด)
@ControllerAdvicePublic คลาส TestControllerAdvice {@ExceptionHandler Public ModelandView ExceptionHandler (Exception Ex) {ModelAndView MV = ModelAndView ใหม่ ("ข้อผิดพลาด"); mv.addobject ("ข้อยกเว้น", ex); System.out.println ("ใน testcontrolleradvice"); กลับ MV; -3. อีกวิธีหนึ่งในการจัดการกับข้อยกเว้นทั่วโลก
กำหนดค่าในไฟล์กำหนดค่า SpringMvc
<!-กำหนดค่า SimpleMappingExceptionResolver-> <bean> <property name = "ExceptionMappings"> <props> <prop key = "java.lang.arithmeticexception"> ข้อผิดพลาด </prop> </props> </property>
ข้อผิดพลาดคือหน้าข้อผิดพลาด
1. สร้างคลาส myinterceptor และใช้อินเตอร์เฟส handlerInterceptor
คลาสสาธารณะ MyInterceptor ใช้ handlerInterceptor {@Override โมฆะสาธารณะหลังการรวม (httpservletrequest arg0, httpservletResponse arg1, arg2 object arg2, ข้อยกเว้น arg3) โยนข้อยกเว้น {system.out.println ("Aftercompletion"); } @Override โมฆะสาธารณะ Postthandle (httpservletrequest Arg0, httpservletResponse arg1, Object Arg2, ModelandView Arg3) โยนข้อยกเว้น {System.out.println ("Posthandle"); } @Override บูลีนสาธารณะ prehandle (httpservletRequest arg0, httpservletResponse arg1, arg2 object) โยนข้อยกเว้น {system.out.println ("prehandle"); กลับมาจริง; -2. กำหนดค่าในไฟล์การกำหนดค่า SpringMVC
<!-การตั้งค่า Interceptor-> <MVC: Interceptors> <MVC: Interceptor> <MVC: Path Mapping = "/MVC/**"/> <bean> </ebean> gt; </mvc: interceptor> </mvc: interceptors>
3. คำสั่งการดำเนินการ Interceptor
1. นำเข้าแพ็คเกจ JAR ที่ต้องการโดย Hibernate-Validate
(ไม่ได้รับการคัดเลือกไม่จำเป็นต้องนำเข้า)
2. ผู้ใช้ระดับเอนทิตีเขียนและเพิ่มคำอธิบายประกอบการตรวจสอบ
ผู้ใช้ระดับสาธารณะ {public int getId () {return id; } โมฆะสาธารณะ setId (int id) {this.id = id; } สตริงสาธารณะ getName () {ชื่อคืน; } โมฆะสาธารณะ setName (ชื่อสตริง) {this.name = name; } วันที่สาธารณะ getBirth () {ส่งคืน; } โมฆะสาธารณะ setBirth (วันเกิดวันที่) {this.birth = เกิด; } @Override สตริงสาธารณะ toString () {return "user [id =" + id + ", name =" + name + ", birth =" + birth + "]"; } ID INT ส่วนตัว; @NotEmpty ชื่อสตริงส่วนตัว; @past @datetimeformat (pattern = "yyyy-mm-dd") วันเกิดส่วนตัว;}PS: @past หมายความว่าเวลาจะต้องเป็นค่าที่ผ่านมา
3. ใช้แบบฟอร์มแบบฟอร์มของ SpringMvc ใน JSP
<ฟอร์ม: ฟอร์มแอ็คชั่น = "ฟอร์ม/เพิ่ม" เมธอด = "โพสต์" modelattribute = "ผู้ใช้"> id: <ฟอร์ม: อินพุตพา ธ = "id"/> <ฟอร์ม: ข้อผิดพลาดพา ธ = "id"/> <br> ชื่อ: <ฟอร์ม: อินพุตพา ธ = "ชื่อ"/> <ฟอร์ม: path = "เกิด"/> <ฟอร์ม: ข้อผิดพลาด path = "เกิด"/> <ฟอร์ม: ข้อผิดพลาด path = "เกิด"/> <อินพุตประเภท = "ส่ง" value = "ส่ง"> </ฟอร์ม: ฟอร์ม>
PS: เส้นทางที่สอดคล้องกับชื่อ
4. รหัสในคอนโทรลเลอร์
@controller@requestmapping ("/form") คลาสสาธารณะ FormController {@requestmapping (value = "/add", method = requestMethod.post) สตริงสาธารณะเพิ่ม (@valid user u, bindingResult br) {if (br.geterRoCount ()> 0) {return "adduser"; } return "Showuser"; } @RequestMapping (value = "/เพิ่ม", method = requestMethod.get) สตริงสาธารณะเพิ่ม (แผนที่ <สตริงวัตถุ> แผนที่) {map.put ("ผู้ใช้", ผู้ใช้ใหม่ ()); กลับ "adduser"; -PS:
1. เนื่องจากแอตทริบิวต์ modelattribute ถูกใช้ใน JSP จึงต้องมี "ผู้ใช้" ในโดเมนคำขอ
2.@Valid หมายถึงการตรวจสอบพารามิเตอร์ตามคำอธิบายประกอบที่ทำเครื่องหมายไว้ในเอนทิตี
3. กลับไปที่หน้าต้นฉบับเพื่อแสดงออกอีกครั้งและแบบฟอร์มจะแสดงออกอีกครั้ง
5. ปรับแต่งข้อความแสดงข้อผิดพลาด
เพิ่ม locale.properties ในไดเรกทอรี SRC
notempty.user.name = ชื่อไม่สามารถ emptypast.user.birth = การเกิดควรเป็น ValuedateTimeTimeFormat.user.birth = รูปแบบของอินพุตคือ unchypemismatch.user.birth = รูปแบบของอินพุตคือผิด
กำหนดค่าในไฟล์กำหนดค่า SpringMvc
<!-กำหนดค่าทรัพยากรในสถานที่-> <bean id = "MessagesOrce"> <property name = "basename" value = "locale"> </property> </ebean>
6. จอแสดงผลระหว่างประเทศ
เพิ่ม locale_zh_cn.properties ภายใต้ src
ชื่อผู้ใช้ = รหัสผ่านบัญชี = รหัสผ่าน
เพิ่มใน locale.properties
username = ผู้ใช้ namepassword = รหัสผ่าน
สร้าง locale.jsp
<body> <fmt: คีย์ข้อความ = "ชื่อผู้ใช้"> </fmt: ข้อความ> <fmt: คีย์ข้อความ = "รหัสผ่าน"> </fmt: ข้อความ> </body>
กำหนดค่าใน SpringMVC
<!-ทำให้หน้า JSP สามารถเข้าชมได้-> <MVC: view-controller path = "/locale" view-name = "locale"/>
ให้ locale.jsp เข้าถึงได้โดยตรงภายใต้ web-inf
ในที่สุดเยี่ยมชม locale.jsp สลับภาษาเบราว์เซอร์และภาษาที่สามารถดูบัญชีและรหัสผ่านก็ถูกสลับไปด้วย
1. สร้างแพ็คเกจ test.springmvc.integrate เพื่อสาธิตการรวมและสร้างประเภทต่างๆ
2. ผู้ใช้ระดับเอนทิตี
ผู้ใช้ระดับสาธารณะ {public int getId () {return id; } โมฆะสาธารณะ setId (int id) {this.id = id; } สตริงสาธารณะ getName () {ชื่อคืน; } โมฆะสาธารณะ setName (ชื่อสตริง) {this.name = name; } วันที่สาธารณะ getBirth () {ส่งคืน; } โมฆะสาธารณะ setBirth (วันเกิดวันที่) {this.birth = เกิด; } @Override สตริงสาธารณะ toString () {return "user [id =" + id + ", name =" + name + ", birth =" + birth + "]"; } ID INT ส่วนตัว; @NotEmpty ชื่อสตริงส่วนตัว; @past @datetimeformat (pattern = "yyyy-mm-dd") วันเกิดส่วนตัว;}3. ผู้ใช้บริการ
@componentpublic คลาส Userservice {Public UserserVice () {System.out.println ("Userservice Constructor .../N/N/N/N/N/N/N/N/N/N"); } โมฆะสาธารณะบันทึก () {system.out.println ("บันทึก"); -4.USERCONTROLLER
@controller @requestmapping ("/รวม") คลาสสาธารณะ userController {@AutoWired Userservice Userservice; @RequestMapping ("/ผู้ใช้") สตริงสาธารณะ saveUser (@requestbody @modelattribute User U) {system.out.println (u); userservice.save (); กลับ "สวัสดี"; -5. ไฟล์กำหนดค่า
สร้างไฟล์การกำหนดค่า SpringIoc ApplicationContext.xml ในไดเรกทอรี SRC
<? xml version = "1.0" การเข้ารหัส = "utf-8"?> <beans xmlns = "http://www.springframework.org/schema/beans" xmlns: xsi = "http://ww.w3.org/2001/xml XSI: schemalocation = "http://www.springframework.org/schema/beans http://www.springframework.org/schema/util http://ww.springframework.org/schema/til-util http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd "xmlns: util =" http://ww.springframework xmlns: p = "http://www.springframework.org/schema/p" xmlns: บริบท = "http://www.springframework.org/schema/context" expression = "org.springframework.steretype.controller"/> <บริบท: ยกเว้นตัวกรองประเภท = "คำอธิบายประกอบ" นิพจน์ = "org.springframework.web.bind.annotation.controlleradvice"
เพิ่มการกำหนดค่าใน web.xml
<!-กำหนดค่า SpringIoc-> <Listener> <Sistener-Lass> org.springFramework.web.context.contextloaderListener </listener-class> </listener> <context-param>
6. สร้างการกำหนดค่าบางอย่างใน SpringMVC เพื่อป้องกัน SpringMVC และ SpringIOC จากการจัดการที่ทับซ้อนกันของวัตถุเดียวกัน
<!-สแกนแพ็คเกจและแพ็คเกจย่อย-> <บริบท: Component-Scan base-base-package = "test.springmvc.integrate"> <บริบท: รวมประเภทตัวกรอง = "คำอธิบายประกอบ" นิพจน์ = "org.springframework.steretype.controller"/> <บริบท: expression = "org.springframework.web.bind.annotation.controlleradvice"/> </บริบท: Component-Scan>
1. SpringMVC ได้รับการพัฒนาตามวิธีการและ Struts2 ได้รับการพัฒนาตามชั้นเรียน SpringMVC แมป URL และวิธีการในคอนโทรลเลอร์ หลังจากการทำแผนที่สำเร็จแล้ว SpringMVC จะสร้างวัตถุ Handler ซึ่งรวมถึงวิธีการเท่านั้น การดำเนินการวิธีการสิ้นสุดและข้อมูลพารามิเตอร์ที่เป็นทางการถูกทำลาย การพัฒนาคอนโทรลเลอร์ของ SpringMVC นั้นคล้ายคลึงกับการพัฒนาบริการเว็บ
2. SpringMVC สามารถทำการพัฒนาซิงเกิลตันและขอแนะนำให้ใช้การพัฒนาซิงเกิล Struts2 ได้รับพารามิเตอร์ผ่านตัวแปรสมาชิกของชั้นเรียน ไม่สามารถใช้ซิงเกิลตันได้มีเพียงหลายกรณีเท่านั้นที่สามารถใช้ได้
3. หลังจากการทดสอบจริง struts2 ช้าเพราะใช้แท็ก struts หากคุณใช้ Struts ขอแนะนำให้ใช้ JSTL