来源头条作者:学日语的咩咩1.自定义转换器1.1基本介绍springboot 在响应客户端请求时,将提交的数据封装成对象时,使用了内置的转换器,也就是自动帮我们封装对象。springboot 自带了124个转换器,可以实现大部分的类型间的转换。springboot 也支持自定义转换器。但当前台发送请求传递的参数使用内置的转换器不能转换时,这时就需要写一个自定义的数据类型转换器,我们只需要实现 converter 接口的 convert 方法即可。1.2应用案例演示自定义转换器的使用。(1)save.htmlsave 编号: 姓名: 年龄: 婚否: 生日: 坐骑: (2)自定义转换器(string-->car)package com.li.config; import com.li.bean.car;import org.springframework.context.annotation.configuration;import org.springframework.core.convert.converter.converter;import org.springframework.format.formatterregistry;import org.springframework.util.objectutils;import org.springframework.web.servlet.config.annotation.webmvcconfigurer; /** * @author 李 * @version 1.0 * (proxybeanmethods = false) * 1.表示启用lite模式,保证修饰的配置类中,每个@bean方法被调用多少次返回的组件都是新创建的, * 是多例对象,是非代理方式。 * 2.proxybeanmethods 在调用 @bean 方法时才生效,因此需要先获取beanconfig 组件,再调用方法 */@configuration(proxybeanmethods = false)//设置为设置类public class webconfig { //注入bean-webmvcconfigurer @bean public webmvcconfigurer webmvcconfigurer() { return new webmvcconfigurer() { @override public void addformatters(formatterregistry registry) { /** * 1.在 addformatters()方法中添加一个自定义的转换器 * 2.自定义转换器要完成的功能是 string ->car * 3.增加的转换器会注册到 converters 容器中 * 4.converters 底层结构是 concurrenthashmap,默认内置了124个转换器 */ registry.addconverter(new converter() { // //匿名内部类 @override public car convert(string source) {//source即传入的字符串 //加入转换的业务代码 if (!objectutils.isempty(source)) { car car = new car(); string[] strings = source.split(","); car.setname(strings[0]); car.setprice(double.parsedouble(strings[1])); return car; } return null; } }); //还可以增加更多的转换器 } }; }}(3)控制器monster和car是级联对象,car为monster对象的属性。//处理添加monster的方法@postmapping("/savemonster")@responsebodypublic string savemonster(monster monster) { system.out.println("monster=" monster); return "success";}(4)浏览器提交表单,后台输出如下:monster=monster(id=10001, name=齐天大圣, age=888, ismarried=false, birth=sun dec 12 00:00:00 cst 1456, car=car(name=避水金晶兽, price=666.6))可以看到服务器成功获取到表单数据,并将car表单项的value值转换为car对象的属性值。1.3注意事项不同转换器通过key值区分,key=[源类型->目标类型]如果实现的两个自定义转换器的 key 值相同(即源类型和目标类型相同),则在注入容器时,根据注入的顺序,后一个转换器会覆盖前一个转换器!2.处理jsonspringboot 支持返回 json 格式的数据,在启用 web 开发场景时,已经引入了相关的依赖:spring-boot-starter-json。例子-使用@responsebody处理返回 jsonpackage com.li.controller; import com.li.bean.car;import com.li.bean.monster;import org.springframework.stereotype.controller;import org.springframework.web.bind.annotation.getmapping;import org.springframework.web.bind.annotation.responsebody; import java.util.date; /** * @author 李 * @version 1.0 */@controllerpublic class responsecontroller { //编写方法,以json格式返回数据 @getmapping("/get/monster") @responsebody public monster getmonster() { monster monster = new monster(); monster.setid(199); monster.setname("孙悟空"); monster.setage(23); monster.setismarried(false); monster.setbirth(new date()); car car = new car(); car.setname("奔驰"); car.setprice(20000.0); monster.setcar(car); return monster; }}浏览器访问该方法,返回如下:为什么springboot可以将monster对象以 json格式返回呢?它的底层仍然用到了一个转换器:abstractjackson2httpmessageconverter其中一个重要的方法如下:返回数据的格式是按照你设置的contenttype类型。如果没有指定,默认为json格式。//参数object object就是控制器方法返回的对象类型,如monsterprotected void writeinternal(object object, @nullable type type, httpoutputmessage outputmessage) throws ioexception, httpmessagenotwritableexception { //当控制器方法返回的时候,获取返回对象的contenttype,一般为application/json mediatype contenttype = outputmessage.getheaders().getcontenttype(); //获取编码,一般为utf-8 jsonencoding encoding = this.getjsonencoding(contenttype); class clazz = object instanceof mappingjacksonvalue ? ((mappingjacksonvalue)object).getvalue().getclass() : object.getclass(); objectmapper objectmapper = this.selectobjectmapper(clazz, contenttype); assert.state(objectmapper != null, "no objectmapper for " clazz.getname()); outputstream outputstream = streamutils.nonclosing(outputmessage.getbody()); try {//生成一个utf8jsongenerator对象 jsongenerator generator = objectmapper.getfactory().creategenerator(outputstream, encoding); throwable var10 = null; try {//对返回的数据类型进行一系列处理 this.writeprefix(generator, object); object value = object; class serializationview = null; filterprovider filters = null; javatype javatype = null; if (object instanceof mappingjacksonvalue) { mappingjacksonvalue container = (mappingjacksonvalue)object; value = container.getvalue(); serializationview = container.getserializationview(); filters = container.getfilters(); } if (type != null && typeutils.isassignable(type, value.getclass())) { javatype = this.getjavatype(type, (class)null); } objectwriter objectwriter = serializationview != null ? objectmapper.writerwithview(serializationview) : objectmapper.writer(); if (filters != null) { objectwriter = objectwriter.with(filters); } if (javatype != null && javatype.iscontainertype()) { objectwriter = objectwriter.fortype(javatype); } serializationconfig config = objectwriter.getconfig(); if (contenttype != null && contenttype.iscompatiblewith(mediatype.text_event_stream) && config.isenabled(serializationfeature.indent_output)) { objectwriter = objectwriter.with(this.sseprettyprinter); } //utf8jsongenerator对象处理返回的数据 objectwriter.writevalue(generator, value); this.writesuffix(generator, object); generator.flush(); } catch (throwable var26) { var10 = var26; throw var26; } finally { if (generator != null) { if (var10 != null) { try { generator.close(); } catch (throwable var25) { var10.addsuppressed(var25); } } else { generator.close(); } } } } catch (invaliddefinitionexception var28) { throw new httpmessageconversionexception("type definition error: " var28.gettype(), var28); } catch (jsonprocessingexception var29) { throw new httpmessagenotwritableexception("could not write json: " var29.getoriginalmessage(), var29); }}3.内容协商3.1基本说明内容协商:服务端和请求端协商决定最终返回什么格式的内容。客户端发送请求的时候可以告知服务器,自己希望对方返回的数据格式列表,而服务器的接口也有能支持响应的格式列表,最终返回的结果会根据这两个类型列表,找到一种两边都能支持的类型返回,如果找不到合适的类型,则报错。简单来说就是:根据客户端接收能力不同,springboot 返回不同媒体类型的数据比如:客户端 http 请求 accept: application/xml 则返回 xml 数据客户端 http 请求 accept: application/json 则返回 json 数据例子1:使用postman测试(1)使用postman发送http请求,在此期间服务器的代码不变,根据请求头不同,返回的数据格式也会不同返回json格式:返回xml格式:springboot 默认支持返回 json数据,不支持返回xml数据,所以需要导入jackson-dataformat-xmlcom.fasterxml.jackson.dataformat jackson-dataformat-xml例子2:使用浏览器测试浏览器不能指定accept属性,我们在浏览器发出请求,发现返回的数据为xml格式:这是因为浏览器的accept中指定了多种媒体类型,如下:支持接收html,xhtml xml,xml格式类型的权重为0.9支持接收image和 */* [所有类型] 格式的权重为0.8所以服务器会优先返回xhtml xml格式3.2问题如上,客户端通过http请求的accept来指定能接收的媒体类型。那么服务端的接口是怎么响应这个类型的呢?内容协商原理内容协商原理:判断当前响应头中是否已经有确定的媒体类型获取客户端accept请求头字段遍历循环所有当前系统的 messageconverter,看谁支持操作这个对象找到支持操作当前操作对象的converter,把converter支持的媒体类型统计出来进行内容协商得到最佳匹配媒体类型3.3注意事项postman可以通过修改accept的值来返回不同的数据格式。对于浏览器来说,我们无法修改其accept的值,这时如果要指定返回json格式,怎么办呢?pg网赌游戏的解决方案:开启支持基于请求参数的内容协商功能(1)修改application.ymlspring: mvc: contentnegotiation: favor-parameter: true #开启基于请求参数的内容协商,默认不开启(2)在浏览器请求的时候带上format参数,此时返回的就是指定的格式了注意:参数format的值是规定好的,在开启请求参数的内容协商功能后,springboot底层parametercontentnegotiationstrategy会通过format来接收参数,然后返回对应的媒体类型/数据格式,因此format的值也要是springboot能处理的才行。当然format这个属性名本身也可以通过配置文件修改:
赞 (0)
打赏微信扫一扫
相关推荐
日文大全10000个可复制(日文大全10000可复制免费)
来源头条作者:爱日语的萌妹子今天想跟大家分享日语数字的读法废话不多说,直接看正文〈0〜10〉0 ゼロ/れい 1 いち2 に 3 さん4 よん/し 5 ご 6 ろく 7 なな/しち 8 はち 9 きゅう/く10 じゅう 注意:0,4,7,9,都有两种读法,在电话号码里面,通常都是用前者,即0 ゼロ,4...
2023年08月01日
pg电子夺宝试玩的版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请通知我们,一经查实,本站将立刻删除。