Hiển thị các bài đăng có nhãn spring. Hiển thị tất cả bài đăng
Hiển thị các bài đăng có nhãn spring. Hiển thị tất cả bài đăng

Thứ Năm, 20 tháng 2, 2014

Conflict giữa Apache basic authentication và spring security

Nếu Tomcat có sử dụng Apache basic authentication để xác thực. nếu ứng dụng sử dụng tomcat trên, và có tích hợp với spring security thì sẽ có conflict giữa 2 dạng xác thực này. Mình đã gặp lỗi này và phải mất 1 tiếng chạy đi hỏi lại network, rồi test lại chương trình. chỉ cần thay tag cấu hình <http> cho spring security thì sẽ không config.
thay

<http auto-config="true">
 <form-login login-page="/login" default-target-url="/index"
 authentication-failure-url="/failure"  />
 <logout logout-success-url="/login" />
 <access-denied-handler error-page="/denied"/>
</http>
bằng cách bỏ auto-config đi


<http>
 <form-login login-page="/login" default-target-url="/index"
 authentication-failure-url="/failure"  />
 <logout logout-success-url="/login" />
 <access-denied-handler error-page="/denied"/>
</http>

Tham khảo tại đây: http://docs.spring.io/autorepo/docs/spring-security/3.1.4.RELEASE/reference/ns-config.html

Thứ Ba, 11 tháng 2, 2014

Asian japanese chinese korean characters in ITextPDF


   com.itextpdf
   itextpdf
   5.4.5
  
  
   com.itextpdf
   itext-asian
   5.2.0
  

để write các ký tự utf-8 trong itextpdf ta sử dụng:
BaseFont base = BaseFont.createFont("KozMinPro-Regular", "UniJIS-UCS2-H", BaseFont.NOT_EMBEDDED);
  Font font = new Font(base, 12, Font.NORMAL);
  Phrase p = new Phrase("部品カタログプロテクター無プロテクター無プロテクター無プロテクター無",font);
  document.add(new Paragraph(p));
Result:

Thứ Tư, 1 tháng 1, 2014

Ckeditor trong Spring MVC

Để áp dụng một rich-text ta sử dụng ckeditor: http://ckeditor.com/download (basic package, standard package, full package) và jquery http://jquery.com/download/ example lấy từ đây: http://diepviends.blogspot.com/2013/12/xu-ly-form-trong-spring-mvc.html
Trước tiên ta thêm ckeditor và jquery vào resources

Trong Product class ta thêm description về product đó
package vn.ds.store.domains;

import java.io.Serializable;

public class Product implements Serializable {
 /**
  * 
  */
 private static final long serialVersionUID = 1L;
 private String name;
 private String price;
 private String description;

 public String getName() {
  return name;
 }

 public void setName(String name) {
  this.name = name;
 }

 public String getPrice() {
  return price;
 }

 public void setPrice(String price) {
  this.price = price;
 }

 public String getDescription() {
  return description;
 }

 public void setDescription(String description) {
  this.description = description;
 }
}
Thêm link của ckeditor và jquery



apply ckeditor thì có 2 cách:
 Cách 1: sử dụng ngay trong hàm ready của jquery

Cách 2: viết script trong body tag
    Description


    
 


   
Kết quả:


source code:
http://www.mediafire.com/download/br9fc35go9f572t/Store_ckeditor.rar
Thanks & Regard!

Thứ Hai, 30 tháng 12, 2013

i18n trong Spring MVC

Trong bài này ta sẽ xây dựng website đa ngôn ngữ i18n (Internationalization)
Cấu trúc thư mục sẽ như sau:

trong thư mục /WEB-INF/i18n ta sẽ tạo 2 file properties application.properties và application_vi.properties lưu trữ các label cho ngôn ngữ mặc định  và ngôn ngữ tiếng việt ( ngôn ngữ mặc định đây là tùy chọn, cấu hình trong servlet-context.xml)
file application_vi.properties
file application.properties

và sửa lại view để hỗ trợ hiển thị theo ngôn ngữ tùy chọn
createProduct.jsp
listProduct.jsp

ở đây ta dùng <spring:message code="application.name" /> được hỗ trợ bởi spring, khai báo taglib là <%@taglib uri="http://www.springframework.org/tags" prefix="spring"%> để lấy message theo code được khai báo trong properties
Bây giờ sẽ cấu hình để ứng dụng có thể load các label theo key mà ta đã định nghĩa trong file properties
mở file config: /WEB-INF/spring/appServlet/servlet-context.xml
thêm vào đoạn sau:
 
 
  
 
 
 
  
 
 
  
  
 
 

