springmvc的controller层如何获取到请求的数据
javaweb应用开发,最常用到的就是应用之间的信息交互,调用别的应用模块得到自己想获取的数据信息,然后解析数据并进行处理返回到上一层。那controller层的方法如何获取http请求/webservice请求中的参数,或者说请求数据呢?
按照我个人的接触和理解,把请求可以分为两大类:
1.页面请求到后台controller层的请求。
2.别的应用http/webservice调用本应用中封装接口的请求。
无论哪种方式的请求,都是http请求(webservice底层也是http请求,待考证),controller层对请求数据的解析是按照json还是xml的依据就是请求头content-type,接下来我们就先来详细介绍一下。
content-type
content-type请求头是干吗的呢,http请求头有四种类型,分别是通用头部,请求头部,响应头部以及内容头部.
首先,我们要弄清楚,content-type是属于内容头部,既然是内容头部,那这个请求头是用来向接收端解释传递的该内容主体的,content-type的取值是告诉服务端,你传递过去的内容是啥,你应该准备好如何接收和解析。常用的content-type可以分为application/x-www-form-urlencoded
, multipart/form-data
,application/json
, text/xml
四种。下面一一介绍
1.application/x-www-form-urlencoded
application/x-www-form-urlencoded是常用的表单发包方式,普通的表单提交(即不带文件上传的提交),或者js (例如:post方式)发包,默认都是通过这种方式,提交代码demo如下:
function searchInfo() {$("#cxjg").datagrid({url : basepath + 'jijin/getList',queryParams : getParam($("#query").serializeArray()),method : "post"});
function searchInfo(){$("#cxjg").datagrid({url:basepath+'jijin/getList',queryParams : {'age':23,'name':'zhangsan'},method:"post"
});
请求头信息如下所示,可以看到content-type和FormData(表单的数据格式)
如何获取这种数据结构的请求?有两种方式来解决
1.1 String 参数值=reqeust.getParameter(“参数名”);
(以springmvc 的controller层的方法为例)
@RequestMapping("/getParam")
public String getParamFromRequest(HttpServletRequest request){String jiJinCode=(String)request.getParameter("jinJinCode");...
}
1.2
Map<String,String[]> paramMap=request.getParameterMap();
@RequestMapping("/getParam")
public String getParamFromRequest(HttpServletRequest request){Map<String,String[]> paramMap=request.getParameterMap();StringBuffer inputDate=new StringBuffer();inputDate.append("<jiJinBean>");for(Map.Entry<String,String[]> entry :paramMap.entrySet()){String key=entry.getKey();String[] values=entry.getValue();String value=null;if(values.length>0){value=values[0];}inputDate.append("<"+key+">"+value+"</"+key+">");}return inputDate.toString();
}
两种方法比较来说,第一种适合当参数不多时,可以一个一个取。但第二种则是遍历出所有的请求参数,并生成标签格式,利于自动生成报文格式。
2.multipart/form-data
multipart/form-data用在页面(提交)发送文件的POST请求。之所以会和第一种content-type同是post提交,为啥在这里就变成multipart/form-data了呢?当然程序不会自动识别是不是文件,而是我们在<form>
这个标签里加上了这句话:enctype="multipart/form-data"
,这才是让请求头发生变化的原因!具体代码demo如下
$("#batchAddInfo").form('submit',{url:basepath+"jijin/fileUpload",onSubmit:function(){},success:function(data){data=eval('('+data+')');var flag=data.flag;if(flag){$("#batchDivDialog").window("close");$.messager.alert('提示',"批量新增成功!");searchInfo();}else{$("#batchDivDialog").window("close");$.messager.alert('提示',"批量新增失败!");searchInfo();}}});
对应的谷歌页面request调试信息如下:
这里Content-Type告诉我们,发包是以multipart/form-data格式来传输,另外,还有boundary用于分割数据。
这种方式的请求数据如何获取?出文件外的表单参数值当然还是和上面一样——request.getParameter(“parameterName”)来获取,不一样的是文件怎么来获取?要用到MultipartHttpServletRequest,这个MultipartHttpServletRequest 继承于HttpServletRequest,MultipartRequest。我们要从这个子类里面来获取,具体代码如下:
@RequestMapping("/fileUpload")
public void fileUpload(HttpServletRequest request,HttpServletResponse response){InputStream is=null;//创建解析器CommonsMultipartResolver resolver=new CommonsMultipartResolver(request.getSession().getServletContext());//判断request是否有文件上传,即多部请求if(resolver.isMultipart(request)){MultipartHttpServletRequest multiRequest=(MultipartHttpServletRequest)request;//获取多部request中的文件名Iterator<String> iter=multiRequest.getFileNames();while(iter.hasNext()){//取得上传的文件MultipartFile file=multiRequest.getFile(iter.next());if(file!=null){is=new ByteArrayInputStream(file.getBytes());}}}
Workbook wb=new XSSFWorkbook(is);
...
}
3.text/xml
这种请求头一般出现实在webservice请求时才会有。由于别的应用请求我们,所以我们这边就是服务端,他们是客户端。这里无法用浏览器模拟,只能给出客户端和服务端代码,然后看如何解析客户端的请求数据。
客户端代码;
public class AxisClientTest {public static void main(String[] args) throws Exception {String nameSpaceURI = "com.serviceTargetName";String publishUrl = "http://localhost:8080/springCXFWebserviceDemo01/service/HelloWorldService?wsdl";Service service = new Service();
// 通过service创建call对象Call call = (Call) service.createCall();// 设置webservice接口地址call.setTargetEndpointAddress(new URL(publishUrl));call.setOperationName(new QName(nameSpaceURI, "sayHello"));call.addParameter("parameterName", XMLType.XSD_STRING, ParameterMode.IN);
call.setReturnType(XMLType.XSD_STRING);// 给方法传递参数,并且调用方法String name = "zhanglifeng";String temp = getXml(name);// 这里的obj{}是放入几个入参,完全由service提供的接口方法的入参决定,且顺序和你存放的顺序一致!一般入参为String类型的xml报文,回参也是xml报文。Object[] obj = new Object[] { temp };String result = (String) call.invoke(obj);}private static String getXml(String name) {StringBuffer sb = new StringBuffer("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");sb.append("<userBean>");sb.append("<userName>" + name + "</userName>");sb.append("</userBean>");return sb.toString();}}
上面的方法getXml(String name)就是客户端发给服务端的请求:
<?xml version="1.0" encoding="UTF-8"?><userBean><userName>" + 入参:人名 + </userName></userBean>
下面我们再看服务端,也就是我们这边接受请求的代码是啥样的:
/*** 由于实现类和接口不在同一个包中。所以要加上targetNamespace属性。* 另外,这里的endpointInterface是实现类对应接口的全路径* @author Administrator*/
@WebService(targetNamespace="com.serviceTargetName",endpointInterface="com.zlf.HelloWorld")
@Component("HelloWord")//spring注入用
public class HelloWorldImpl implements HelloWorld {@Overridepublic String sayHello(String str) {String username="aaa";Document document = XMLUtils.parse(str);//首先接口开发肯定是双发都知道此方法要接受的报文格式的。我们获取报文中人名对应的节点即可。Node node = document.getElementsByTagName("userName").item(0);if(node !=null){username=node.getTextContent();}return "你好,"+username+" 你已成功访问了webservice服务端!" ;}
}
这里我们是直接拿着入参str进行Documen解析,因为客户端的请求数据已经绑定到这个入参上了。由于我们知道他的请求报文格式是xml的,所以可以进行Document转换,然后我们从节点中取值既可以实现请求数据的解析了。
解析的代码请查看我以前的博文: 基于cxf和axis两种框架下的webservice客户端开发文的最后就是这个解析的工具类。
4.application/json
application/json 这个 Content-Type 作为响应头大家肯定不陌生。实际上,现在越来越多的人把它作为请求头,用来告诉服务端消息主体是序列化后的 JSON 字符串。由于 JSON 规范的流行,除了低版本 IE 之外的各大浏览器都原生支持 JSON.stringify,服务端语言也都有处理 JSON 的函数,使用 JSON 不会遇上什么麻烦。
JSON 格式支持比键值对复杂得多的结构化数据,这一点也很有用。
这个请求头还有一个特殊点就是页面通过jquery过来的数据结构和其他应用请求的数据结构不一样,因为jquery对json的数据做了转换:
"data":{"mobilenum":"15867426421",'age':23,'name':'zhangsan'}——>mobilenum=15867426421&age=23&name=zhangsan
然而应用没有发生转化,还是json结构的数据。所以获取上会有所不同。这里我们分成页面和应用两种请求来分别说
4.1 页面请求的数据获取
4.1.1 页面js请求如下,数据结构为json,且data为var data={}的json类型时
$.ajax({
type: "post",
data:{'mobilenum':'15867426421','age':'23','name':'zhangsan'},
contentType: "application/json; charset=utf-8",
url :basepath+'jijin/getList',
success: function(data){ ... }
});
但是当用浏览器来看是这样的:
我们的数据结构明显发生了变化,由json变成了用&符号连接的普通传值方式。所以这时候获取参数值通过:String name=request.getParameter(“name”)这种来获取。
4.1.2 如果页面js请求如下,数据结构为json,且data为var data=”“的String类型时,controller获取数据则可以和下面的4.2一样通过注解@RequestBody来绑定到入参上。
$.ajax({dataType: "json",type: "POST",data:"{'mobilenum':'15867426421','age':'23','name':'zhangsan'}",contentType: "application/json; charset=utf-8",url :basepath+'jijin/getList',success: function(data){ }});}
这时对应的浏览器的请求头信息如下:
可以看到串到后台的数据结构为json格式的数据结构,和4.1.1完全不同了。就是因为data的数据类型不同导致的,4.1.1的data是json类型,结果转成普通的get方式拼接的参数结构,4.1.2的data是String类型,反而保持住了json类型的数据结构。从而可以实现在controller层通过参数绑定来获取请求参数。
4.1总结
通过上面两个比较可以知道,页面的jquery还是能够识别json数据的,真是由于识别才导致数据转换而。String类型的字符串没有转换的意义,而是直接传给后台,从而保证了数据结构的不变。故:我们真想让后台接受json数据结构的参数话,还是传String类型的吧!
4.2 当别的应用调用我们的服务,发送json数据的请求时如何解析(springmvc controller层)?总的来说通过@RequestBody 注解方法的入参,可以让请求的参数绑定到该参数上,然后用Gson转换成json即可获得jsonObject/实体类(这里的UserBo),具体代码如下
@RequestMapping("/url")
public void getUrlByPhone(@RequestBody String json,HttpServletRequest request){Gson gson=new Gson();UserBo ub=gson.fromJson(json,UserBo.class);//这里还可以通过jackson的ObjectMapper()把String json转成JsonNode,然后用jsonNode.get(fieldName)来获取各个json字段。例如:JsonNode node=new ObjectMapper().readTree(json);String name=node.get("name");......
}
参考博文:理解HTTP之Content-Type
springmvc的controller层如何获取到请求的数据相关推荐
- php获取 POST请求的数据
普通键值对的数据: $_POST['username']; // 获取 username的信息:$_REQUEST; //则会获取 整个请求中的键值对,返回结果为数组: 如果是,流数据,则需要使用: ...
- node 请求数据_使用Node获取HTTP请求主体数据
node 请求数据 Here is how you can extract the data that was sent as JSON in the request body. 这是在请求正文中提取 ...
- springMVC 注解 controller层的优化
1类中方法对应的URL请求路径有相同部分,可以放在类外面 @Controller @RequestMapping("/user") public class LonginContr ...
- 三、Springmvc之Controller层方法返回值
ItemController @Controller public class ItemController {@Autowiredprivate ItemService itemService;/* ...
- mvc ajax异常,使用SpringMVC的controller中能获取数据但直接跳到异常页面,使用Ajax。...
Controller代码 import java.util.Date; import org.springframework.stereotype.Controller; import org.spr ...
- springMVC的controller层显示问好解决方案
今天我在做axios和spirngMVC实行跨域的时候经过测试发现前台获取的内容中文是问好,我就第一时间想到的是数据库那里出现了问题可是用控制台打印的时候是没有问好的这就说明是springMVC可能没 ...
- springMVC中 Controller层为什么可以用map来传输数据
在springmvc中 我们可以知道 model使用来传输数据用的 如图所示: model: @GetMapping("/")public String getStudents(M ...
- pojo层,Dao层,Mapper层,service层,controller层
MVC框架即模型-视图-控制器(model-View-controller) M即model模型是指模型表示业务规则 V即View视图是指用户看到并与之交互的界面 C即controller控制器是指控 ...
- Web项目实战 | 购物系统v2.0 | 开发记录(九)Controller层返回数据的封装 | 商品批量操作 | 五表联立实现商品搜索
--若发现文章内容有误,敬请指正,望不吝赐教,感谢! 文章目录 以往记录 运行环境 一.设计Bean用于Controller层返回数据 二.商品批量操作 2.1 批量操作的前端设计 2.2 批量操作的 ...
最新文章
- 「日常训练」Bad Luck Island(Codeforces Round 301 Div.2 D)
- 当postgres的主键序列不同步时,如何重置?
- 数据绑定控件之ListView
- JPA中实现双向一对多的关联关系
- 我们离DevOps有多远--持续集成思想的延伸
- MySQL+多线程+Redis+算法+网络
- 没有bug队——加贝——Python 练习实例 15,16
- C++关键字this
- java 蓝桥杯 乘法次数(题解)
- python3怎么安装docx_如何在 Python 3.4 上安装 python-docx
- idea 搜索快捷键
- Raspberry3B+搭建有线路由器-实现网口转发
- c语言调用pdf文档,使用PDFLib生成PDF文档方法介绍(C语言版)
- excel表突然不会自动计算机,怎么实现EXCEL表格中自动记录当前时间而不是日期,并且不会更新变动...
- C++的四种强制转换
- 一个IT人的咖啡爱情
- SWI-Prolog特性
- 时钟插件TextClock的使用
- “智慧城市”让景观照明更“绿色”!
- 电信版系统可随时升级支持4G网络