现如今,对于javaweb开发的领域,spring一直是绕不过的技术核心,发展到4.x版本之后,更是愈发强大。还记得学生时代的我,曾一度排斥着这些框架,一个是趋于避难就易的惰性,另一个在学校也确实没能有机会去接触到一个量级的项目来见证这些框架的强大,还在自己的世界里,坐进观天,憧憬着靠自己的手和脑来支撑一切,现在看到这是多么的狭隘和无知(不过,学生时代的“我们”确实见识有限)。后来,在使用过spring/springmvc之后,不禁越来越越喜欢他们,爱不释手。的确,框架在背后默默地为我们做了很多事情,以致于可以让我们忽略那些琐碎的事情,而专注于业务本身,如此程度的松耦合,不禁让我们平时在写代码时有了更多的思考,开始思考自己的代码,再次审度自己的思维习惯。关于spring/springmvc相关的一些体会和心得,相信大家都深有体会。这次这篇博客,只为记录工作和学习中遇到的一些问题,用以备忘和总结。
注:如果理解有误请友情联系一个,大家共同学习,共同进步。
问题一、在使用@RequestBody注解接受ajax提交的form参数时,出现ajax请求400、415错误问题。
场景:前端有一个表单,需要提交到后台处理,为此,后台构造了一个JavaBean用于接受参数,前端用ajax的post方式提交请求,采用
(formid).serialize()序列化参数,在没有用springmvc之前,我们会用到BeanUtils的populate函数来做对象的填充,但是springmvc给我们提供了一个强大的注解@RequestBody,它可以将post提交的json字符串直接反射成一个对应的对象,但是在实战中,前端ajax始终收到的是服务器400的错误。出错原因:默认的@RequestBody可以将json数据处理成对应对象,其它格式不能直接转化解决办法:1、为自己的自定义数据类型构造对应的HttpMessageConverter解析。2、将前端数据处理为json格式后提交。注意,
(formid).serialize()序列化得到的结果是类似于:name=zhangsan&age=19的格式。
于是,我们对此进行一点小小的加工,在前端写一个js的方法:
function transToJson(data)
{
data=data.replace(/&/g,"\",\"");
data=data.replace(/=/g,"\":\"");
data="{\""+data+"\"}";
return data;
}
将$(formid).serialize()得到的字符串作为参数传进去。得到json。再次运行程序,居然还是报错。。
这时真的是郁闷了,最后在查证后,才发现,虽然数据是json格式,要在ajax里面加上:
contentType: "application/json; charset=utf-8",
才行,再次运行得到答案,此时后台完美拿到结果。
这只是其中一个解决办法,我只提供我自己使用并且通过的, 如果有其他的解决办法,欢迎大家一起交流和学习。
问题二,在使用@ResponesBody注解时,出现中文乱码问题(截选自:http://www.tuicool.com/articles/zeeQfe)
出现乱码的原因:SpringMVC的@ResponseBody返回中文乱码的原因是SpringMVC默认处理的字符集是ISO-8859-1,在Spring的org.springframework.http.converter.StringHttpMessageConverter类中可以看到如下代码:
public static final Charset DEFAULT_CHARSET = Charset.forName("ISO-8859-1");
解决返回中文乱码的问题有两种,第一种是局部的,只针对于某个方法的返回进行处理,第二种是全局的,针对于整个项目,如下:
第一种:在@RequestMapping中添加produces=”text/html;charset=UTF-8,如:
@RequestMapping(value="/login.do",method=RequestMethod.POST,produces="text/html;charset=UTF-8")
@ResponseBody
public String login(@RequestParam(value="username") String userName,@RequestParam(value="password") String password){
return JSONMessageUtil.getSuccessJSON("登录成功");
}
第二种:在配置文件中的mvc:annotation-driven中添加如下代码:
<mvc:annotation-driven >
<!-- 消息转换器 -->
<mvc:message-converters register-defaults="true">
<bean class="org.springframework.http.converter.StringHttpMessageConverter">
<property name="supportedMediaTypes" value="text/html;charset=UTF-8"/>
</bean>
</mvc:message-converters>
</mvc:annotation-driven>
<mvc:resources location="/resources/" mapping="/resources/**" />
重启服务,一切正常,中文没有乱码了。
问题三:在非spring context中的class想要拿到spring context的几种途径
有时候,我们经常会在项目中引用一些第三方的工具,但是他们本身没有集成在spring,我们想在其中注入我们spring的bean时,常用的有以下几种策略:
- 在测试代码中:
public static ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
public static Object getBean(String serviceName){
return context.getBean(serviceName);
}
这种方式可以用于纯spring项目中,但是不建议使用,因为指定文件这种事情维护起来容易疏漏。关键的是,这样会重新初始化一次上下文。
- 在spring项目中使用ApplicationContextAware 接口,获取正在运行中的上下文环境。
@Component
public class SpringContextUtil implements ApplicationContextAware {
private static ApplicationContext applicationContext; // Spring应用上下文环境
/*
* 实现了ApplicationContextAware 接口,必须实现该方法;
*通过传递applicationContext参数初始化成员变量applicationContext
*/
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
SpringContextUtil.applicationContext = applicationContext;
}
public static ApplicationContext getApplicationContext() {
return applicationContext;
}
@SuppressWarnings("unchecked")
public static <T> T getBean(String name) throws BeansException {
return (T) applicationContext.getBean(name);
}
}
注意,这里需要在xml中配置这个bean(当然直接注解也行)。
- 在spring web的环境中,可以使用WebApplicationObjectSupport接口完成。例如:
@Component
public final class SpringContextGetter extends WebApplicationObjectSupport {
private static ApplicationContext applicationContext = null;
@Override
protected void initApplicationContext(ApplicationContext context) {
super.initApplicationContext(context);
if(applicationContext == null){
applicationContext = context;
}
}
public static ApplicationContext getAppContext() {
return applicationContext;
}
public static Object getBean(String name){
return applicationContext.getBean(name);
}
}
这样,就可以啦。
关于方法二和方法三,我们看看他的代码,就不难发现它的原理,将上下文装载进来之后,让在容器中,通过static方法提供出去。很巧妙吧。