bean localeChangeInterceptor sẽ xử lý yêu cầu về load resource theo ngôn ngữ được lựa chọn, dựa vào parameter là "lang"
bean localeResolver sẽ lưu ngôn ngữ hiện tại vào cookie của trình duyệt, ngôn ngữ mặc định đây là "en" (tùy chọn)
và bean messageSource sẽ load file properties được định nghĩa trong WEB-INF/i18n/, các file được load là application*.properties.
sau khi Run As project
vào theo các url sau để xem kết quả
http://localhost:8080/store/product/create?lang=en
http://localhost:8080/store/product/create?lang=vi
source code
https://www.mediafire.com/?skzzpktm4c5pmwm
Thks & rgds!

Thứ Năm, 26 tháng 12, 2013

Xử lý form trong Spring MVC

Trong phần này ta sẽ làm ví dụ xử lý dữ liệu lấy từ form ở trang JSP.
File->new->Spring project->Spring MVC Project
cấu trúc thư mục sẽ như sau:

Nội dung:
Sử dụng domain sau để lưu trữ thông tin của Product
package vn.ds.store.domains;

import java.io.Serializable;

public class Product implements Serializable {
 /**
  * 
  */
 private static final long serialVersionUID = 1L;
 private String name;
 private String price;

 public String getName() {
  return name;
 }

 public void setName(String name) {
  this.name = name;
 }

 public String getPrice() {
  return price;
 }

 public void setPrice(String price) {
  this.price = price;
 }
}


Chương trình sẽ lấy dữ liệu khi người dùng nhập vào

 và in ra danh sách


dữ liệu nhập vào sẽ được validate như hình sau

Đầu tiên ta xây dựng file properties để lưu trữ thông báo cho chương trình.
file product-messages.properties sẽ được tạo ra ở thư mục src/main/resources

các parameter được tryền vào theo các vị trí {0} {1}...
Để spring đọc được file resources này ta định nghĩa thêm 1 bean  là thể hiện của lớp org.springframework.context.support.ReloadableResourceBundleMessageSource để đọc messages.
vào file WEB-INF/spring/appServlet/servlet-context.xml thêm đoạn sau:

  
 

Toàn bộ file servlet-context.xml sẽ như thế này:


 
 
 
 

 
 

 
 
  
  
 
 
 
 
 
  
 
 



Xong phần cấu hình, giờ sẽ xây dựng một lớp ProductValidator để valid dữ liệu từ người dùng. Vì spring đã hỗ trợ validate trong interface Validator nên class của ta chỉ việc implements giao diện đó và triển khai phương thức validate() của Validator interface.
package vn.ds.store.validators;

import org.springframework.validation.Errors;
import org.springframework.validation.ValidationUtils;
import org.springframework.validation.Validator;

import vn.ds.store.domains.Product;

public class ProductValidator implements Validator {

 @Override
 public boolean supports(Class clazz) {

  return Product.class.isAssignableFrom(clazz);
 }

 @Override
 public void validate(Object target, Errors errors) {
  ValidationUtils.rejectIfEmptyOrWhitespace(errors, "name",
    "msg.required", new Object[] { "name" });
  ValidationUtils.rejectIfEmptyOrWhitespace(errors, "price",
    "msg.required", new Object[] { "price" });
  Product product = (Product) target;
  String name = product.getName();
  int max = 6;
  if (!name.isEmpty() && name.length() > max)
   errors.rejectValue("name", "msg.maxlength", new Object[] { "name",
     max }, "");
  if (!isNumber(product.getPrice().trim()))
   errors.rejectValue("price", "msg.number", new Object[] { "price",
     max }, "");
 }

 public boolean isNumber(String s) {
  for (int i = 0; i < s.length(); i++) {
   if (!Character.isDigit(s.charAt(i)))
    return false;
  }
  return true;
 }

}


Phương thức
ValidationUtils.rejectIfEmptyOrWhitespace(errors, "name",
    "msg.required", new Object[] { "name" });
sẽ kiểm tra xem trường "name" có emty hay có space không, nếu có sẽ add thêm một message vào đối tượng errors, nội dung msg sẽ được lấy theo id của msg trong resources là "msg.required" và truyền vào một parameter cho msg đó là một mảng Object có 1 phần tử là "name". Tương tự phương thức
errors.rejectValue("price", "msg.number", new Object[] { "price",
     max }, "");
