javaWeb - 2 — ajax、json — 最后附:后台获取前端中的input type = "file"中的信息 — 更新完毕

时间:2023-03-09 08:48:19
javaWeb - 2 — ajax、json — 最后附:后台获取前端中的input type = "file"中的信息 — 更新完毕

1、ajax是什么?

  • 面向百度百科一下就知道了,这里就简单提炼一下

    • Ajax即Asynchronous Javascript And XML(异步JavaScript和XML)。当然其实我们学的应该叫:异步JavaScript和ajax
    • 包括: HTML 或 XHTML, CSS, JavaScript, DOM, XML, XSLT, 以及最重要的XMLHttpRequest
    • 使用Ajax技术网页应用能够快速地将增量更新呈现在用户界面上,而不需要重载(刷新)整个页面,这使得程序能够更快地回应用户的操作
  • 用我的话说就是:ajax就是为了异步提交请求,从而只刷新一个局部区域的内容,不影响另外内容的刷新

    • 什么意思?很简单,都见过一个场景,当我们在注册账号的时候,我们输入用户名,输入框后面就会提示:该用户重名了,但是不是刷新了整个页面,而是只刷新了这一个用户名的输入框。这是怎么做到的,就是通过ajax异步请求做到的

2、原生的ajax应该怎么玩儿?

  • 对于学java的人来说:简单得要死,就他喵的三部曲

    1. 获取xmlHttpRequest对象
    2. 回调监听 onreadystatechange / 获取需要传递的数据
    3. 向后台发起请求、发送数据( 注:get、post这两种方式的发送数据的方法不太一样,但是道理其实都没变
  • (1)、那么就来实操一下嘛,先用get方式提交请求

  // 1、创建XMLRequest对象( 注意:考虑浏览器的不同 )
var xmlhttp;
if (window.XMLHttpRequest)
{
// IE7+, Firefox, Chrome, Opera, Safari 这几种浏览器获取XMLRequest对象的方式
xmlhttp=new XMLHttpRequest();
}
else
{
// IE6, IE5 浏览器执行代码
xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
} // 2、回调监听onreadystatechange
xmlhttp.onreadystatechange=function(){
if (xmlhttp.readyState==4 && xmlhttp.status==200){ document.getElementById("myDiv").innerHTML=xmlhttp.responseText;
}
} // 3、发送数据( 发送get请求 )
xmlhttp.open("GET","/接口名 ? 要传给后台的数据参数"); // 注意这个参数是:key-value的形式传送的
// 多个参数数据使用 & 隔开
xmlhttp.send(); // 发送请求
  • (2)、post方式提交
    • 其实和get方式是差不多的,只是发送数据哪里做一下修改即可,改成如下方式:
xmlhttp.open("POST","/后端的接口名 ? 要给后台传送的数据参数");
xmlhttp.send();

或者是:

xmlhttp.open("POST","/后台的接口名",true);
xmlhttp.setRequestHeader("Content-type","application/x-www-form-urlencoded"); // 这是请求头的设置,不会的可以直接百度
xmlhttp.send("fname=Henry&lname=Ford"); // 即:这里面直接跟要发给后台的数据参数
  • (3)、后端是怎么获取这个ajax中传递过去的参数的呢?
    • 很简单:get和post发给后台的数据不是都是以key-value的形式发过去的吗,那么:在后端直接使用 httpServletRequest对象.getParameter( String key ) 的方式即可获取到get或post中携带的value值。

多提一嘴:后台获取前端的数据,基本上都是通过 httpServletRequest对象.getParameter( String key / name ) 的方式获取的数据。但是:前端中input type = “file”的值不是这么获取的,而是需要在前端中 new一个FormData对象来进行操作。

即:在前端

  • 获取file的files属性( 获取file的节点.prop( "files" ) )
  • 然后通过 FormData对象.append("file" , files[0]) 的方式把这个file中的信息存到FormData中去
  • 最后通过ajax传递到后台去( 这里必须使用:$.ajax()的方式进行传递 —— 这是jQuery中的ajax异步请求方式,即:jQuery对ajax进行了封装,而原理就是上面说的get和post的执行过程。
    • 另外:记得对这个ajax设置:cache:false , contentType:false , processData:false

在后台:

  • 后台获取这个file中的值是通过 httpServletRequest对象.getParts() 获取file的所有value值( 但是:浏览器不同,这个值不同,所以:需要对这个信息进行截取,得到自己想要的那个文件名( 当然:这个servlet必须加一个注解才可以实现对文件的操作:即 @multipartConfig ) , 不说多了,这个后续会进行演示

3、JSON

1)、JSON是个什么鬼东西?

  • JSON( JavaScript Object Notation, JS 对象简谱 ) 是一种轻量级的数据交换格式

  • 它基于 ECMAScript (欧洲计算机协会制定的js规范)的一个子集,采用完全独立于编程语言的文本格式来存储和表示数据。

  • 简洁和清晰的层次结构使得 JSON 成为理想的数据交换语言

  • 易于人阅读和编写,同时也易于机器解析和生成,并有效地提升网络传输效率

  • 当然:这些都是网上的话,好像不太通俗易懂,那就换一下语言表达

    • 用java中能够让人一眼就明白的话来说就是:JSON就是用来存储东西的一个容器,这个容器在传输的时候very地快,同时很容易被解析( 无论是前端还是后台解析 )。这个玩意儿就这么回事儿

2)、JSON这个东西长什么样子嘞?

  • 也非常的好理解,在前面说明前端的时候不是玩过js对象吗,这个js对象长什么样子?
    • { fieldName1:"value" , fieldName2:"valud" ....... }

    • JSON对象 / 字符串就长这么个鬼样子

      • ' { fieldName1:"value" , fieldName2:"valud" ....... } '
    • JSON数组长什么样子?

      • ' [ { fieldName1:"value" , fieldName2:"valud" ....... } , { fieldName1:"value" , fieldName2:"valud" ....... } ] '

3)、那拿这个JSON来玩的是什么?

  • java对象 ---转成---> JSON字符串 / 对象 <---转成---> js对象

