Мы можем установить кодировку символов по умолчанию, используемую для чтения тел запросов, с помощью ServletContext#setRequestCharacterEncoding
(начиная с Servlet 4.0).
Я думаю, что кодировка символов для HttpServletRequest#getReader
может быть установлена с помощью ServletContext#setRequestCharacterEncoding(*)
.
Но читатель, который возвращает HttpServletRequest#getReader
, похоже, декодирует символы, не используя кодировку, установленную ServletContext#setRequestCharacterEncoding
.
Мои вопросы:
- Почему
ServletContext#setRequestCharacterEncoding
не влияет на HttpServletRequest#getReader
(но влияет на HttpServletRequest#getParameter
)?
- Существует ли какая-либо спецификация, описывающая такое поведение
ServletContext#setRequestCharacterEncoding
и HttpServletRequest#getReader
?
(Я читал спецификацию сервлетов версии 4.0, но не могу найти никакой спецификации о таком поведении.)
Я создал простое военное приложение и протестировал ServletContext#setRequestCharacterEncoding
.
[Env]
- Tomcat9.0.19 (я не изменяю конфигурацию по умолчанию)
- JDK11
- Windows8.1
[index.html]
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
</head>
<body>
<form action="/SimpleWarApp/app/simple" method="post">
<!-- The value is Japanese character '\u3042' -->
<input type="text" name="hello" value="あ"/>
<input type="submit" value="submit!"/>
</form>
<button type="button" id="the_button">post</button>
<script>
document.getElementById('the_button').addEventListener('click', function() {
var xhttp = new XMLHttpRequest();
xhttp.open('POST', '/SimpleWarApp/app/simple');
xhttp.setRequestHeader('Content-Type', 'text/plain');
<!-- The body content is Japanese character '\u3042' -->
xhttp.send('あ');
});
</script>
</body>
</html>
[InitServletContextListener.java]
@WebListener
public class InitServletContextListener implements ServletContextListener {
@Override
public void contextInitialized(ServletContextEvent sce) {
sce.getServletContext().setRequestCharacterEncoding("UTF-8");
}
}
[SimpleServlet.java]
@WebServlet("/app/simple")
@SuppressWarnings("serial")
public class SimpleServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// req.setCharacterEncoding("UTF-8");
System.out.println("requestCharacterEncoding : " + req.getServletContext().getRequestCharacterEncoding());
System.out.println("req.getCharacterEncoding() : " + req.getCharacterEncoding());
String hello = req.getParameter("hello");
if (hello != null) {
System.out.println("hello : " + req.getParameter("hello"));
} else {
System.out.println("body : " + req.getReader().readLine());
}
}
}
У меня нет никаких фильтров сервлетов.
Выше три все компоненты этого военного приложения.
( GitHub ) * +1051 *
Случай 1:
Когда я отправляю форму с параметром «привет», значение «привет» успешно декодируется следующим образом.
requestCharacterEncoding : UTF-8
req.getCharacterEncoding() : UTF-8
hello : あ
Случай 2:
Когда я нажимаю «отправить» и отправляю текстовое содержимое, тело запроса не может быть успешно декодировано следующим образом.
(Хотя я подтверждаю, что тело запроса кодируется UTF-8 следующим образом: E3 81 82
)
requestCharacterEncoding : UTF-8
req.getCharacterEncoding() : UTF-8
body : ???
Случай 3:
Когда я также установил кодировку, используя HttpServletRequest#setCharacterEncoding
в первой строке метода doPost сервлета, тело запроса успешно декодировалось.
requestCharacterEncoding : UTF-8
req.getCharacterEncoding() : UTF-8
body : あ
Случай 4:
Когда я использую http.setRequestHeader('Content-Type', 'text/plain; charset=UTF-8');
javascript, тело запроса успешно декодируется.
requestCharacterEncoding : UTF-8
req.getCharacterEncoding() : UTF-8
body : あ
Случай 5:
Когда я не вызываю req.getParameter("hello")
, тело запроса не может быть успешно декодировано.
requestCharacterEncoding : UTF-8
req.getCharacterEncoding() : UTF-8
body : ???
Случай 6:
Когда я не вызываю ServletContext#setRequestCharacterEncoding
на InitServletContextListener.java
, кодировка символов не устанавливается.
requestCharacterEncoding : null
req.getCharacterEncoding() : null
body : ???
[Примечание]
(*) Я так думаю, потому что:
- (1) В Java-документе
HttpServletRequest#getReader
сказано
«Считыватель переводит данные символов в соответствии с кодировкой символов, используемой в теле».
- (2) В Java-документе
HttpServletRequest#getCharacterEncoding
сказано
«Возвращает имя кодировки символов, используемой в теле этого запроса».
- (3) Документ Java
HttpServletRequest#getCharacterEncoding
также говорит
"Следующие методы для указания кодировки символов запроса используются в порядке убывания приоритета: для запроса, для веб-приложения (с использованием ServletContext.setRequestCharacterEncoding, дескриптор развертывания)".
ServletContext#setResponseCharacterEncoding
работает нормально. Когда я использую ServletContext#setResponseCharacterEncoding
, средство записи, которое возвращает HttpServletResponse#getWriter
, кодирует тело ответа в соответствии с установленной им кодировкой символов.