cũng sẽ add thêm một msg của trường "price" vào errors theo msg là "msg.number" và set vào 2 parameter là một biến String "price" và một biến Integer max
Controller
package vn.ds.store.controllers;

import java.util.ArrayList;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

import vn.ds.store.domains.Product;
import vn.ds.store.validators.ProductValidator;

@Controller
@RequestMapping("product")
public class ProductController {

 private ProductValidator validator = new ProductValidator();

 @RequestMapping(value = "create", method = RequestMethod.GET)
 public String doGet(Model model) {
  model.addAttribute("product", new Product());
  return "createProduct";
 }

 @RequestMapping(value = "save", method = RequestMethod.POST)
 public String doPost(@ModelAttribute Product product,
   Model model, BindingResult errors) {
  validator.validate(product, errors);
  if (errors.hasErrors()) {
   return "createProduct";
  }
  ArrayList lst = new ArrayList();
  Product p = new Product();
  p.setName("product 1");
  p.setPrice("100");
  lst.add(p);
  lst.add(product);
  model.addAttribute("products", lst);
  return "listProduct";
 }
}


Ở đây Phương thức GET của url "/product/create" sẽ được xử lý bởi hàm doGet(). hàm này sẽ tạo mới một đối tượng Product và add vào model. sau đó trả về một view có tên là "createProduct". view này là view jsp được định nghĩa trong file servlet-context.xml. vì ta không định nghĩa cụ thể nên spring sẽ xem id của view theo tên file jsp. Phương thức POST của url "/product/save" sẽ xử lý khi người dụng submit form trong method doPost()
Đầu tiên sẽ validate dữ liệu theo đối tượng ProductValidator. nếu có lỗi sẽ trả về view "createProduct" là trang nhập dữ liệu
Nếu không có lỗi sẽ thực hiện add dữ liệu vào model và gửi xuống view "listProduct".
JSP
file createProduct.jsp trong thư mục WEB-INF/views sẽ như sau:
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
 pageEncoding="ISO-8859-1"%>
<%@ taglib uri="http://www.springframework.org/tags/form" prefix="form"%>




Insert title here



 
  
create
Name
Price
 

và view hiển thị danh sách listProduct.jsp
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
    pageEncoding="ISO-8859-1"%>
 <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>   




Insert title here



 
List of products
Name Price
${p.name} ${p.price}

Source code theo link http://www.mediafire.com/download/vki3lvwpsqtpam8/Store_handling_form.rar Thanks & Rgds!!!

Thứ Tư, 25 tháng 12, 2013

Hướng dẫn sử dụng Spring Tool Suice (STS)

Spring Tool Suice (STS) là một plugin cho Eclipse hỗ trợ dev phát triển các project dựa trên Spring framework
http://spring.io/tools/sts
Bài viết này sẽ hướng dẫn cách sử dụng STS
Trên thanh công cụ của Eclipse->Help->EclipseMarketplace
Gõ vào ô tìm kiếm với từ khóa STS
Chọn STS phù hợp với phiên bản Eclipse-> Install


Sau khi eclipse hoàn tất cài đặt và khởi động lại
cần phải bỏ valid derived query để tránh các cảnh báo lỗi không cần thiết
Window->Preferences->Spring.
ở tab Project validators->Data validator và bỏ check  ở Invalid Derived Query-> OK

Create một project Spring web MVC

File->New->Spring Project->Spring MVC Project

Nhập tên package và Finish



STS sẽ tự động tạo một project mẫu với một controller Home

Nếu Project bị lỗi, là do version của spring đó không còn maven không hỗ trợ để load thư viện về.
để sửa bạn vào file pom.xml. chọn properties của spring và thay bằng version khác (có thể tham khảo tại http://mvnrepository.com/artifact/org.springframework)


Sau đó save lại, và chọn Project->clean.
bây giờ click phải chuột vào Store->Run As
và xem kết quả!

Bây giờ hãy xem lại example vừa được tạo ra
cấu trúc thư mục sẽ như thế này

Một ứng dụng spring MVC sẽ theo đúng mô hình MVC chuẩn, ta quan tâm đến các file sau: HomeController.java, web.xml, servlet-context.xml

HomeController.java
package vn.ds.store;

import java.text.DateFormat;
import java.util.Date;
import java.util.Locale;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

/**
 * Handles requests for the application home page.
 */
@Controller
public class HomeController {
 
 private static final Logger logger = LoggerFactory.getLogger(HomeController.class);
 
 /**
  * Simply selects the home view to render by returning its name.
  */
 @RequestMapping(value = "/", method = RequestMethod.GET)
 public String home(Locale locale, Model model) {
  logger.info("Welcome home! The client locale is {}.", locale);
  
  Date date = new Date();
  DateFormat dateFormat = DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG, locale);
  
  String formattedDate = dateFormat.format(date);
  
  model.addAttribute("serverTime", formattedDate );
  
  return "home";
 }
 
}


