Кто устанавливает тип содержимого ответа в Spring MVC (@ResponseBody)

У меня есть в моем приложении, посвященном annotations, Spring Web MVC Java, запущенном на причальном веб-сервере (в настоящее время в плагине maven).

Я пытаюсь выполнить некоторую поддержку AJAX с помощью одного метода controllerа, возвращающего только текст справки String. Ресурсы находятся в кодировке UTF-8, а также строка, но мой ответ с сервера приходит с

content-encoding: text/plain;charset=ISO-8859-1 

даже когда мой браузер отправляет

 Accept-Charset windows-1250,utf-8;q=0.7,*;q=0.7 

Я использую как-то конфигурацию по умолчанию весны

Я нашел подсказку, чтобы добавить этот компонент в конфигурацию, но я думаю, что он просто не используется, потому что он говорит, что он не поддерживает кодировку, а используется по умолчанию.

    

Мой код controllerа (обратите внимание, что это изменение типа ответа не работает для меня):

 @RequestMapping(value = "ajax/gethelp") public @ResponseBody String handleGetHelp(Locale loc, String code, HttpServletResponse response) { log.debug("Getting help for code: " + code); response.setContentType("text/plain;charset=UTF-8"); String help = messageSource.getMessage(code, null, loc); log.debug("Help is: " + help); return help; } 

Простое объявление компонента StringHttpMessageConverter недостаточно, вам нужно ввести его в AnnotationMethodHandlerAdapter :

          

Однако, используя этот метод, вы должны переопределить все HttpMessageConverter s, а также не работать с .

Таким образом, возможно, наиболее удобным, но уродливым методом является перехват экземпляра AnnotationMethodHandlerAdapter с помощью BeanPostProcessor :

 public class EncodingPostProcessor implements BeanPostProcessor { public Object postProcessBeforeInitialization(Object bean, String name) throws BeansException { if (bean instanceof AnnotationMethodHandlerAdapter) { HttpMessageConverter[] convs = ((AnnotationMethodHandlerAdapter) bean).getMessageConverters(); for (HttpMessageConverter conv: convs) { if (conv instanceof StringHttpMessageConverter) { ((StringHttpMessageConverter) conv).setSupportedMediaTypes( Arrays.asList(new MediaType("text", "html", Charset.forName("UTF-8")))); } } } return bean; } public Object postProcessAfterInitialization(Object bean, String name) throws BeansException { return bean; } } 

  

Я нашел решение для Spring 3.1. с использованием annotations @ResponseBody. Вот пример controllerа с использованием Json-вывода:

 @RequestMapping(value = "/getDealers", method = RequestMethod.GET, produces = "application/json; charset=utf-8") @ResponseBody public String sendMobileData() { } 

Обратите внимание, что в Spring MVC 3.1 вы можете использовать пространство имен MVC для настройки преобразователей сообщений:

        

