对于后端开发来讲,常常要和前端进行联系的两个面就是:一、表单form提交至servlet。二、ajax提交至servlet进行处理。javascript
显然,有必要对这两个经常使用的功能进行一次梳理。html
在表单传值和后台进行交流的时候,一个最大的坑就是中文的乱码问题了。这个坑的具体分析不过多阐述,最佳实践就是: 使用post
方式进行数据的提交,后台设置字符集过滤器,对request
、response
的字符集都设置为utf-8
。前端
HTML表单如何打包数据文件是由enctype这个属性决定的。enctype有如下几种取值:java
application/x-www-form-urlencoded
在发送数据以前,编码全部字符(空格被编码为’+’,特殊字符被编码为ASCII十六进制字符,中文会被编码,英文不会)。此时,数据是以编码后的字符串形式进行传输。 multipart/form-data
不对字符编码。在使用包含文件上传控件的表单时,必须使用该值。此时,数据是以二进制流的形式进行传输。 text/plain
空格转换为 “+” 加号,但不对特殊字符编码。默认值是enctype=application/x-www-form-urlencoded
,因此表单的内容会按URL规则编码,而后根据表单的提交方法:jquery
method="get"
,编码后的表单内容附加在请求链接后method="post"
,编码后的表单内容做为post请求的正文内容action
的表单前端的表单,在填写了数据以后将数据发送给后端进行处理。这里,咱们所指的表单意为经过action
字段进行提交,经过ajax
模拟提交的状况放在下一大点中讨论。web
而这里的表单又分为2种状况:ajax
key-value
的形式,对于复选框亦如此。<input type="file" ...>
字段。例如表单:spring
<form action="/webapp/formServlet" method="post"> <input type="text" name="username"> <!-- 单选框 --> <input type="radio" name="sex" value="male">male <input type="radio" name="sex" value="female">female <!-- 下拉框 --> <select name="education"> <option value="primary">primary</option> <option value="middle">middle</option> <option value="high">high</option> </select> <!-- 复选框 --> <input type="checkbox" name="hobby" value="basket">basket <input type="checkbox" name="hobby" value="tennis">tennis <input type="checkbox" name="hobby" value="football">football <input type="submit" value="提交"> </form>
在servlet中获取数据:apache
String username = request.getParameter("username"); String sex = request.getParameter("sex"); String education = request.getParameter("education"); String[] hobby = request.getParameterValues("hobby");
数据编码: 对于纯文本的表单,其字段enctype=application/x-www-form-urlencoded
是默认值,表示表单的数据进行url编码,如:表单的数据被编码成username=123&password=222
。json
传输方式: 数据传输方式method
: 若是使用get
,那么该字符串会追加到请求的url地址后面;而若是使用post
,那么打开调试台,查看Form Data
项也能够查看到字符串。
这种表单提交数据的方式最为简单。
例如表单:
<form action="/webapp/formServlet" method="post" enctype="multipart/form-data"> <input type="text" name="username"> <input type="password" name="password"> <input type="file" name="file"> <input type="submit" value="提交"> </form>
在servlet中获取数据以及保存文件:
由于传输过来的是二进制流,所以没法使用getParameter()
等现成的方法来获取值。推荐使用apache upload
框架来进行数据的读取操做。固然,servlet也有原生的方法来获取,参考(https://docs.oracle.com/javae... 、(https://docs.oracle.com/javae... 。
传输方式: 由于是二进制流, 因此method
只能使用post
进行提交,没法使用get
。
既然咱们在servlet中能够获取到表单传过来的值了,那么咱们的返回又应该是什么样的呢?对于使用action
提交的表单,咱们的servlet必须将请求转发或者使用重定向,以此进行页面的切换(跳转)。若是想携带新的数据,只能在请求转发的request
对象上进行数据的添加。
请求转发:
request.setAttribute("msg","登陆成功!"); // 携带数据 request.getRequestDispatcher("/success.jsp").forward(request,response);
重定向:
response.sendRedirect("/webapp/success.jsp");
解读
很明显,直接使用action
提交是很很差的。由于在提交至servlet时,地址栏的路径会变成指向servlet的路径,而这时候,若是使用请求转发的话,那么地址栏的路径并不会改变,这样就不是很优雅。而若是使用重定向的话,就没法携带数据,对于常见的登陆验证(须要错误信息)就没法完成了。另外一个缺点就是,不管是请求转发仍是重定向,本来填写的表单数据都被清空,这样是极为糟糕的。
表单提交的最多见场景,每每就是用户登陆或者是文件上传,这些都须要服务器作出反馈,鉴于上面所说的缺点,咱们就不会使用action
的表单,而是使用更为强大ajax技术。
前言:
咱们先聊一聊ajax技术,ajax是发起一个http请求,固然能够携带数据,这个数据是以字符串的形式来传输的。固然,这个请求被发送至servlet进行处理,servlet返回处理后的信息,这个信息被ajax的回调函数所接受,而后ajax就能够进行相应的操做了。
当使用ajax时,能够没有表单的存在,由于咱们不须要action
了,咱们只须要获得要传输的数据便可。同时,对于type="submit"
字段也要当心设置,由于咱们其实能够不设置该值,或者在js事件中进行表单提交的判断。
区别:
ajax的过程和表单提交几乎差很少,不一样的是:ajax发出的http请求并非浏览器发出的请求,所以servlet是没有办法影响页面的跳转的 ,因此要想进行页面的跳转只能是ajax的回调函数中进行处理。而且大多数时候,servlet的处理也会返回json
数据至前台。这里的话,就涉及到json
数据的反序列化和java
对象(或者是Map
、List
)的序列化了。
缓存: ajax发出的请求一般会被浏览器缓存,所以咱们能够应该拒绝缓存。一般是在url地址后面追加一个随机字符参数,而使用jquery的ajax能够设置cache:false
这个属性就ok了。
jquery的ajax:
由于原生的ajax技术代码较多,所以咱们使用jquery封装好的ajax函数来说解其用法。在jQuery中,$.ajax()
方法属于最底层的方法,第2层是$.load()
,$.get()
,和$.post()
,第3层是$.getScript()
和$.getJSON()
方法。第二、3层都是调用了第1层来实现的。
有时候,在点击提交以后,页面会自动刷新,咱们没法查看相关的数据,这是一个大坑。正确的解决方法,使用<input type="button" value="提交" />
这个按钮来进行事件绑定并提交。固然,这是针对ajax来用的。
当咱们不须要发送数据的时候,其实只须要在一个js的事件中使用ajax就能够了,不须要表单。这种方式实际用的比较少。
一个触发ajax的按钮:
<button id="bt_1">ajax_1</button>
jquery代码:(请求servlet,接收返回数据)
var bt_1=$("#bt_1"); bt_1.on("click",function () { $.ajax({ url:"/webTest/ajax1", // 请求的servlet type:"post", // 由于没有携带数据,无所谓 async: true, // 异步 cache: false, // 不准缓存 success:function(data){ // 请求成功,200 console.log(data); }, error:function(error){ // 请求失败 console.log(error); } }) })
servlet处理代码:(返回数据)
PrintWriter out = null; try { out = response.getWriter(); // 打开response的输入流 } catch (IOException e) { e.printStackTrace(); } out.print("I give u a feedback"); // 写入信息到response out.close();
有的时候,咱们须要携带一些数据,能够是常见的表单,也能够是一些零散的数据。在这种状况下,咱们须要将数据封装成json
数据格式进行传输。
json
数据:对象形式jquery代码:
var sub=$("#sub"); sub.on("click",function () { $.ajax({ url:"/webTest/ajax2", type:"post", async:true, cache: false, data: { // json数据(注意,不能使用JSON.stringify()方法,不然出错) "username": "liSi", "password": "ps" }, success:function(data){ console.log(data); }, error:function(error){ console.log(error); } }) })
servlet处理代码:(接收数据,返回数据)
String username = request.getParameter("username"); String password = request,getParameter("password"); PrintWriter out = null; try { out = response.getWriter(); // 打开response的输入流 } catch (IOException e) { e.printStackTrace(); } out.print("I give u a feedback"); // 写入信息到response中 out.close();
在这种状况下,封装的json数据由于比较简单,因此数据被编码成字符串发送至servlet,就和以前使用action
的表单提交文本数据的状况同样。
注意,一旦json
数据复杂一点点,如{"username":"liSi","hobby":{"todya":"ttennis"}}
;就没法使用getParameter("hobby")
来获取数据了,这也是下面要将的第二种封装的json
数据。显然,这种封装的json
数据的获取,是一种特殊状况,在大多数不复制的状况是一种很好的方式。
当咱们使用了表单的时候,若是咱们只是想传输表单的值,那么就没有必要手工取值化成json形式,jquery提供了相应的方法来简化操做。固然,只是针对文本数据而言。
jquery代码1:
var data_json = $("#form_1").serialize(); data: data_json,
这里经过序列化函数,会自动把表单的数据转化为字符串形式(url),也就是和action
表单提交一致的效果。在servlet中能够直接经过getParameter()
方法来获取参数。
jquery代码2:
var data_json = $("#form_1").serializeArray(); data: data_json,
这里经过序列化函数,会自动把表单的数据转化为json数据格式,省去了手工封装成json的过程。
json
数据:数组形式一旦json
数据变复杂,那么在servlet中就没法经过getParameter()
获取数据了。这个时候咱们须要把json
数据先字符串化,使得json
在传输的时候就是原数据(打开调试台看到的Form Data
就和json
原数据同样)。
jquery代码:
var sub=$("#sub"); var data_json=[{"sex": '男',"submit":"111"},{"sex": '女',"submit":"222"}]; sub.on("click",function () { $.ajax({ url:"/webTest/ajax2", type:"post", async:true, cache: false, data: JSON.stringify(data_json), // 先序列化json数据 success:function(data){ console.log(data); }, error:function(error){ console.log(error); } }) })
在这里,json
数据就是比较复杂的了,咱们要先使用JSON.stringify()
序列化json
数据。
servlet代码:
BufferedReader reader = request.getReader(); // 获取请求的输出流 String jsonData = ""; jsonData += reader.readLine(); reader.close(); // 获取到一致的json数据 System.out.println(json); // [{"sex": '男',"submit":"111"},{"sex": '女',"submit":"222"}]
java操做json
数据:
对于获得的json
数据,咱们须要反序列,把咱们须要的值给取出来。一般是使用json
的解析库,如GSON、fastJson等。这里咱们使用GSON来说解。
因为篇幅的缘由,GSON
操做json
数据,序列化与反序列化的内容在另外一章中进行讲解。总之,咱们能够操做任何复杂的json
数据,而且从中取出咱们须要的属性。
得益于json
数据格式,使得先后端之间的数据交流变得十分方便。具体如何在java中操做json,请看有关于json的文章。
ajax
技术参数解读在ajax的代码中,有几个参数比较重要。
一、 contentType: "application/json;charset=utf-8"
这个参数是指明提交的数据的数据类型,不指明的话,默认是:
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
。
而指明了数据格式为json
的话,在后台有些框架能够直接获取,好比说springmvc。
注意: 一旦使用了指明了数据类型是json以后,就应该使用JSON.stringify()
方法来处理json数据。在后台的处理程序中就没法使用getParameter()
方法来获取值了。
二、 dataType:"json"
这个参数是指明返回的数据的数据类型,不指明的话,默认是:"text"
。
一样的一句话,只要涉及到文件数据,那么就是二进制流传输,是没法使用getParameter()
直接获取数据的。而且再啰嗦一句,之因此推荐使用ajax,就是由于它能够作到页面不跳转的提交。
咱们仍是能够选择是否使用表单,这也无所谓。当multiple="multiple"
时,能够一次上传多个文件。
表单:
<form id="form_1"> <input type="text" name="user" id="user"> <input type="file" name="file" multiple="multiple" id="file"> <input type="button" id="sub" value="submit it"/> </form>
jquery代码:
var formData = new FormData(); var name = $("input").val(); // formData对象放入值 formData.append("name",name); formData.append("file",$("#file")[0].files[0]); // 只选择第一个文件 $.ajax({ url : Url, type : 'POST', data : formData, processData : false, // 告诉jQuery不要去处理发送的数据 contentType : false, // 告诉jQuery不要去设置Content-Type请求头 success:function(data){ console.log(data); }, error:function(error){ console.log(error); } });
固然,咱们能够直接传入表单对象。这样更加快速。
var form_1 = document.getElementById("form_1"); var formData = new FormData(form_1); data: formData,
关于前端的表单提交数据至后台servlet的总结就先告一段落了。内容上能够分红2块,一是直接使用action
的表单提交,二是使用ajax
技术模拟的表单提交。而在数据上又能够分红2块,一是只含有文本数据,而是含有上传文件。