Controller này sẽ xử lý request cho ull "/"  và trả về một view có tên là "home"

web.xml


 
 
  contextConfigLocation
  /WEB-INF/spring/root-context.xml
 
 
 
 
  org.springframework.web.context.ContextLoaderListener
 

 
 
  appServlet
  org.springframework.web.servlet.DispatcherServlet
  
   contextConfigLocation
   /WEB-INF/spring/appServlet/servlet-context.xml
  
  1
 
  
 
  appServlet
  /
 
Ứng dụng Spring sẽ được xoay quanh một servlet trung tâm là DispatcherServlet, các request khi yêu cầu đến ứng dụng đều được servlet này xử lý sau đó lựa chọn controller xử lý và trả về model and view nào phù hợp
Các request sẽ được xử lý theo url-mapping là "/"
ở đây bạn có thể sửa url để DispatcherServlet xử lý  như .html, .do, .xxx ....
Servlet-context.xml


 
 
 
 

 
 

 
 
  
  
 
 
 
 
 
 


Dòng <annotation-driven /> sẽ cho phép sử dụng các @notation, đây là một đặc điểm của spring kể từ spring 3 trở đi
các phương thức GET yêu cầu resources(image, js, css..) sẽ được khai báo bởi dòng
<resources mapping="/resources/**" location="/resources/" />
Khai báo viewResolver là jsp ở dòng
<beans:bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<beans:property name="prefix" value="/WEB-INF/views/" />
<beans:property name="suffix" value=".jsp" />
</beans:bean>
Có thể khai báo nhiều viewResolver khác như pdf, excel...
Cuối cùng dòng
<context:component-scan base-package="vn.ds.store" />
sẽ cho phép quét các class được khai báo là controller (bởi anotation @Controller) ở trong package được chỉ ra, ở đây là vn.ds.store
Tương tự bạn có thể tạo ra nhiều controller khác  để xử lý các nghiệp vụ khác nhau trong package đó, và tạo file jsp trong /WEB-INF/views/ để hiển thị.

Thks & Rgds!

Thứ Ba, 22 tháng 10, 2013

MyBatis là gì?

