Ответы (8)
ins0mnia | 17.04.2009, 17:32 #
Добрый день, всезнающий all
У меня возник stupid blocking point при реализации моего веб-приложения с использованием Postgresql 8.3 (running on Windows).
Кратко о приложении: чистая JSP&Servlet платформа (даже без базовых taglibs), деплоится на JBoss AS 4.2.2.GA и использует Win PostgreSQL 8.3.
Проблема заключается в сохранении в базе данных записей, поступивших из JSP (все JSP pages используют
Java
1
charset=UTF-8" and pageEncoding="UTF-8"
, в некорректной кодировке (некорректность определена визуально - при просмотре записей чере pgAdmin III, а также при дальнейшей их выборке из БД и передаче через HttpSession для отображения их в тех же JSP страницах.
Скрипты создания БД и таблицы:
Database 'test'
Java
1
2
3
CREATE DATABASE test
WITH OWNER = dwh
ENCODING = 'UTF8';
Table 'users'
Java
1
2
3
4
5
6
7
8
9
CREATE TABLE events
(
id serial NOT NULL,
field1 text NOT NULL,
field2 text NOT NULL,
CONSTRAINT events_pk PRIMARY KEY (id)
)
WITH (OIDS=FALSE);
ALTER TABLE events OWNER TO dev;
Страница JSP requestsList.jsp (часть кода):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%
String flowControl = (String)session.getAttribute("flowControl");
%>
<table cellspacing="0" cellspacing="5" width="150" border="0">
<tr>
<td bgcolor="F6F6F6">
<font face="Verdana">Поиск</font>
<form>
<input type="hidden" name="action" value="search">
<input type="text" name="keyword" size="10">
<input type="submit" value="Искать">
</form>
После ввода в поле значени "тест" и нажатия кнопки "Создать" действие передаётся по следующей ссылку
Вот код обработки в сервлете:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
...
if(request.getParameter("action").equals("search")) {
session = request.getSession();
boolean created = dbHelper.createEvent(request.getParameter("keyword"), session);
if(created)
session.setAttribute("message", "New event created successfully.");
else
session.setAttribute("message", "New event creation failed.");
session.setAttribute("action", request.getParameter("action"));
RequestDispatcher rd = getServletContext().getRequestDispatcher("/WEB-INF/requestsList.jsp");
rd.forward(request, response);
}
...
Код dbHelper.createEvent(String value):
Вот собственно говоря все детали.
Сервер - Windows 2003 Server, Location=Ukraine, lang for the non-Unicode program (Advanced tab in Regional Settings)=Ukrainian (все чекбоксы включены).
При просмотре через pgAdmin:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
1
14;"òåñò";"òåñò";1
public boolean createEvent(String keyword, HttpSession session)
{
boolean result = false;
Connection conn = this.getConnection();
try {
Statement createStatement = conn.createStatement();
String test = new String(keyword.getBytes("UTF-8"), "UTF-8"); // также были попытки не трансформить строку
System.out.println(test);
PreparedStatement prep = conn.prepareStatement("insert into events(field1, field2) values(?, ?)");
prep.setString(1, keyword);
prep.setString(2, keyword);
int affect = prep.executeUpdate();
if(affect == 1)
result = true;
}
catch (SQLException sqle) {
sqle.printStackTrace();
} catch (UnsupportedEncodingException ioe) {
ioe.printStackTrace();
}
return result;
}
На JSP выводит: òåñò
Интересно то, что если я ввожу на другой JSP в поле ввода "тест", а затем ищу это значение в таблице - возвращается одна запись.
Большая просьба ткнуть носом в тот момент, где скрывается ошибка.
Заранее благодарен
NeoNYura | 17.04.2009, 17:39 #
Вы бы распечатали, вашу информацию во всех точках, для того что бы понять где происходит проблема с кодировкой.\
Если в Сервлете то можно добавить следующий код
Java
1
2
3
4
5
try
{
request.setCharacterEncoding("utf8");
} catch
(UnsupportedEncodingException e1) {
e1.printStackTrace();
}
1
System.out.println(test);
если текст правильный, то база таки у вас не в утф-8 (хотя создается база вроде правильно)
Добавлено позднее:
это излишество
Java
1
String test = new
String(keyword.getBytes("UTF-8"), "UTF-8");
Добавлено позднее:
так не пробвали писать?
Xml
1
<%@ page contentType="text/html; charset=utf-8"%>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
try
{
Statement createStatement = conn.createStatement();
//String test = new String(keyword.getBytes("UTF-8"), "UTF-8");
System.out.println(keyword);
PreparedStatement prep = conn.prepareStatement("insert into events(field1, field2) values(?, ?)");
prep.setString(1, keyword);
prep.setString(2, keyword);
int
affect = prep.executeUpdate();
if(affect == 1)
result = true;
}
catch
(SQLException sqle) {
sqle.printStackTrace();
}
Вот результат
Java
1
2
3
4
System.out.println(keyword);
18:01:56,858
INFO [STDOUT] ?????? ?????? ??????
Также в начале doGet и doPost поставил:
Java
1
request.setCharacterEncoding("utf-8");
...не помогло
Asal | 20.04.2009, 17:51 #
еще можно попробывать поставить в настройках соединения UTF-8 для результата и данных которые вставляются
ins0mnia | 21.04.2009, 11:52 #
Есть некий прогресс: явно указал метод post для формы и action (на контроллер действий) - в логах jboss и таблице postgresql данные пошли русскими, корректными символами
Java
1
2
3
4
5
6
7
8
9
10
11
12
13
<%@ page language="java"
contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%
String flowControl = (String)session.getAttribute("flowControl");
%>
<table cellspacing="0"
cellspacing="5"
width="150"
border="0">
<tr>
<td bgcolor="F6F6F6">
<font face="Verdana">Поиск</font>
<form method="post"
action="/ssweb/Controller">
<input type="hidden"
name="action"
value="search">
<input type="text"
name="keyword"
size="10">
<input type="submit"
value="Искать">
</form>
Также установил, что при отсутствии
Java
1
request.setCharacterEncoding("utf-8");
символы в jboss log & postgre table будут в некорректной кодировке.
В принципе это решение удовлетворяет текущим потребностям, но на будущее хотелось бы разъяснить для себя эту тему.
Взглянув на значение keyword в этой uri
Java
1
http://serv_ip:8081/ssweb/Controller?action=search&keyword=%F2%E5%F1%F2
, я подумал, что при [code=java]request.getParameter("keyword") в программу данные попадают вот в такой вот, неприемлемой, кодировке.
Есть мнение использовать атрибут Connector'a URIEncoding (server.xml JBoss'овского Tomcat'а)
This specifies the character encoding used to decode the URI bytes, after %xx decoding the URL. If not specified, ISO-8859-1 will be used.
и возможно это позволит решить трабл с обработкой в doGet().
ins0mnia | 21.04.2009, 12:38 #
Прошу простить за общение с самим собой:)
С doGet решилась проблема использованием того самого атрибута URIEncoding. Теперь мой Connector выглядит так:
Java
1
2
3
4
5
<Connector port="8081"
address="${jboss.bind.address}"
maxThreads="250"
maxHttpHeaderSize="8192"
emptySessionPath="true"
protocol="HTTP/1.1"
enableLookups="false"
redirectPort="8443"
acceptCount="100"
connectionTimeout="20000"
disableUploadTimeout="true"
URIEncoding="UTF-8"/>
URL, в свою очередь, получается таким:
Java
1
http://serv_ip:8081/ssweb/Controller?action=search&keyword=тест
Собственно сабж, мне кажется, можно считать разобранным
ins0mnia | 27.04.2009, 09:08 #
considered as solved