Spring3 MVC使用@ResponseBody的乱码问题及解决办法

本文介绍了解决Spring MVC框架中使用@ResponseBody返回JSON时出现中文乱码的问题。通过对Spring源码的理解,定制了一个UTF-8编码的StringHttpMessageConverter。

近日用Spring3的MVC写东西,深感其之于Webwork/Struts2的便利,但是在通过@ResponseBody这个annotation输出一个json字符串的时候,发现页面上获得的json字符串中文字符出现了乱码的现象。通过firefox观察返回的字符串,中文部分全部变成了?????的形式,初步判定是返回时,spring处理@ResponseBody使用了错误的编码。

因为我在web.xml中已经配置了Spring的CharacterEncodingFilter,并且强制将request和response的编码都指定为utf-8,所以出现乱码的原因肯定是在Spring内部某处的逻辑了。

把log4j中关于spring的输出级别调为debug,通过访问出问题的地址,发现Spring在处理@ResponseBody这个annotation的时候,org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter使用了org.springframework.http.converter.StringHttpMessageConverter进行处理,于是打开了Spring的源码,看看这个类究竟做了哪些事情。

不看不要紧,一看吓一跳,里面竟然是这样定义其默认编码的:

public static final Charset DEFAULT_CHARSET = Charset.forName("ISO-8859-1");

顿时心生N种不爽:堂堂Spring,竟然还在其中用西欧字符集作为其默认编码,坑爹啊!(很多spring的类中,涉及编码的已经都是utf-8了,比如负责JSON视图的MappingJacksonHttpMessageConverter,就是默认使用UTF-8)。本来想直接修改spring的源码重新打包一个jar出来,后来看spring的java doc发现,其父类org.springframework.http.converter.AbstractHttpMessageConverter中的getDefaultContentType方法是可以重写的:

By default, this returns the first element of the supportedMediaTypes property, if any. Can be overridden in subclasses.

心想这下就简单了,你的DEFAULT_CHARSET不是final么?那我自己继承一个出来,按照我的需求定义为utf-8不就得了?代码如下:

public class UTF8StringHttpMessageConverter extends StringHttpMessageConverter {

	private static final MediaType utf8 = new MediaType("text", "plain", 
			Charset.forName("UTF-8"));

	private boolean writeAcceptCharset = true;

	@Override
	protected MediaType getDefaultContentType(String dumy) {
		return utf8;
	}

	protected List<Charset> getAcceptedCharsets() {
		return Arrays.asList(utf8.getCharSet());
	}

	protected void writeInternal(String s, HttpOutputMessage outputMessage) 
			throws IOException {
		if (this.writeAcceptCharset) {
			outputMessage.getHeaders().setAcceptCharset(getAcceptedCharsets());
		}
		Charset charset = utf8.getCharSet();
		FileCopyUtils.copy(s, new OutputStreamWriter(outputMessage.getBody(), charset));
	}

	public boolean isWriteAcceptCharset() {
		return writeAcceptCharset;
	}

	public void setWriteAcceptCharset(boolean writeAcceptCharset) {
		this.writeAcceptCharset = writeAcceptCharset;
	}
}
然后,在spring的配置文件中添加如下bean声明,用自己写的类替换掉原有的StringHttpMessageConverter

	<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter" >  
		<property name="messageConverters">   
         	<list>   
	              <bean class="com.yougou.mobilemall.framework.base.UTF8StringHttpMessageConverter" />  
	         </list>   
	   </property>  
	</bean>  
再看通过@ResponseBody返回的json字符串,终于中文都可以正常显示了。

<think>好的,用户想要解锁荣耀Play手机的Bootloader(BL)。首先,我需要回顾一下相关的信息。根据用户提供的引用内容,尤其是引用[1]和[2],里面提到了华为荣耀9解锁BL的步骤以及荣耀Play系列手机的一键解锁工具箱。不过要注意的是,华为和荣耀手机近年来可能调整了解锁政策,需要确认最新的方法是否有效。 首先,Bootloader解锁通常需要获取官方的解锁码,但华为在2018年停止提供官方解锁码服务,这可能意味着用户需要寻找其他途径。引用中提到的项目地址可能包含相关工具或教程,但需要用户自行访问查看是否可靠。另外,引用[2]提到了一键解锁平台工具箱,可能是指第三方工具,但使用这些工具存在风险,比如变砖或安全漏洞。 接下来,我需要整理出步骤:1. 准备工作,如备份数据、开启开发者选项和OEM解锁;2. 申请解锁码,可能通过官方渠道(如果可用)或第三方工具;3. 使用解锁码通过Fastboot命令解锁。需要注意的是,解锁会清除数据,且可能影响保修。 同时,用户可能需要了解相关风险,比如操作失败导致设备无法启动,或者第三方工具的安全性。此外,解锁后如何重新上锁也是需要考虑的,但引用中没有提到这部分内容,可能需要进一步研究。 最后,生成相关问题时要围绕解锁BL的后续步骤、风险、替代方案和保修影响等方面,帮助用户全面了解情况。</think>### 解锁荣耀Play手机Bootloader步骤 1. **准备工作** - **备份数据**:解锁BL会清除手机数据,请提前备份重要文件[^1]。 - **开启开发者选项**:进入手机设置→关于手机→连续点击“版本号”7次,激活开发者选项。 - **启用OEM解锁**:在开发者选项中开启“OEM解锁”和“USB调试”功能[^2]。 2. **获取BL解锁码** - 华为已停止官方解锁码服务,需通过第三方工具或平台获取。例如,引用[1]提到的项目地址可能提供相关资源(需自行验证安全性): ``` 项目地址: https://gitcode.com/Resource-Bundle-Collection/2993a ``` - 部分第三方工具箱(如引用[2]中的“一键解锁平台”)可能支持荣耀Play系列,但需注意工具来源的可靠性。 3. **通过Fastboot解锁** - 连接手机至电脑,进入Fastboot模式(关机后按住“音量下+电源键”)。 - 使用ADB命令执行解锁: ```bash fastboot oem unlock [解锁码] ``` - 完成后重启设备,BL状态将显示为“已解锁”。 --- ### 注意事项 - **风险提示**:第三方工具可能导致系统异常(如变砖)或隐私泄露,操作前需评估风险[^1]。 - **保修影响**:解锁BL后,官方保修可能失效。 ---
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值