Bạn cần phải có các software và tool sau:
- Java JDK 1.5+
- MyBatis version (https://code.google.com/p/mybatis/)
- MySQL (http://www.mysql.com/) hoặc CSDL quan hệ nào có thể kết nối bởi JDBC Driver
- Eclipse (http://www.eclipse.org) hoặc IDE khác ( tốt nhất là eclipse)
- Apache Maven build tool(nên dùng)

Getting started

  • MyBatis là gì?
  • Tại sao lại dùng MyBatis?
  • Cài đặt và cấu hình MyBatis

  1. MyBatis là gì?
MyBatis là một persistence framework mã nguồn mở được tạo ra nhằm đơn giản hóa việc kết nối đến CSDL của JDBC và cung cấp các API để thao tác với Database dễ dàng hơn.
Trước đây MyBatis được gọi là iBatis và được viết ra năm 2002 bởi Clinton Begin. Mybatis 3 được thiết kế lại từ iBatis, có hỗ trợ Mapper và Annotations.
MyBatis được sử dụng phổ biến là do tính đơn giản và dễ sử dụng của nó. Người sử dụng có thể thao tác dễ dàng với SQL mà không cần sử dụng đến code JDBC ở mức thấp(viết lặp lại nhiều và rất nản: open,close,createStatement..) MyBatis tự động xử lý câu lệnh SQL và lấy kết quả trả về ( từ các ResultSet của JDBC) gán vào các đối tượng java được xây dựng bởi lập trình viên (POJOs) hoặc lưu dữ liệu từ các đối tượng java xuống Database.

2. Tại sao lại dùng MyBatis?
Có rất nhiều Persistence framework được viết ra cho lập trình java, nhưng MyBatis được sử dụng nhiều vì các lý do sau:
  • Giảm thiểu đáng kể code JDBC
  • Dễ học và sử dụng
  • Có thể nhúng SQL query thuần
  • hỗ trợ để tích hợp với Spring và Guice framework
  • Hiệu năng truy vấn cao.


  • Giảm thiểu đáng kể code JDBC
Java cung cấp các JDBC API (Java DataBase Connectivity) để làm việc với CSDL quan hệ, nhưng mà code JDBC là ở mức thấp (có trộn lẫn SQL query vào code java) và lập trình viên thường phải viết đi viết lại nhiều đoạn code để thực hiện các thao tác với CSDL.
  • Dễ học và sử dụng
Vì MyBatis được thiết kế nhằm mapping các câu truy vấn SQL nên chỉ cần bạn có kiến thức về SQL và Java là có thể học được và sử dụng hiệu quả, và điều đó cũng không tốn nhiều thời gian bằng học các framework khác như Hibernate hoặc EJB. :D

  • Có thể nhúng SQL query thuần
MyBatis cho phép người dùng có thể viết câu lệnh SQL thông thường, ngoài ra còn cho phép người dùng tùy biến câu lệnh truy vấn theo các parameter truyền vào. Ví dụ tìm kiếm sinh viên theo ID, Name, Mark, nếu các parameter trên mà có thì thêm vào ở trong điều kiện WHERE,để thực hiện điều này trong JDBC rất vất vả là bạn phải if … else rồi cộng chuỗi sql, sau đó mới đưa vào đối tượng Statement hoặc preparedStatement. Nhưng với MyBatis bạn sẽ có cấu trúc điều khiển sử dụng rất rõ ràng và hiệu quả mà không gây ra lỗi khi bạn muốn thay đổi câu truy vấn, vấn đề này sẽ được đề cập sau.

  • hỗ trợ để tích hợp với Spring và Guice framework
MyBatis có thể tích hợp dễ dàng với Spring và Guice. Ví dụ các dự án dùng Spring thường đi kèm với persistence framework là Hibernate (ORM – Object Relation Mapping – nôm na là mapping các row trong DB thành các đối tượng trong java) hoặc MyBatis( có thể hiểu nôm na là mapping câu truy vấn SQL – để dễ so sánh với Hibernate :) :D)

  • Hiệu năng truy vấn cao.

Hiệu năng là một vấn đề cần quan tâm của một dự án phần mềm, trong đó đóng vai trò quan trọng của framework nào sử dụng để viết ra nó. MyBatis được đánh giá là có hiệu năng cao và nhiều developer sử dụng, vì MyBatis hỗ trợ các tính năng sau:

- Connection pool: điều này thì không phải bàn cãi, một ứng dụng sử dụng connection pool sẽ cải thiện tốc độ xử lý đáng kể và sử dụng tối đa một connection ( search google nhé :))
- Caching data: MyBatis sử dụng một cơ chế gọi là in-build cache mechanism để lưu kết quả của truy vấn vào SqlSession. Việc này rất hữu ích khi bạn sử dụng lại kết quả, thì MyBatis chỉ việc trả về kết quả trong cache mà không phải truy vấn lại Database lần nữa.
- MyBatis không sử dụng proxy cho việc kết nối nên sẽ có hiệu suất tốt hơn so với các framework ORM khác.

3. Cài đặt và cấu hình MyBatis

Việc cài đặt MyBatis rất đơn giản, bạn chỉ việc coppy file mybatis-x.x.x.jar vào thư mục lib của WEB-INF nếu bạn xây dựng project Dynamic Web hoặc thêm vào dependencies trong file pom.xml của project maven
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.2.2</version>
</dependency>

Để cấu hình MyBatis trong ứng dụng ta sẽ xây dựng một demo đơn giản mà tôi chắc chắn rằng bạn sẽ hiểu được ngay sau khi deploy được nó.

Ta sẽ tạo một demo có thể:
-  xem danh sách sinh viên
- tìm kiếm sinh viên theo id
- thêm 1 sinh viên vào csdl

Sử dụng MySQL với script sau:

CREATE TABLE STUDENT
(
  ID INT(11) NOT NULL AUTO_INCREMENT,
  NAME VARCHAR(50) NOT NULL,  
  PRIMARY KEY (ID)
) ENGINE=INNODB AUTO_INCREMENT=1 DEFAULT CHARSET=LATIN1;

Tạo một maven project như sau:





Cấu trúc chương trình như hình sau:


Chương trình ta sẽ sử dụng CSDL MySQL, ghi log thì sử dụng slf4j và log4j.

Các dependencies cần thiết trong file pom.xml là

   org.mybatis
   mybatis
   3.2.2
  
  
   mysql
   mysql-connector-java
   5.1.22
   runtime
  
  
   org.slf4j
   slf4j-api
   1.7.5
  
  
   org.slf4j
   slf4j-log4j12
   1.7.5
   runtime
  
  
   log4j
   log4j
   1.2.17
   runtime
  

Việc đầu tiên là tạo file cấu hình cho MyBatis, file mybatis-config.xml này phải đặt trong thư mục classpath của project thì mới đọc được, tôi sẽ đặt nó trong thư mục resources.

 
  
 
 
  
   
   
    
    
    
    
   
  
 
 
  
 


Tiếp đến cấu hình cho log. File log4j.properties cũng nằm trong thư mục resources.
log4j.rootLogger=ERROR, stdout
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d [%-5p] %c - %m%n

Việc cấu hình đã xong, bây giờ ta sẽ xây dựng lớp FactoryUtil để quản lý SqlSessionFactory.
package vn.ds.util;

import java.io.IOException;
import java.io.InputStream;

import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.apache.log4j.Logger;

public class FactoryUtil {
 private static SqlSessionFactory sessionFactory = getSessionFactory();
 private static Logger log = Logger.getLogger(FactoryUtil.class);

 public static SqlSessionFactory getSessionFactory() {
  if (sessionFactory == null) {
   InputStream stream;
   try {
    stream = Resources.getResourceAsStream("mybatis-config.xml");
    sessionFactory = new SqlSessionFactoryBuilder().build(stream);
   } catch (IOException e) {
    log.error("not find mybatis-config.xml");
    throw new RuntimeException(e.getCause());
   }
  }
  return sessionFactory;
 }

 public static SqlSession openSession() {
  return sessionFactory.openSession();
 }
}

Tiếp đến là tạo mapper. File StudentMapper.xml sẽ mapping các câu truy vấn vào bản g STUDENT bao gồm 2 câu SELECT và 1 câu INSERT. File StudentMapper.java là một interface chứa các method để thực hiện các tác vụ, các method này chính là các id trong tag select và insert của file StudentMapper.xml. Lưu ý là 2 file này sau khi biên dịch, phải nằm cũng một thư mục (file .class) ở đây ta đăt chung vào thư mục vn.ds.mapper.
package vn.ds.mapper;

import java.util.List;

import vn.ds.domain.Student;

public interface StudentMapper {
 List findAllStudents();

 Student findStudentById(Integer id);

 void insertStudent(Student student);
}


 
  
  
 
 
 
 
  INSERT INTO STUDENT(ID,NAME)
  VALUES(#{id},#{name})
 



domain
Chứa các lớp POJOs lưu trữ dữ liệu từ DB, các lớp này bao gồm các thuộc tính, setter và getter.
cụ thể lớp Student như sau:


package vn.ds.domain;

public class Student {
 private Integer id;
 private String name;

 public Integer getId() {
  return id;
 }

 public void setId(Integer id) {
  this.id = id;
 }

 public String getName() {
  return name;
 }

 public void setName(String name) {
  this.name = name;
 }

 @Override
 public String toString() {
  return "Student{'ID' : " + id + ", NAME : " + name + "}";
 }

}

Tiếp theo ta tạo lớp service để thực thi interface StudentMapper.


package vn.ds.service;

import java.util.List;

import org.apache.ibatis.session.SqlSession;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import vn.ds.domain.Student;
import vn.ds.mapper.StudentMapper;
import vn.ds.util.FactoryUtil;

public class StudentService {
 private Logger logger = LoggerFactory.getLogger(getClass());

 public List findAllStudents() {
  SqlSession session = FactoryUtil.openSession();
  try {
   StudentMapper mapper = session.getMapper(StudentMapper.class);
   return mapper.findAllStudents();
  } finally {
   session.close();
  }
 }

 public Student findStudentById(Integer studId) {
  logger.debug("Select Student By ID :{}", studId);
  SqlSession sqlSession = FactoryUtil.openSession();
  try {
   StudentMapper studentMapper = sqlSession
     .getMapper(StudentMapper.class);
   return studentMapper.findStudentById(studId);
  } finally {
   sqlSession.close();
  }
 }

 public void createStudent(Student student) {
  SqlSession sqlSession = FactoryUtil.openSession();
  try {
   StudentMapper studentMapper = sqlSession
     .getMapper(StudentMapper.class);
   studentMapper.insertStudent(student);
   sqlSession.commit();
  } finally {
   sqlSession.close();
  }
 }
}

Cuối cùng ta tạo một controller để gọi service trên

package vn.ds.controller;
import java.util.List;

import vn.ds.domain.Student;
import vn.ds.service.StudentService;

public class StudentController {
 public static void main(String[] args) {
  StudentService service = new StudentService();
  List list =service.findAllStudents();
  for(Student s : list)
  System.out.println(s.toString());
  Student student = new Student();
  student.setId(4);
  student.setName("Student 4");
  service.createStudent(student);
  System.out.println(service.findStudentById(3));
 }
}

source code: http://www.mediafire.com/download/aoi5zxqixdt3t2u/Mybatis1.rar

Thứ Năm, 26 tháng 9, 2013

Export Excel, PDF trong SpringMVC

Xuất file excel ta dùng thư viện apache poi: http://poi.apache.org/Xuất file pdf ta dùng thư viện itextpdf: http://itextpdf.com/

Ví dụ này ta sẽ xuất ra dưới dạng bảng thống kê, tức là có title, có các header cho các column và data cho bảng đó, như vậy, ta sẽ xây dựng 2 lớp builder nhận vào các đối là
Title: 1 chuỗi String
header: 1 Vector
data: 1 Vector
Đây là lớp ExcelBuilder để export ra file excel:

package vn.diepviends.util;

import java.util.Map;
import java.util.Vector;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.poi.hssf.usermodel.HSSFFont;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.hssf.util.HSSFColor;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.Font;
import org.springframework.web.servlet.view.document.AbstractExcelView;

public class ExcelBuilder extends AbstractExcelView {
 @Override
 protected void buildExcelDocument(Map model,
   HSSFWorkbook workbook, HttpServletRequest request,
   HttpServletResponse response) throws Exception {
  // get data
  Vector vHeader = (Vector) model.get("header");
  Vector vData = (Vector) model.get("data");
  String sTitle = model.get("title").toString();
  // create a excel sheet
  HSSFSheet sheet = workbook.createSheet(sTitle);
  sheet.setDefaultColumnWidth(30);
  // create style for header cells
  CellStyle style = workbook.createCellStyle();
  Font font = workbook.createFont();
  font.setFontName("Times New Roman");
  style.setFillForegroundColor(HSSFColor.BLUE.index);
  style.setFillPattern(CellStyle.SOLID_FOREGROUND);
  font.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD);
  font.setColor(HSSFColor.WHITE.index);
  style.setFont(font);
  // create header row
  HSSFRow title = sheet.createRow(0);
  title.createCell(0).setCellValue(sTitle);
  HSSFRow header = sheet.createRow(1);  
  for (int i = 0; i < vHeader.size(); i++) {
   header.createCell(i).setCellValue(vHeader.get(i).toString());
   header.getCell(i).setCellStyle(style);
  }
  // fill data
  int r = 2;
  for (int i = 0; i < vData.size(); i++) {
   Vector v = (Vector) vData.get(i);
   HSSFRow row = sheet.createRow(r++);
   for (int j = 0; j < v.size(); j++)
    row.createCell(j).setCellValue(v.get(j).toString());
  }
 }
}

Controller ta sẽ viết như sau:
@RequestMapping("/registerReport/export2excel")
 public String exportExcel(@RequestParam(value = "from") String from,
   @RequestParam(value = "to") String to, Model model) {
  ProvisionReportDAO dao = new ProvisionReportDAO();
  String title = "Register Report";
  Vector header = new Vector();
  Vector data = new Vector();
  ArrayList list = dao.getByDate(from, to);  
  header.add("Date");
  header.add("Quantity");
  header.add("Provision Type");
  header.add("provision Code");
  for(ProvisionReport it : list){
   Vector v = new Vector();
   v.add(it.getDate());
   v.add(it.getQuantity());
   v.add(it.getType());
   v.add(it.getCode());
   data.add(v);
  }  
  model.addAttribute("title", title);
  model.addAttribute("header", header);  
  model.addAttribute("data",data); 
  return "excelView";
 }

Với PDF thì ta phải xây dựng một lớp Abstract trung gian:
package vn.diepviends.util;

import java.io.ByteArrayOutputStream;
import java.io.OutputStream;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.web.servlet.view.AbstractView;

import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.PageSize;
import com.itextpdf.text.pdf.PdfWriter;

public abstract class AbstractITextPdfView extends AbstractView {

 public AbstractITextPdfView() {
  setContentType("application/pdf");
 }

 @Override
 protected boolean generatesDownloadContent() {
  return true;
 }
  
 @Override
 protected void renderMergedOutputModel(Map model,
   HttpServletRequest request, HttpServletResponse response) throws Exception {
  // IE workaround: write into byte array first.
  ByteArrayOutputStream baos = createTemporaryOutputStream();

  // Apply preferences and build metadata.
  Document document = newDocument();
  PdfWriter writer = newWriter(document, baos);
  prepareWriter(model, writer, request);
  buildPdfMetadata(model, document, request);

  // Build PDF document.
  document.open();
  buildPdfDocument(model, document, writer, request, response);
  document.close();

  // Flush to HTTP response.
  writeToResponse(response, baos);
 }

 protected Document newDocument() {
  return new Document(PageSize.A4);
 }
 
 protected PdfWriter newWriter(Document document, OutputStream os) throws DocumentException {
  return PdfWriter.getInstance(document, os);
 }
 
 protected void prepareWriter(Map model, PdfWriter writer, HttpServletRequest request)
   throws DocumentException {

  writer.setViewerPreferences(getViewerPreferences());
 }
 
 protected int getViewerPreferences() {
  return PdfWriter.ALLOW_PRINTING | PdfWriter.PageLayoutSinglePage;
 }
 
 protected void buildPdfMetadata(Map model, Document document, HttpServletRequest request) {
 }
 
 protected abstract void buildPdfDocument(Map model, Document document, PdfWriter writer,
   HttpServletRequest request, HttpServletResponse response) throws Exception; 
}

Lớp PDFBuilder extends lớp Abstract trên:
package vn.diepviends.util;

import java.util.Map;
import java.util.Vector;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.itextpdf.text.BaseColor;
import com.itextpdf.text.Document;
import com.itextpdf.text.Font;
import com.itextpdf.text.FontFactory;
import com.itextpdf.text.Paragraph;
import com.itextpdf.text.Phrase;
import com.itextpdf.text.pdf.PdfPCell;
import com.itextpdf.text.pdf.PdfPTable;
import com.itextpdf.text.pdf.PdfWriter;

public class PDFBuilder extends AbstractITextPdfView {

 @Override
 protected void buildPdfDocument(Map model, Document doc,
   PdfWriter writer, HttpServletRequest request,
   HttpServletResponse response) throws Exception {
  // get data
  Vector vHeader = (Vector) model.get("header");
  Vector vData = (Vector) model.get("data");
  String sTitle = model.get("title").toString();
  
  doc.add(new Paragraph(sTitle));
  PdfPTable table = new PdfPTable(vHeader.size());
  table.setWidthPercentage(100.0f); 
  table.setSpacingBefore(10);
  // define font for table header row
  Font font = FontFactory.getFont(FontFactory.HELVETICA);
  font.setColor(BaseColor.WHITE);

  // define table header cell
  PdfPCell cell = new PdfPCell();
  cell.setBackgroundColor(BaseColor.BLUE);
  cell.setPadding(5);
  for (int i = 0; i < vHeader.size(); i++) {
   // write table header
   cell.setPhrase(new Phrase(vHeader.get(i).toString(), font));
   table.addCell(cell);
  }  
  // write table row data
  int x = vData.size();
  int y = vHeader.size();
  for(int i = 0; i


Controller ta sẽ viết như sau:
@RequestMapping("/registerReport/export2pdf")
 public String exportPdf(@RequestParam(value = "from") String from,
   @RequestParam(value = "to") String to, Model model) {
  ProvisionReportDAO dao = new ProvisionReportDAO();
  String title = "Register Report";
  Vector header = new Vector();
  Vector data = new Vector();
  ArrayList list = dao.getByDate(from, to);  
  header.add("Date");
  header.add("Quantity");
  header.add("Provision Type");
  header.add("provision Code");
  for(ProvisionReport it : list){
   Vector v = new Vector();
   v.add(it.getDate());
   v.add(it.getQuantity());
   v.add(it.getType());
   v.add(it.getCode());
   data.add(v);
  }  
  model.addAttribute("title", title);
  model.addAttribute("header", header);  
  model.addAttribute("data",data); 
  return "pdfView";
 }

Định nghĩa các view để hiển thị ra excel và pdf

     
    
     


Trong dispatcher của spring ta gọi view.xml vào:

        
 
 
  
  
         
        
   
   
    



và đây là kết quả: