私は注釈駆動のSpring MVC Java Webアプリケーションをjetty Webサーバーで実行しています(現在はMaven jettyプラグインで実行しています)。
Stringヘルプテキストを返す1つのコントローラーメソッドで、いくつかのAJAXサポートを実行しようとしています。リソースはUTF-8エンコードであり、文字列もそうですが、サーバーからの応答には
content-encoding: text/plain;charset=ISO-8859-1
ブラウザが送信する場合でも
Accept-Charset windows-1250,utf-8;q=0.7,*;q=0.7
私は何らかの形で春のデフォルト構成を使用しています
このBeanを構成に追加するためのヒントを見つけましたが、エンコーディングをサポートしておらず、代わりにデフォルトのエンコーディングが使用されていると言われているため、使用されていないと思います。
<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;
}
StringHttpMessageConverter
Beanの単純な宣言では十分ではありません。それを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 />
では機能しません。
したがって、おそらく最も便利だがbutい方法は、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 " />
Spring 3.1のソリューションを見つけました。 @ResponseBodyアノテーションを使用します。 Json出力を使用したコントローラーの例を次に示します。
@RequestMapping(value = "/getDealers", method = RequestMethod.GET,
produces = "application/json; charset=utf-8")
@ResponseBody
public String sendMobileData() {
}
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 ...
}
}
念のため、次の方法でもエンコードを設定できます。
@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の使用はこれよりも優れていると思います。
プロデュース= "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);
}
私は最近この問題と戦っていて、Spring 3.1で利用できるより良い答えを見つけました。
@RequestMapping(value = "ajax/gethelp", produces = "text/plain")
そのため、すべてのコメントが示すように、JAX-RSと同じくらい簡単です。
ContentNegotiatingViewResolver BeanのMarshallingViewでcontent-typeを設定します。簡単に、きれいに、スムーズに動作します:
<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>
Producesを使用して、コントローラーから送信する応答のタイプを示すことができます。この「produces」キーワードは、ajaxリクエストで最も役立ち、私のプロジェクトで非常に役立ちました。
@RequestMapping(value = "/aURLMapping.htm", method = RequestMethod.GET, produces = "text/html; charset=utf-8")
public @ResponseBody String getMobileData() {
}
Web.xmlで構成されたCharacterEncodingFilterを使用しています。たぶんそれが役立ちます。
<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>
Digz6666に感謝します。jsonを使用しているため、わずかな変更を加えるだけで解決できます
responseHeaders.add( "Content-Type"、 "application/json; charset = utf-8");
Axtavt(あなたがお勧めした)によって与えられた答えは、私にとってはうまくいきません。正しいメディアタイプを追加した場合でも:
if(StringHttpMessageConverterのインスタンス){ ((StringHttpMessageConverter)conv).setSupportedMediaTypes( Arrays.asList( new MediaType( "text"、 "html" 、Charset.forName( "UTF-8"))、 new MediaType( "application"、 "json"、Charset.forName( "UTF-8")))); }
次の構成でこの問題を修正する場合:
<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>
すべての* .xmlファイルにmvc:annotation-drivenタグが1つだけあることを確認する必要があります。そうしないと、構成が有効にならない場合があります。
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");
}
}
この問題に対して多くの回避策を試した後、私はこれを考え出したが、うまく機能した。
Spring 3.1.1でこの問題を解決する簡単な方法は、次の構成コードをservlet-context.xml
に追加することです。
<annotation-driven>
<message-converters register-defaults="true">
<beans:bean class="org.springframework.http.converter.StringHttpMessageConverter">
<beans:property name="supportedMediaTypes">
<beans:value>text/plain;charset=UTF-8</beans:value>
</beans:property>
</beans:bean>
</message-converters>
</annotation-driven>
何もオーバーライドまたは実装する必要はありません。
上記のどれもうまくいかなかった場合、「GET」ではなく「POST」でajaxリクエストを作成しようとすると、うまくいきました...上記のどれもうまくいきませんでした。 characterEncodingFilterもあります。
link によると、文字エンコーディングが指定されていない場合、サーブレット仕様ではISO-8859-1のエンコーディングを使用する必要があります。 "Spring 3.1以降を使用している場合は、休閑設定を使用してcharset = UTF-8を応答本文に設定します
@ RequestMapping(value = "your mapping url"、produces = "text/plain; charset = UTF-8")
public final class ConfigurableStringHttpMessageConverter extends AbstractHttpMessageConverter<String> {
private Charset defaultCharset;
public Charset getDefaultCharset() {
return defaultCharset;
}
private final List<Charset> 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>(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>(Charset.availableCharsets().values());
}
/**
* Indicates whether the {@code Accept-Charset} should be written to any outgoing request.
* <p>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}.
*
* <p>By default, returns {@link Charset#availableCharsets()}. Can be overridden in subclasses.
*
* @return the list of accepted charsets
*/
protected List<Charset> getAcceptedCharsets() {
return this.availableCharsets;
}
private Charset getContentTypeCharset(MediaType contentType) {
if (contentType != null && contentType.getCharSet() != null) {
return contentType.getCharSet();
}
else {
return defaultCharset;
}
}
}
サンプル構成:
<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
<property name="messageConverters">
<util:list>
<bean class="ru.dz.mvk.util.ConfigurableStringHttpMessageConverter">
<constructor-arg index="0" value="UTF-8"/>
</bean>
</util:list>
</property>
</bean>