(1)、先来玩一下前端中js对象和json对象之间的转换( 其实就只需要记住parse()、stringify()两个方法就完了 )

 <script>
// json 对象
var jsonStr = ' {"id":69","name":"苍老师","size":"G"} ';
// json 数组
var jsonArray = ' [{"id":"1","name":"波多野结衣","size":"F"},{"id":"8","name":"汤wei","size":"B"} ] '; // JSON.parse( json格式的字符串 ) json字符串 = > JS对象(数组) ****重要***
// json对象 转 js对象
var js= JSON.parse(jsonStr);
console.log( js.id , js.name , js.size); // json数组 转 js对象
var js= JSON.parse( jsonArray );
js.forEach( function (v,i) {
console.log(v.name)
}) // JSON.stringify( js对象 ) JS对象 = > JSON字符串 ****重要****
var perosn = { name:"张三",age:10};
var json = JSON.stringify(perosn);
console.log(json) </script>

(2)、java对象 转 json对象

  • 这个就需要一个jar包了,有如下这些jar包供选择
    • fastjson [ 流行 , 所以建议用这个 ]
    • jackson
    • json-lib

      javaWeb - 2 — ajax、json — 最后附:后台获取前端中的input type = "file"中的信息 — 更新完毕
package cn.xieGongZi.servlet;