Или конфигурация на основе кода:

 @Configuration @EnableWebMvc public class WebConfig extends WebMvcConfigurerAdapter { private static final Charset UTF8 = Charset.forName("UTF-8"); @Override public void configureMessageConverters(List> converters) { StringHttpMessageConverter stringConverter = new StringHttpMessageConverter(); stringConverter.setSupportedMediaTypes(Arrays.asList(new MediaType("text", "plain", UTF8))); converters.add(stringConverter); // Add other converters ... } } 

На всякий случай вы также можете установить кодировку следующим образом:

 @RequestMapping(value = "ajax/gethelp") public ResponseEntity handleGetHelp(Locale loc, String code, HttpServletResponse response) { HttpHeaders responseHeaders = new HttpHeaders(); responseHeaders.add("Content-Type", "text/html; charset=utf-8"); log.debug("Getting help for code: " + code); String help = messageSource.getMessage(code, null, loc); log.debug("Help is: " + help); return new ResponseEntity("returning: " + help, responseHeaders, HttpStatus.CREATED); } 

Я думаю, что использование StringHttpMessageConverter лучше, чем это.

вы можете добавить results = “text / plain; charset = UTF-8” в RequestMapping

 @RequestMapping(value = "/rest/create/document", produces = "text/plain;charset=UTF-8") @ResponseBody public String create(Document document, HttpServletRespone respone) throws UnsupportedEncodingException { Document newDocument = DocumentService.create(Document); return jsonSerializer.serialize(newDocument); } 

подробнее см. в этом блоге

Недавно я боролся с этой проблемой и нашел гораздо лучший ответ, ansible весной 3.1:

 @RequestMapping(value = "ajax/gethelp", produces = "text/plain") 

Итак, так же просто, как JAX-RS, точно так же, как и все комментарии, которые он мог / должен быть.

Я установил тип содержимого в MarshallingView в компоненте ContentNegotiationViewResolver . Он работает легко, чисто и плавно:

           

Вы можете использовать результаты, чтобы указать тип ответа, который вы отправляете с controllerа. Это ключевое слово «производит» будет наиболее полезным в запросе ajax и было очень полезно в моем проекте

 @RequestMapping(value = "/aURLMapping.htm", method = RequestMethod.GET, produces = "text/html; charset=utf-8") public @ResponseBody String getMobileData() { } 

Я использую CharacterEncodingFilter, настроенный в web.xml. Может быть, это помогает.

   characterEncodingFilter org.springframework.web.filter.CharacterEncodingFilter  encoding UTF-8   forceEncoding true   

Спасибо digz6666, ваше решение работает для меня с небольшими изменениями, потому что я использую json:

 responseHeaders.add («Content-Type», «application / json; charset = utf-8»);

Ответ, данный axtavt (который вы рекомендовали), не будет работать для меня. Даже если я добавил правильный тип носителя:

 if (conv instanceof StringHttpMessageConverter) {                   
                     ((StringHttpMessageConverter) conv) .setSupportedMediaTypes (
                         Arrays.asList (
                                 новый MediaType («текст», «html», Charset.forName («UTF-8»)),
                                 новый MediaType («приложение», «json», Charset.forName («UTF-8»))));
                 }

если ни одно из вышеперечисленных действий для вас не пыталось сделать ajax-запросы на «POST», а не «GET», это сработало для меня красиво … ни один из вышеперечисленных дел не сделал. У меня также есть characterEncodingFilter.

 package com.your.package.spring.fix; import java.io.UnsupportedEncodingException; import java.net.URLDecoder; import java.net.URLEncoder; /** * @author Szilard_Jakab (JaKi) * Workaround for Spring 3 @ResponseBody issue - get incorrectly encoded parameters from the URL (in example @ JSON response) * Tested @ Spring 3.0.4 */ public class RepairWrongUrlParamEncoding { private static String restoredParamToOriginal; /** * @param wrongUrlParam * @return Repaired url param (UTF-8 encoded) * @throws UnsupportedEncodingException */ public static String repair(String wrongUrlParam) throws UnsupportedEncodingException { /* First step: encode the incorrectly converted UTF-8 strings back to the original URL format */ restoredParamToOriginal = URLEncoder.encode(wrongUrlParam, "ISO-8859-1"); /* Second step: decode to UTF-8 again from the original one */ return URLDecoder.decode(restoredParamToOriginal, "UTF-8"); } } 

После того, как я пробовал много обходного пути для этой проблемы .. Я подумал об этом, и все работает отлично.

Простой способ решить эту проблему весной 3.1.1 заключается в следующем: добавьте следующие коды конфигурации в servlet-context.xml

      text/plain;charset=UTF-8     

Не нужно переопределять или внедрять что-либо.

Согласно ссылке «Если кодировка символов не указана, спецификация Servlet требует использования кодировки ISO-8859-1». Если вы используете Spring 3.1 или более позднюю версию, используйте конфигурацию для установки charset = UTF-8 на орган реагирования
@RequestMapping (value = “ваш URL-адрес для сопоставления”, производит = “text / plain; charset = UTF-8”)

если вы решите исправить эту проблему в следующей конфигурации:

        

вы должны подтвердить, что во всем вашем файле * .xml должен быть только один тег mvc: annotation. в противном случае конфигурация может быть неэффективной.

 public final class ConfigurableStringHttpMessageConverter extends AbstractHttpMessageConverter { private Charset defaultCharset; public Charset getDefaultCharset() { return defaultCharset; } private final List availableCharsets; private boolean writeAcceptCharset = true; public ConfigurableStringHttpMessageConverter() { super(new MediaType("text", "plain", StringHttpMessageConverter.DEFAULT_CHARSET), MediaType.ALL); defaultCharset = StringHttpMessageConverter.DEFAULT_CHARSET; this.availableCharsets = new ArrayList(Charset.availableCharsets().values()); } public ConfigurableStringHttpMessageConverter(String charsetName) { super(new MediaType("text", "plain", Charset.forName(charsetName)), MediaType.ALL); defaultCharset = Charset.forName(charsetName); this.availableCharsets = new ArrayList(Charset.availableCharsets().values()); } /** * Indicates whether the {@code Accept-Charset} should be written to any outgoing request. * 

Default is {@code true}. */ public void setWriteAcceptCharset(boolean writeAcceptCharset) { this.writeAcceptCharset = writeAcceptCharset; } @Override public boolean supports(Class clazz) { return String.class.equals(clazz); } @Override protected String readInternal(Class clazz, HttpInputMessage inputMessage) throws IOException { Charset charset = getContentTypeCharset(inputMessage.getHeaders().getContentType()); return FileCopyUtils.copyToString(new InputStreamReader(inputMessage.getBody(), charset)); } @Override protected Long getContentLength(String s, MediaType contentType) { Charset charset = getContentTypeCharset(contentType); try { return (long) s.getBytes(charset.name()).length; } catch (UnsupportedEncodingException ex) { // should not occur throw new InternalError(ex.getMessage()); } } @Override protected void writeInternal(String s, HttpOutputMessage outputMessage) throws IOException { if (writeAcceptCharset) { outputMessage.getHeaders().setAcceptCharset(getAcceptedCharsets()); } Charset charset = getContentTypeCharset(outputMessage.getHeaders().getContentType()); FileCopyUtils.copy(s, new OutputStreamWriter(outputMessage.getBody(), charset)); } /** * Return the list of supported {@link Charset}. * *

By default, returns {@link Charset#availableCharsets()}. Can be overridden in subclasses. * * @return the list of accepted charsets */ protected List getAcceptedCharsets() { return this.availableCharsets; } private Charset getContentTypeCharset(MediaType contentType) { if (contentType != null && contentType.getCharSet() != null) { return contentType.getCharSet(); } else { return defaultCharset; } } }

Пример конфигурации:

           
  • Изменение кодировки PowerShell по умолчанию для UTF-8
  • Давайте будем гением компьютера.