Кодировка символов запроса сервлета

У меня есть сервлет Java, который получает данные из восходящей системы через HTTP GET-запрос. Этот запрос включает параметр с именем "текст". Если восходящая система устанавливает этот параметр в значение:

TEST3 please ignore:

Он отображается в журналах восходящей системы как:

00 54 00 45 00 53 00 54 00 33 00 20 00 70 00 6c   //TEST3 pl
00 65 00 61 00 73 00 65 00 20 00 69 00 67 00 6e   //ease ign
00 6f 00 72 00 65 00 3a                           //ore:   

(комментарии//не отображаются в журналах)

В моем сервлете я прочитал этот параметр с помощью:

String text = request.getParameter("text");

Если я печатаю значение text на консоли, оно выглядит как:

T E S T 3  p l e a s e  i g n o r e :

Если я проверяю значение text в отладчике, оно выглядит как:

\u000T\u000E\u000S\u000T\u0003\u0000 \u000p\u000l\u000e\u000a\u000s\u000e\u0000 
\u000i\u000g\u000n\u000o\u000r\u000e\u000:

Итак, кажется, что проблема с кодировкой символов. Предполагается, что восходящая система использует UTF-16. Я предполагаю, что сервлет принимает UTF-8 и поэтому читает в два раза больше символов, которые должны быть. Для сообщения "TEST3, пожалуйста, игнорируйте": первый байт каждого символа 00. Это интерпретируется как пространство при чтении сервлетом, что объясняет пространство, которое появляется перед каждым символом, когда сообщение регистрируется сервлетом.

Очевидно, моя цель - просто получить сообщение "TEST3, пожалуйста, проигнорируйте:", когда я прочитал параметр запроса text. Я предполагаю, что я мог бы достичь этого, указав кодировку символов параметра запроса, но я не знаю, как это сделать.

Ответ 1

Используйте это как

new String(req.getParameter("<my request value>").getBytes("ISO-8859-1"),"UTF-8")

Ответ 2

Похоже, что он был закодирован с помощью UTF-16LE (Little Endian) кодирования, вот класс, который успешно печатает вашу строку:

import java.io.UnsupportedEncodingException;
import java.math.BigInteger;

public class Test {
    public static void main(String[] args) throws UnsupportedEncodingException {
            String hex = "00 54 00 45 00 53 00 54 00 33 00 20 00 70 00 6c"  +
                            "00 65 00 61 00 73 00 65 00 20 00 69 00 67 00 6e" +
                           "00 6f 00 72 00 65 00 3a"; // + " 00";
            System.out.println(new String(new BigInteger(hex.replaceAll(" ", ""), 16).toByteArray(), "UTF-16LE"));
    }
}

Вывод:

TEST3 please ignore?

Выход с двумя нулями, добавленными на вход

TEST3 please ignore:

UPDATE

Чтобы выполнить эту работу с помощью Servlet, вы можете попробовать:

  String value = request.getParameter("text");
  try {
      value = new String(value.getBytes(), "UTF-16LE");
  } catch(java.io.UnsupportedEncodingException ex) {}

UPDATE

см. следующую ссылку , она проверяет, что полученный гекс действительно UTF-16LE

Ответ 3

Попробуйте использовать фильтр для этого

public class CustomCharacterEncodingFilter implements Filter {

    public void init(FilterConfig config) throws ServletException {
    }

    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) 
                                                       throws IOException, ServletException {
        request.setCharacterEncoding("UTF-8");
        response.setCharacterEncoding("UTF-8");
        chain.doFilter(request, response);
    }

    public void destroy() {
    }

Это должно установить право кодирования для всего приложения