SpringMVC 中整合JSON
- 格式:doc
- 大小:278.00 KB
- 文档页数:31
SpringMVC+GSON对象序列化--⽇期格式的处理Gson异常强⼤因此使⽤它代替了Jackson作为SpringMVC消息转换器。
在⾃⼰的项⽬中,发现对象在序列化后,⽇期格式出现了问题。
先看问题在员⼯表中有⼀列是⽣⽇,字段类型为Date,也就是只存储到年⽉⽇,不带⼩时分秒,见下图数据库中的数据前台列表向后台请求数据,然后在页⾯显⽰,可以看到,⽇期后⾯带有了⼩时分秒,⽽对于⽣⽇来说,这是没有意义的。
见下图问题出现在哪?问题就出现在了 spring 的 message-converters 上,在我的项⽬中,配置的类型转换器为 google的 gson。
可以看到全局配置为“yyyy-MM-dd HH:mm:ss:SSS” ,这是带有⼩时分秒的。
所以当请求返回给浏览器的时候,spring会利⽤Gson将对象序列化输出到前端,按照配置的规则,就会带有⼩时分秒了。
具体见下⾯的代码:<!--开启 spring-mvc注解--><mvc:annotation-driven><!--设置JSON转换器为Gson--><mvc:message-converters register-defaults="true"><bean class="org.springframework.http.converter.StringHttpMessageConverter"><property name="supportedMediaTypes"><list><value>text/plain;charset=UTF-8</value><value>text/html;charset=UTF-8</value></list></property></bean><bean class="org.springframework.http.converter.json.GsonHttpMessageConverter"><property name="supportedMediaTypes"><list><value>text/plain;charset=UTF-8</value><value>application/json;charset=UTF-8</value></list></property><property name="gson"><bean class="org.springframework.http.converter.json.GsonFactoryBean"><property name="serializeNulls" value="true"/><property name="disableHtmlEscaping" value="true"/><property name="dateFormatPattern" value="yyyy-MM-dd HH:mm:ss:SSS"/></bean></property></bean></mvc:message-converters></mvc:annotation-driven>如何解决呢?两种办法:1、修改全局设置,将上述的配置修改yyyy-MM-dd。
Spring整合RedisJSON序列化SpringWeb项⽬部署相关⼏种JSON框架⽤法和效率对⽐:json-lib:Jackson:Gson:fastJson:Spring整合JUnit4:Spring注解加载配置⽂件:Spring代码获取配置⽂件属性值:SpringBoot读取配置⽂件:Spring的@Configuration配置类引⼊xml:纯注解配置SpringMVC:传统配置消息转换器和⾃定义消息转换器:旧版消息转换器配置:Web项⽬部署问题:1.Mapper⽅法找不到对应绑定:源于pom⽂件中的maven打包没有配置resource把Mapper.xml打包到classes⽬录中,也就是实际运⾏缺少Mapper.xml⽂件,需要在pom.xml中加⼊(如果Mapper.xml放在resources⾥⾯就不需要了):<build><resources><resource><directory>src/main/java</directory><includes><include>**/*.xml</include></includes></resource><resource><directory>src/main/resources</directory></resource></resources></build>问题和解决办法详见:2.找不到/WEB-INF/views下⾃定义的jsp页⾯,源于使⽤IDEA的Artifacts打包时,Web模块的⾃定义⽂件夹需要⼿动加⼊,具体⽅法如下:补充:jsp的c:foreach标签⽤法:3.maven命令打包报错找不到webxml配置或web.xml⽂件:需要在pom.xml中⼿动指定其位置:<plugins><plugin><artifactId>maven-war-plugin</artifactId><configuration><!--<version>2.5</version>--><webXml>web/WEB-INF/web.xml</webXml></configuration></plugin></plugins>参考:不创建web.xml的解决办法:IDEA中有时部署Tomcat需要重新编译,在Project Structure中指定Web模块的根⽬录位置,让其变成⼩地球标志,然后按2中⽅式,在Artifacts中加⼊⾃定义⽂件夹,有时需要加⼊web.xml⽂件maven打包时打war包:<packaging>war</packaging>使⽤Lifecycle下的install命令:或使⽤build中配置的各种插件(⽐如compile插件,spring boot插件等)springmvc(Web)整合logback:mybatis打印sql:mybatis官⽅⽂档:MyBatis中Mapper.xml⽂件位置配置和打包引⼊⽅式:Spring整合MyBatis的Mapper类配置:Maven打包⾃定义包含资源⽂件:在Web项⽬使⽤maven打包时,就使⽤maven-war-plugin插件,指定web资源根⽬录,配置成WEB-INF⽬录即可,这样在IDEA中配置Web模块时也指定根⽬录为WEB-INF,这样在Artifacts中导出war包和使⽤maven打war包时就可以包含到WEB-INF⽬录下的jsp资源⽬录和web.xml⽂件,具体配置如下:<build><plugins><plugin><artifactId>maven-war-plugin</artifactId><configuration><!--<version>2.5</version>--><webResources><resource><!-- 元配置⽂件的⽬录,相对于pom.xml⽂件的路径 --><directory>web/WEB-INF</directory><!-- 是否过滤⽂件,也就是是否启动auto-config的功能 --><filtering>true</filtering><!-- ⽬标路径 --><targetPath>WEB-INF</targetPath></resource></webResources><webXml>web/WEB-INF/web.xml</webXml></configuration></plugin></plugins><resources><resource><directory>src/main/java</directory><includes><include>**/*.xml</include></includes></resource><resource><directory>src/main/resources</directory></resource></resources></build>Spring整合Redis作为缓存(使⽤@EnableCaching):⼿动(代码)缓存(结合Spring):Spring缓存注解:缓存注解操作多个缓存(使⽤@Caching):SpEL表达式:⼿写模糊和批量删除(aspect,aop):缓存注解key异常问题(字符串类型要加单引号!!):<cache:annotation-driven/>启动缓存注解,和使⽤Cache接⼝⾃定义缓存操作、序列化:Jackson序列化注解实现POJO的JSON序列化(⽤于SpringMVC的@ResponseBody返回POJO数据,需要配合Jackson消息转换器):Spring整合Redis序列化:Spring整合Redis序列化原理和⾃定义序列化:序列化问题:序列化性能⽐较和压⼒测试:缓存key⽣成问题:官⽅gitHub问题解答:截取:@Configuration@EnableCachingpublic class RedisConfig {@Beanpublic KeyGenerator simpleKeyGenerator() {return (target, method, params) -> {StringBuilder sb = new StringBuilder();sb.append(target.getClass().getName());sb.append(method.getName());for (Object obj : params) {sb.append(obj.toString());}return sb.toString();};}@Beanpublic CacheManager cacheManager(RedisTemplate redisTemplate) {return new RedisCacheManager(redisTemplate);}@Beanpublic StringRedisTemplate redisTemplate(RedisConnectionFactory factory) {final StringRedisTemplate template = new StringRedisTemplate(factory);Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);ObjectMapper om = new ObjectMapper();om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);jackson2JsonRedisSerializer.setObjectMapper(om);template.setValueSerializer(jackson2JsonRedisSerializer);template.afterPropertiesSet();return template;}}@CacheConfig(cacheNames = "bangumis")@CacheableI am not sure that your KeyGenerator is taken into account. Could you please extend CachingConfigurerSupport and make sure you override the keyGenerator() method please? (This is actually unrelated to Spring Boot).More infoif i set keyGenerator@CacheConfig(cacheNames = "bangumis",keyGenerator = "simpleKeyGenerator")it work,but for this I must set this keyGenerator in everywhere?I just told you.@Configuration@EnableCachingpublic class RedisConfig extends CachingConfigurerSupport {@Bean@Overridepublic KeyGenerator keyGenerator() { ... }...}ok,thank you@EnableCaching注解:spring-data-redis缓存序列化:spring-data-redis缓存注解:⾼可⽤Redis配置:Spring Boot整合Redis:Redis安装问题:1.Ubuntu默认⽆法使⽤root⽤户(没有密码),普通⽤户执⾏make等需要sudo2.cp,tar,wget这些命令在/usr/local这样的⽬录使⽤普通⽤户执⾏,没有权限,⼀般是因为⽆法在这些⽬录创建新的⽂件或⽬录,因为普通⽤户没有这些⽬录的写权限(w),所以也要⽤sudo3.普通⽤户启动Redis等软件应⽤,是否能成功,要看其是否有相关命令⽂件的可执⾏权限(x),配置⽂件的读权限(r),⽽不是安装在了什么⽬录,当然⼀般需要能进⼊这些⽬录4.Redis启动后⽆法通过redis-cli或强制ctrl+c终⽌,提⽰⽆法向DB保存数据,是因为启动⽤户没有配置⽂件redis.conf中配置的DB⽬录写权限。
SpringMVC更灵活的控制json返回问题(⾃定义过滤字段)这篇⽂章主要讲 Spring MVC 如何动态的去返回 Json 数据在我们做 Web 接⼝开发的时候,经常会遇到这种场景。
两个请求,返回同⼀个对象,但是需要的返回字段并不相同。
如以下场景/*** 返回所有名称以及Id*/@RequestMapping("list")@ResponseBodypublic List<Article> findAllNameAndId() {return articleService.findAll();}/*** 返回所有⽬录详情*/@RequestMapping("list-detail")@ResponseBodypublic List<Article> findAllDetail() {return articleService.findAll();}Spring MVC 默认使⽤转json框架是 jackson。
⼤家也知道, jackson 可以在实体类内加注解,来指定序列化规则,但是那样⽐较不灵活,不能实现我们⽬前想要达到的这种情况。
这篇⽂章主要讲的就是通过⾃定义注解,来更加灵活,细粒化控制 json 格式的转换。
最终我们需要实现如下的效果:@RequestMapping(value = "{id}", method = RequestMethod.GET)// 返回时候不包含 filter 内的 createTime, updateTime 字段@JSON(type = Article.class, filter="createTime,updateTime")public Article get(@PathVariable String id) {return articleService.get(id);}@RequestMapping(value="list", method = RequestMethod.GET)// 返回时只包含 include 内的 id, name 字段@JSON(type = Article.class , include="id,name")public List<Article> findAll() {return articleService.findAll();}jackson 编程式过滤字段jackson 中,我们可以在实体类上加上 @JsonFilter 注解,并且通过 ObjectMapper.setFilterProvider 来进⾏过滤规则的设置。
MVC中返回json数据的两种⽅式⾸先解释⼀下ActionResult与IActionResultActionResult⼀般⽤来返回ViewResult,PartialViewResult,JsonResultIActionResult⼀般⽤来返回预定义响应和错误,⽐如404MVC⾥⾯如果直接将数据返回到前端页⾯,我们常⽤的⽅式就是⽤return view();那么我不想直接⽤razor语法,毕竟razor这玩意⼉实在是太难记了,还不如写ajax对接来得舒服不是那么我们可以这么做1.定义ActionResult,返回json,标记属性可以采⽤HttpPost,也可以是⽤HttpGet,按⾃⼰的需求来使⽤public ActionResult UpdateDownloadInJson(string deviceNames,string programNames){string[] deviceName = deviceNames.Split(',');string[] programName = programNames.Split(',');List<DownloadViewModel> DownloadViewModelList = new List<DownloadViewModel>();foreach (string tempDeviceName in deviceName){var _deviceId=deviceInfoService.FindSingle<DeviceInfo>(r => r.DeviceName == tempDeviceName).Id;foreach (string tempProgramName in programName){int _programId = publishDetailService.Set<ProgramInfo>().Where(r => r.ProgramName == tempProgramName).FirstOrDefault().Id;var progress= publishDetailService.Set<DeviceMaterial>().Where(r => r.DeviceId == _deviceId && r.ProgramId == _programId).FirstOrDefault().DownProgress; DownloadViewModelList.Add(new DownloadViewModel{DeviceId= (int)_deviceId,DeviceName = tempDeviceName,ProgramName = tempProgramName,DownloadProgress = (int)progress});}}return Json(new AjaxResult{Result = DoResult.Success,RetValue = DownloadViewModelList}, JsonRequestBehavior.AllowGet);}2.采⽤JsonResult,最主要拿来处理ajax请求[HttpPost][HandlerAjaxOnly]public JsonResult CheckLogin(string username, string password, string code){UserManage.LoginResult result = erLogin(username, password, code);if (result == UserManage.LoginResult.Success){return Json(new AjaxResult { Result = DoResult.Success, DubugMessage = "登陆成功。
springmvccontroller返回json出错解决1、出错的地方:@RequestMapping(value = "/query")@JsonSerialize(include=JsonSerialize.Inclusion.NON_NULL)public @ResponseBodyJSONObject query(@RequestParam("startTime") String startTime,@RequestParam("endTime") String endTime,@RequestParam("oid") String oid, @RequestParam("cid") Integer cid, @RequestParam("pay_channel") String payChannel,@RequestParam("device_type") String deviceType,@RequestParam("phone") Integer phone,@RequestParam("perPage") Integer pageSize,@RequestParam("skipIndex") Integer startIndex) throws Exception {LogInfo info = populateQueryParam(startTime, endTime, oid, cid, payChannel, deviceType, phone, pageSize, startIndex);// 总记录数Long totalCount = logMoniterService.queryLogInfoCount(info);if (totalCount == null) {totalCount = 0L;}List<LogInfo> list = logMoniterService.queryLogInfo(info);JSONObject retData = new JSONObject();retData.put("success", true);retData.put("data", list);retData.put("error", "");retData.put("totalRecords", totalCount);return retData;}2、结果报错:<html><head><title>Apache Tomcat/7.0.42 - Errorreport</title><style><!--H1{font-family:Tahoma,Arial,sans-serif;color:white;background-color:#52 5D76;font-size:22px;} H2{font-family:Tahoma,Arial,sans-serif;color:white;background-color:#52 5D76;font-size:16px;} H3{font-family:Tahoma,Arial,sans-serif;color:white;background-color:#52 5D76;font-size:14px;} BODY{font-family:Tahoma,Arial,sans-serif;color:black;background-color:whi te;} B{font-family:Tahoma,Arial,sans-serif;color:white;background-color:#52 5D76;} P{font-family:Tahoma,Arial,sans-serif;background:white;color:black;fon t-size:12px;}A {color : black;} {color : black;}HR {color :#525D76;}--></style> </head><body><h1>HTTP Status 500 - Could not write JSON: Object is null (through reference chain:net.sf.json.JSONObject["data"]->net.sf.json.JSONArray[0] ->net.sf.json.JSONObject["createTime"]->net.sf.json.J SONNull["empty"]); nested exception isorg.codehaus.jackson.map.JsonMappingException: Object is null (through reference chain:net.sf.json.JSONObject["data"]->net.sf.json.JSONArray[0] ->net.sf.json.JSONObject["createTime"]->net.sf.json.J SONNull["empty"])</h1><HR size="1"noshade="noshade"><p><b>type</b> Exception report</p><p><b>message</b> <u>Could not write JSON: Object is null (through reference chain: net.sf.json.JSONObject["data"]->net.sf.json.JSONArray[0] ->net.sf.json.JSONObject["createTime"]->net.sf.json.J SONNull["empty"]); nested exception isorg.codehaus.jackson.map.JsonMappingException: Object is null (through reference chain:net.sf.json.JSONObject["data"]->net.sf.json.JSONArray[0] ->net.sf.json.JSONObject["createTime"]->net.sf.json.J SONNull["empty"])</u></p><p><b>description</b> <u>The server encountered an internal error that prevented it from fulfilling this request.</u></p><p><b>exception</b><pre>org.springframework.http.converter.HttpMessageNotWritableExcepti on: Could not write JSON: Object is null (through reference chain: net.sf.json.JSONObject["data"]->net.sf.json.JSONArray[0] ->net.sf.json.JSONObject["createTime"]->net.sf.json.J SONNull["empty"]); nested exception isorg.codehaus.jackson.map.JsonMappingException: Object is null (through reference chain:net.sf.json.JSONObject["data"]->net.sf.json.JSONArray[0] ->net.sf.json.JSONObject["createTime"]->net.sf.json.J SONNull["empty"])org.springframework.http.converter.json.MappingJacksonHttpMessageConv erter.writeInternal(MappingJacksonHttpMessageConverter.java:203)org.springframework.http.converter.AbstractHttpMessageConverter.write (AbstractHttpMessageConverter.java:179)org.springframework.web.servlet.mvc.method.annotation.AbstractMessage ConverterMethodProcessor.writeWithMessageConverters(AbstractMessageCo nverterMethodProcessor.java:148)org.springframework.web.servlet.mvc.method.annotation.AbstractMessage ConverterMethodProcessor.writeWithMessageConverters(AbstractMessageCo nverterMethodProcessor.java:90)org.springframework.web.servlet.mvc.method.annotation.RequestResponse BodyMethodProcessor.handleReturnValue(RequestResponseBodyMethodProces sor.java:189)org.springframework.web.method.support.HandlerMethodReturnValueHandle rComposite.handleReturnValue(HandlerMethodReturnValueHandlerComposite .java:69)org.springframework.web.servlet.mvc.method.annotation.ServletInvocabl eHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:122 )org.springframework.web.servlet.mvc.method.annotation.RequestMappingH andlerAdapter.invokeHandleMethod(RequestMappingHandlerAdapter.java:74 5)org.springframework.web.servlet.mvc.method.annotation.RequestMappingH andlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:686)org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapt er.handle(AbstractHandlerMethodAdapter.java:80)org.springframework.web.servlet.DispatcherServlet.doDispatch(Dispatch erServlet.java:925)org.springframework.web.servlet.DispatcherServlet.doService(Dispatche rServlet.java:856)org.springframework.web.servlet.FrameworkServlet.processRequest(Frame workServlet.java:936)org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServ let.java:838)javax.servlet.http.HttpServlet.service(HttpServlet.java:647)org.springframework.web.servlet.FrameworkServlet.service(FrameworkSer vlet.java:812)javax.servlet.http.HttpServlet.service(HttpServlet.java:728)org.apache.shiro.web.servlet.ProxiedFilterChain.doFilter(ProxiedFilte rChain.java:61)org.apache.shiro.web.servlet.AdviceFilter.executeChain(AdviceFilter.j ava:108)org.apache.shiro.web.servlet.AdviceFilter.doFilterInternal(AdviceFilt er.java:137)org.apache.shiro.web.servlet.OncePerRequestFilter.doFilter(OncePerReq uestFilter.java:125)org.apache.shiro.web.servlet.ProxiedFilterChain.doFilter(ProxiedFilte rChain.java:66)org.apache.shiro.web.servlet.AbstractShiroFilter.executeChain(Abstrac tShiroFilter.java:449)org.apache.shiro.web.servlet.AbstractShiroFilter$1.call(AbstractShiro Filter.java:365)org.apache.shiro.subject.support.SubjectCallable.doCall(SubjectCallab le.java:90)org.apache.shiro.subject.support.SubjectCallable.call(SubjectCallable .java:83)org.apache.shiro.subject.support.DelegatingSubject.execute(Delegating Subject.java:383)org.apache.shiro.web.servlet.AbstractShiroFilter.doFilterInternal(Abs tractShiroFilter.java:362)org.apache.shiro.web.servlet.OncePerRequestFilter.doFilter(OncePerReq uestFilter.java:125)org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(D elegatingFilterProxy.java:343)org.springframework.web.filter.DelegatingFilterProxy.doFilter(Delegat ingFilterProxy.java:260)org.springframework.web.filter.CharacterEncodingFilter.doFilterIntern al(CharacterEncodingFilter.java:88)org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerR equestFilter.java:107)</pre></p><p><b>root cause</b><pre>org.codehaus.jackson.map.JsonMappingException: Object is null (through reference chain:net.sf.json.JSONObject["data"]->net.sf.json.JSONArray[0] ->net.sf.json.JSONObject["createTime"]->net.sf.json.J SONNull["empty"])org.codehaus.jackson.map.JsonMappingException.wrapWithPath(JsonMappin gException.java:218)org.codehaus.jackson.map.JsonMappingException.wrapWithPath(JsonMappin gException.java:183)org.codehaus.jackson.map.ser.std.SerializerBase.wrapAndThrow(Serializ erBase.java:140)3原因分析:可能是json序列化的问题代码修改为@RequestMapping(value = "/query")public @ResponseBodyMap<String, Object> query(@RequestParam("startTime") String startTime, @RequestParam("endTime") String endTime,@RequestParam("oid") String oid, @RequestParam("cid") Integer cid,@RequestParam("pay_channel") String payChannel,@RequestParam("device_type") String deviceType,@RequestParam("phone") Integer phone,@RequestParam("perPage") Integer pageSize,@RequestParam("skipIndex") Integer startIndex) throws Exception {LogInfo info = populateQueryParam(startTime, endTime, oid, cid, payChannel, deviceType, phone, pageSize, startIndex);// 总记录数Long totalCount = logMoniterService.queryLogInfoCount(info);if (totalCount == null) {totalCount = 0L;}List<LogInfo> list = logMoniterService.queryLogInfo(info); Map<String, Object> result = new HashMap<String, Object>();result.put("success", true);result.put("data", list);result.put("error", "");result.put("totalRecords", totalCount);return result;}4、问题解决。
springMVC中jackson的使⽤(包含JsonFormat时间格式)前台使⽤ajax,后台 springMVCJava下常见的Json类库有Gson、JSON-lib和Jackson等,Jackson相对来说⽐较⾼效,在项⽬中主要使⽤Jackson进⾏JSON和Java对象转换,下⾯给出⼀些Jackson的JSON操作⽅法。
jackson库作⽤:(1)在前台传的json格式的字符串格式数据,后台可以⽤相关的类,Map,List来接收(如果不⽤jackson库,但后台却使⽤了除string类型之外的类型来接收json格式数据,则后台报错 Content type 'application/json' not supported);(2)如果使⽤了jackson库,后台返回给前台的数据类型可以是Map,相关类,List等,JACKSON库会⾃动将类型转换为json字符串给前台,如果不使⽤,则会报 convert 错⼀、准备⼯作⾸先去官⽹下载Jackson⼯具包,下载地址/JacksonDownload。
Jackson有1.x系列和2.x系列,截⽌⽬前2.x系列的最新版本是2.2.3,2.x系列有3个jar包需要下载:jackson-core-2.2.3.jar(核⼼jar包,)jackson-annotations-2.2.3.jar(该包提供Json注解⽀持,)jackson-databind-2.2.3.jar()[java]1. //JSON序列化和反序列化使⽤的User类2. import java.util.Date;3.4. public class User {5. private String name;6. private Integer age;7. private Date birthday;8. private String email;9.10. public String getName() {11. return name;12. }13. public void setName(String name) {14. = name;15. }16.17. public Integer getAge() {18. return age;19. }20. public void setAge(Integer age) {21. this.age = age;22. }23.24. public Date getBirthday() {25. return birthday;26. }27. public void setBirthday(Date birthday) {28. this.birthday = birthday;29. }30.31. public String getEmail() {32. return email;33. }34. public void setEmail(String email) {35. this.email = email;36. }37. }⼆、JAVA对象转JSON[JSON序列化][java]1. import java.io.IOException;2. import java.text.ParseException;3. import java.text.SimpleDateFormat;4.5. import com.fasterxml.jackson.databind.ObjectMapper;6.7. public class JacksonDemo {8. public static void main(String[] args) throws ParseException, IOException {9. User user = new User();10. user.setName("⼩民");11. user.setEmail("xiaomin@");12. user.setAge(20);13.14. SimpleDateFormat dateformat = new SimpleDateFormat("yyyy-MM-dd");15. user.setBirthday(dateformat.parse("1996-10-01"));16.17. /**18. * ObjectMapper是JSON操作的核⼼,Jackson的所有JSON操作都是在ObjectMapper中实现。
解决SpringMvc后台接收json数据中⽂乱码问题的⼏种⽅法1、使⽤ajax从前台页⾯传输数据到后台controller控制器的时候,出现中⽂乱码(问号)。
之前在⽹上找了各种解决⽅案,都⾏不通,最后发现是tomcat服务器接收数据的问题解决⽅案:⽅式⼀:在controller接收参数时,对参数进⾏转码@ResponseBody@RequestMapping(value="/getJsonDataByCityName",produces="application/json")public String getJsonByName(HttpServletRequest request,HttpServletResponse response,@RequestParam String city_name)throws ServletException,IOException {//response.setContentType("text/html;charset=UTF-8");//request.setCharacterEncoding("UTF-8");//解决post乱码问题System.out.println(request.getCharacterEncoding());city_name = new String(city_name.getBytes("ISO-8859-1"), "UTF-8");System.out.println("city_name:"+city_name);}⽅式⼆:配置tomcat⽬录下的service.xml⽂件tomcat7/conf/server.xml给该⾏代码加上 URIEncoding="UTF-8" 的编码属性<Connector port="8080" protocol="HTTP/1.1"connectionTimeout="20000"redirectPort="8443" URIEncoding="UTF-8" />原因分析:其实乱码问题出现的原因,就是由于默认的tomcat配置,接收请求是以ISO-8859-1来转码,导致中⽂出现了乱码问题,只要能正确的以utf-8来转码,则可以解决乱码问题。
spring接⼝通过配置⽀持返回多种格式(xml,json,html,excel)1. 简介本⽂主要给⼤家介绍使⽤SpringMVC的后端服务如何通过配置来⽀持多种返回值类型(xml,json,html,excel)2. 基础概念2.1 HttpHeader中Content-Type和Accept设置的区别Accept:接⼝要返回给客户端的数据格式curl --header 'Accept:application/json' http://localhost:8080/todoContent-Type:客户端发送给服务器端的数据格式curl -X PUT --header 'Content-Type:application/json' -d '{"title":"周末⽇程","content":"睡觉"}' http://localhost:8080/todo2.2 SpringMVC⽣成输出的两种⽅式1)当服务端使⽤Restful的⽅式,只为客户端的ajax或其他服务端请求提供数据时,通常会使⽤@ResponseBody来标识你的返回,这时候Spring使⽤HttpMessageConverter来把返回的对象格式化成所需的格式。
2)当你需要提供表现层(⽐如:HTML),这时候SpringMVC使⽤ViewResolver来将处理你的返回。
有时候你的应⽤程序这两者都要提供2.3 SpringMVC输出格式判定很多时候为了⽀持多个系统或多个终端,你需要让相同的数据已不同的表现形式输出。
SpringMVC使⽤ContentNegotationStrategy来判定⽤户请求希望得到什么格式的数据。
ContentNegotationStrategy通过三种⽅式来识别⽤户想要返回什么样的数据通过请求URL后缀:http://myserver/myapp/accounts/list.html 返回html格式通过请求的参数:http://myserver/myapp/accounts/list?format=xls 该设置默认不开启,默认key是format。
springMVC中前台ajax传json数据后台controller接受对象为null 在jquery的ajax中,如果没加contentType:"application/json",那么data就应该对应的是json对象,反之,如果加了contentType:"application/json",那么ajax发送的就必须是字符串。
下⾯便是两种犯错的例⼦:1>前台ajax多加了contentType:"application/json",data却错传成json对象:后台处理:(employee该pojo对象⾥有username和password等String字段)结果都为null将contentType去掉后,后台成功反射出对象:2>ajax中没加contentType:"application/json",data却直接使⽤了json字符串(和上⾯的⼀个道理)后台情况:3>第三点是真的有点恶⼼的⼀点,找了好久才找到。
那就是有些关键的属性在Mvc层中反射失败,会导致其他所有属性都为null⽐如上⾯的joindate对应的pojo是Date,本来input框⾥的值是 Thu Dec 30 00:00:00 CST 1999 ,传到后台⽤Date接收,但是显然格式不对,于是Date合成出了错,然后坑爹的就来了,因为这个特殊的属性反射失败,Mvc层就将请求打回去然后导致浏览器报错400 bad request ,从⽽导致其他所有属性都为null。
最后把joindate属性注释掉,后台什么属性的值都收到了。
补充:我们都知道,不管前台发送的是json字符串还是对象,服务器本质上收到的都是字符流,那么为什么ajax⼜可以直接传对象呢?因为不加contentType:"application/json"的时候,发送类型变为默认的application/x-www-form-urlencoded,⽽这种⽅式会以键值对的形式将对象序列化,所以传进去的对象实际上还是变成了字符流原⽂连接:https:///qq_37960007/article/details/79542727。
SpringMVCJson⾃定义序列化和反序列化需求背景需求⼀:SpringMVC构建的微服务系统,数据库对⽇期的存储是Long类型的时间戳,前端之前是默认使⽤Long类型时间,现在前端框架改动,要求后端响应数据时,Long类型的时间⾃动变成标准时间格式(yyyy-MM-dd HH:mm:ss)。
涉及到这个转换的范围挺⼤,所有的实体表都有创建时间createTime和修改时间updateTime,⽬前的主要诉求也是针对这两个字段,并且在实体详情数据和列表数据都存在,需要⼀个统⼀的⽅法,对这两个字段进⾏处理。
需求⼆:前端请求上传的JSON报⽂,String类型的内容,可能会出现前后有空格的现象,如果前端框架未对此问题进⾏处理,后端收到的JSON请求反序列化为对象时,就会出现String类型的值,前后有空格,现需要⼀个统⼀的处理⽅法,对接收的String类型属性执⾏trim⽅法。
解决⽅案SpringMVC默认的JSON框架为jackson,也可以使⽤fastjson。
jackson框架⾃定义序列化如果项⽬使⽤jackson框架做json序列化,推荐的⽅案是使⽤@JsonSerialize注解,⽰例代码如下:@JsonSerialize(using = CustomDateSerializer.class)private Long createTime;@JsonSerialize(using = CustomDateSerializer.class)private Long updateTime;CustomDateSerializer类的实现⽰例如下:public class CustomDateSerializer extends JsonSerializer<Long> {@Overridepublic void serialize(Long aLong, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");Date date = new Date(aLong);jsonGenerator.writeString(sdf.format(date));}}这种⽅案的好处如下:1. ⾃定义的实现类可以复⽤2. 精准到需要转换处理的字段,不受限于createTime和updateTime,更贴近于需求缺点就是需要转换的字段都需要使⽤注解,⼯作量有点⼤当然有其他的统⼀处理⽅案,这⾥不赘述。
SpringMVC 中整合JSON、XML视图二上篇文章介绍了程序整合的准备工作、结合MarshallingView视图完成jaxb2转换XML、xStream转换XML工作,这次将介绍castor、jibx转换XML。
还有MappingJacksonView用Jackson转换JSON,自己拓展AbstractView定义Jsonlib 的视图完成JSON-lib转换JSON。
上一篇文章:/hoojo/archive/2011/04/29/2032571.html四、用Castor转换XML1、castor可以通过一个mapping.xml文件对即将转换的Java对象进行描述,然后可以将Java对象按照描述的情况输出XML内容。
利用castor转换xml需要添加如下jar包:如果你还不清楚castor,可以阅读:for csblogs:/hoojo/archive/2011/04/25/2026819.html for csdn:/IBM_hoojo/archive/2011/04/25/6360916.aspx2、你需要在dispatcher.xml中添加castor的相关视图,配置如下:<--继承MarshallingView,重写locateToBeMarshalled方法;解决对象添加到ModelAndView中,转换后的xml是BindingResult信息的bug --><bean name="castorMarshallingView"class="com.hoo.veiw.xml.OverrideMarshallingView"><property name="marshaller"><bean class="org.springframework.oxm.castor.CastorMarshaller"> <property name="mappingLocations"><array><value>classpath:mapping.xml</value></array></property><property name="encoding"value="UTF-8"/></bean></property></bean>mapping.xml配置<?xml version="1.0"encoding="UTF-8"?><!DOCTYPE mapping PUBLIC"-//EXOLAB/Castor Mapping DTD Version 1.0//EN" "/mapping.dtd"><mapping><class name="com.hoo.entity.Account"auto-complete="true"> <map-to xml="Account"/><field name="id"type="integer"><bind-xml name="id"node="attribute"/></field><field name="name"type="string"><bind-xml name="name"node="element"/></field><field name="email"type="string"><bind-xml name="email"node="element"/></field><field name="address"type="string"><bind-xml name="address"node="element"/></field><field name="brithday"type="com.hoo.entity.Brithday"> <bind-xml name="生日"node="element"/></field></class><class name="com.hoo.entity.Brithday"auto-complete="true"> <map-to xml="brithday"/><field name="brithday"type="string"><bind-xml name="brithday"node="attribute"/></field></class><class name="com.hoo.entity.MapBean"auto-complete="true"> <field name="map"collection="map"><bind-xml name="map"><class name="org.exolab.castor.mapping.MapItem"><field name="key"type="ng.String"><bind-xml name="key"node="attribute"/></field><field name="value"type="com.hoo.entity.Account"><bind-xml name="value"auto-naming="deriveByClass"/></field></class></bind-xml></field></class><class name="com.hoo.entity.ListBean"auto-complete="true"> <map-to xml="listBean"/><field name="list"collection="arraylist"type="com.hoo.entity.Account"><bind-xml name="beans"auto-naming="deriveByClass"/> </field><field name="name"type="string"/></class><class name="com.hoo.entity.AccountArray"auto-complete="true"> <map-to xml="account-array"/><field name="size"type="int"/><field name="accounts"collection="array"type="com.hoo.entity.Account"><bind-xml name="accounts"auto-naming="deriveByClass"/> </field></class></mapping>关于mapping.xml配置的介绍,你可以参考/hoojo/archive/2011/04/25/2026819.html这篇文章的第三栏目。
3、在使用Spring的MarshallingView的时候,转换的xml结果有时候会带有BindingResult 对象的信息。
所以解决办法是重写MarshallingView里面的locateToBeMarshalled方法,这样就可以解决了。
下面是重新MarshallingView的class代码:package com.hoo.veiw.xml;import java.util.Map;import javax.servlet.ServletException;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import org.springframework.beans.BeansException;import org.springframework.oxm.Marshaller;import org.springframework.validation.BindingResult;import org.springframework.web.servlet.view.xml.MarshallingView;/*** <b>function:</b>继承MarshallingView,重写locateToBeMarshalled方法;* 解决对象添加到ModelAndView中,转换后的xml是BindingResult信息的bug* @author hoojo* @createDate 2010-11-29 下午05:58:45* @file OverrideMarshallingView.java* @package com.hoo.veiw.xml* @project Spring3* @blog /IBM_hoojo* @email hoojo_@* @version 1.0*/public class OverrideMarshallingView extends MarshallingView { private Marshaller marshaller;private String modelKey;public OverrideMarshallingView() {super();}public OverrideMarshallingView(Marshaller marshaller) {super(marshaller);this.marshaller = marshaller;}public void setMarshaller(Marshaller marshaller) {super.setMarshaller(marshaller);this.marshaller = marshaller;}public void setModelKey(String modelKey) {super.setModelKey(modelKey);this.modelKey = modelKey;}@Overrideprotected void initApplicationContext() throws BeansException { super.initApplicationContext();}@SuppressWarnings("unchecked")@Overrideprotected void renderMergedOutputModel(Map model, HttpServletRequest request, HttpServletResponse response)throws Exception {super.renderMergedOutputModel(model, request, response);}@SuppressWarnings("unchecked")@Overrideprotected Object locateToBeMarshalled(Map model) throws ServletException {if (modelKey != null) {Object o = model.get(modelKey);if (!this.marshaller.supports(o.getClass())) {throw new ServletException("Model object [" + o + "] retrieved via key [" + modelKey+ "] is not supported by the Marshaller");}return o;}for (Object o : model.values()) {//解决对象添加到ModelAndView中,转换后的xml是BindingResult信息的bugif (o instanceof BindingResult) {continue;}if (this.marshaller.supports(o.getClass())) {return o;}}return null;}}4、下面来看看Castor来转换普通JavaBeanpackage com.hoo.controller;import java.util.ArrayList;import java.util.Date;import java.util.HashMap;import java.util.List;import java.util.Map;import org.springframework.stereotype.Controller;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.servlet.ModelAndView;import com.hoo.entity.Account;import com.hoo.entity.Brithday;import com.hoo.entity.ListBean;import com.hoo.entity.MapBean;import er;/*** <b>function:</b>利用MarshallingView视图,配置CastorMarshaller将Java 对象转换XML* @author hoojo* @createDate 2011-4-28 上午10:14:43* @file CastorMarshallingViewController.java* @package com.hoo.controller* @project SpringMVC4View* @blog /IBM_hoojo* @email hoojo_@* @version 1.0*/@Controller@RequestMapping("/castor/view")public class CastorMarshallingViewController {@RequestMapping("/doBeanXMLCastorView")public ModelAndView doBeanXMLCastorView() {System.out.println("#################ViewController doBeanXMLCastorView##################");ModelAndView mav = new ModelAndView("castorMarshallingView"); Account bean = new Account();bean.setAddress("北京");bean.setEmail("email");bean.setId(1);bean.setName("haha");Brithday day = new Brithday();day.setBrithday("2010-11-22");bean.setBrithday(day);Map<String, Object> map = new HashMap<String, Object>();map.put("day", day);map.put("account", bean);mav.addObject(bean);//重写MarshallingView的locateToBeMarshalled方法//mav.addObject(BindingResult.MODEL_KEY_PREFIX, bean);//mav.addObject(BindingResult.MODEL_KEY_PREFIX + "account", bean);return mav;}}Account在mapping配置文件中有进行配置描述。