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数据的三种⽅式Spring MVC属于SpringFrameWork的后续产品,已经融合在Spring Web Flow⾥⾯。
Spring 框架提供了构建 Web 应⽤程序的全功能 MVC 模块。
使⽤ Spring 可插⼊的 MVC架构,从⽽在使⽤Spring进⾏WEB开发时,可以选择使⽤Spring的SpringMVC框架或集成其他MVC开发框架,如Struts1,Struts2等。
1、第⼀种⽅式是spring2时代的产物,也就是每个json视图controller配置⼀个Jsoniew。
如:<bean id="defaultJsonView" class="org.springframework.web.servlet.view.json.MappingJacksonJsonView"/>或者<bean id="defaultJsonView" class="org.springframework.web.servlet.view.json.MappingJackson2JsonView"/>同样要⽤jackson的jar包。
2、第⼆种使⽤JSON⼯具将对象序列化成json,常⽤⼯具Jackson,fastjson,gson。
利⽤HttpServletResponse,然后获取response.getOutputStream()或response.getWriter()直接输出。
⽰例:public class JsonUtil{private static Gson gson=new Gson();/*** @MethodName : toJson* @Description : 将对象转为JSON串,此⽅法能够满⾜⼤部分需求* @param src* :将要被转化的对象* @return :转化后的JSON串*/public static String toJson(Object src) {if (src == null) {return gson.toJson(JsonNull.INSTANCE);}return gson.toJson(src);}}3、第三种利⽤spring mvc3的注解@ResponseBody例如:@ResponseBody@RequestMapping("/list")public List<String> list(ModelMap modelMap) {String hql = "select c from Clothing c ";Page<Clothing> page = new Page<Clothing>();page.setPageSize(6);page = clothingServiceImpl.queryForPageByHql(page, hql);return page.getResult();}然后使⽤spring mvc的默认配置就可以返回json了,不过需要jackson的jar包哦。
SpringBoot自定义注解实现后台接收Json参数Spring Boot是一个用于构建独立的、基于生产级别的Java应用程序的框架。
它使得开发人员可以轻松地创建具有高效、可靠和可扩展特性的Spring应用程序。
在Spring Boot中,我们可以使用自定义注解来处理后台接收JSON参数的需求。
```javaimport org.springframework.web.bind.annotation.RequestBody;import ng.annotation.ElementType;import ng.annotation.Retention;import ng.annotation.RetentionPolicy;import ng.annotation.Target;```接下来,我们可以在Spring Boot的Controller中使用这个自定义注解来接收JSON参数。
下面是一个简单的例子:```javaimport org.springframework.web.bind.annotation.PostMapping;importorg.springframework.web.bind.annotation.RestController;public class UserController//处理用户添加的逻辑}```需要注意的是,为了使Spring Boot能够正确地将请求体中的JSON 数据转换为Java对象,我们需要在项目中引入相关的依赖。
可以在`pom.xml`文件中添加以下依赖:```xml<dependency><artifactId>jackson-databind</artifactId></dependency>```这个依赖将提供JSON与Java对象之间的转换功能。
总结来说,Spring Boot的自定义注解可以很方便地实现后台接收JSON参数的功能。
SpringMVC关于json、xml自动转换的原理研究<mvc:resources location="/static/"mapping="/static/**"/><mvc:annotation-driven/><context:component-scanbase-package="org.format.demo.controller" />视图配置省略.....pom中需要有以下依赖(Spring依赖及其他依赖不显示):<dependency> <groupId>org.codehaus.jackson</groupId><artifactId>jackson-core-asl</artifactId> <version>1.9.13</version> </dependency> <dependency> <groupId>org.codehaus.jackson</groupId><artifactId>jackson-mapper-asl</artifactId> <version>1.9.13</version> </dependency>这个依赖分别是json序列化的依赖。
ok。
我们在Controller中添加一个method:@RequestMapping("/)@ResponseBodypublic Map<String, Object> <String, Object> map = new HashMap<String, Object>();map.put("list", employeeService.list());return map;}直接访问地址:我们看到,短短几行配置。
Springmvc 组合jackson与fastjson使用心得1、解决方案可以将其中的main方法删掉。
测试用的。
我测试的结果是,jackson比fastjson 快。
fastjson是1.1.36jackson是2.2.3jdk是1.7.40,clientcpu是intel i32、主要代码package org.springframework.web.servlet.view.json;import java.io.ByteArrayOutputStream;import java.io.IOException;import java.io.OutputStream;import java.io.StringReader;import java.io.StringWriter;import java.nio.charset.Charset;import java.util.ArrayList;import java.util.Collections;import java.util.HashMap;import java.util.List;import java.util.Map;import java.util.Set;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import org.springframework.util.CollectionUtils;import org.springframework.validation.BindingResult;import org.springframework.web.servlet.view.AbstractView;import com.alibaba.fastjson.JSON;import com.alibaba.fastjson.parser.Feature;import com.alibaba.fastjson.serializer.SerializerFeature;import com.fasterxml.jackson.core.JsonFactory;import com.fasterxml.jackson.core.JsonGenerator;import com.fasterxml.jackson.core.JsonParseException;import com.fasterxml.jackson.core.JsonProcessingException;import com.fasterxml.jackson.core.type.TypeReference;import com.fasterxml.jackson.databind.JsonMappingException;import com.fasterxml.jackson.databind.MappingIterator;import com.fasterxml.jackson.databind.ObjectMapper;import mon.collect.Lists;import mon.collect.Maps;import mon.collect.Sets;import er;public class MappingFastJsonView extends AbstractView {/*** Default content type: "application/json".* Overridable through {@link #setContentType}.*/public static final String DEFAULT_CONTENT_TYPE = "application/json"; private String encoding = "UTF-8";private String jsonPrefix;private Boolean prettyPrint;private Set<String> modelKeys;private boolean extractValueFromSingleKeyModel = false;private boolean disableCaching = true;private boolean updateContentLength = false;/*** Construct a new {@code MappingFastJsonView}, setting the content type to {@code application/json}.*/public MappingFastJsonView() {setContentType(DEFAULT_CONTENT_TYPE);setExposePathVariables(false);}public String getEncoding() {return encoding;}public void setEncoding(String encoding) {this.encoding = encoding;}/*** Specify a custom prefix to use for this view's JSON output.* Default is none.* @see #setPrefixJson*/public void setJsonPrefix(String jsonPrefix) {this.jsonPrefix = jsonPrefix;}/*** Indicates whether the JSON output by this view should be prefixed with <tt>"{} && "</tt>.* Default is {@code false}.* <p>Prefixing the JSON string in this manner is used to help prevent JSON Hijacking.* The prefix renders the string syntactically invalid as a script so that it cannot be hijacked.* This prefix does not affect the evaluation of JSON, but if JSON validation is performed* on the string, the prefix would need to be ignored.* @see #setJsonPrefix*/public void setPrefixJson(boolean prefixJson) {// if (prefixJson) {// if (jsonPrefix == null) {// jsonPrefix = "{} && ";// }// }this.jsonPrefix = (prefixJson ? "{} && " : null);}/*** Whether to use the default pretty printer when writing JSON. * This is a shortcut for setting up an {@code JSON}* <p>The default value is {@code false}.*/public void setPrettyPrint(boolean prettyPrint) {this.prettyPrint = prettyPrint;}/*** Set the attribute in the model that should be rendered by this view. * When set, all other model attributes will be ignored.*/public void setModelKey(String modelKey) {this.modelKeys = Collections.singleton(modelKey);}/*** Set the attributes in the model that should be rendered by this view.* When set, all other model attributes will be ignored.*/public void setModelKeys(Set<String> modelKeys) {this.modelKeys = modelKeys;}/*** Return the attributes in the model that should be rendered by this view.*/public final Set<String> getModelKeys() {return this.modelKeys;}/*** Set whether to serialize models containing a single attribute as a map or whether to* extract the single value from the model and serialize it directly. * <p>The effect of setting this flag is similar to using {@code MappingJacksonHttpMessageConverter}* with an {@code @ResponseBody} request-handling method.* <p>Default is {@code false}.*/public void setExtractValueFromSingleKeyModel(boolean extractValueFromSingleKeyModel) {this.extractValueFromSingleKeyModel = extractValueFromSingleKeyModel;}* Disables caching of the generated JSON.* <p>Default is {@code true}, which will prevent the client from caching the generated JSON.*/public void setDisableCaching(boolean disableCaching) {this.disableCaching = disableCaching;}/*** Whether to update the 'Content-Length' header of the response. When set to* {@code true}, the response is buffered in order to determine the content* length and set the 'Content-Length' header of the response.* <p>The default setting is {@code false}.*/public void setUpdateContentLength(boolean updateContentLength) { this.updateContentLength = updateContentLength;}@Overrideprotected void prepareResponse(HttpServletRequest request, HttpServletResponse response) {setResponseContentType(request, response);response.setCharacterEncoding(encoding);if (this.disableCaching) {response.addHeader("Pragma", "no-cache");response.addHeader("Cache-Control", "no-cache, no-store, max-age=0");response.addDateHeader("Expires", 1L);}}@Overrideprotected void renderMergedOutputModel(Map<String, Object> model, HttpServletRequest request, HttpServletResponse response)throws Exception {OutputStream stream = (this.updateContentLength ? createTemporaryOutputStream() : response.getOutputStream());Object value = filterModel(model);writeContent(stream, value, this.jsonPrefix);if (this.updateContentLength) {writeToResponse(response, (ByteArrayOutputStream) stream);}/*** Filter out undesired attributes from the given model.* The return value can be either another {@link Map} or a single value object.* <p>The default implementation removes {@link BindingResult} instances and entries* not included in the {@link #setRenderedAttributes renderedAttributes} property.* @param model the model, as passed on to {@link#renderMergedOutputModel}* @return the value to be rendered*/protected Object filterModel(Map<String, Object> model) {Map<String, Object> result = new HashMap<String,Object>(model.size());Set<String> renderedAttributes =(!CollectionUtils.isEmpty(this.modelKeys) ? this.modelKeys :model.keySet());for (Map.Entry<String, Object> entry : model.entrySet()) {if (!(entry.getValue() instanceof BindingResult) && renderedAttributes.contains(entry.getKey())) {result.put(entry.getKey(), entry.getValue());}}return (this.extractValueFromSingleKeyModel && result.size() == 1 ? result.values().iterator().next() : result);}/*** Write the actual JSON content to the stream.* @param stream the output stream to use* @param value the value to be rendered, as returned from {@link #filterModel}* @param jsonPrefix the prefix for this view's JSON output* (as indicated through {@link #setJsonPrefix}/{@link#setPrefixJson})* @throws IOException if writing failed*/protected void writeContent(OutputStream stream, Object value, String jsonPrefix) throws IOException {List<SerializerFeature> list = newArrayList<SerializerFeature>();if (prettyPrint != null && prettyPrint) {list.add(SerializerFeature.PrettyFormat);}SerializerFeature[] features = newSerializerFeature[list.size()];list.toArray(features);byte[] jsonBytes = JSON.toJSONBytes(value, features);if (jsonPrefix != null) {//此处亦可字符串相加,然后转成字节数组byte[] prefixBytes =jsonPrefix.getBytes(Charset.forName("UTF-8"));int prefixLength = prefixBytes.length;int jsonLength = jsonBytes.length;byte[] finalJsonBytes = new byte[prefixLength + jsonLength];System.arraycopy(prefixBytes, 0, finalJsonBytes, 0, prefixLength);System.arraycopy(jsonBytes, 0, finalJsonBytes, prefixLength, jsonLength);stream.write(finalJsonBytes);} else {stream.write(jsonBytes);}stream.flush();}public static void main(String[] args) {List<User> users = Lists.newArrayList();for (int j = 0; j < 10; j++) {User value = new User();value.setAddress("asdfjklasdjf");value.setAge(22);value.setGender(1);value.setPassword("jkljklj");value.setUserName("");List<String> strList = Lists.newArrayList();Map<String, String> strMap = Maps.newHashMap();Set<Integer> setInt = Sets.newHashSet();for (int i = 0; i < 10; i++) {strList.add("a" + i);strMap.put("a" + i, "a" + i);setInt.add(i);}value.setSetInt(setInt);value.setStrList(strList);value.setStrMap(strMap);users.add(value);}int times = 1;// long d = System.currentTimeMillis();// String jsonPrefix = "aaa{}";//// for (int i = 0; i < times; i++) {// byte[] jsonBytes = JSON.toJSONBytes(value);// byte[] prefixBytes =jsonPrefix.getBytes(Charset.forName("UTF-8"));// int prefixLength = prefixBytes.length;// int jsonLength = jsonBytes.length;// byte[] finalJsonBytes = new byte[prefixLength + jsonLength];//// System.arraycopy(prefixBytes, 0, finalJsonBytes, 0, prefixLength);// System.arraycopy(jsonBytes, 0, finalJsonBytes, prefixLength, jsonLength);// }// System.out.println(System.currentTimeMillis() - d);String json = "";String json2 = "";long d2 = System.currentTimeMillis();//String jsonPrefix2 = "aaa{}";for (int i = 0; i < times; i++) {json = JSON.toJSONString(users);// jsonBytes = jsonPrefix2 + jsonBytes;//// byte[] prefixBytes =jsonBytes.getBytes(Charset.forName("UTF-8"));}System.out.println("fastjson parser :" +(System.currentTimeMillis() - d2));ObjectMapper mapper = new ObjectMapper();//org.codehaus.jackson.map.ObjectMapper mapper = new org.codehaus.jackson.map.ObjectMapper();long d3 = System.currentTimeMillis();//String jsonPrefix3 = "aaa{}";for (int i = 0; i < times; i++) {//String jsonBytes = null;try {//StringWriter writer = new StringWriter();//JsonGenerator generator = newJsonFactory().createGenerator(writer);//mapper.writeValue(writer, value);//jsonBytes = writer.toString();json2 = mapper.writeValueAsString(users);//mapper.readValue(new StringReader(""), class1); } catch (Exception e) {e.printStackTrace();}// jsonBytes = jsonPrefix3 + jsonBytes;//// byte[] prefixBytes =jsonBytes.getBytes(Charset.forName("UTF-8"));}System.out.println("jackson parser :" +(System.currentTimeMillis() - d3));long d5 = System.currentTimeMillis();for (int i = 0; i < times; i++) {JSON.parseArray(json, User.class);}System.out.println("fastjson deserializer :" + (System.currentTimeMillis() - d5));long d4 = System.currentTimeMillis();for (int i = 0; i < times; i++) {try {//List<User> userList = Lists.newArrayList();mapper.readValue(json2, new TypeReference<List<User>>() {});// List<User> userList = Lists.newArrayList();// for (;iterator.hasNext();) {// userList.add(iterator.nextValue());// }//System.out.println(userList);} catch (JsonParseException e) {e.printStackTrace();} catch (JsonMappingException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}}System.out.println("jackson deserializer :" +(System.currentTimeMillis() - d4));}}package com.test;import java.util.List;import java.util.Map;import java.util.Set;import javax.xml.bind.annotation.XmlRootElement;@XmlRootElementpublic class User {private String userName;private String address;private int age;private int gender;private String password;private List<String> strList;private Map<String, String> strMap;private Set<Integer> setInt;public String getUserName() {return userName;}public void setUserName(String userName) {erName = userName;}public String getAddress() {return address;}public void setAddress(String address) {this.address = address;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}public int getGender() {return gender;}public void setGender(int gender) {this.gender = gender;}public String getPassword() {return password;}public void setPassword(String password) {this.password = password;}public List<String> getStrList() {return strList;}public void setStrList(List<String> strList) { this.strList = strList;}public Map<String, String> getStrMap() {return strMap;}public void setStrMap(Map<String, String> strMap) { this.strMap = strMap;}public Set<Integer> getSetInt() {return setInt;}public void setSetInt(Set<Integer> setInt) {this.setInt = setInt;}}。
springmvc总结(配置传递参数去除前后空格、参数绑定时处理⽇期)1.属性为Integer时,前台表单不填,默认为null;属性为String,前台表单不填,默认为"";2.属性为Integer时,前台表单填空格,model封装为null;属性为String,前台表单填空格,model封装为" ";3.属性为Integer,后台model封装时【去除】前后空格;属性为String,后台model封装时【不去除】前后空格;4.属性为Integer,表单填⾮数字,报错http400(Bad Request)⽬录:⼀、⼆、三、四、五、⼀、springmvc配置传递参数去除前后空格来⾃:1. 创建⾃定义转换器类package com.java1234.test;import org.springframework.core.convert.converter.Converter;/*** ⾃定义转换器去掉前后空格 <S, T> : S 页⾯上类型 T :转换后的类型*/public class CustomConverter implements Converter<String, String> {// 去掉前后空格@Overridepublic String convert(String source) {// TODO Auto-generated method stubtry {if (null != source) {source = source.trim();if (!"".equals(source)) {return source;}}} catch (Exception e) {// TODO: handle exception } return null; } }}return null;}}2. 在springmvc⽂件中进⾏配置<!-- 处理器映射器适配器 --><mvc:annotation-driven conversion-service="conversionService"/><!-- Converter转换器⼯⼚注:需要在适配器中进⾏配置 --><bean id="conversionService" class="org.springframework.format.support.FormattingConversionServiceFactoryBean"><!-- ⽇期 --><!-- 去掉前后空格 --><property name="converters"><list><bean class="mon.conversion.CustomConverter"></bean></list></property></bean>⼆、使⽤filter拦截参数去掉两端的空格(资料+亲测解决)三、springmvc+jackson处理date参考资料:MappingJacksonHttpMessageConverter主要通过ObjectMapper来实现返回json字符串。
SpringMVCJackson库解析json串属性名⼤⼩写⾃动转换问题问题描述在项⽬开发中,当实体类和表中定义的某个字段为 RMBPrice,⾸字母是⼤写的,sql 查询出来的列名也是⼤写的 RMBPrice,但是使⽤jquery 的 ajax 返回请求响应时却出错,字段名变⾃动转换成了⼩写的 rmbprice 了。
问题分析将服务器响应 ajax 请求的数据打印出来,字段名仍然是⼤写的 RMBPrice 。
所以,只可能是将 Java 对象转换到 json 串发给客户端的时候出了问题。
经过测试确实如此,即第三⽅ jackson 库在解析 Java 对象为 json 串规则如下:当Java 对象属性名的前⼏个字母都是⼤写的字母时,都⾃动会转换成⼩写,直到不是⼤写为⽌,若⼩写后⾯还有⼤写,则保持⼤写。
举例:RRRddRRR 会⾃动转换为 rrrddRRR ;所以,按照以上规则,RMBPrice 会⾃动转换为 rmbprice。
解决办法⽅法⼀:将 RMBPrice 按照⾃动转换规则直接改为 rmbprice 即可;但是,这样变量名看起来不是很舒服⽅法⼆:使⽤第三⽅ jackson 库时使⽤ @JsonProperty("属性名") 注解@JsonProperty("RMBPrice")private String RMBPrice;这个注解的作⽤就是告诉 jackson 解析 json 串时直接使⽤注解定义的属性名。
注意:SpringMVC 默认使⽤的是第三⽅库 jackson 解析 Java 对象。
使⽤第三⽅ fastjson 库时使⽤ @JSONField(name = "属性名") 注解@JSONField(name = "Name")public String getName(){return name;}注意:该注解应该放在 get ⽅法前总结在实际项⽬开发时,⼀定要遵守 Java 编码规范,可以少踩很多坑,避免很多不必要的问题和⿇烦。
整合SpringMVC之路径匹配规则本章节,我会给⼤家讲解Spring Boot中定制URL匹配规则的⽅法。
⼀.URL路径匹配1.概述在Spring Boot1.5的版本中,假如我们定义了⼀个’/show‘接⼝,默认情况下,我们可以按照/show来访问页⾯,也可以按照/show.do 这样带有“.do”后缀的接⼝来访问资源。
但是到了Spring Boot2.x之后,我们发现再使⽤.do的扩展名就⽆法访问资源了。
也就是说,现在的Spring Boot在默认情况下,禁⽤了后缀匹配模式!但是我们在开发Web应⽤程序时,并不总是使⽤⼀些默认的配置。
有时,我们要创建包含字符 “.” 的RESTful风格的URL;有时候我们也希望识别斜杠的存在。
这些需求,Spring都为我们提供了接⼝供开发⼈员按照需求定制。
“.” 字符在Spring中作为分隔符定义格式,例如/projects/spring-boot.json中的 “点” ,另外我们也可能想识别路径尾部的斜杠,如“/home/”中的 “/” 等。
2.案例说明我们在SpringBoot1.x版本中,可以创建如下控制器接⼝:@RestController@RequestMapping("/")public class HelloController {@RequestMapping("hello")public String showHello() {return "Hello,⼀⼀哥Sun!";}}在Spring Boot1.x版本的控制器中,我们可以使⽤下⾯的规则来进⾏访问:/hello/hello.*但是如果我们将⼯程升级到SpringBoot2.x后,默认情况下我们只能使⽤/hello访问,那么怎样才能使⽤1.x的访问规则呢?接下来我就带⼤家在SpringBoot 2.x版本中实现⼀下,进⾏⾃定义的URL路径匹配。
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配置文件中有进行配置描述。