Проблема кодирования UTF-8 в Spring MVC
Я бин Spring MVC, и я хотел бы вернуть турецкий символ, установив кодировку UTF-8. но хотя моя строка "şŞğĞİıçÇöÖüÜ", она возвращается как "??????çÇöÖüÜ". а также, когда я смотрю на страницу ответа, которая является страницей Internet Explorer, кодировка - это западноевропейский iso, а не UTF-8.
Вот код:
@RequestMapping(method=RequestMethod.GET,value="/GetMyList")
public @ResponseBody String getMyList(HttpServletRequest request, HttpServletResponse response) throws CryptoException{
String contentType= "text/html;charset=UTF-8";
response.setContentType(contentType);
try {
request.setCharacterEncoding("utf-8");
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
response.setCharacterEncoding("utf-8");
String str="şŞğĞİıçÇöÖüÜ";
return str;
}
13 ответов
Я понял это, вы можете добавить к отображению запроса производит = "text/plain;charset=UTF-8"
@RequestMapping(value = "/rest/create/document", produces = "text/plain;charset=UTF-8")
@ResponseBody
public void create(Document document, HttpServletRespone respone) throws UnsupportedEncodingException {
Document newDocument = DocumentService.create(Document);
return jsonSerializer.serialize(newDocument);
}
см. этот пост в блоге для более подробной информации о решении
В контексте xml сервлет-диспетчера вы должны добавить свойство "<property name="contentType" value="text/html;charset=UTF-8" />"
на ваш взгляд bean Resolver. мы используем freemarker для просмотров.
это выглядит примерно так:
<bean id="viewResolver" class="org.springframework.web.servlet.view.freemarker.FreeMarkerViewResolver">
...
<property name="contentType" value="text/html;charset=UTF-8" />
...
</bean>
Конвертируйте строку JSON в UTF-8 самостоятельно.
@RequestMapping(value = "/example.json", method = RequestMethod.GET)
@ResponseBody
public byte[] example() throws Exception {
return "{ 'text': 'äöüß' } ".getBytes("UTF-8");
}
В Spring 5 или, может быть, в более ранних версиях есть MediaType
класс. В нем уже есть правильная строка, если вы хотите следовать DRY:
public static final String APPLICATION_JSON_UTF8_VALUE = "application/json;charset=UTF-8";
Поэтому я использую этот набор аннотаций, связанных с контроллером:
@RestController
@RequestMapping(value = "my/api/url", produces = APPLICATION_JSON_UTF8_VALUE)
public class MyController {
// ... Methods here
}
В документации он помечен как устаревший, но я столкнулся с этой проблемой, и я думаю, что это лучше, чем копировать вышеупомянутую строку для каждого метода / контроллера во всем вашем приложении.
Вам нужно добавить кодировку в аннотацию RequestMapping:
@RequestMapping(path = "/account", produces = "application/json;charset=UTF-8")
вот и все.
Я обнаружил, что "@RequestMapping производит =" и другие изменения конфигурации мне не помогли. К тому времени, как вы выполните функцию resp.getWriter(), будет уже слишком поздно устанавливать кодировку для писателя.
Добавление заголовка в HttpServletResponse работает.
@RequestMapping(value="/test", method=RequestMethod.POST)
public void test(HttpServletResponse resp) {
try {
resp.addHeader("content-type", "application/json; charset=utf-8");
PrintWriter w = resp.getWriter();
w.write("{\"name\" : \"μr μicron\"}");
w.flush();
w.close();
} catch (Exception e) {
e.printStackTrace();
}
}
Есть несколько похожих вопросов: проблема с кодировкой ответов Spring MVC, Custom HttpMessageConverter с @ResponseBody для выполнения задач Json.
Тем не менее, мое простое решение:
@RequestMapping(method=RequestMethod.GET,value="/GetMyList")
public ModelAndView getMyList(){
String test = "čćžđš";
...
ModelAndView mav = new ModelAndView("html_utf8");
mav.addObject("responseBody", test);
}
и представление html_utf8.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>${responseBody}
Никаких дополнительных классов и настроек.
И Вы также можете создать другое представление (например, json_utf8) для другого типа контента.
Если вы используете весеннюю загрузку, просто добавьте эти свойства в файл application.properties:
server.servlet.encoding.charset=UTF-8
server.servlet.encoding.force=true
Когда вы пытаетесь отправить специальные символы, такие как è,à,ù и т. Д., Возможно, вы видите на своей странице Jsp Post много символов, таких как "£", "Ä" или "Æ". Чтобы решить эту проблему в 99% случаев, вы можете переместить в своем файле web.xml этот фрагмент кода в начало файла:
<filter>
<filter-name>encodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
<init-param>
<param-name>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>encodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
Полный пример см. Здесь: https://lentux-informatica.com/spring-mvc-utf-8-encoding-problem-solved/
Если вы используете Spring Boot (протестировано с версией 3.0.4), то UTF-8 по умолчанию будет работать как для запросов, так и для ответов HTTP POST.
Если вы вручную добавили Spring MVC, вам необходимо настроить две вещи:
- CharacterEncodingFilter : фильтр сервлетов Spring Web, который позволяет:
укажите кодировку символов для запросов . Это полезно, поскольку современные браузеры обычно не устанавливают кодировку символов, даже если она указана на странице или форме HTML.
- StringHttpMessageConverter: Spring HttpMessageConverter, который позволяет изменять поле HTTP-заголовка ответа. Без этого заголовок обычно будет вместо UTF-8.
Как установить FeatureEncodingFilter?
Это зависит от конфигурации вашего веб-приложения. Вам следует изучить, как вообще можно установить фильтр сервлетов. ДляCharacterEncodingFilter
вам нужно будет установитьencoding
параметр дляutf-8
иforceEncoding
кtrue
.
Например, если вы используете для настройки фильтров сервлетов, вы можете использовать что-то вроде этого в своем:
<filter>
<filter-name>characterEncodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>utf-8</param-value>
</init-param>
<init-param>
<param-name>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
<init-param>
<param-name>forceResponseEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>characterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
<dispatcher>REQUEST</dispatcher>
</filter-mapping>
Если это не работает (то есть ваш контроллер MVC не получает параметры запроса в формате UTF-8), вам необходимо переместитьcharacterEncodingFilter
выше вweb.xml
, чтобы он вызывался раньше других фильтров.
Как установить StringHttpMessageConverter?
Изменить/добавить свойWebMvcConfigurer
что-то вроде этого:
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import java.nio.charset.StandardCharsets;
import java.util.List;
public class MyCustomWebMvcConfigurer implements WebMvcConfigurer {
@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
converters.add(0, new StringHttpMessageConverter(StandardCharsets.UTF_8));
}
}
Оно используетStandardCharsets.ISO_8859_1
по умолчанию, но приведенный выше код изменит его на UTF-8. Вы можете проверить, работает ли это, проверивContent-Type
заголовок в ответах HTTP. Который теперь должен показатьtext/html;charset=UTF-8
вместоtext/html;charset=ISO-8859-1
.
Если вы используете Spring MVC версии 5, вы можете установить кодировку, также используя @GetMapping
аннотаций. Вот пример, который устанавливает тип контента в JSON, а также тип кодировки в UTF-8:
@GetMapping(value="/rest/events", produces = "application/json; charset=UTF-8")
Больше информации об аннотации @GetMapping здесь:
Я решил эту проблему, выведя полученный тип возврата в первый метод GET requestMethod. Важной частью здесь является
produces="application/json;charset=UTF-8
Поэтому каждый, кто использует /account/**, Spring будет возвращать application/json;charset=UTF-8 тип контента.
@Controller
@Scope("session")
@RequestMapping(value={"/account"}, method = RequestMethod.GET,produces="application/json;charset=UTF-8")
public class AccountController {
protected final Log logger = LogFactory.getLog(getClass());
....//More parameters and method here...
@RequestMapping(value={"/getLast"}, method = RequestMethod.GET)
public @ResponseBody String getUltimo(HttpServletResponse response) throws JsonGenerationException, JsonMappingException, IOException{
ObjectWriter writer = new ObjectMapper().writer().withDefaultPrettyPrinter();
try {
Account account = accountDao.getLast();
return writer.writeValueAsString(account);
}
catch (Exception e) {
return errorHandler(e, response, writer);
}
}
Таким образом, вам не нужно настраивать каждый метод в вашем контроллере, вы можете сделать это для всего класса. Если вам нужен больший контроль над конкретным методом, вам просто нужно определить тип содержимого возвращаемого продукта.
Также добавьте в свои бобы:
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
<property name="messageConverters">
<array>
<bean class="org.springframework.http.converter.StringHttpMessageConverter">
<constructor-arg index="0" name="defaultCharset" value="UTF-8"/>
<property name="supportedMediaTypes">
<list>
<value>text/plain;charset=UTF-8</value>
<value>text/html;charset=UTF-8</value>
<value>application/json;charset=UTF-8</value>
<value>application/x-www-form-urlencoded;charset=UTF-8</value>
</list>
</property>
</bean></bean>
Для @ExceptionHandler:
enter code<bean class="org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver">
<property name="messageConverters">
<array>
<bean class="org.springframework.http.converter.StringHttpMessageConverter">
<constructor-arg index="0" name="defaultCharset" value="UTF-8"/>
<property name="supportedMediaTypes">
<list>
<value>text/plain;charset=UTF-8</value>
<value>text/html;charset=UTF-8</value>
<value>application/json;charset=UTF-8</value>
<value>application/x-www-form-urlencoded;charset=UTF-8</value>
</list>
</property>
</bean>
<bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
<property name="supportedMediaTypes">
<list>
<value>text/plain;charset=UTF-8</value>
<value>text/html;charset=UTF-8</value>
<value>application/json;charset=UTF-8</value>
<value>application/x-www-form-urlencoded;charset=UTF-8</value>
</list>
</property>
</bean>
</array>
</property>
</bean>
Если вы используете <mvc:annotation-driven/>
это должно быть после бобов.