Кто устанавливает тип содержимого ответа в Spring MVC (@ResponseBody) - PullRequest
117 голосов
/ 01 сентября 2010

У меня в Java-приложении Spring MVC, управляемом Annotation, запущено на веб-сервере Jetty (в настоящее время в плагине Maven Jetty).

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

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

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

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

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

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

<bean class="org.springframework.http.converter.StringHttpMessageConverter">
    <property name="supportedMediaTypes" value="text/plain;charset=UTF-8" />
</bean>

Код моего контроллера (обратите внимание, что это изменение типа ответа у меня не работает):

@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;
}

Ответы [ 16 ]

154 голосов
/ 08 августа 2012

Я нашел решение для Spring 3.1. с использованием аннотации @ResponseBody. Вот пример контроллера, использующего вывод Json:

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

}
59 голосов
/ 01 сентября 2010

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

<bean class = "org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
    <property name="messageConverters">
        <array>
            <bean class = "org.springframework.http.converter.StringHttpMessageConverter">
                <property name="supportedMediaTypes" value = "text/plain;charset=UTF-8" />
            </bean>
        </array>
    </property>
</bean>

Однако, используя этот метод, вы должны переопределить все HttpMessageConverter s, итакже он не работает с <mvc:annotation-driven />.

Итак, возможно, самый удобный, но уродливый метод - перехватить создание экземпляра 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;
    }
}

-

<bean class = "EncodingPostProcessor " />
49 голосов
/ 14 октября 2011

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

<mvc:annotation-driven>
  <mvc:message-converters register-defaults="true">
    <bean class="org.springframework.http.converter.StringHttpMessageConverter">
      <property name="supportedMediaTypes" value = "text/plain;charset=UTF-8" />
    </bean>
  </mvc:message-converters>
</mvc:annotation-driven>

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

@Configuration
@EnableWebMvc
public class WebConfig extends WebMvcConfigurerAdapter {

  private static final Charset UTF8 = Charset.forName("UTF-8");

  @Override
  public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
    StringHttpMessageConverter stringConverter = new StringHttpMessageConverter();
    stringConverter.setSupportedMediaTypes(Arrays.asList(new MediaType("text", "plain", UTF8)));
    converters.add(stringConverter);

    // Add other converters ...
  }
}
44 голосов
/ 11 марта 2011

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

@RequestMapping(value = "ajax/gethelp")
public ResponseEntity<String> 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<String>("returning: " + help, responseHeaders, HttpStatus.CREATED);
}

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

19 голосов
/ 19 августа 2012

Вы можете добавить продукции = "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);
}

см. Этот блог для более подробной информации

10 голосов
/ 05 июля 2012

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

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

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

4 голосов
/ 27 мая 2013

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

@RequestMapping(value = "/aURLMapping.htm", method = RequestMethod.GET, produces = "text/html; charset=utf-8") 

public @ResponseBody String getMobileData() {

}
4 голосов
/ 28 ноября 2011

Я устанавливаю тип содержимого в MarshallingView в bean-компоненте ContentNegotiatingViewResolver .Работает легко, чисто и плавно:

<property name="defaultViews">
  <list>
    <bean class="org.springframework.web.servlet.view.xml.MarshallingView">
      <constructor-arg>
        <bean class="org.springframework.oxm.xstream.XStreamMarshaller" />     
      </constructor-arg>
      <property name="contentType" value="application/xml;charset=UTF-8" />
    </bean>
  </list>
</property>
3 голосов
/ 12 марта 2011

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

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

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

if (conv instanceof StringHttpMessageConverter) {                   
                    ((StringHttpMessageConverter) conv).setSupportedMediaTypes(
                        Arrays.asList(
                                new MediaType("text", "html", Charset.forName("UTF-8")),
                                new MediaType("application", "json", Charset.forName("UTF-8")) ));
                }
3 голосов
/ 01 сентября 2010

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

    <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>
</filter>
...