import com.alibaba.fastjson.JSON;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map; public class ToJson extends HttpServlet { @Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { req.setCharacterEncoding("utf-8");
resp.setCharacterEncoding("utf-8");
resp.setContentType("text/html;charset = utf-8"); // 这个其实这里不用配置也行,因为:要响应的是网页才设置这个嘛,这个示例哪里需要响应网页
// 要转成json对象,不让中文乱码,还需要做一件事情
resp.setContentType("application/json;charset=utf-8"); // 这里就直接硬拼一个对象出来
Map<String, Object> map = new HashMap<>();
map.put("name", "紫邪情");
map.put("sex", 18);
map.put("code", 200); String jsonStr = JSON.toJSONString(map); // 这里就把java对象转成一个json对象了 resp.getWriter().print(jsonStr); // 这一步就是响应给前端
/*
但是:这里涉及到了ajax的使用 [ 其实就是ajax中回调监听哪里的xmlHttpRequest.responseText ] )
请求获取响应文本嘛,这个响应文本内容不就是后台这里的响应流向浏览器发送的数据吗,但是被前端获取过去了
这样前端就可以拿到后端这里传过去的数据了 ———— 不会的,看不懂的,现在不理解没事,等到前后端连起来玩ajax时就懂了
*/ }
}

4、实操玩一下ajax

  • 前面说了这么多理论的废话,没多大意思,所以:还是来实操一手儿ajax吧

  • 使用jQuery中封装好了的ajax

    • 要使用jQuery,那肯定需要导入jQuery的js咯
      • javaWeb - 2 — ajax、json — 最后附:后台获取前端中的input type = "file"中的信息 — 更新完毕
  • get方式的ajax语法如下:


$.get( ' 后端的接口名-servlet中的那个servlet路径 ' ,{ fieldName1:valued , fieldName2:value .....} , function( 参数 ) { 逻辑代码; } , 'json' )
  • post方式的ajax语法如下:

$.post( ' 后端的接口名-servlet中的那个servlet路径 ' ,{ fieldName1:valued , fieldName2:value .....} , function( 参数 ) { 逻辑代码; } , 'json' )
  • 对如上式子的说明:
    • { fieldName1:valued , fieldName2:value .....} 就是要传给后端 ' 后端的接口名-servlet中的那个servlet路径 ' 这个路径下的数据参数

      • 这个数据参数的本质其实就是js对象,因此:要是要传的数据参数有多个的时候就可以封装成一个js对象,然后把对象名甩到这里来当数据参数就可以了
    • 'json' 这个就是期望后端传回前端的数据格式类型是什么,具体可以填哪些类型,自行百度百科,这里用json类型

    • function( 参数 ) 这个就是回调函数 , 这个“ 参数 ”就是后端传给前端的数据( 一般都是json字符串 )

      • 这个参数后端一般是怎么封装传过来的?
        • 看前端需要的json格式是怎么样的
        • 然后通过不断的使用map,从而一层之中套一层...达到想要的json格式,从而使用resq.getWriter().print()把这个json对象传到前端去
    • 整个过程结合ajax的原生使用方法( 即 : 美没封装之前的用法 —— 前面说的那个三部曲 ), 这样就很好理解了

    • 举个例子( **这个例子很重要很重要 , 后端获取前端的input type = “file”中的信息就是通过这个方法流程得到的 ):

    • 前端需要的格式是这样的:

      "errno":0 data:[ { url:"图片地址“ } , { alt:"图片说明“ } , { href:"null" } ] // href 其实是跳转链接

    • 后端就是这么玩的:

package cn.xieGongZi.commons.util.http;

import com.alibaba.fastjson.JSON;

