HowTo - Υποστήριξη Ελληνικών με Java JSP και SQL Server

Σε αυτό το έγγραφο δίνονται απλές οδηγίες για την ομαλή υποστήριξη ελληνικών χαρακτήρων σε σελίδες που δημιουργούνται και επεξεργάζονται με Java JSPs. Δίνονται επίσης οδηγίες για την ασφαλή αποθήκευση και ανάκτηση ελληνικών χαρακτήρων σε σχεσιακές βάσεις δεδομένων και ειδικότερα στον SQL Server 7+.

Θεωρούνται γνωστά τα προβλήματα κωδικοποίησης χαρακτήρων (character encoding) που συναντώνται στον Παγκόσμιο Ιστό και γενικότερα κατά την αποθήκευση, ανάκτηση και μετάδοση συμβολοσειρών (π.χ. http://www.joelonsoftware.com/articles/Unicode.html).

Όπου δεν αναφέρεται διαφορετικά, τα παραδείγματα βασίζονται στο Servlet API 2.3 (π.χ. Tomcat 4.x)

Στο τέλος υπάρχουν συνοπτικές οδηγίες για όσους ανυπομονούν.

JSP

Υπάρχουν τρία διαφορετικά ζητήματα όσων αφορά τα JSP

Όλες οι προτάσεις που θα γίνουν βασίζονται στο γενικό κανόνα ότι χρησιμοποιείται πάντα κωδικοποίηση utf-8.

Αποθήκευση πηγαίων αρχείων JSP

Όπως αναφέρθηκε, χρησιμοποιείται για την αποθήκευση utf-8. Οποιοσδήποτε σύγχρονος text-editor μπορεί να αποθηκεύσει με διάφορες κωδικοποιήσεις τα αρχεία του.

Προτείνονται:

Επειδή η σελίδες θα είναι αποθηκευμένες με διαφορετική κωδικοποίηση από αυτή που το JSP Standard θεωρεί default (iso-8859-1), πρέπει να λεχθεί στον Java Compiler που θα κληθεί να διαβάσει και να μεταγλωτίσει το αρχείο σας, σε τι κωδικοποίηση είναι αποθηκευμένο. Αυτό γίνεται με παράμετρο στο page directive (που υπάρχει σε κάθε αρχείο JSP). <%@ page pageEncoding="utf-8" %>

Κωδικοποίηση μετάδοσης

Το αποτέλεσμα της κλήσης ενός JSP μπορεί να είναι μία σελίδα HTML, αλλά γενικά θα μπορούσε να είναι και ο,τιδήποτε άλλο, όπως μία εικόνα. Σε κάθε περίπτωση, το περιεχόμενο που θα παραχθεί με ένα JSP καθορίζεται από το ένα mime type. Σε αυτό βασίζονται οι user agents για να ερμηνεύσουν το περιεχόμενο. Το mime type ορίζεται πάλι με παράμετερο στο page directive.

Στη δική μας περίπτωση πρόκειται για σελίδες HTML οπότε το mime type είναι text/html. Επειδή θέλουμε όμως συγκεκριμένη κωδικοποίηση έχουμε

<%@ page contentType="text/html; charset=utf-8" %>

Σε συνδυασμό με την προηγούμενη παράγραφο, όλα τα αρχεία πρέπει να έχουν το ακόλουθο page diretive

<%@ page contentType="text/html; charset=utf-8" pageEncoding="utf-8" %>

Ανάκτηση παραμέτρων

Για να μπορέσετε να πάρετε τις τιμές που έδωσε κάποιος χρήστης σε μία φόρμα HTML (με το request.getParameter(xxx) ) πρέπει να γνωρίζετε με τι κωδικοποίηση αυτές στάλθηκαν στον εξυπηρετητή. Οι user agents χρησιμοποιούν την κωδικοποίηση της σελίδας στην οποία ήταν ενσωματωμένη η φόρμα. Στη δική μας περίπτωση utf-8 (όλες οι σελίδες στέλντοναι σε utf-8).

Πριν την πρώτη ανάκτηση οποιασδήποτε παραμέτρου, αρκεί να καλέσετε το

request.setCharacterEncoding("UTF-8");

SQL Server

Ο Microsoft SQL Server 7 και πάνω επιτρέπει να αποθήκευση κειμένων σε unicode. Για αυτό το σκοπό υπάρχουν οι τύποι nchar, nvarchar και ntext (οι γνωστοί τύποι χαρακτήρων δηλαδή με πρόθεμα το n).

Όλες οι εκφράσεις SQL που χρησιμοποιούν του παραπάνω τύπους πρέπει να έχουν πριν την τιμή της συμβολοσειράς ένα λατινικό N. Για παράδειγμα select * from xxx where textattributecolumn = N'κάτι σε ελληνικά' insert into xxx(a,b) values(10,N'ελληνικά')

Από την έκδοση SQL Server 2000 η Microsoft δίνει δικό της JDBC driver (http://www.microsoft.com/sql/downloads/) αλλά εδώ θα αναφερθεί μόνο ο jTDS driver που υποστηρίζει SQL Server και unicode.

Παράδειγμα σύνδεσης υπάρχει στο τέλος.

Η συγκεκριμένη υλοποίηση δημιουργεί νέα σύνδεση στη βάση δεδομένων όποτε καλείται η μέθοδος createStatement(). Αυτό σημαίνει ότι όσον αφορά συναλλαγές με τη χρήση της μεθόδου setAutoCommit(), αυτό θα δουλεύει μόνο εάν χρησιμοποιείτε το ίδιο Statement από τη σύνδεση.

Συνοπτικά

Όταν αποθηκεύετε τα αρχεία JSP να επιλέγετε κωδικοποίηση utf-8.

Σε κάθε JSP αρχείο να έχετε στην αρχή

<%@ page contentType="text/html; charset=utf-8" pageEncoding="utf-8" %>
request.setCharacterEncoding("UTF-8");

Παράδειγμα σύνδεσης JDBC με τον Driver jTDS

Connection con = null;
Statement stmt = null;
ResultSet rs = null;
try {
	Class.forName("net.sourceforge.jtds.jdbc.Driver");
}
catch (ClassNotFoundException e)
{
	// error handling
}
try
{
    	con = DriverManager.getConnection
		(	"jdbc:jtds:sqlserver://IP_ADDRESS/DB_NAME",
			"USERNAME",
			"PWD");
	stmt = con.createStatement();
	rs = stmt.executeQuery("select * from xxx where attr=Ν'τιμή'");
	while (rs.next())
	{
		System.err.println(rs.getObject(1));
	}
	// do your stuff
}
catch (SQLException e)
{
	// error handling
	System.err.println(e.getMessage());
	e.printStackTrace();
}
finally
{
	// close connection !!!!
}

Οκτώβριος 2003
Στέφανος Καρασαββίδης
sk at karasavvidis dot gr

Valid HTML 4.01!