import javax.servlet.ServletException;
import javax.servlet.annotation.MultipartConfig;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.Part;
import java.io.File;
import java.io.IOException;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap; // @MultipartConfig 注解就是文件注解,要获取前端的文件信息,必须加这个注解,不然做的所有事情都是无用功
@MultipartConfig
@WebServlet("/ajax/upload.do")
public class UploadServlet extends HttpServlet { @Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { /*
* 想要构建的是这么一个玩意儿
* "errno":0 data:[ { url:"图片地址“ } , { alt:"图片说明“ } , { href:"null" } ] // href 其实是跳转链接
*
* */ ArrayList<Object> list = new ArrayList<>(); Collection<Part> parts = req.getParts(); // 这是获取前台上传的文件 for (Part part : parts) { // 先构建 data:[ { } , { } ]中的[ { } , { } ] // 获取文件的全路径
String filePath = part.getSubmittedFileName(); // 但是:不同浏览器的这个全路径都不一样,所以需要截取从而自定义文件名
// System.out.println(filePath);
// 截取文件的后缀名
int subFileName = filePath.lastIndexOf(".");
String fileSuffix = filePath.substring(subFileName); // 自己给文件重新定义一个名字,并规定存放的地方
String timeStr = LocalDate.now().toString(); // 获取当前项目的一个指定文件夹名字,用来保存文件 注意:getRealPath这是获取的当前项目的全路径,即:从盘符开始的路径
String proPathName = this.getServletContext().getRealPath("/upload/" + timeStr );
File file = new File(proPathName);
if ( !file.exists() ){
file.mkdirs();
} // 拼接文件后缀名并保存文件
long timeStamp = new Date().getTime();
part.write(proPathName + "/" + timeStamp + fileSuffix ); HashMap<String, String> map = new HashMap<>();
map.put( "url" , "/upload/" + timeStr + "/" + timeStamp + fileSuffix );
map.put( "alt" , timeStamp + fileSuffix );
map.put( "href" , null );
list.add(map);
} // 再构建"errno":0 data:[ { url:"图片地址“ } , { alt:"图片说明“ } , { href:"null" } ]
HashMap<String, Object> map = new HashMap<>();
map.put("errno", "0");
map.put("data", list); resp.getWriter().print( JSON.toJSONString(map) );
}
}
  • 前端的html是这样的:

<div id="image">
<label for="">标题图片:</label>
<input type="file" id="file" name="file" >
<img src="" alt="" width="100px" height="150px">
</div>
  • 前端的script是这样弄的:
    // 当图片发生改变时 —— 也就是用户点击file框,上传文件时
$("#file").on( 'change' , function () { // 创建一个FormData空对象,就相当于是伪造了一个form表单
let formData = new FormData(); // 这个FromData对象就用来装文件内容
let files = $("#file").prop("files"); // 文件的files属性本质是个数组,可以使用 获取file输入框的节点.files 看一下答案
formData.append("upFile" , files[0] ); $.ajax( { // 这个就是jQuery中ajax的用法,“万变不离其宗”,上面的get和post使用也就会了 url: '/ajax/upload.do',
type: 'post',
data: formData,
dataType: 'json', cache: false, // 上传文件不需要缓存
contentType: false, // 不需要对内容类型进行处理 因为内容是一个FormData对象
processData: false, // 不需要对数据进行处理,因为上面的data是一个FormData对象 // 后台返回的格式 :
// { "errno":"0" , "data":[ {"alt":"1633528500498.jpg" , "url":"/upload/2021-10-06/1633528500498.jpg"} ] }
success: function (info) {
info.data.forEach( function (data) { // $("#image img").remove();
// $("#image").append( ' <img src=" '+data.url+' " alt="" width="100px" height="150px"> ' )
/*
注掉的这种是:html中没有img标签时使用
因为:使用下面这种方法的情景是 —— 页面本来就有一个img框( 即:初始页面上这个file本身有一张图片 ),所以下面这种可以做到图片改变时把图片的路径换掉
也就是图片渲染( 这也是数据渲染 / 数据回填 的思想 )
但是:如果页面一开始file的位置是不应该有图片的,是后面用户选了之后才出现图片预览效果,那么:就使用注释掉的这种方法:追加
*、 $("#image img").attr("src" , data.url );
});
}
} ); })
  • 这个的效果是这样的,这个图片的信息是可以在后端获取到的( 当然:文件也可以 )

    javaWeb - 2 — ajax、json — 最后附:后台获取前端中的input type = "file"中的信息 — 更新完毕

ajax、json的相关内容也就差不多是这些了,主要是:会用就行